Merge branch '0.7.x' of github.com:appwrite/appwrite into swoole-and-functions

This commit is contained in:
Eldad Fux 2020-08-30 08:09:14 +03:00
commit 8625f692b5
11 changed files with 167 additions and 7 deletions

View file

@ -16,7 +16,7 @@ FROM php:7.4-cli-alpine as step1
ENV TZ=Asia/Tel_Aviv \
PHP_REDIS_VERSION=5.3.1 \
PHP_SWOOLE_VERSION=4.5.2 \
PHP_SWOOLE_VERSION=4.5.3 \
PHP_XDEBUG_VERSION=sdebug_2_9-beta
RUN \

View file

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

View file

@ -66,7 +66,7 @@ App::post('/v1/database/collections')
'rules' => $parsedRules,
]);
} catch (AuthorizationException $exception) {
throw new Exception('Unauthorized action', 401);
throw new Exception('Unauthorized permissions', 401);
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
} catch (\Exception $exception) {
@ -263,7 +263,7 @@ App::put('/v1/database/collections/:collectionId')
'rules' => $parsedRules,
]));
} catch (AuthorizationException $exception) {
throw new Exception('Unauthorized action', 401);
throw new Exception('Unauthorized permissions', 401);
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
} catch (\Exception $exception) {
@ -401,7 +401,7 @@ App::post('/v1/database/collections/:collectionId/documents')
$authorization = new Authorization($parentDocument, 'write');
if (!$authorization->isValid($new->getPermissions())) {
throw new Exception('Unauthorized action', 401);
throw new Exception('Unauthorized permissions', 401);
}
$parentDocument
@ -426,7 +426,7 @@ App::post('/v1/database/collections/:collectionId/documents')
try {
$data = $projectDB->createDocument($data);
} catch (AuthorizationException $exception) {
throw new Exception('Unauthorized action', 401);
throw new Exception('Unauthorized permissions', 401);
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
} catch (\Exception $exception) {
@ -613,7 +613,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
try {
$data = $projectDB->updateDocument($data);
} catch (AuthorizationException $exception) {
throw new Exception('Unauthorized action', 401);
throw new Exception('Unauthorized permissions', 401);
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
} catch (\Exception $exception) {
@ -666,7 +666,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
try {
$projectDB->deleteDocument($documentId);
} catch (AuthorizationException $exception) {
throw new Exception('Unauthorized action', 401);
throw new Exception('Unauthorized permissions', 401);
} catch (StructureException $exception) {
throw new Exception('Bad structure. '.$exception->getMessage(), 400);
} catch (\Exception $exception) {

View file

@ -403,3 +403,48 @@ App::delete('/v1/users/:userId/sessions')
$response->noContent();
}, ['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

@ -29,6 +29,7 @@ class DeletesV1
{
$projectId = $this->args['projectId'];
$document = $this->args['document'];
$document = new Document($document);
switch ($document->getCollection()) {
@ -38,6 +39,9 @@ class DeletesV1
case Database::SYSTEM_COLLECTION_FUNCTIONS:
$this->deleteFunction($document, $projectId);
break;
case Database::SYSTEM_COLLECTION_USERS:
$this->deleteUser($document, $projectId);
break;
default:
Console::error('No lazy delete operation available for document of type: '.$document->getCollection());
@ -62,6 +66,23 @@ class DeletesV1
$cache->delete($cache->getRoot(), true);
}
protected function deleteUser(Document $document, $projectId)
{
$tokens = $document->getAttribute('tokens', []);
foreach ($tokens as $token) {
if (!$this->getProjectDB($projectId)->deleteDocument($token->getId())) {
throw new Exception('Failed to remove token from DB', 500);
}
}
// Delete Memberships
$this->deleteByGroup([
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
'userId='.$document->getId(),
], $this->getProjectDB($projectId));
}
protected function deleteFunction(Document $document, $projectId)
{
$projectDB = $this->getProjectDB($projectId);

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';
@ -350,6 +351,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
}