1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00

Merge pull request #464 from TorstenDittmann/delete-user

Delete user endpoint
This commit is contained in:
Eldad A. Fux 2020-08-29 23:32:47 +03:00 committed by GitHub
commit dbadacfae1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 168 additions and 0 deletions

View file

@ -1187,6 +1187,13 @@ $collections = [
],
],
],
Database::SYSTEM_COLLECTION_RESERVED => [
'$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS,
'$id' => Database::SYSTEM_COLLECTION_RESERVED,
'$permissions' => ['read' => ['*']],
'name' => 'Reserved',
'structure' => true,
],
];
/*

View file

@ -187,6 +187,49 @@ $utopia->get('/v1/users/:userId')
}
);
$utopia->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) use ($response, $deletes, $projectDB) {
$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();
}
);
$utopia->get('/v1/users/:userId/prefs')
->desc('Get User Preferences')
->groups(['api', 'users'])

View file

@ -29,6 +29,9 @@ class DeletesV1
case Database::SYSTEM_COLLECTION_PROJECTS:
$this->deleteProject($document);
break;
case Database::SYSTEM_COLLECTION_USERS:
$this->deleteUser($document);
break;
default:
break;
@ -52,4 +55,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);
}
}
}
}

View file

@ -0,0 +1 @@
Delete a user by its unique ID.

View file

@ -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.
*

View file

@ -366,6 +366,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.
*

View file

@ -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.
*

View file

@ -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';
@ -309,6 +310,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
*/

View file

@ -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
}