1
0

Fix: Pillow error when uploading RGBA image (#3325) (#6241)

* commit '81731c6e7':
  Fix: Pillow error when uploading RGBA image (#3325) (#6241)
  Add User-Interactive Auth to /account/3pid/add (#6119)
  Lint
  Changelog
  Discard retention policies when retrieving state
  blacklist more tests
  Newsfile
  Add tests
  Propagate reason in remotely rejected invites
  MSC2367 Allow reason field on all member events
This commit is contained in:
Andrew Morgan
2020-03-19 16:07:29 +00:00
13 changed files with 183 additions and 14 deletions

View File

@@ -57,3 +57,10 @@ Don't get pushed for rooms you've muted
Rejected events are not pushed
Test that rejected pushers are removed.
Events come down the correct room
# https://buildkite.com/matrix-dot-org/sytest/builds/326#cca62404-a88a-4fcb-ad41-175fd3377603
Presence changes to UNAVAILABLE are reported to remote room members
If remote user leaves room, changes device and rejoins we see update in sync
uploading self-signing key notifies over federation
Inbound federation can receive redacted events
Outbound federation can request missing events

1
changelog.d/6119.feature Normal file
View File

@@ -0,0 +1 @@
Require User-Interactive Authentication for `/account/3pid/add`, meaning the user's password will be required to add a third-party ID to their account.

1
changelog.d/6241.bugfix Normal file
View File

@@ -0,0 +1 @@
Fix error from the Pillow library when uploading RGBA images.

1
changelog.d/6434.feature Normal file
View File

@@ -0,0 +1 @@
Add support for MSC 2367, which allows specifying a reason on all membership events.

View File

@@ -1435,9 +1435,9 @@ class FederationHandler(BaseHandler):
return event
@defer.inlineCallbacks
def do_remotely_reject_invite(self, target_hosts, room_id, user_id):
def do_remotely_reject_invite(self, target_hosts, room_id, user_id, content):
origin, event, event_format_version = yield self._make_and_verify_event(
target_hosts, room_id, user_id, "leave"
target_hosts, room_id, user_id, "leave", content=content,
)
# Mark as outlier as we don't have any state for this event; we're not
# even in the room.

View File

@@ -99,7 +99,9 @@ class RoomMemberHandler(object):
raise NotImplementedError()
@abc.abstractmethod
def _remote_reject_invite(self, requester, remote_room_hosts, room_id, target):
def _remote_reject_invite(
self, requester, remote_room_hosts, room_id, target, content
):
"""Attempt to reject an invite for a room this server is not in. If we
fail to do so we locally mark the invite as rejected.
@@ -109,6 +111,7 @@ class RoomMemberHandler(object):
reject invite
room_id (str)
target (UserID): The user rejecting the invite
content (dict): The content for the rejection event
Returns:
Deferred[dict]: A dictionary to be returned to the client, may
@@ -526,7 +529,7 @@ class RoomMemberHandler(object):
# send the rejection to the inviter's HS.
remote_room_hosts = remote_room_hosts + [inviter.domain]
res = yield self._remote_reject_invite(
requester, remote_room_hosts, room_id, target
requester, remote_room_hosts, room_id, target, content,
)
return res
@@ -1056,13 +1059,15 @@ class RoomMemberMasterHandler(RoomMemberHandler):
)
@defer.inlineCallbacks
def _remote_reject_invite(self, requester, remote_room_hosts, room_id, target):
def _remote_reject_invite(
self, requester, remote_room_hosts, room_id, target, content
):
"""Implements RoomMemberHandler._remote_reject_invite
"""
fed_handler = self.federation_handler
try:
ret = yield fed_handler.do_remotely_reject_invite(
remote_room_hosts, room_id, target.to_string()
remote_room_hosts, room_id, target.to_string(), content=content,
)
return ret
except Exception as e:

View File

@@ -55,7 +55,9 @@ class RoomMemberWorkerHandler(RoomMemberHandler):
return ret
def _remote_reject_invite(self, requester, remote_room_hosts, room_id, target):
def _remote_reject_invite(
self, requester, remote_room_hosts, room_id, target, content
):
"""Implements RoomMemberHandler._remote_reject_invite
"""
return self._remote_reject_client(
@@ -63,6 +65,7 @@ class RoomMemberWorkerHandler(RoomMemberHandler):
remote_room_hosts=remote_room_hosts,
room_id=room_id,
user_id=target.to_string(),
content=content,
)
def _user_joined_room(self, target, room_id):

View File

@@ -93,6 +93,7 @@ class ReplicationRemoteRejectInviteRestServlet(ReplicationEndpoint):
{
"requester": ...,
"remote_room_hosts": [...],
"content": { ... }
}
"""
@@ -107,7 +108,7 @@ class ReplicationRemoteRejectInviteRestServlet(ReplicationEndpoint):
self.clock = hs.get_clock()
@staticmethod
def _serialize_payload(requester, room_id, user_id, remote_room_hosts):
def _serialize_payload(requester, room_id, user_id, remote_room_hosts, content):
"""
Args:
requester(Requester)
@@ -118,12 +119,14 @@ class ReplicationRemoteRejectInviteRestServlet(ReplicationEndpoint):
return {
"requester": requester.serialize(),
"remote_room_hosts": remote_room_hosts,
"content": content,
}
async def _handle_request(self, request, room_id, user_id):
content = parse_json_object_from_request(request)
remote_room_hosts = content["remote_room_hosts"]
event_content = content["content"]
requester = Requester.deserialize(self.store, content["requester"])
@@ -134,7 +137,7 @@ class ReplicationRemoteRejectInviteRestServlet(ReplicationEndpoint):
try:
event = await self.federation_handler.do_remotely_reject_invite(
remote_room_hosts, room_id, user_id
remote_room_hosts, room_id, user_id, event_content,
)
ret = event.get_pdu_json()
except Exception as e:

View File

@@ -715,7 +715,7 @@ class RoomMembershipRestServlet(TransactionRestServlet):
target = UserID.from_string(content["user_id"])
event_content = None
if "reason" in content and membership_action in ["kick", "ban"]:
if "reason" in content:
event_content = {"reason": content["reason"]}
await self.room_member_handler.update_membership(

View File

@@ -725,6 +725,7 @@ class ThreepidAddRestServlet(RestServlet):
self.auth = hs.get_auth()
self.auth_handler = hs.get_auth_handler()
@interactive_auth_handler
@defer.inlineCallbacks
def on_POST(self, request):
requester = yield self.auth.get_user_by_req(request)
@@ -735,6 +736,10 @@ class ThreepidAddRestServlet(RestServlet):
client_secret = body["client_secret"]
sid = body["sid"]
yield self.auth_handler.validate_user_via_ui_auth(
requester, body, self.hs.get_ip_from_request(request)
)
validation_session = yield self.identity_handler.validate_threepid_session(
client_secret, sid
)

View File

@@ -129,5 +129,8 @@ class Thumbnailer(object):
def _encode_image(self, output_image, output_type):
output_bytes_io = BytesIO()
output_image.save(output_bytes_io, self.FORMATS[output_type], quality=80)
fmt = self.FORMATS[output_type]
if fmt == "JPEG":
output_image = output_image.convert("RGB")
output_image.save(output_bytes_io, fmt, quality=80)
return output_bytes_io

View File

@@ -100,9 +100,9 @@ def filter_events_for_client(
retention_policies = {}
for room_id in room_ids:
retention_policies[room_id] = (
yield storage.main.get_retention_policy_for_room(room_id)
)
retention_policies[
room_id
] = yield storage.main.get_retention_policy_for_room(room_id)
def allowed(event):
"""

View File

@@ -1180,3 +1180,143 @@ class PerRoomProfilesForbiddenTestCase(unittest.HomeserverTestCase):
res_displayname = channel.json_body["content"]["displayname"]
self.assertEqual(res_displayname, self.displayname, channel.result)
class RoomMembershipReasonTestCase(unittest.HomeserverTestCase):
"""Tests that clients can add a "reason" field to membership events and
that they get correctly added to the generated events and propagated.
"""
servlets = [
synapse.rest.admin.register_servlets_for_client_rest_resource,
room.register_servlets,
login.register_servlets,
]
def prepare(self, reactor, clock, homeserver):
self.creator = self.register_user("creator", "test")
self.creator_tok = self.login("creator", "test")
self.second_user_id = self.register_user("second", "test")
self.second_tok = self.login("second", "test")
self.room_id = self.helper.create_room_as(self.creator, tok=self.creator_tok)
def test_join_reason(self):
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/join".format(self.room_id),
content={"reason": reason},
access_token=self.second_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def test_leave_reason(self):
self.helper.join(self.room_id, user=self.second_user_id, tok=self.second_tok)
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/leave".format(self.room_id),
content={"reason": reason},
access_token=self.second_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def test_kick_reason(self):
self.helper.join(self.room_id, user=self.second_user_id, tok=self.second_tok)
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/kick".format(self.room_id),
content={"reason": reason, "user_id": self.second_user_id},
access_token=self.second_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def test_ban_reason(self):
self.helper.join(self.room_id, user=self.second_user_id, tok=self.second_tok)
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/ban".format(self.room_id),
content={"reason": reason, "user_id": self.second_user_id},
access_token=self.creator_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def test_unban_reason(self):
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/unban".format(self.room_id),
content={"reason": reason, "user_id": self.second_user_id},
access_token=self.creator_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def test_invite_reason(self):
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/invite".format(self.room_id),
content={"reason": reason, "user_id": self.second_user_id},
access_token=self.creator_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def test_reject_invite_reason(self):
self.helper.invite(
self.room_id,
src=self.creator,
targ=self.second_user_id,
tok=self.creator_tok,
)
reason = "hello"
request, channel = self.make_request(
"POST",
"/_matrix/client/r0/rooms/{}/leave".format(self.room_id),
content={"reason": reason},
access_token=self.second_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self._check_for_reason(reason)
def _check_for_reason(self, reason):
request, channel = self.make_request(
"GET",
"/_matrix/client/r0/rooms/{}/state/m.room.member/{}".format(
self.room_id, self.second_user_id
),
access_token=self.creator_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
event_content = channel.json_body
self.assertEqual(event_content.get("reason"), reason, channel.result)