Consolidate List User Logs API params
Replace limit and offset params with a single queries param since the Queries V2 change now allows for different types of queries.
This commit is contained in:
parent
f0d66985f7
commit
27f69e3c09
6 changed files with 244 additions and 25 deletions
|
@ -10,7 +10,9 @@ use Appwrite\Event\Audit as EventAudit;
|
|||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Stats\Stats;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Users;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\LimitOffsetQuery;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
|
@ -30,7 +32,6 @@ use Utopia\Database\Validator\Authorization;
|
|||
use Utopia\Validator\Assoc;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Boolean;
|
||||
use MaxMind\Db\Reader;
|
||||
|
||||
|
@ -306,14 +307,13 @@ 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 ID.')
|
||||
->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
|
||||
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
|
||||
->param('queries', [], new Queries(new LimitOffsetQuery(), strict: false), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Only supported methods are limit and offset', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('usage')
|
||||
->action(function (string $userId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Stats $usage) {
|
||||
->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Stats $usage) {
|
||||
|
||||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
|
@ -321,6 +321,11 @@ App::get('/v1/users/:userId/logs')
|
|||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$queries = Query::parseQueries($queries);
|
||||
$grouped = Query::groupByType($queries);
|
||||
$limit = $grouped['limit'] ?? 25;
|
||||
$offset = $grouped['offset'] ?? 0;
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
|
||||
$logs = $audit->getLogsByUser($user->getId(), $limit, $offset);
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"utopia-php/cache": "0.6.*",
|
||||
"utopia-php/cli": "0.13.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.22.*",
|
||||
"utopia-php/database": "0.23.0 as 0.22.0",
|
||||
"utopia-php/locale": "0.4.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
|
@ -88,6 +88,9 @@
|
|||
"ext-phpiredis": "*"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"allow-plugins": false,
|
||||
"preferred-install": "dist",
|
||||
"platform": {
|
||||
"php": "8.0"
|
||||
}
|
||||
|
|
20
composer.lock
generated
20
composer.lock
generated
|
@ -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": "175fe4abafd8bde4053b91eea905c328",
|
||||
"content-hash": "1858c544a5b5ae59bc6ff146a375a683",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
@ -2052,16 +2052,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.22.0",
|
||||
"version": "0.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "22c45ae83612e907203b7571cd8e3115ae3ae4c5"
|
||||
"reference": "e4a23f8e26a3d96f292e549cebe0ff6937ec5d71"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/22c45ae83612e907203b7571cd8e3115ae3ae4c5",
|
||||
"reference": "22c45ae83612e907203b7571cd8e3115ae3ae4c5",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/e4a23f8e26a3d96f292e549cebe0ff6937ec5d71",
|
||||
"reference": "e4a23f8e26a3d96f292e549cebe0ff6937ec5d71",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2110,9 +2110,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.22.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.23.0"
|
||||
},
|
||||
"time": "2022-08-17T12:55:37+00:00"
|
||||
"time": "2022-08-18T19:08:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
@ -5354,6 +5354,12 @@
|
|||
"version": "9999999-dev",
|
||||
"alias": "0.19.5",
|
||||
"alias_normalized": "0.19.5.0"
|
||||
},
|
||||
{
|
||||
"package": "utopia-php/database",
|
||||
"version": "0.23.0.0",
|
||||
"alias": "0.22.0",
|
||||
"alias_normalized": "0.22.0.0"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Utopia\Database\Validator\Queries;
|
||||
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query as QueryValidator;
|
||||
|
||||
class LimitOffsetQuery extends QueryValidator
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $message = 'Invalid query';
|
||||
|
||||
protected int $maxLimit;
|
||||
protected int $maxOffset;
|
||||
|
||||
/**
|
||||
* Query constructor
|
||||
*
|
||||
* @param int $maxLimit
|
||||
* @param int $maxOffset
|
||||
* @param int $maxValuesCount
|
||||
*/
|
||||
public function __construct(int $maxLimit = 100, int $maxOffset = 5000)
|
||||
{
|
||||
$this->maxLimit = $maxLimit;
|
||||
$this->maxOffset = $maxOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is valid.
|
||||
*
|
||||
* Returns true if method is limit or offset and values are within range.
|
||||
*
|
||||
* @param Query $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid($query): bool
|
||||
{
|
||||
// Validate method
|
||||
$method = $query->getMethod();
|
||||
switch ($method) {
|
||||
case Query::TYPE_LIMIT:
|
||||
$limit = $query->getValue();
|
||||
return $this->isValidLimit($limit);
|
||||
|
||||
case Query::TYPE_OFFSET:
|
||||
$offset = $query->getValue();
|
||||
return $this->isValidOffset($offset);
|
||||
|
||||
default:
|
||||
$this->message = 'Query method invalid: ' . $method;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
namespace Tests\E2E\Services\Users;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\ID;
|
||||
|
||||
trait UsersBase
|
||||
|
@ -673,26 +672,44 @@ trait UsersBase
|
|||
/**
|
||||
* 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()));
|
||||
$i = 0;
|
||||
do {
|
||||
$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()));
|
||||
|
||||
$i++;
|
||||
} while ($logs['body']['total'] === 0 && $i < 1000);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
$this->assertIsArray($logs['body']['logs']);
|
||||
$this->assertIsNumeric($logs['body']['total']);
|
||||
$this->assertCount(1, $logs['body']['logs']);
|
||||
$this->assertEquals(1, $logs['body']['total']);
|
||||
$this->assertIsArray($logs['body']['logs'][0]);
|
||||
|
||||
$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
|
||||
'queries' => ['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']['total']);
|
||||
$this->assertCount(1, $logs['body']['logs']);
|
||||
$this->assertEquals(1, $logs['body']['total']);
|
||||
|
||||
$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()), [
|
||||
'queries' => ['limit(0)']
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
$this->assertIsArray($logs['body']['logs']);
|
||||
$this->assertCount(0, $logs['body']['logs']);
|
||||
$this->assertEquals(1, $logs['body']['total']);
|
||||
|
||||
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
@ -703,7 +720,8 @@ trait UsersBase
|
|||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
$this->assertIsArray($logs['body']['logs']);
|
||||
$this->assertIsNumeric($logs['body']['total']);
|
||||
$this->assertCount(0, $logs['body']['logs']);
|
||||
$this->assertEquals(1, $logs['body']['total']);
|
||||
|
||||
$logs = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
@ -717,8 +735,74 @@ trait UsersBase
|
|||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
$this->assertIsArray($logs['body']['logs']);
|
||||
$this->assertLessThanOrEqual(1, count($logs['body']['logs']));
|
||||
$this->assertIsNumeric($logs['body']['total']);
|
||||
$this->assertCount(0, $logs['body']['logs']);
|
||||
$this->assertEquals(1, $logs['body']['total']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(-1)']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(101)']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(-1)']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(5001)']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "asdf")']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("$id")']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAsc("$id")']
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Utopia\Database\Validator\Queries;
|
||||
|
||||
use Appwrite\Utopia\Database\Validator\Queries;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\LimitOffsetQuery;
|
||||
use Utopia\Database\Query;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class LimitOffsetQueryTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Key
|
||||
*/
|
||||
protected $validator = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->validator = new LimitOffsetQuery();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testValue(): void
|
||||
{
|
||||
// Test for Success
|
||||
$this->assertEquals($this->validator->isValid(Query::limit(1)), true, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::limit(0)), true, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::limit(100)), true, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::offset(1)), true, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::offset(0)), true, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::offset(5000)), true, $this->validator->getDescription());
|
||||
|
||||
// Test for Failure
|
||||
$this->assertEquals($this->validator->isValid(Query::limit(-1)), false, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::limit(101)), false, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::offset(-1)), false, $this->validator->getDescription());
|
||||
$this->assertEquals($this->validator->isValid(Query::offset(5001)), false, $this->validator->getDescription());
|
||||
}
|
||||
|
||||
public function testValues(): void
|
||||
{
|
||||
|
||||
$validator = new Queries($this->validator, strict: false);
|
||||
|
||||
// Test for Success
|
||||
$this->assertEquals($validator->isValid(['limit(1)']), true, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['limit(0)']), true, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['limit(100)']), true, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['offset(1)']), true, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['offset(0)']), true, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['offset(5000)']), true, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['limit(25)', 'offset(25)']), true, $validator->getDescription());
|
||||
|
||||
// Test for Failure
|
||||
$this->assertEquals($validator->isValid(['limit(-1)']), false, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['limit(101)']), false, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['offset(-1)']), false, $validator->getDescription());
|
||||
$this->assertEquals($validator->isValid(['offset(5001)']), false, $validator->getDescription());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue