Compare commits
17 Commits
quenting/l
...
bbz/info-m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcf1b9c276 | ||
|
|
0825299cfc | ||
|
|
8d9ae573f3 | ||
|
|
2506e36cf5 | ||
|
|
60784d81ef | ||
|
|
0b8f4c328b | ||
|
|
91d309397d | ||
|
|
cc71678425 | ||
|
|
5858093815 | ||
|
|
1fa060e8de | ||
|
|
1a7d96aa6f | ||
|
|
e70810934f | ||
|
|
b8a05b5a3f | ||
|
|
2e9f389fd2 | ||
|
|
80c66c4bca | ||
|
|
09cb7dec5f | ||
|
|
456fa172cf |
@@ -1223,6 +1223,11 @@ account_validity:
|
||||
# Mandate that users are only allowed to associate certain formats of
|
||||
# 3PIDs with accounts on this server.
|
||||
#
|
||||
# Use an Identity Server to establish which 3PIDs are allowed to register?
|
||||
# Overrides allowed_local_3pids below.
|
||||
#
|
||||
#check_is_for_allowed_local_3pids: matrix.org
|
||||
#
|
||||
#allowed_local_3pids:
|
||||
# - medium: email
|
||||
# pattern: '.*@matrix\.org'
|
||||
|
||||
@@ -99,6 +99,9 @@ class RegistrationConfig(Config):
|
||||
|
||||
self.registrations_require_3pid = config.get("registrations_require_3pid", [])
|
||||
self.allowed_local_3pids = config.get("allowed_local_3pids", [])
|
||||
self.check_is_for_allowed_local_3pids = config.get(
|
||||
"check_is_for_allowed_local_3pids", None
|
||||
)
|
||||
self.enable_3pid_lookup = config.get("enable_3pid_lookup", True)
|
||||
self.registration_shared_secret = config.get("registration_shared_secret")
|
||||
|
||||
@@ -296,6 +299,11 @@ class RegistrationConfig(Config):
|
||||
# Mandate that users are only allowed to associate certain formats of
|
||||
# 3PIDs with accounts on this server.
|
||||
#
|
||||
# Use an Identity Server to establish which 3PIDs are allowed to register?
|
||||
# Overrides allowed_local_3pids below.
|
||||
#
|
||||
#check_is_for_allowed_local_3pids: matrix.org
|
||||
#
|
||||
#allowed_local_3pids:
|
||||
# - medium: email
|
||||
# pattern: '.*@matrix\\.org'
|
||||
|
||||
@@ -719,6 +719,27 @@ class GroupsServerHandler(GroupsServerWorkerHandler):
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
async def change_user_admin_in_group(
|
||||
self, group_id, user_id, want_admin, requester_user_id, content
|
||||
):
|
||||
"""Promotes or demotes a user in a group.
|
||||
"""
|
||||
|
||||
await self.check_group_is_ours(group_id, requester_user_id, and_exists=True)
|
||||
|
||||
if requester_user_id == user_id:
|
||||
raise SynapseError(400, "User cannot target themselves")
|
||||
|
||||
is_admin = await self.store.is_user_admin_in_group(
|
||||
group_id, requester_user_id
|
||||
)
|
||||
if not is_admin:
|
||||
raise SynapseError(403, "User is not admin in group")
|
||||
|
||||
await self.store.change_user_admin_in_group(group_id, user_id, want_admin)
|
||||
|
||||
return {}
|
||||
|
||||
async def remove_user_from_group(
|
||||
self, group_id, user_id, requester_user_id, content
|
||||
):
|
||||
|
||||
@@ -463,6 +463,25 @@ class GroupsLocalHandler(GroupsLocalWorkerHandler):
|
||||
|
||||
return {"state": "invite", "user_profile": user_profile}
|
||||
|
||||
async def change_user_admin_in_group(
|
||||
self, group_id, user_id, want_admin, requester_user_id, content
|
||||
):
|
||||
"""Promotes or demotes a user in a group.
|
||||
"""
|
||||
|
||||
if not self.is_mine_id(user_id):
|
||||
raise SynapseError(400, "User not on this server")
|
||||
|
||||
# TODO: We should probably support federation, but this is fine for now
|
||||
if not self.is_mine_id(group_id):
|
||||
raise SynapseError(400, "Group not on this server")
|
||||
|
||||
res = await self.groups_server_handler.change_user_admin_in_group(
|
||||
group_id, user_id, want_admin, requester_user_id, content
|
||||
)
|
||||
|
||||
return res
|
||||
|
||||
async def remove_user_from_group(
|
||||
self, group_id: str, user_id: str, requester_user_id: str, content: JsonDict
|
||||
) -> JsonDict:
|
||||
|
||||
@@ -374,7 +374,7 @@ class EmailThreepidRequestTokenRestServlet(RestServlet):
|
||||
send_attempt = body["send_attempt"]
|
||||
next_link = body.get("next_link") # Optional param
|
||||
|
||||
if not check_3pid_allowed(self.hs, "email", email):
|
||||
if not await check_3pid_allowed(self.hs, "email", email):
|
||||
raise SynapseError(
|
||||
403,
|
||||
"Your email domain is not authorized on this server",
|
||||
@@ -455,7 +455,7 @@ class MsisdnThreepidRequestTokenRestServlet(RestServlet):
|
||||
|
||||
msisdn = phone_number_to_msisdn(country, phone_number)
|
||||
|
||||
if not check_3pid_allowed(self.hs, "msisdn", msisdn):
|
||||
if not await check_3pid_allowed(self.hs, "msisdn", msisdn):
|
||||
raise SynapseError(
|
||||
403,
|
||||
"Account phone numbers are not authorized on this server",
|
||||
|
||||
@@ -590,6 +590,31 @@ class GroupAdminUsersKickServlet(RestServlet):
|
||||
|
||||
return 200, result
|
||||
|
||||
class GroupAdminChangeAdminServlet(RestServlet):
|
||||
"""Promote or demote a user in the group
|
||||
"""
|
||||
|
||||
PATTERNS = client_patterns(
|
||||
"/groups/(?P<group_id>[^/]*)/admin/users/admins/(?P<user_id>[^/]*)$"
|
||||
)
|
||||
|
||||
def __init__(self, hs):
|
||||
super(GroupAdminChangeAdminServlet, self).__init__()
|
||||
self.auth = hs.get_auth()
|
||||
self.clock = hs.get_clock()
|
||||
self.groups_handler = hs.get_groups_local_handler()
|
||||
|
||||
async def on_POST(self, request, group_id, user_id):
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
requester_user_id = requester.user.to_string()
|
||||
|
||||
content = parse_json_object_from_request(request)
|
||||
want_admin = content["is_admin"]
|
||||
result = await self.groups_handler.change_user_admin_in_group(
|
||||
group_id, user_id, want_admin, requester_user_id, content
|
||||
)
|
||||
|
||||
return 200, result
|
||||
|
||||
class GroupSelfLeaveServlet(RestServlet):
|
||||
"""Leave a joined group
|
||||
@@ -768,6 +793,7 @@ def register_servlets(hs, http_server):
|
||||
GroupAdminRoomsConfigServlet(hs).register(http_server)
|
||||
GroupAdminUsersInviteServlet(hs).register(http_server)
|
||||
GroupAdminUsersKickServlet(hs).register(http_server)
|
||||
GroupAdminChangeAdminServlet(hs).register(http_server)
|
||||
GroupSelfLeaveServlet(hs).register(http_server)
|
||||
GroupSelfJoinServlet(hs).register(http_server)
|
||||
GroupSelfAcceptInviteServlet(hs).register(http_server)
|
||||
|
||||
@@ -119,10 +119,10 @@ class EmailRegisterRequestTokenRestServlet(RestServlet):
|
||||
send_attempt = body["send_attempt"]
|
||||
next_link = body.get("next_link") # Optional param
|
||||
|
||||
if not check_3pid_allowed(self.hs, "email", email):
|
||||
if not await check_3pid_allowed(self.hs, "email", email, during_registration=True):
|
||||
raise SynapseError(
|
||||
403,
|
||||
"Your email domain is not authorized to register on this server",
|
||||
"You currently can't create an account with this email address",
|
||||
Codes.THREEPID_DENIED,
|
||||
)
|
||||
|
||||
@@ -200,7 +200,7 @@ class MsisdnRegisterRequestTokenRestServlet(RestServlet):
|
||||
|
||||
msisdn = phone_number_to_msisdn(country, phone_number)
|
||||
|
||||
if not check_3pid_allowed(self.hs, "msisdn", msisdn):
|
||||
if not await check_3pid_allowed(self.hs, "msisdn", msisdn, during_registration=True):
|
||||
raise SynapseError(
|
||||
403,
|
||||
"Phone numbers are not authorized to register on this server",
|
||||
@@ -552,7 +552,9 @@ class RegisterRestServlet(RestServlet):
|
||||
medium = auth_result[login_type]["medium"]
|
||||
address = auth_result[login_type]["address"]
|
||||
|
||||
if not check_3pid_allowed(self.hs, medium, address):
|
||||
if not await check_3pid_allowed(
|
||||
self.hs, medium, address, during_registration=True
|
||||
):
|
||||
raise SynapseError(
|
||||
403,
|
||||
"Third party identifiers (email/phone numbers)"
|
||||
|
||||
@@ -1116,6 +1116,16 @@ class GroupServerStore(GroupServerWorkerStore):
|
||||
"remove_user_from_group", _remove_user_from_group_txn
|
||||
)
|
||||
|
||||
async def change_user_admin_in_group(
|
||||
self, group_id: str, user_id: str, is_admin: bool
|
||||
) -> int:
|
||||
return await self.db_pool.simple_update(
|
||||
table="group_users",
|
||||
keyvalues={"group_id": group_id, "user_id": user_id},
|
||||
updatevalues={"is_admin": is_admin},
|
||||
desc="change_user_admin_in_group"
|
||||
)
|
||||
|
||||
async def add_room_to_group(
|
||||
self, group_id: str, room_id: str, is_public: bool
|
||||
) -> None:
|
||||
|
||||
@@ -19,7 +19,7 @@ import re
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_3pid_allowed(hs, medium, address):
|
||||
async def check_3pid_allowed(hs, medium, address, during_registration: bool = False):
|
||||
"""Checks whether a given format of 3PID is allowed to be used on this HS
|
||||
|
||||
Args:
|
||||
@@ -27,10 +27,57 @@ def check_3pid_allowed(hs, medium, address):
|
||||
medium (str): 3pid medium - e.g. email, msisdn
|
||||
address (str): address within that medium (e.g. "wotan@matrix.org")
|
||||
msisdns need to first have been canonicalised
|
||||
during_registration: Whether this request has been made while registering a new
|
||||
user.
|
||||
Returns:
|
||||
bool: whether the 3PID medium/address is allowed to be added to this HS
|
||||
"""
|
||||
|
||||
if hs.config.check_is_for_allowed_local_3pids and during_registration:
|
||||
# If this 3pid is being approved as part of registering a new user,
|
||||
# we'll want to make sure the 3pid has been invited by someone already.
|
||||
#
|
||||
# We condition on registration so that user 3pids do not require an invite while
|
||||
# doing tasks other than registration, such as resetting their password or adding a
|
||||
# second email to their account.
|
||||
data = await hs.get_simple_http_client().get_json(
|
||||
"https://%s%s" % (
|
||||
hs.config.check_is_for_allowed_local_3pids,
|
||||
"/_matrix/identity/api/v1/internal-info"
|
||||
),
|
||||
{'medium': medium, 'address': address}
|
||||
)
|
||||
logger.info(
|
||||
"Received internal-info data for medium '%s', address '%s': %s",
|
||||
medium, address, data,
|
||||
)
|
||||
|
||||
# Check for invalid response
|
||||
if 'hs' not in data and 'shadow_hs' not in data:
|
||||
return False
|
||||
|
||||
# Check if this user is intended to register for this homeserver
|
||||
if (
|
||||
data.get('hs') != hs.config.server_name
|
||||
and data.get('shadow_hs') != hs.config.server_name
|
||||
):
|
||||
logger.info(
|
||||
"%s did not match %s or %s did not match %s",
|
||||
data.get("hs"), hs.config.server_name,
|
||||
data.get("shadow_hs"), hs.config.server_name,
|
||||
)
|
||||
return False
|
||||
|
||||
if data.get('requires_invite', False) and not data.get('invited', False):
|
||||
# Requires an invite but hasn't been invited
|
||||
logger.info(
|
||||
"3PID check failed due to 'required_invite' = '%s' and 'invited' = '%s'",
|
||||
data.get('required_invite'), data.get("invited"),
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if hs.config.allowed_local_3pids:
|
||||
for constraint in hs.config.allowed_local_3pids:
|
||||
logger.debug(
|
||||
|
||||
Reference in New Issue
Block a user