-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Allow admin to register a new user #5742
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Allow admin to register a new user. Contributed by Awesome Technologies Innovationslabor GmbH. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,25 +52,98 @@ | |
|
||
|
||
class UsersRestServlet(RestServlet): | ||
PATTERNS = historical_admin_path_patterns("/users/(?P<user_id>[^/]*)") | ||
PATTERNS = historical_admin_path_patterns("/users") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hrm. Can you make this continue to accept (but ignore) a /user_id, for compatibility with applications which have hacked around the existing broken API? |
||
|
||
"""Get request to list all local users. | ||
This needs user to have administrator access in Synapse. | ||
|
||
GET /_synapse/admin/v1/users | ||
|
||
returns: | ||
200 OK with list of users if success otherwise an error. | ||
|
||
|
||
Post request to allow an administrator to add a user. | ||
This needs user to have administrator access in Synapse. | ||
|
||
POST /_synapse/admin/v1/users | ||
{ | ||
"username": "user", | ||
"password": "secret", | ||
"displayname": "User" | ||
} | ||
|
||
returns: | ||
200 OK with empty object if success otherwise an error. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't be an empty object afaict. (Indeed, your test even asserts that.) |
||
""" | ||
|
||
def __init__(self, hs): | ||
self.hs = hs | ||
self.auth = hs.get_auth() | ||
self.handlers = hs.get_handlers() | ||
|
||
@defer.inlineCallbacks | ||
def on_GET(self, request, user_id): | ||
target_user = UserID.from_string(user_id) | ||
yield assert_requester_is_admin(self.auth, request) | ||
def on_GET(self, request): | ||
requester = yield self.auth.get_user_by_req(request) | ||
yield assert_user_is_admin(self.auth, requester.user) | ||
|
||
if not self.hs.is_mine(target_user): | ||
raise SynapseError(400, "Can only users a local user") | ||
if not self.hs.is_mine(requester.user): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is redundant. The requester is a local user by definition. |
||
raise SynapseError(400, "Can only list local users") | ||
|
||
ret = yield self.handlers.admin_handler.get_users() | ||
|
||
return (200, ret) | ||
|
||
@defer.inlineCallbacks | ||
def on_POST(self, request): | ||
yield assert_requester_is_admin(self.auth, request) | ||
|
||
body = parse_json_object_from_request(request) | ||
|
||
if "username" not in body: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider assert_params_in_dict here (https://github.com/matrix-org/synapse/blob/master/synapse/http/servlet.py#L258) |
||
raise SynapseError( | ||
400, "username must be specified", errcode=Codes.BAD_JSON | ||
) | ||
else: | ||
if ( | ||
not isinstance(body["username"], text_type) | ||
or len(body["username"]) > 512 | ||
): | ||
raise SynapseError(400, "Invalid username") | ||
|
||
if "password" not in body: | ||
raise SynapseError( | ||
400, "password must be specified", errcode=Codes.BAD_JSON | ||
) | ||
else: | ||
if ( | ||
not isinstance(body["password"], text_type) | ||
or len(body["password"]) > 512 | ||
): | ||
raise SynapseError(400, "Invalid password") | ||
|
||
admin = body.get("admin", None) | ||
user_type = body.get("user_type", None) | ||
displayname = body.get("displayname", body["username"]) | ||
|
||
if user_type is not None and user_type not in UserTypes.ALL_USER_TYPES: | ||
raise SynapseError(400, "Invalid user type") | ||
|
||
# Reuse the parts of RegisterRestServlet to reduce code duplication | ||
from synapse.rest.client.v2_alpha.register import RegisterRestServlet | ||
|
||
register = RegisterRestServlet(self.hs) | ||
|
||
user_id = yield register.registration_handler.register_user( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there are better ways of getting hold of the registration_handler than via the |
||
localpart=body["username"].lower(), | ||
password=body["password"], | ||
admin=bool(admin), | ||
default_display_name=displayname, | ||
user_type=user_type, | ||
) | ||
|
||
result = yield register._create_registration_details(user_id, body) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will issue an access token for the user, which I'm not sure is the right thing to do. (even if you do want to end up with an access token for the new user, I think that might be better served via a different API per #6054). In short, I don't think you need to call _create_registration_details here, which is good since it's meant to be a private method and instantiating a |
||
return (200, result) | ||
|
||
|
||
class VersionServlet(RestServlet): | ||
PATTERNS = (re.compile("^/_synapse/admin/v1/server_version$"),) | ||
|
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 document the response format?