Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Enable changing user type via users admin API (#11174)
Browse files Browse the repository at this point in the history
Users admin API can now also modify user
type in addition to allowing it to be
set on user creation.

Signed-off-by: Jason Robinson <jasonr@matrix.org>
Co-authored-by: Brendan Abolivier <babolivier@matrix.org>
  • Loading branch information
jaywink and babolivier committed Oct 26, 2021
1 parent c1510c9 commit 63cbdd8
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog.d/11174.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Users admin API can now also modify user type in addition to allowing it to be set on user creation.
9 changes: 7 additions & 2 deletions docs/admin_api/user_admin_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ It returns a JSON body like the following:
"auth_provider": "<provider2>",
"external_id": "<user_id_provider_2>"
}
]
],
"user_type": null
}
```

Expand Down Expand Up @@ -97,7 +98,8 @@ with a body of:
],
"avatar_url": "<avatar_url>",
"admin": false,
"deactivated": false
"deactivated": false,
"user_type": null
}
```

Expand Down Expand Up @@ -135,6 +137,9 @@ Body parameters:
unchanged on existing accounts and set to `false` for new accounts.
A user cannot be erased by deactivating with this API. For details on
deactivating users see [Deactivate Account](#deactivate-account).
- `user_type` - string or null, optional. If provided, the user type will be
adjusted. If `null` given, the user type will be cleared. Other
allowed options are: `bot` and `support`.

If the user already exists then optional parameters default to the current value.

Expand Down
3 changes: 3 additions & 0 deletions synapse/rest/admin/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ async def on_PUT(
target_user.to_string()
)

if "user_type" in body:
await self.store.set_user_type(target_user, user_type)

user = await self.admin_handler.get_user(target_user)
assert user is not None

Expand Down
18 changes: 18 additions & 0 deletions synapse/storage/databases/main/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,24 @@ def set_shadow_banned_txn(txn):

await self.db_pool.runInteraction("set_shadow_banned", set_shadow_banned_txn)

async def set_user_type(self, user: UserID, user_type: Optional[UserTypes]) -> None:
"""Sets the user type.
Args:
user: user ID of the user.
user_type: type of the user or None for a user without a type.
"""

def set_user_type_txn(txn):
self.db_pool.simple_update_one_txn(
txn, "users", {"name": user.to_string()}, {"user_type": user_type}
)
self._invalidate_cache_and_stream(
txn, self.get_user_by_id, (user.to_string(),)
)

await self.db_pool.runInteraction("set_user_type", set_user_type_txn)

def _query_for_auth(self, txn, token: str) -> Optional[TokenLookupResult]:
sql = """
SELECT users.name as user_id,
Expand Down
51 changes: 51 additions & 0 deletions tests/rest/admin/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,57 @@ def test_set_user_as_admin(self):
self.assertEqual("@user:test", channel.json_body["name"])
self.assertTrue(channel.json_body["admin"])

def test_set_user_type(self):
"""
Test changing user type.
"""

# Set to support type
channel = self.make_request(
"PUT",
self.url_other_user,
access_token=self.admin_user_tok,
content={"user_type": UserTypes.SUPPORT},
)

self.assertEqual(200, channel.code, msg=channel.json_body)
self.assertEqual("@user:test", channel.json_body["name"])
self.assertEqual(UserTypes.SUPPORT, channel.json_body["user_type"])

# Get user
channel = self.make_request(
"GET",
self.url_other_user,
access_token=self.admin_user_tok,
)

self.assertEqual(200, channel.code, msg=channel.json_body)
self.assertEqual("@user:test", channel.json_body["name"])
self.assertEqual(UserTypes.SUPPORT, channel.json_body["user_type"])

# Change back to a regular user
channel = self.make_request(
"PUT",
self.url_other_user,
access_token=self.admin_user_tok,
content={"user_type": None},
)

self.assertEqual(200, channel.code, msg=channel.json_body)
self.assertEqual("@user:test", channel.json_body["name"])
self.assertIsNone(channel.json_body["user_type"])

# Get user
channel = self.make_request(
"GET",
self.url_other_user,
access_token=self.admin_user_tok,
)

self.assertEqual(200, channel.code, msg=channel.json_body)
self.assertEqual("@user:test", channel.json_body["name"])
self.assertIsNone(channel.json_body["user_type"])

def test_accidental_deactivation_prevention(self):
"""
Ensure an account can't accidentally be deactivated by using a str value
Expand Down

0 comments on commit 63cbdd8

Please sign in to comment.