diff --git a/synapse/federation/transport/client.py b/synapse/federation/transport/client.py
index 5a6b63350b..0f7f656824 100644
--- a/synapse/federation/transport/client.py
+++ b/synapse/federation/transport/client.py
@@ -860,9 +860,9 @@ class TransportLayerClient(object):
@log_function
def set_group_joinable(self, destination, group_id, requester_user_id,
content):
- """Sets whether a group is joinable without an invite or knock
+ """Sets the join policy for a group
"""
- path = PREFIX + "/groups/%s/joinable" % (group_id,)
+ path = PREFIX + "/groups/%s/setting/m.join_policy" % (group_id,)
return self.client.post_json(
destination=destination,
diff --git a/synapse/federation/transport/server.py b/synapse/federation/transport/server.py
index 107deb4e1e..a52d3948f4 100644
--- a/synapse/federation/transport/server.py
+++ b/synapse/federation/transport/server.py
@@ -1125,10 +1125,10 @@ class FederationGroupsBulkPublicisedServlet(BaseFederationServlet):
defer.returnValue((200, resp))
-class FederationGroupsJoinableServlet(BaseFederationServlet):
+class FederationGroupsSettingJoinPolicyServlet(BaseFederationServlet):
"""Sets whether a group is joinable without an invite or knock
"""
- PATH = "/groups/(?P<group_id>[^/]*)/joinable$"
+ PATH = "/groups/(?P<group_id>[^/]*)/setting/m.join_policy$"
@defer.inlineCallbacks
def on_POST(self, origin, content, query, group_id):
@@ -1136,7 +1136,7 @@ class FederationGroupsJoinableServlet(BaseFederationServlet):
if get_domain_from_id(requester_user_id) != origin:
raise SynapseError(403, "requester_user_id doesn't match origin")
- new_content = yield self.handler.set_group_joinable(
+ new_content = yield self.handler.set_group_join_policy(
group_id, requester_user_id, content
)
@@ -1191,7 +1191,7 @@ GROUP_SERVER_SERVLET_CLASSES = (
FederationGroupsSummaryUsersServlet,
FederationGroupsAddRoomsServlet,
FederationGroupsAddRoomsConfigServlet,
- FederationGroupsJoinableServlet,
+ FederationGroupsSettingJoinPolicyServlet,
)
diff --git a/synapse/groups/groups_server.py b/synapse/groups/groups_server.py
index 25cbfb1691..70781e1854 100644
--- a/synapse/groups/groups_server.py
+++ b/synapse/groups/groups_server.py
@@ -207,20 +207,24 @@ class GroupsServerHandler(object):
defer.returnValue({})
@defer.inlineCallbacks
- def set_group_joinable(self, group_id, requester_user_id, content):
- """Sets whether a group is joinable without an invite or knock
+ def set_group_join_policy(self, group_id, requester_user_id, content):
+ """Sets the group join policy.
+
+ Currently supported policies are:
+ - "invite": an invite must be received and accepted in order to join.
+ - "open": anyone can join.
"""
yield self.check_group_is_ours(
group_id, requester_user_id, and_exists=True, and_is_admin=requester_user_id
)
- is_joinable = content.get('joinable')
- if is_joinable is None:
+ join_policy = _parse_join_policy_from_contents(content)
+ if join_policy is None:
raise SynapseError(
- 400, "No value specified for 'joinable'"
+ 400, "No value specified for 'm.join_policy'"
)
- yield self.store.set_group_joinable(group_id, is_joinable=is_joinable)
+ yield self.store.set_group_join_policy(group_id, join_policy=join_policy)
defer.returnValue({})
@@ -854,6 +858,31 @@ class GroupsServerHandler(object):
})
+def _parse_join_policy_from_contents(content):
+ """Given a content for a request, return the specified join policy or None
+ """
+
+ join_policy_dict = content.get("m.join_policy")
+ if join_policy_dict:
+ return _parse_join_policy_dict(join_policy_dict)
+ else:
+ return None
+
+
+def _parse_join_policy_dict(join_policy_dict):
+ """Given a dict for the "m.join_policy" config return the join policy specified
+ """
+ join_policy_type = join_policy_dict.get("type")
+ if not join_policy_type:
+ return True
+
+ if join_policy_type not in ("invite", "open"):
+ raise SynapseError(
+ 400, "Synapse only supports 'invite'/'open' join rule"
+ )
+ return join_policy_type
+
+
def _parse_visibility_from_contents(content):
"""Given a content for a request parse out whether the entity should be
public or not
diff --git a/synapse/handlers/groups_local.py b/synapse/handlers/groups_local.py
index c9671b9046..5f7b0ff305 100644
--- a/synapse/handlers/groups_local.py
+++ b/synapse/handlers/groups_local.py
@@ -91,7 +91,7 @@ class GroupsLocalHandler(object):
get_group_role = _create_rerouter("get_group_role")
get_group_roles = _create_rerouter("get_group_roles")
- set_group_joinable = _create_rerouter("set_group_joinable")
+ set_group_join_policy = _create_rerouter("set_group_join_policy")
@defer.inlineCallbacks
def get_group_summary(self, group_id, requester_user_id):
diff --git a/synapse/rest/client/v2_alpha/groups.py b/synapse/rest/client/v2_alpha/groups.py
index aa94130e57..8faaa1d6a0 100644
--- a/synapse/rest/client/v2_alpha/groups.py
+++ b/synapse/rest/client/v2_alpha/groups.py
@@ -402,13 +402,13 @@ class GroupInvitedUsersServlet(RestServlet):
defer.returnValue((200, result))
-class GroupJoinableServlet(RestServlet):
- """Set whether a group is joinable without an invite
+class GroupSettingJoinPolicyServlet(RestServlet):
+ """Set group join policy
"""
- PATTERNS = client_v2_patterns("/groups/(?P<group_id>[^/]*)/joinable$")
+ PATTERNS = client_v2_patterns("/groups/(?P<group_id>[^/]*)/setting/m.join_policy$")
def __init__(self, hs):
- super(GroupJoinableServlet, self).__init__()
+ super(GroupSettingJoinPolicyServlet, self).__init__()
self.auth = hs.get_auth()
self.groups_handler = hs.get_groups_local_handler()
@@ -419,7 +419,7 @@ class GroupJoinableServlet(RestServlet):
content = parse_json_object_from_request(request)
- result = yield self.groups_handler.set_group_joinable(
+ result = yield self.groups_handler.set_group_join_policy(
group_id,
requester_user_id,
content,
@@ -765,7 +765,7 @@ def register_servlets(hs, http_server):
GroupInvitedUsersServlet(hs).register(http_server)
GroupUsersServlet(hs).register(http_server)
GroupRoomServlet(hs).register(http_server)
- GroupJoinableServlet(hs).register(http_server)
+ GroupSettingJoinPolicyServlet(hs).register(http_server)
GroupCreateServlet(hs).register(http_server)
GroupAdminRoomsServlet(hs).register(http_server)
GroupAdminRoomsConfigServlet(hs).register(http_server)
diff --git a/synapse/storage/group_server.py b/synapse/storage/group_server.py
index 96553d4fb1..db66ea1eb0 100644
--- a/synapse/storage/group_server.py
+++ b/synapse/storage/group_server.py
@@ -30,16 +30,16 @@ _DEFAULT_ROLE_ID = ""
class GroupServerStore(SQLBaseStore):
- def set_group_joinable(self, group_id, is_joinable):
+ def set_group_join_policy(self, group_id, join_policy):
return self._simple_update_one(
table="groups",
keyvalues={
"group_id": group_id,
},
updatevalues={
- "is_joinable": is_joinable,
+ "join_policy": join_policy,
},
- desc="set_group_joinable",
+ desc="set_group_join_policy",
)
def get_group(self, group_id):
diff --git a/synapse/storage/schema/delta/48/groups_joinable.sql b/synapse/storage/schema/delta/48/groups_joinable.sql
index ace7d0a723..ab3b00286d 100644
--- a/synapse/storage/schema/delta/48/groups_joinable.sql
+++ b/synapse/storage/schema/delta/48/groups_joinable.sql
@@ -13,4 +13,10 @@
* limitations under the License.
*/
-ALTER TABLE groups ADD COLUMN is_joinable SMALLINT DEFAULT 0 NOT NULL;
+/*
+ * This isn't a real ENUM because sqlite doesn't support it
+ * and we use a default of NULL for inserted rows and interpret
+ * NULL at the python store level as necessary so that existing
+ * rows are given the correct default policy.
+ */
+ALTER TABLE groups ADD COLUMN join_policy TEXT DEFAULT NULL;
|