Merge pull request #517 from appwrite/feat-delete-user
Feat delete user
This commit is contained in:
commit
230a00a1ed
9 changed files with 170 additions and 0 deletions
|
@ -1433,6 +1433,13 @@ $collections = [
|
|||
],
|
||||
],
|
||||
],
|
||||
Database::SYSTEM_COLLECTION_RESERVED => [
|
||||
'$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS,
|
||||
'$id' => Database::SYSTEM_COLLECTION_RESERVED,
|
||||
'$permissions' => ['read' => ['*']],
|
||||
'name' => 'Reserved',
|
||||
'structure' => true,
|
||||
],
|
||||
];
|
||||
|
||||
/*
|
||||
|
|
|
@ -526,3 +526,48 @@ App::delete('/v1/users/:userId/sessions')
|
|||
|
||||
$response->json(array('result' => 'success'));
|
||||
}, ['response', 'projectDB']);
|
||||
|
||||
App::delete('/v1/users/:userId')
|
||||
->desc('Delete User')
|
||||
->groups(['api', 'users'])
|
||||
->label('scope', 'users.write')
|
||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'deleteUser')
|
||||
->label('sdk.description', '/docs/references/users/delete-user.md')
|
||||
->label('abuse-limit', 100)
|
||||
->param('userId', '', function () {return new UID();}, 'User unique ID.')
|
||||
->action(function ($userId, $response, $projectDB, $deletes) {
|
||||
/** @var Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
|
||||
$user = $projectDB->getDocument($userId);
|
||||
|
||||
if (empty($user->getId()) || Database::SYSTEM_COLLECTION_USERS != $user->getCollection()) {
|
||||
throw new Exception('User not found', 404);
|
||||
}
|
||||
if (!$projectDB->deleteDocument($userId)) {
|
||||
throw new Exception('Failed to remove user from DB', 500);
|
||||
}
|
||||
|
||||
if (!$projectDB->deleteUniqueKey(md5('users:email='.$user->getAttribute('email', null)))) {
|
||||
throw new Exception('Failed to remove unique key from DB', 500);
|
||||
}
|
||||
|
||||
$reservedId = $projectDB->createDocument([
|
||||
'$collection' => Database::SYSTEM_COLLECTION_RESERVED,
|
||||
'$id' => $userId,
|
||||
'$permissions' => [
|
||||
'read' => ['*'],
|
||||
],
|
||||
]);
|
||||
|
||||
if (false === $reservedId) {
|
||||
throw new Exception('Failed saving reserved id to DB', 500);
|
||||
}
|
||||
|
||||
$deletes->setParam('document', $user);
|
||||
|
||||
$response->noContent();
|
||||
}, ['response', 'projectDB', 'deletes']);
|
||||
|
|
|
@ -30,6 +30,9 @@ class DeletesV1
|
|||
case Database::SYSTEM_COLLECTION_PROJECTS:
|
||||
$this->deleteProject($document);
|
||||
break;
|
||||
case Database::SYSTEM_COLLECTION_USERS:
|
||||
$this->deleteUser($document);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -58,4 +61,32 @@ class DeletesV1
|
|||
$uploads->delete($uploads->getRoot(), true);
|
||||
$cache->delete($cache->getRoot(), true);
|
||||
}
|
||||
|
||||
protected function deleteUser(Document $user)
|
||||
{
|
||||
global $projectDB;
|
||||
|
||||
$tokens = $user->getAttribute('tokens', []);
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
if (!$projectDB->deleteDocument($token->getId())) {
|
||||
throw new Exception('Failed to remove token from DB', 500);
|
||||
}
|
||||
}
|
||||
|
||||
$memberships = $projectDB->getCollection([
|
||||
'limit' => 2000, // TODO add members limit
|
||||
'offset' => 0,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
||||
'userId='.$user->getId(),
|
||||
],
|
||||
]);
|
||||
|
||||
foreach ($memberships as $membership) {
|
||||
if (!$projectDB->deleteDocument($membership->getId())) {
|
||||
throw new Exception('Failed to remove team membership from DB', 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1
docs/references/users/delete-user.md
Normal file
1
docs/references/users/delete-user.md
Normal file
|
@ -0,0 +1 @@
|
|||
Delete a user by its unique ID.
|
|
@ -88,6 +88,15 @@ abstract class Adapter
|
|||
*/
|
||||
abstract public function deleteDocument($id);
|
||||
|
||||
/**
|
||||
* Delete Unique Key.
|
||||
*
|
||||
* @param int $key
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function deleteUniqueKey($key);
|
||||
|
||||
/**
|
||||
* Create Namespace.
|
||||
*
|
||||
|
|
|
@ -350,6 +350,26 @@ class MySQL extends Adapter
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Unique Key.
|
||||
*
|
||||
* @param int $key
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function deleteUniqueKey($key)
|
||||
{
|
||||
$st1 = $this->getPDO()->prepare('DELETE FROM `'.$this->getNamespace().'.database.unique` WHERE `key` = :key');
|
||||
|
||||
$st1->bindValue(':key', $key, PDO::PARAM_STR);
|
||||
|
||||
$st1->execute();
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Relation.
|
||||
*
|
||||
|
|
|
@ -153,6 +153,22 @@ class Redis extends Adapter
|
|||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Unique Key.
|
||||
*
|
||||
* @param $key
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function deleteUniqueKey($key)
|
||||
{
|
||||
$data = $this->adapter->deleteUniqueKey($key);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Namespace.
|
||||
*
|
||||
|
|
|
@ -23,6 +23,7 @@ class Database
|
|||
const SYSTEM_COLLECTION_USAGES = 'usages'; //TODO add structure
|
||||
const SYSTEM_COLLECTION_DOMAINS = 'domains';
|
||||
const SYSTEM_COLLECTION_CERTIFICATES = 'certificates';
|
||||
const SYSTEM_COLLECTION_RESERVED = 'reserved';
|
||||
|
||||
// Auth, Account and Users (private to user)
|
||||
const SYSTEM_COLLECTION_USERS = 'users';
|
||||
|
@ -344,6 +345,18 @@ class Database
|
|||
return new Document($this->adapter->deleteDocument($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $key
|
||||
*
|
||||
* @return Document|false
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
*/
|
||||
public function deleteUniqueKey($key)
|
||||
{
|
||||
return new Document($this->adapter->deleteUniqueKey($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
|
|
@ -168,6 +168,34 @@ trait UsersBase
|
|||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGetUser
|
||||
*/
|
||||
public function testDeleteUser(array $data):array
|
||||
{
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals($user['headers']['status-code'], 204);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
$user = $this->client->call(Client::METHOD_DELETE, '/users/' . $data['userId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals($user['headers']['status-code'], 404);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
// TODO add test for session delete
|
||||
// TODO add test for all sessions delete
|
||||
}
|
Loading…
Reference in a new issue