Feature: Add deactivate account admin API
Allows server admins to "deactivate" accounts, which: - Revokes all access tokens - Removes all threepids - Removes password The API is a POST to `/admin/deactivate/<user_id>`
This commit is contained in:
parent
aac546c978
commit
f328d95cef
|
@ -77,6 +77,32 @@ class PurgeMediaCacheRestServlet(ClientV1RestServlet):
|
||||||
defer.returnValue((200, ret))
|
defer.returnValue((200, ret))
|
||||||
|
|
||||||
|
|
||||||
|
class DeactivateAccountRestServlet(ClientV1RestServlet):
|
||||||
|
PATTERNS = client_path_patterns("/admin/deactivate/(?P<target_user_id>[^/]*)")
|
||||||
|
|
||||||
|
def __init__(self, hs):
|
||||||
|
self.store = hs.get_datastore()
|
||||||
|
super(DeactivateAccountRestServlet, self).__init__(hs)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def on_POST(self, request, target_user_id):
|
||||||
|
UserID.from_string(target_user_id)
|
||||||
|
requester = yield self.auth.get_user_by_req(request)
|
||||||
|
is_admin = yield self.auth.is_server_admin(requester.user)
|
||||||
|
|
||||||
|
if not is_admin:
|
||||||
|
raise AuthError(403, "You are not a server admin")
|
||||||
|
|
||||||
|
# FIXME: Theoretically there is a race here wherein user resets password
|
||||||
|
# using threepid.
|
||||||
|
yield self.store.user_delete_access_tokens(target_user_id)
|
||||||
|
yield self.store.user_delete_threepids(target_user_id)
|
||||||
|
yield self.store.user_set_password_hash(target_user_id, None)
|
||||||
|
|
||||||
|
defer.returnValue((200, {}))
|
||||||
|
|
||||||
|
|
||||||
def register_servlets(hs, http_server):
|
def register_servlets(hs, http_server):
|
||||||
WhoisRestServlet(hs).register(http_server)
|
WhoisRestServlet(hs).register(http_server)
|
||||||
PurgeMediaCacheRestServlet(hs).register(http_server)
|
PurgeMediaCacheRestServlet(hs).register(http_server)
|
||||||
|
DeactivateAccountRestServlet(hs).register(http_server)
|
||||||
|
|
|
@ -807,6 +807,11 @@ class SQLBaseStore(object):
|
||||||
if txn.rowcount > 1:
|
if txn.rowcount > 1:
|
||||||
raise StoreError(500, "more than one row matched")
|
raise StoreError(500, "more than one row matched")
|
||||||
|
|
||||||
|
def _simple_delete(self, table, keyvalues, desc):
|
||||||
|
return self.runInteraction(
|
||||||
|
desc, self._simple_delete_txn, table, keyvalues
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _simple_delete_txn(txn, table, keyvalues):
|
def _simple_delete_txn(txn, table, keyvalues):
|
||||||
sql = "DELETE FROM %s WHERE %s" % (
|
sql = "DELETE FROM %s WHERE %s" % (
|
||||||
|
|
|
@ -384,6 +384,15 @@ class RegistrationStore(SQLBaseStore):
|
||||||
defer.returnValue(ret['user_id'])
|
defer.returnValue(ret['user_id'])
|
||||||
defer.returnValue(None)
|
defer.returnValue(None)
|
||||||
|
|
||||||
|
def user_delete_threepids(self, user_id):
|
||||||
|
return self._simple_delete(
|
||||||
|
"user_threepids",
|
||||||
|
keyvalues={
|
||||||
|
"user_id": user_id,
|
||||||
|
},
|
||||||
|
desc="user_delete_threepids",
|
||||||
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def count_all_users(self):
|
def count_all_users(self):
|
||||||
"""Counts all users registered on the homeserver."""
|
"""Counts all users registered on the homeserver."""
|
||||||
|
|
Loading…
Reference in New Issue