1
0
Fork 0
mirror of synced 2024-06-29 19:50:26 +12:00

Merge pull request #2420 from appwrite/feat-database-logs-pagination

feat(controllers): add pagination to logs endpoints
This commit is contained in:
Torsten Dittmann 2021-11-18 11:28:00 +01:00 committed by GitHub
commit d0769018ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 220 additions and 47 deletions

View file

@ -23,6 +23,7 @@ use Utopia\Database\Validator\UID;
use Utopia\Exception;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Assoc;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
@ -1182,13 +1183,15 @@ App::get('/v1/account/logs')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true)
->inject('response')
->inject('user')
->inject('locale')
->inject('geodb')
->inject('dbForInternal')
->inject('usage')
->action(function ($response, $user, $locale, $geodb, $dbForInternal, $usage) {
->action(function ($limit, $offset, $response, $user, $locale, $geodb, $dbForInternal, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
@ -1198,8 +1201,7 @@ App::get('/v1/account/logs')
/** @var Appwrite\Stats\Stats $usage */
$audit = new Audit($dbForInternal);
$logs = $audit->getLogsByUserAndEvents($user->getId(), [
$auditEvents = [
'account.create',
'account.delete',
'account.update.name',
@ -1215,7 +1217,9 @@ App::get('/v1/account/logs')
'teams.membership.create',
'teams.membership.update',
'teams.membership.delete',
]);
];
$logs = $audit->getLogsByUserAndEvents($user->getId(), $auditEvents, $limit, $offset);
$output = [];
@ -1245,7 +1249,11 @@ App::get('/v1/account/logs')
$usage
->setParam('users.read', 1)
;
$response->dynamic(new Document(['logs' => $output]), Response::MODEL_LOG_LIST);
$response->dynamic(new Document([
'sum' => $audit->countLogsByUserAndEvents($user->getId(), $auditEvents),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::get('/v1/account/sessions/:sessionId')

View file

@ -458,12 +458,14 @@ App::get('/v1/database/collections/:collectionId/logs')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('collectionId', '', new UID(), 'Collection unique ID.')
->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForExternal')
->inject('locale')
->inject('geodb')
->action(function ($collectionId, $response, $dbForInternal, $dbForExternal, $locale, $geodb) {
->action(function ($collectionId, $limit, $offset, $response, $dbForInternal, $dbForExternal, $locale, $geodb) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
@ -478,8 +480,8 @@ App::get('/v1/database/collections/:collectionId/logs')
}
$audit = new Audit($dbForInternal);
$logs = $audit->getLogsByResource('collection/'.$collection->getId());
$resource = 'collection/'.$collection->getId();
$logs = $audit->getLogsByResource($resource, $limit, $offset);
$output = [];
@ -539,7 +541,10 @@ App::get('/v1/database/collections/:collectionId/logs')
}
}
$response->dynamic(new Document(['logs' => $output]), Response::MODEL_LOG_LIST);
$response->dynamic(new Document([
'sum' => $audit->countLogsByResource($resource),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::put('/v1/database/collections/:collectionId')

View file

@ -259,12 +259,14 @@ App::get('/v1/users/:userId/logs')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('userId', '', new UID(), 'User unique ID.')
->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true)
->inject('response')
->inject('dbForInternal')
->inject('locale')
->inject('geodb')
->inject('usage')
->action(function ($userId, $response, $dbForInternal, $locale, $geodb, $usage) {
->action(function ($userId, $limit, $offset, $response, $dbForInternal, $locale, $geodb, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
@ -279,8 +281,7 @@ App::get('/v1/users/:userId/logs')
}
$audit = new Audit($dbForInternal);
$logs = $audit->getLogsByUserAndEvents($user->getId(), [
$auditEvents = [
'account.create',
'account.delete',
'account.update.name',
@ -296,7 +297,9 @@ App::get('/v1/users/:userId/logs')
'teams.membership.create',
'teams.membership.update',
'teams.membership.delete',
]);
];
$logs = $audit->getLogsByUserAndEvents($user->getId(), $auditEvents, $limit, $offset);
$output = [];
@ -355,7 +358,11 @@ App::get('/v1/users/:userId/logs')
$usage
->setParam('users.read', 1)
;
$response->dynamic(new Document(['logs' => $output]), Response::MODEL_LOG_LIST);
$response->dynamic(new Document([
'sum' => $audit->countLogsByUserAndEvents($user->getId(), $auditEvents),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::patch('/v1/users/:userId/status')

View file

@ -41,11 +41,11 @@
"utopia-php/framework": "0.19.*",
"utopia-php/abuse": "0.6.*",
"utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.6.*",
"utopia-php/audit": "0.7.*",
"utopia-php/cache": "0.4.*",
"utopia-php/cli": "0.11.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.10.*",
"utopia-php/database": "0.11.*",
"utopia-php/locale": "0.4.*",
"utopia-php/orchestration": "0.2.*",
"utopia-php/registry": "0.5.*",

28
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "de8b7360734c246c97d8cee4779983e3",
"content-hash": "8427bbf013694d9771cd09341a81562e",
"packages": [
{
"name": "adhocore/jwt",
@ -1928,22 +1928,22 @@
},
{
"name": "utopia-php/audit",
"version": "0.6.3",
"version": "0.7.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "d79b467fbc7d03e5e02f12cdeb08761507a60ca0"
"reference": "485cdd2354db7eb8f7aa74bbe39c39b583e99c04"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/d79b467fbc7d03e5e02f12cdeb08761507a60ca0",
"reference": "d79b467fbc7d03e5e02f12cdeb08761507a60ca0",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/485cdd2354db7eb8f7aa74bbe39c39b583e99c04",
"reference": "485cdd2354db7eb8f7aa74bbe39c39b583e99c04",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"php": ">=7.4",
"utopia-php/database": ">=0.6 <1.0"
"utopia-php/database": ">=0.11 <1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
@ -1975,9 +1975,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.6.3"
"source": "https://github.com/utopia-php/audit/tree/0.7.0"
},
"time": "2021-08-16T18:49:55+00:00"
"time": "2021-11-17T17:23:42+00:00"
},
{
"name": "utopia-php/cache",
@ -2138,16 +2138,16 @@
},
{
"name": "utopia-php/database",
"version": "0.10.1",
"version": "0.11.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "9b4697612a2cd1ad55beeb6a02570f6ffe26dc1e"
"reference": "5fc0476d05567d1a156b00e17033f32148c93a38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/9b4697612a2cd1ad55beeb6a02570f6ffe26dc1e",
"reference": "9b4697612a2cd1ad55beeb6a02570f6ffe26dc1e",
"url": "https://api.github.com/repos/utopia-php/database/zipball/5fc0476d05567d1a156b00e17033f32148c93a38",
"reference": "5fc0476d05567d1a156b00e17033f32148c93a38",
"shasum": ""
},
"require": {
@ -2195,9 +2195,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.10.1"
"source": "https://github.com/utopia-php/database/tree/0.11.0"
},
"time": "2021-11-02T15:10:39+00:00"
"time": "2021-11-17T09:53:02+00:00"
},
{
"name": "utopia-php/domains",

View file

@ -194,7 +194,7 @@ class Response extends SwooleResponse
->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT))
->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER))
->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION))
->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG, false))
->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG))
->setModel(new BaseList('Files List', self::MODEL_FILE_LIST, 'files', self::MODEL_FILE))
->setModel(new BaseList('Teams List', self::MODEL_TEAM_LIST, 'teams', self::MODEL_TEAM))
->setModel(new BaseList('Memberships List', self::MODEL_MEMBERSHIP_LIST, 'memberships', self::MODEL_MEMBERSHIP))

View file

@ -283,10 +283,10 @@ trait AccountBase
$this->assertEquals('', $response['body']['sessions'][0]['deviceBrand']);
$this->assertEquals('', $response['body']['sessions'][0]['deviceModel']);
$this->assertEquals($response['body']['sessions'][0]['ip'], filter_var($response['body']['sessions'][0]['ip'], FILTER_VALIDATE_IP));
$this->assertEquals('--', $response['body']['sessions'][0]['countryCode']);
$this->assertEquals('Unknown', $response['body']['sessions'][0]['countryName']);
$this->assertEquals(true, $response['body']['sessions'][0]['current']);
/**
@ -325,7 +325,8 @@ trait AccountBase
$this->assertIsArray($response['body']['logs']);
$this->assertNotEmpty($response['body']['logs']);
$this->assertCount(2, $response['body']['logs']);
$this->assertIsNumeric($response['body']['sum']);
$this->assertContains($response['body']['logs'][0]['event'], ['account.create', 'account.sessions.create']);
$this->assertEquals($response['body']['logs'][0]['ip'], filter_var($response['body']['logs'][0]['ip'], FILTER_VALIDATE_IP));
$this->assertIsNumeric($response['body']['logs'][0]['time']);
@ -344,7 +345,7 @@ trait AccountBase
$this->assertEquals('', $response['body']['logs'][0]['deviceBrand']);
$this->assertEquals('', $response['body']['logs'][0]['deviceModel']);
$this->assertEquals($response['body']['logs'][0]['ip'], filter_var($response['body']['logs'][0]['ip'], FILTER_VALIDATE_IP));
$this->assertEquals('--', $response['body']['logs'][0]['countryCode']);
$this->assertEquals('Unknown', $response['body']['logs'][0]['countryName']);
@ -366,10 +367,61 @@ trait AccountBase
$this->assertEquals('', $response['body']['logs'][1]['deviceBrand']);
$this->assertEquals('', $response['body']['logs'][1]['deviceModel']);
$this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP));
$this->assertEquals('--', $response['body']['logs'][1]['countryCode']);
$this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']);
$responseLimit = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
]), [
'limit' => 1
]);
$this->assertEquals($responseLimit['headers']['status-code'], 200);
$this->assertIsArray($responseLimit['body']['logs']);
$this->assertNotEmpty($responseLimit['body']['logs']);
$this->assertCount(1, $responseLimit['body']['logs']);
$this->assertIsNumeric($responseLimit['body']['sum']);
$this->assertEquals($response['body']['logs'][0], $responseLimit['body']['logs'][0]);
$responseOffset = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
]), [
'offset' => 1
]);
$this->assertEquals($responseOffset['headers']['status-code'], 200);
$this->assertIsArray($responseOffset['body']['logs']);
$this->assertNotEmpty($responseOffset['body']['logs']);
$this->assertCount(1, $responseOffset['body']['logs']);
$this->assertIsNumeric($responseOffset['body']['sum']);
$this->assertEquals($response['body']['logs'][1], $responseOffset['body']['logs'][0]);
$responseLimitOffset = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
]), [
'limit' => 1,
'offset' => 1
]);
$this->assertEquals($responseLimitOffset['headers']['status-code'], 200);
$this->assertIsArray($responseLimitOffset['body']['logs']);
$this->assertNotEmpty($responseLimitOffset['body']['logs']);
$this->assertCount(1, $responseLimitOffset['body']['logs']);
$this->assertIsNumeric($responseLimitOffset['body']['sum']);
$this->assertEquals($response['body']['logs'][1], $responseLimitOffset['body']['logs'][0]);
/**
* Test for FAILURE
*/

View file

@ -33,7 +33,7 @@ class DatabaseConsoleClientTest extends Scope
return ['moviesId' => $movies['body']['$id']];
}
public function testGetDatabaseUsage()
{
/**
@ -48,7 +48,7 @@ class DatabaseConsoleClientTest extends Scope
]);
$this->assertEquals($response['headers']['status-code'], 400);
/**
* Test for SUCCESS
*/
@ -122,4 +122,58 @@ class DatabaseConsoleClientTest extends Scope
$this->assertIsArray($response['body']['documents.update']);
$this->assertIsArray($response['body']['documents.delete']);
}
/**
* @depends testCreateCollection
*/
public function testGetCollectionLogs(array $data)
{
/**
* Test for SUCCESS
*/
$logs = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertIsNumeric($logs['body']['sum']);
$logs = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'limit' => 1
]);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertLessThanOrEqual(1, count($logs['body']['logs']));
$this->assertIsNumeric($logs['body']['sum']);
$logs = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'offset' => 1
]);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertIsNumeric($logs['body']['sum']);
$logs = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'offset' => 1,
'limit' => 1
]);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertLessThanOrEqual(1, count($logs['body']['logs']));
$this->assertIsNumeric($logs['body']['sum']);
}
}

View file

@ -204,14 +204,6 @@ trait UsersBase
$this->assertEquals($sessions['headers']['status-code'], 200);
$this->assertIsArray($sessions['body']);
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']);
$users = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -428,6 +420,61 @@ trait UsersBase
return $data;
}
/**
* @depends testGetUser
*/
public function testGetLogs(array $data): void
{
/**
* Test for SUCCESS
*/
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertIsNumeric($logs['body']['sum']);
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'limit' => 1
]);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertLessThanOrEqual(1, count($logs['body']['logs']));
$this->assertIsNumeric($logs['body']['sum']);
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'offset' => 1
]);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertIsNumeric($logs['body']['sum']);
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'offset' => 1,
'limit' => 1
]);
$this->assertEquals($logs['headers']['status-code'], 200);
$this->assertIsArray($logs['body']['logs']);
$this->assertLessThanOrEqual(1, count($logs['body']['logs']));
$this->assertIsNumeric($logs['body']['sum']);
}
/**
* @depends testGetUser
*/