1
0
Fork 0
mirror of synced 2024-09-29 08:51:28 +13:00

Merge pull request #517 from appwrite/feat-delete-user

Feat delete user
This commit is contained in:
Eldad A. Fux 2020-08-30 07:26:26 +03:00 committed by GitHub
commit 230a00a1ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 170 additions and 0 deletions

View file

@ -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,
],
];
/*

View file

@ -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']);

View file

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

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

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

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';
@ -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
*/

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
}