pull/8756/head
Erik Johnston 2020-11-17 10:24:39 +00:00
parent 6c52df437a
commit 628e84dd8d
2 changed files with 53 additions and 12 deletions

View File

@ -42,6 +42,7 @@ from synapse.rest.admin.rooms import (
DeleteRoomRestServlet,
JoinRoomAliasServlet,
ListRoomRestServlet,
MakeRoomAdminRoomServlet,
RoomMembersRestServlet,
RoomRestServlet,
ShutdownRoomRestServlet,
@ -232,6 +233,7 @@ def register_servlets(hs, http_server):
EventReportDetailRestServlet(hs).register(http_server)
EventReportsRestServlet(hs).register(http_server)
PushersRestServlet(hs).register(http_server)
MakeRoomAdminRoomServlet(hs).register(http_server)
def register_servlets_for_client_rest_resource(hs, http_server):

View File

@ -17,7 +17,7 @@ from http import HTTPStatus
from typing import TYPE_CHECKING, List, Optional
from synapse.api.constants import EventTypes, JoinRules, Membership
from synapse.api.errors import Codes, NotFoundError, SynapseError
from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError
from synapse.http.servlet import (
RestServlet,
assert_params_in_dict,
@ -344,6 +344,17 @@ class JoinRoomAliasServlet(RestServlet):
class MakeRoomAdminRoomServlet(RestServlet):
"""Allows a server admin to get power in a room if a local user has power in
a room. Will also invite the user if they're not in the room and its a
private room. Can specify another user (rather than the admin user) to be
granted power, e.g.:
POST /_synapse/admin/v1/make_room_admin/<room_id_or_alias>
{
"user_id": "@foo:example.com"
}
"""
PATTERNS = admin_patterns("/make_room_admin/(?P<room_identifier>[^/]*)")
def __init__(self, hs: "HomeServer"):
@ -359,6 +370,7 @@ class MakeRoomAdminRoomServlet(RestServlet):
await assert_user_is_admin(self.auth, requester.user)
content = parse_json_object_from_request(request, allow_empty_body=True)
# Resolve to a room ID, if necessary.
if RoomID.is_valid(room_identifier):
room_id = room_identifier
elif RoomAlias.is_valid(room_identifier):
@ -370,10 +382,11 @@ class MakeRoomAdminRoomServlet(RestServlet):
400, "%s was not legal room ID or room alias" % (room_identifier,)
)
# Which user to grant room admin rights to.
user_to_add = content.get("user_id", requester.user.to_string())
# Figure out which local users currently have power in the room, if any.
room_state = await self.state_handler.get_current_state(room_id)
if not room_state:
raise SynapseError(400, "Server not in room")
@ -381,33 +394,59 @@ class MakeRoomAdminRoomServlet(RestServlet):
power_levels = room_state.get((EventTypes.PowerLevels, ""))
if power_levels is not None:
# We pick the local user with the highest power.
user_power = power_levels.content.get("users", {})
admin_users = [
user_id
for user_id, power in power_levels.content.get("users")
for user_id, power in user_power.items()
if self.is_mine_id(user_id)
]
admin_users.sort(key=lambda user: power_levels.content.get("users")[user])
admin_users.sort(key=lambda user: user_power[user])
if not admin_users:
raise SynapseError(400, "No local admin user in room")
admin_user_id = admin_users[-1]
pl_content = power_levels.content
else:
# If there is no power level events then the creator has rights.
pl_content = {}
admin_user_id = create_event.sender
if not self.is_mine_id(admin_user_id):
raise SynapseError(400, "No local admin user in room")
raise SynapseError(
400, "No local admin user in room",
)
# Grant the user power equal to the room admin by attempting to send an
# updated power level event.
new_pl_content = dict(pl_content)
new_pl_content["users"] = dict(pl_content.get("users", {}))
new_pl_content["users"][user_to_add] = new_pl_content["users"][admin_user_id]
fake_requester = create_requester(
admin_user_id, authenticated_entity=requester.authenticated_entity,
)
new_pl_content = dict(pl_content)
new_pl_content["users"] = dict(pl_content.get("users", {}))
new_pl_content["users"][user_to_add] = new_pl_content["users"][admin_user_id]
await self.event_creation_handler.create_and_send_nonmember_event(
fake_requester, event_dict=new_pl_content,
)
try:
await self.event_creation_handler.create_and_send_nonmember_event(
fake_requester,
event_dict={
"content": new_pl_content,
"sender": admin_user_id,
"type": EventTypes.PowerLevels,
"state_key": "",
"room_id": room_id,
},
)
except AuthError:
# The admin user we found turned out not to have enough power.
raise SynapseError(
400, "No local admin user in room with power to update power levels."
)
# Now we check if the user we're granting admin rights to is already in
# the room. If not and its not a public room we invite them.
member_event = room_state.get((EventTypes.Member, user_to_add))
is_joined = False
if member_event: