From 7dd81e472411e573ecfd9acb3d3ba71b912758a7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 21 Oct 2017 12:16:29 -0600 Subject: [PATCH 1/6] Allow group members to not be made public to outsiders Useful for bridges that wish to have flair in rooms, but not advertise a members list. Signed-off-by: Travis Ralston --- synapse/groups/groups_server.py | 11 ++++++++--- synapse/storage/group_server.py | 5 +++-- synapse/storage/prepare_database.py | 2 +- .../46/track_group_membership_publicity.sql | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 synapse/storage/schema/delta/46/track_group_membership_publicity.sql diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index fc4edb7f046a..1c2ea8e97007 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -383,10 +383,13 @@ def get_users_in_group(self, group_id, requester_user_id): yield self.check_group_is_ours(group_id, and_exists=True) is_user_in_group = yield self.store.is_user_in_group(requester_user_id, group_id) + group = yield self.store.get_group(group_id) - user_results = yield self.store.get_users_in_group( - group_id, include_private=is_user_in_group, - ) + user_results = [] + if not group.membership_is_private: + user_results = yield self.store.get_users_in_group( + group_id, include_private=is_user_in_group, + ) chunk = [] for user_result in user_results: @@ -725,6 +728,7 @@ def create_group(self, group_id, user_id, content): short_description = profile.get("short_description") long_description = profile.get("long_description") user_profile = content.get("user_profile", {}) + membership_is_private = content.get("membership_is_private", False) yield self.store.create_group( group_id, @@ -733,6 +737,7 @@ def create_group(self, group_id, user_id, content): avatar_url=avatar_url, short_description=short_description, long_description=long_description, + membership_is_private=membership_is_private, ) if not self.hs.is_mine_id(user_id): diff --git a/synapse/storage/group_server.py b/synapse/storage/group_server.py index 9e63db5c6cd2..fe8204f7b81a 100644 --- a/synapse/storage/group_server.py +++ b/synapse/storage/group_server.py @@ -35,7 +35,7 @@ def get_group(self, group_id): keyvalues={ "group_id": group_id, }, - retcols=("name", "short_description", "long_description", "avatar_url",), + retcols=("name", "short_description", "long_description", "avatar_url", "membership_is_private"), allow_none=True, desc="is_user_in_group", ) @@ -1017,7 +1017,7 @@ def _register_user_group_membership_txn(txn, next_id): @defer.inlineCallbacks def create_group(self, group_id, user_id, name, avatar_url, short_description, - long_description,): + long_description, membership_is_private): yield self._simple_insert( table="groups", values={ @@ -1026,6 +1026,7 @@ def create_group(self, group_id, user_id, name, avatar_url, short_description, "avatar_url": avatar_url, "short_description": short_description, "long_description": long_description, + "membership_is_private": membership_is_private, }, desc="create_group", ) diff --git a/synapse/storage/prepare_database.py b/synapse/storage/prepare_database.py index ccaaabcfa0e4..73bbda5b336a 100644 --- a/synapse/storage/prepare_database.py +++ b/synapse/storage/prepare_database.py @@ -25,7 +25,7 @@ # Remember to update this number every time a change is made to database # schema files, so the users will be informed on server restarts. -SCHEMA_VERSION = 45 +SCHEMA_VERSION = 46 dir_path = os.path.abspath(os.path.dirname(__file__)) diff --git a/synapse/storage/schema/delta/46/track_group_membership_publicity.sql b/synapse/storage/schema/delta/46/track_group_membership_publicity.sql new file mode 100644 index 000000000000..73ad7d654b7e --- /dev/null +++ b/synapse/storage/schema/delta/46/track_group_membership_publicity.sql @@ -0,0 +1,17 @@ +/* Copyright 2017 Travis Ralston + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +ALTER TABLE groups ADD COLUMN membership_is_private BOOLEAN; From bd968f4507f862482faa0f298a22dfbf430b4884 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 21 Oct 2017 12:28:07 -0600 Subject: [PATCH 2/6] Check for public membership correctly Signed-off-by: Travis Ralston --- synapse/groups/groups_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 1c2ea8e97007..19efd0d84297 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -386,7 +386,7 @@ def get_users_in_group(self, group_id, requester_user_id): group = yield self.store.get_group(group_id) user_results = [] - if not group.membership_is_private: + if not group["membership_is_private"] or group["membership_is_private"] is None: user_results = yield self.store.get_users_in_group( group_id, include_private=is_user_in_group, ) From 1c046021b586a0078a77f15245591b2178b4c7e0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 21 Oct 2017 12:32:39 -0600 Subject: [PATCH 3/6] Allow users in the group to see the membership list Signed-off-by: Travis Ralston --- synapse/groups/groups_server.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 19efd0d84297..d4f3f239fb19 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -384,9 +384,10 @@ def get_users_in_group(self, group_id, requester_user_id): is_user_in_group = yield self.store.is_user_in_group(requester_user_id, group_id) group = yield self.store.get_group(group_id) + is_membership_public = not group["membership_is_private"] or group["membership_is_private"] is None user_results = [] - if not group["membership_is_private"] or group["membership_is_private"] is None: + if is_membership_public or is_user_in_group: user_results = yield self.store.get_users_in_group( group_id, include_private=is_user_in_group, ) From 45d3e993917b8848b4f622b8ac00805d3d899289 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 21 Oct 2017 12:44:44 -0600 Subject: [PATCH 4/6] pep8 Signed-off-by: Travis Ralston --- synapse/groups/groups_server.py | 3 ++- synapse/storage/group_server.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index d4f3f239fb19..7d1294cdd9f4 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -384,7 +384,8 @@ def get_users_in_group(self, group_id, requester_user_id): is_user_in_group = yield self.store.is_user_in_group(requester_user_id, group_id) group = yield self.store.get_group(group_id) - is_membership_public = not group["membership_is_private"] or group["membership_is_private"] is None + is_membership_public = not group["membership_is_private"] \ + or group["membership_is_private"] is None user_results = [] if is_membership_public or is_user_in_group: diff --git a/synapse/storage/group_server.py b/synapse/storage/group_server.py index fe8204f7b81a..e9db1a1587e2 100644 --- a/synapse/storage/group_server.py +++ b/synapse/storage/group_server.py @@ -35,7 +35,8 @@ def get_group(self, group_id): keyvalues={ "group_id": group_id, }, - retcols=("name", "short_description", "long_description", "avatar_url", "membership_is_private"), + retcols=("name", "short_description", "long_description", "avatar_url", + "membership_is_private"), allow_none=True, desc="is_user_in_group", ) From 095be7cd14b81305e96f1ae081ee640c2d32db03 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 21 Oct 2017 12:49:56 -0600 Subject: [PATCH 5/6] more pep8 Signed-off-by: Travis Ralston --- synapse/groups/groups_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 7d1294cdd9f4..7f3f4af6efa0 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -385,7 +385,7 @@ def get_users_in_group(self, group_id, requester_user_id): is_user_in_group = yield self.store.is_user_in_group(requester_user_id, group_id) group = yield self.store.get_group(group_id) is_membership_public = not group["membership_is_private"] \ - or group["membership_is_private"] is None + or group["membership_is_private"] is None user_results = [] if is_membership_public or is_user_in_group: From f4e19c5baa33320109bed97b33c2f4d755eb9e3e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 21 Oct 2017 13:52:18 -0600 Subject: [PATCH 6/6] Save changes to membership_is_private on update Signed-off-by: Travis Ralston --- synapse/groups/groups_server.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py index 7f3f4af6efa0..47ffd93dd38a 100644 --- a/synapse/groups/groups_server.py +++ b/synapse/groups/groups_server.py @@ -370,6 +370,8 @@ def update_group_profile(self, group_id, requester_user_id, content): if not isinstance(value, basestring): raise SynapseError(400, "%r value is not a string" % (keyname,)) profile[keyname] = value + if not isinstance(content["membership_is_private"], bool): + profile["membership_is_private"] = content["membership_is_private"] yield self.store.update_group_profile(group_id, profile)