From b370fe61c0aeccac7745ad404dad925ec217ba6d Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 28 Mar 2018 17:18:02 +0100 Subject: Implement group join API --- synapse/groups/groups_server.py | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 70781e1854..77b6273e39 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -723,6 +723,51 @@ class GroupsServerHandler(object): "attestation": local_attestation, }) + @defer.inlineCallbacks + def join_group(self, group_id, requester_user_id, content): + """User tries to join the group. + + This will error if the group requires an invite/knock to join + """ + + yield self.check_group_is_ours(group_id, requester_user_id, and_exists=True) + + group_info = yield self.store.get_group( + group_id, + ) + if not group_info['is_joinable']: + raise SynapseError(403, "Group is not publicly joinable") + + if not self.hs.is_mine_id(requester_user_id): + local_attestation = self.attestations.create_attestation( + group_id, requester_user_id, + ) + remote_attestation = content["attestation"] + + yield self.attestations.verify_attestation( + remote_attestation, + user_id=requester_user_id, + group_id=group_id, + ) + else: + local_attestation = None + remote_attestation = None + + is_public = _parse_visibility_from_contents(content) + + yield self.store.add_user_to_group( + group_id, requester_user_id, + is_admin=False, + is_public=is_public, + local_attestation=local_attestation, + remote_attestation=remote_attestation, + ) + + defer.returnValue({ + "state": "join", + "attestation": local_attestation, + }) + @defer.inlineCallbacks def knock(self, group_id, requester_user_id, content): """A user requests becoming a member of the group -- cgit 1.4.1 From 6eb3aa94b6befcc89f6fee426053b3feee316bb9 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 3 Apr 2018 11:48:17 +0100 Subject: Factor out add_user from accept_invite and join_group --- synapse/groups/groups_server.py | 70 +++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 41 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 77b6273e39..2c02da4725 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -678,30 +678,21 @@ class GroupsServerHandler(object): raise SynapseError(502, "Unknown state returned by HS") @defer.inlineCallbacks - def accept_invite(self, group_id, requester_user_id, content): - """User tries to accept an invite to the group. + def add_user(self, group_id, user_id, content): + """Add a user to a group based on a content dict. - This is different from them asking to join, and so should error if no - invite exists (and they're not a member of the group) + See accept_invite, join_group. """ - - yield self.check_group_is_ours(group_id, requester_user_id, and_exists=True) - - is_invited = yield self.store.is_user_invited_to_local_group( - group_id, requester_user_id, - ) - if not is_invited: - raise SynapseError(403, "User not invited to group") - - if not self.hs.is_mine_id(requester_user_id): + if not self.hs.is_mine_id(user_id): local_attestation = self.attestations.create_attestation( - group_id, requester_user_id, + group_id, user_id, ) + remote_attestation = content["attestation"] yield self.attestations.verify_attestation( remote_attestation, - user_id=requester_user_id, + user_id=user_id, group_id=group_id, ) else: @@ -711,13 +702,33 @@ class GroupsServerHandler(object): is_public = _parse_visibility_from_contents(content) yield self.store.add_user_to_group( - group_id, requester_user_id, + group_id, user_id, is_admin=False, is_public=is_public, local_attestation=local_attestation, remote_attestation=remote_attestation, ) + defer.returnValue(local_attestation) + + @defer.inlineCallbacks + def accept_invite(self, group_id, requester_user_id, content): + """User tries to accept an invite to the group. + + This is different from them asking to join, and so should error if no + invite exists (and they're not a member of the group) + """ + + yield self.check_group_is_ours(group_id, requester_user_id, and_exists=True) + + is_invited = yield self.store.is_user_invited_to_local_group( + group_id, requester_user_id, + ) + if not is_invited: + raise SynapseError(403, "User not invited to group") + + local_attestation = yield self.add_user(group_id, requester_user_id, content) + defer.returnValue({ "state": "join", "attestation": local_attestation, @@ -738,30 +749,7 @@ class GroupsServerHandler(object): if not group_info['is_joinable']: raise SynapseError(403, "Group is not publicly joinable") - if not self.hs.is_mine_id(requester_user_id): - local_attestation = self.attestations.create_attestation( - group_id, requester_user_id, - ) - remote_attestation = content["attestation"] - - yield self.attestations.verify_attestation( - remote_attestation, - user_id=requester_user_id, - group_id=group_id, - ) - else: - local_attestation = None - remote_attestation = None - - is_public = _parse_visibility_from_contents(content) - - yield self.store.add_user_to_group( - group_id, requester_user_id, - is_admin=False, - is_public=is_public, - local_attestation=local_attestation, - remote_attestation=remote_attestation, - ) + local_attestation = yield self.add_user(group_id, requester_user_id, content) defer.returnValue({ "state": "join", -- cgit 1.4.1 From ae85c7804e733aa1adaed06a9de51445a084858e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 5 Apr 2018 16:31:57 +0100 Subject: is_joinable -> join_rule --- synapse/groups/groups_server.py | 2 +- synapse/storage/group_server.py | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 2c02da4725..507ec232c5 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -746,7 +746,7 @@ class GroupsServerHandler(object): group_info = yield self.store.get_group( group_id, ) - if not group_info['is_joinable']: + if group_info['join_policy'] != "open": raise SynapseError(403, "Group is not publicly joinable") local_attestation = yield self.add_user(group_id, requester_user_id, content) diff --git a/synapse/storage/group_server.py b/synapse/storage/group_server.py index 5fbe0ada4e..d81609dd16 100644 --- a/synapse/storage/group_server.py +++ b/synapse/storage/group_server.py @@ -57,15 +57,12 @@ class GroupServerStore(SQLBaseStore): }, retcols=( "name", "short_description", "long_description", - "avatar_url", "is_public", "is_joinable", + "avatar_url", "is_public", "join_rule", ), allow_none=True, desc="get_group", ) - if ret and 'is_joinable' in ret: - ret['is_joinable'] = bool(ret['is_joinable']) - defer.returnValue(ret) def get_users_in_group(self, group_id, include_private=False): -- cgit 1.4.1 From 6850f8aea3482443dff1c330fb63f7ca8dde0025 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 5 Apr 2018 17:16:31 +0100 Subject: Get group_info from existing call to check_group_is_ours --- synapse/groups/groups_server.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 507ec232c5..1b516011d8 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -741,11 +741,7 @@ class GroupsServerHandler(object): This will error if the group requires an invite/knock to join """ - yield self.check_group_is_ours(group_id, requester_user_id, and_exists=True) - - group_info = yield self.store.get_group( - group_id, - ) + group_info = yield self.check_group_is_ours(group_id, requester_user_id, and_exists=True) if group_info['join_policy'] != "open": raise SynapseError(403, "Group is not publicly joinable") -- cgit 1.4.1 From 112c2253e2846b48b75f4171d9dd94bfe6ecc8a1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 5 Apr 2018 17:32:20 +0100 Subject: pep8 --- synapse/federation/transport/client.py | 2 +- synapse/groups/groups_server.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/federation/transport/client.py b/synapse/federation/transport/client.py index 67ff7da51b..50a967a7ec 100644 --- a/synapse/federation/transport/client.py +++ b/synapse/federation/transport/client.py @@ -872,7 +872,7 @@ class TransportLayerClient(object): @log_function def set_group_join_policy(self, destination, group_id, requester_user_id, - content): + content): """Sets the join policy for a group """ path = PREFIX + "/groups/%s/settings/m.join_policy" % (group_id,) diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 1b516011d8..15d31549de 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -741,7 +741,9 @@ class GroupsServerHandler(object): This will error if the group requires an invite/knock to join """ - group_info = yield self.check_group_is_ours(group_id, requester_user_id, and_exists=True) + group_info = yield self.check_group_is_ours( + group_id, requester_user_id, and_exists=True + ) if group_info['join_policy'] != "open": raise SynapseError(403, "Group is not publicly joinable") -- cgit 1.4.1 From b4478e586fe52392a439c94f525c3d885454f0a8 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 6 Apr 2018 11:37:49 +0100 Subject: add_user -> _add_user --- synapse/groups/groups_server.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 15d31549de..72dfed7dbb 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -678,7 +678,7 @@ class GroupsServerHandler(object): raise SynapseError(502, "Unknown state returned by HS") @defer.inlineCallbacks - def add_user(self, group_id, user_id, content): + def _add_user(self, group_id, user_id, content): """Add a user to a group based on a content dict. See accept_invite, join_group. @@ -727,7 +727,7 @@ class GroupsServerHandler(object): if not is_invited: raise SynapseError(403, "User not invited to group") - local_attestation = yield self.add_user(group_id, requester_user_id, content) + local_attestation = yield self._add_user(group_id, requester_user_id, content) defer.returnValue({ "state": "join", @@ -747,7 +747,7 @@ class GroupsServerHandler(object): if group_info['join_policy'] != "open": raise SynapseError(403, "Group is not publicly joinable") - local_attestation = yield self.add_user(group_id, requester_user_id, content) + local_attestation = yield self._add_user(group_id, requester_user_id, content) defer.returnValue({ "state": "join", -- cgit 1.4.1 From 6bd1b7053e41350fcc1b451e40da82257e2120b5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 6 Apr 2018 11:44:18 +0100 Subject: By default, join policy is "invite" --- synapse/groups/groups_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 72dfed7dbb..8310dea031 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -905,7 +905,7 @@ def _parse_join_policy_dict(join_policy_dict): """ join_policy_type = join_policy_dict.get("type") if not join_policy_type: - return True + return "invite" if join_policy_type not in ("invite", "open"): raise SynapseError( -- cgit 1.4.1 From 7945435587704c5abd075140bdd46c11db93c255 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 6 Apr 2018 14:06:32 +0100 Subject: When exposing group state, return is_openly_joinable as opposed to join_policy, which is really only pertinent to the synapse implementation of the group server. By doing this we keep the group server concept extensible by allowing arbitrarily complex rules for deciding whether a group is openly joinable. --- synapse/groups/groups_server.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 8310dea031..290eec7127 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -407,6 +407,11 @@ class GroupsServerHandler(object): group_description = yield self.store.get_group(group_id) if group_description: + join_policy = group_description['join_policy'] + del group_description['join_policy'] + + group_description['is_openly_joinable'] = join_policy == "open" + defer.returnValue(group_description) else: raise SynapseError(404, "Unknown group") -- cgit 1.4.1 From db2fd801f722ae8341b36314fb8929a80fd53996 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 6 Apr 2018 15:51:15 +0100 Subject: Explicitly grab individual columns from group object --- synapse/groups/groups_server.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 290eec7127..ad937c1721 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -404,13 +404,15 @@ class GroupsServerHandler(object): yield self.check_group_is_ours(group_id, requester_user_id) - group_description = yield self.store.get_group(group_id) - - if group_description: - join_policy = group_description['join_policy'] - del group_description['join_policy'] + group = yield self.store.get_group(group_id) - group_description['is_openly_joinable'] = join_policy == "open" + if group: + cols = [ + "name", "short_description", "long_description", + "avatar_url", "is_public", + ] + group_description = { key: group[key] for key in cols } + group_description["is_openly_joinable"] = group['join_policy'] == "open" defer.returnValue(group_description) else: -- cgit 1.4.1 From 020a5013544b1f7046faa97b83eb2acc613334b1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 6 Apr 2018 16:02:06 +0100 Subject: de-lint, quote consistency --- synapse/groups/groups_server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'synapse/groups/groups_server.py') diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index ad937c1721..2d95b04e0c 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -411,8 +411,8 @@ class GroupsServerHandler(object): "name", "short_description", "long_description", "avatar_url", "is_public", ] - group_description = { key: group[key] for key in cols } - group_description["is_openly_joinable"] = group['join_policy'] == "open" + group_description = {key: group[key] for key in cols} + group_description["is_openly_joinable"] = group["join_policy"] == "open" defer.returnValue(group_description) else: -- cgit 1.4.1