-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement MSC4133 to support custom profile fields. #17488
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments, but this is definitely on the right track. Thanks for implementing this!
synapse/storage/schema/main/delta/86/01_custom_profile_fields.sql
Outdated
Show resolved
Hide resolved
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
I pushed some changes to update / flesh out the rest of the MSC, but I haven't yet gone through @anoadragon453's comments so not worth another review yet. (If folks want to test it that would be reasonable...I'm sure it'll break.) |
I think this is close to ready for another review. There's a few open questions on the MSC that will affect this still. |
This is essentially matrix-org/synapse#14392. I didn't see anything in there about updating sytest or complement. The main driver of this is so that I can use `jsonb_path_exists` in #17488. 😄
This comment was marked as off-topic.
This comment was marked as off-topic.
|
Refactor `get_profile` to avoid returning "empty" (`None` / `null`) fields. Currently this is not very important, but will be more useful once #17488 lands. It does update the servlet to use this now which has a minor change in behavior: additional fields served over federation will now be properly sent back to clients. It also adds constants for `avatar_url` / `displayname` although I did not attempt to use it everywhere possible.
@anoadragon453 This should be ready for another review. The commits definitely became very messy so unfortunately probably needs to be reviewed as a single change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thank you! ✨
Just a few minor points below, but nothing fundamental.
if self.config.experimental.msc4133_enabled: | ||
response["capabilities"]["uk.tcpip.msc4133.profile_fields"] = { | ||
"enabled": True, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MSC4133 states that when this field is missing, clients can assume that they are able to upload and modify custom profile fields. However, that won't work as the experimental feature is disabled.
Shouldn't we thus always be advertising this capability as false
, to discourage clients on recent Synapse versions with the experimental feature disabled from trying to set custom profile fields? So:
if self.config.experimental.msc4133_enabled: | |
response["capabilities"]["uk.tcpip.msc4133.profile_fields"] = { | |
"enabled": True, | |
} | |
response["capabilities"]["uk.tcpip.msc4133.profile_fields"] = { | |
"enabled": self.config.experimental.msc4133_enabled, | |
} |
retcol="fields", | ||
desc="get_profile_fields", | ||
) | ||
# The SQLite driver doesn't automatically convert JSON to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# The SQLite driver doesn't automatically convert JSON to | |
# The SQLite driver doesn't automatically convert JSON to | |
# Python objects |
if not UserID.is_valid(user_id): | ||
raise SynapseError( | ||
HTTPStatus.BAD_REQUEST, "Invalid user id", Codes.INVALID_PARAM | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you choose to explicitly perform this check in the GET
implementation, but not in the PUT
or DELETE
ones?
# Discount the opening and closing braces to avoid double counting, | ||
# but add one for a comma. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make it explicit what value this comment is referring to.
# Discount the opening and closing braces to avoid double counting, | |
# but add one for a comma. | |
# Discount the opening and closing braces to avoid double counting, | |
# but add one for a comma. | |
# -2 + 1 = -1 |
|
||
async def delete_profile_field(self, user_id: UserID, field_name: str) -> None: | ||
""" | ||
Set a custom profile field for a user. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set a custom profile field for a user. | |
Remove a custom profile field for a user. |
raise SynapseError(400, "User is not hosted on this homeserver") | ||
|
||
if not by_admin and target_user != requester.user: | ||
raise AuthError(400, "Cannot set another user's profile") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this should be a 403 according to the MSC.
raise AuthError(400, "Cannot set another user's profile") | |
raise AuthError(403, "Cannot set another user's profile") |
"""Set a new avatar URL for a user. | ||
|
||
Args: | ||
target_user: the user whose avatar URL is to be changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""Set a new avatar URL for a user. | |
Args: | |
target_user: the user whose avatar URL is to be changed. | |
"""Delete a field from a user's profile. | |
Args: | |
target_user: the user whose profile is to be changed. |
Args: | ||
target_user: the user whose avatar URL is to be changed. | ||
requester: The user attempting to make this change. | ||
field_name: The name of the profile field to update. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
field_name: The name of the profile field to update. | |
field_name: The name of the profile field to remove. |
@@ -962,7 +962,7 @@ def register(self, http_server: HttpServer) -> None: | |||
"""Register this servlet with the given HTTP server.""" | |||
patterns = getattr(self, "PATTERNS", None) | |||
if patterns: | |||
for method in ("GET", "PUT", "POST", "DELETE"): | |||
for method in ("GET", "PUT", "POST", "DELETE", "PATCH"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this needed?
content={"diff_key": "test"}, | ||
access_token=self.owner_tok, | ||
) | ||
self.assertEqual(channel.code, 400, channel.result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also check for the appropriate errcode
s in this test?
Implementation of MSC4133 to support custom profile fields. It is behind an experimental flag and includes tests.
Pull Request Checklist
EventStore
toEventWorkerStore
.".code blocks
.(run the linters)