Merge branch 'master' of github.com:appwrite/appwrite into remove-globals
This commit is contained in:
commit
4f7d5aa132
|
@ -19,6 +19,7 @@
|
|||
- Added container names to docker-compose.yml (@drandell)
|
||||
- Upgraded ClamAV container image to version 1.0.9
|
||||
- Optimised function execution by using fully-qualified function calls
|
||||
- Added support for boolean 'true' and 'false' in query strings alongside 1 and 0
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
|
@ -38,6 +39,9 @@
|
|||
- Fixed OAuth redirect when using the self-hosted instance default success URL ([#454](https://github.com/appwrite/appwrite/issues/454))
|
||||
- Fixed bug denying authentication with Github OAuth provider
|
||||
|
||||
## Breaking Changes
|
||||
- **Deprecated** `first` and `last` query params for documents list route in the database API
|
||||
|
||||
## Security
|
||||
|
||||
- Access to Health API now requires authentication with an API Key with access to `health.read` scope allowed
|
||||
|
|
|
@ -79,9 +79,8 @@ App::post('/v1/account')
|
|||
}
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -163,9 +162,8 @@ App::post('/v1/account/sessions')
|
|||
->action(
|
||||
function ($email, $password) use ($response, $request, $projectDB, $audit, $webhook) {
|
||||
$protocol = Config::getParam('protocol');
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -418,9 +416,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$projectDB->deleteDocument($current); //throw new Exception('User already logged in', 401);
|
||||
}
|
||||
|
||||
$user = (empty($user->getId())) ? $projectDB->getCollection([ // Get user by provider id
|
||||
$user = (empty($user->getId())) ? $projectDB->getCollectionFirst([ // Get user by provider id
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'oauth2'.\ucfirst($provider).'='.$oauth2ID,
|
||||
|
@ -431,9 +428,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$name = $oauth2->getUserName($accessToken);
|
||||
$email = $oauth2->getUserEmail($accessToken);
|
||||
|
||||
$user = $projectDB->getCollection([ // Get user by provider email address
|
||||
$user = $projectDB->getCollectionFirst([ // Get user by provider email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -809,9 +805,8 @@ App::patch('/v1/account/email')
|
|||
throw new Exception('Invalid credentials', 401);
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -1073,9 +1068,8 @@ App::post('/v1/account/recovery')
|
|||
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.')
|
||||
->action(
|
||||
function ($email, $url) use ($request, $response, $projectDB, $mail, $audit, $project) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -1179,9 +1173,8 @@ App::put('/v1/account/recovery')
|
|||
throw new Exception('Passwords must match', 400);
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'$id='.$userId,
|
||||
|
@ -1331,9 +1324,8 @@ App::put('/v1/account/verification')
|
|||
->param('secret', '', function () { return new Text(256); }, 'Valid verification token.')
|
||||
->action(
|
||||
function ($userId, $secret) use ($response, $user, $projectDB, $audit) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'$id='.$userId,
|
||||
|
|
|
@ -4,6 +4,7 @@ global $utopia, $request, $response;
|
|||
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Range;
|
||||
|
@ -360,7 +361,7 @@ App::get('/v1/avatars/qr')
|
|||
->param('text', '', function () { return new Text(512); }, 'Plain text to be converted to QR code image.')
|
||||
->param('size', 400, function () { return new Range(0, 1000); }, 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
|
||||
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
|
||||
->param('download', 0, function () { return new Range(0, 1); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
|
||||
->param('download', false, function () { return new Boolean(true); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
|
@ -369,6 +370,8 @@ App::get('/v1/avatars/qr')
|
|||
->label('sdk.description', '/docs/references/avatars/get-qr.md')
|
||||
->action(
|
||||
function ($text, $size, $margin, $download) use ($response) {
|
||||
$download = ($download === '1' || $download === 'true' || $download === 1 || $download === true);
|
||||
|
||||
$renderer = new ImageRenderer(
|
||||
new RendererStyle($size, $margin),
|
||||
new ImagickImageBackEnd('png', 100)
|
||||
|
|
|
@ -5,14 +5,15 @@ global $utopia, $register, $request, $response, $webhook, $audit, $projectDB;
|
|||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\JSON;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
// use Utopia\Locale\Locale;
|
||||
// use Utopia\Audit\Audit;
|
||||
// use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Database\Document;
|
||||
use Appwrite\Database\Validator\UID;
|
||||
|
@ -22,8 +23,9 @@ use Appwrite\Database\Validator\Collection;
|
|||
use Appwrite\Database\Validator\Authorization;
|
||||
use Appwrite\Database\Exception\Authorization as AuthorizationException;
|
||||
use Appwrite\Database\Exception\Structure as StructureException;
|
||||
use DeviceDetector\DeviceDetector;
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// use DeviceDetector\DeviceDetector;
|
||||
// use GeoIp2\Database\Reader;
|
||||
|
||||
App::post('/v1/database/collections')
|
||||
->desc('Create Collection')
|
||||
|
@ -481,10 +483,8 @@ App::get('/v1/database/collections/:collectionId/documents')
|
|||
->param('orderType', 'ASC', function () { return new WhiteList(array('DESC', 'ASC')); }, 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true)
|
||||
->param('orderCast', 'string', function () { return new WhiteList(array('int', 'string', 'date', 'time', 'datetime')); }, 'Order field type casting. Possible values are int, string, date, time or datetime. The database will attempt to cast the order field to the value you pass here. The default value is a string.', true)
|
||||
->param('search', '', function () { return new Text(256); }, 'Search query. Enter any free text search. The database will try to find a match against all document attributes and children.', true)
|
||||
->param('first', 0, function () { return new Range(0, 1); }, 'Return only the first document. Pass 1 for true or 0 for false. The default value is 0.', true)
|
||||
->param('last', 0, function () { return new Range(0, 1); }, 'Return only the last document. Pass 1 for true or 0 for false. The default value is 0.', true)
|
||||
->action(
|
||||
function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search, $first, $last) use ($response, $projectDB, $utopia) {
|
||||
function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search) use ($response, $projectDB, $utopia) {
|
||||
$collection = $projectDB->getDocument($collectionId, false);
|
||||
|
||||
if (\is_null($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
||||
|
@ -498,38 +498,32 @@ App::get('/v1/database/collections/:collectionId/documents')
|
|||
'orderType' => $orderType,
|
||||
'orderCast' => $orderCast,
|
||||
'search' => $search,
|
||||
'first' => (bool) $first,
|
||||
'last' => (bool) $last,
|
||||
'filters' => \array_merge($filters, [
|
||||
'$collection='.$collectionId,
|
||||
]),
|
||||
]);
|
||||
|
||||
if ($first || $last) {
|
||||
$response->json((!empty($list) ? $list->getArrayCopy() : []));
|
||||
} else {
|
||||
if (App::isDevelopment()) {
|
||||
$collection
|
||||
->setAttribute('debug', $projectDB->getDebug())
|
||||
->setAttribute('limit', $limit)
|
||||
->setAttribute('offset', $offset)
|
||||
->setAttribute('orderField', $orderField)
|
||||
->setAttribute('orderType', $orderType)
|
||||
->setAttribute('orderCast', $orderCast)
|
||||
->setAttribute('filters', $filters)
|
||||
;
|
||||
}
|
||||
|
||||
if (App::isDevelopment()) {
|
||||
$collection
|
||||
->setAttribute('sum', $projectDB->getSum())
|
||||
->setAttribute('documents', $list)
|
||||
->setAttribute('debug', $projectDB->getDebug())
|
||||
->setAttribute('limit', $limit)
|
||||
->setAttribute('offset', $offset)
|
||||
->setAttribute('orderField', $orderField)
|
||||
->setAttribute('orderType', $orderType)
|
||||
->setAttribute('orderCast', $orderCast)
|
||||
->setAttribute('filters', $filters)
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
|
||||
}
|
||||
|
||||
$collection
|
||||
->setAttribute('sum', $projectDB->getSum())
|
||||
->setAttribute('documents', $list)
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@ use Utopia\App;
|
|||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Domain as DomainValidator;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\URL;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Domains\Domain;
|
||||
|
@ -455,7 +455,7 @@ App::post('/v1/projects/:projectId/webhooks')
|
|||
->param('name', null, function () { return new Text(256); }, 'Webhook name.')
|
||||
->param('events', null, function () { return new ArrayList(new Text(256)); }, 'Webhook events list.')
|
||||
->param('url', null, function () { return new Text(2000); }, 'Webhook URL.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.')
|
||||
->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true)
|
||||
->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password.', true)
|
||||
->action(
|
||||
|
@ -466,6 +466,7 @@ App::post('/v1/projects/:projectId/webhooks')
|
|||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
@ -588,8 +589,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
->param('name', null, function () { return new Text(256); }, 'Webhook name.')
|
||||
->param('events', null, function () { return new ArrayList(new Text(256)); }, 'Webhook events list.')
|
||||
->param('url', null, function () { return new Text(2000); }, 'Webhook URL.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true)
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true)
|
||||
->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password.', true)
|
||||
->action(
|
||||
function ($projectId, $webhookId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB) {
|
||||
|
@ -599,6 +599,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
@ -836,8 +837,7 @@ App::post('/v1/projects/:projectId/tasks')
|
|||
->param('name', null, function () { return new Text(256); }, 'Task name.')
|
||||
->param('status', null, function () { return new WhiteList(['play', 'pause']); }, 'Task status.')
|
||||
->param('schedule', null, function () { return new Cron(); }, 'Task schedule CRON syntax.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('httpMethod', '', function () { return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']); }, 'Task HTTP method.')
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.') ->param('httpMethod', '', function () { return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']); }, 'Task HTTP method.')
|
||||
->param('httpUrl', '', function () { return new URL(); }, 'Task HTTP URL')
|
||||
->param('httpHeaders', null, function () { return new ArrayList(new Text(256)); }, 'Task HTTP headers list.', true)
|
||||
->param('httpUser', '', function () { return new Text(256); }, 'Task HTTP user.', true)
|
||||
|
@ -853,6 +853,7 @@ App::post('/v1/projects/:projectId/tasks')
|
|||
$cron = CronExpression::factory($schedule);
|
||||
$next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null;
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
@ -986,7 +987,7 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
|
|||
->param('name', null, function () { return new Text(256); }, 'Task name.')
|
||||
->param('status', null, function () { return new WhiteList(['play', 'pause']); }, 'Task status.')
|
||||
->param('schedule', null, function () { return new Cron(); }, 'Task schedule CRON syntax.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.')
|
||||
->param('httpMethod', '', function () { return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']); }, 'Task HTTP method.')
|
||||
->param('httpUrl', '', function () { return new URL(); }, 'Task HTTP URL.')
|
||||
->param('httpHeaders', null, function () { return new ArrayList(new Text(256)); }, 'Task HTTP headers list.', true)
|
||||
|
@ -1009,6 +1010,7 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
|
|||
$cron = CronExpression::factory($schedule);
|
||||
$next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null;
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
|
|
@ -237,9 +237,8 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
],
|
||||
]);
|
||||
|
||||
$invitee = $projectDB->getCollection([ // Get user by email address
|
||||
$invitee = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -485,9 +484,8 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
}
|
||||
|
||||
if (empty($user->getId())) {
|
||||
$user = $projectDB->getCollection([ // Get user
|
||||
$user = $projectDB->getCollectionFirst([ // Get user
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'$id='.$userId,
|
||||
|
|
|
@ -35,9 +35,8 @@ App::post('/v1/users')
|
|||
->param('name', '', function () { return new Text(100); }, 'User name.', true)
|
||||
->action(
|
||||
function ($email, $password, $name) use ($response, $projectDB) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
|
|
@ -458,6 +458,10 @@ App::get('/open-api-2.json')
|
|||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(fromCamelCase($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
$node['type'] = 'boolean';
|
||||
$node['x-example'] = false;
|
||||
break;
|
||||
case 'Appwrite\Database\Validator\UID':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(fromCamelCase($node['name'])).']';
|
||||
|
|
|
@ -77,7 +77,7 @@ class CertificatesV1
|
|||
}
|
||||
}
|
||||
|
||||
$certificate = $consoleDB->getCollection([
|
||||
$certificate = $consoleDB->getCollectionFirst([
|
||||
'limit' => 1,
|
||||
'offset' => 0,
|
||||
'orderField' => 'id',
|
||||
|
@ -87,7 +87,6 @@ class CertificatesV1
|
|||
'$collection='.Database::SYSTEM_COLLECTION_CERTIFICATES,
|
||||
'domain='.$domain->get(),
|
||||
],
|
||||
'first' => true,
|
||||
]);
|
||||
|
||||
// $condition = ($certificate
|
||||
|
|
|
@ -130,8 +130,6 @@ class Database
|
|||
'orderField' => '$id',
|
||||
'orderType' => 'ASC',
|
||||
'orderCast' => 'int',
|
||||
'first' => false,
|
||||
'last' => false,
|
||||
'filters' => [],
|
||||
], $options);
|
||||
|
||||
|
@ -141,17 +139,31 @@ class Database
|
|||
$node = new Document($node);
|
||||
}
|
||||
|
||||
if ($options['first']) {
|
||||
$results = \reset($results);
|
||||
}
|
||||
|
||||
if ($options['last']) {
|
||||
$results = \end($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function getCollectionFirst(array $options)
|
||||
{
|
||||
$results = $this->getCollection($options);
|
||||
return \reset($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function getCollectionLast(array $options)
|
||||
{
|
||||
$results = $this->getCollection($options);
|
||||
return \end($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param bool $mock is mocked data allowed?
|
||||
|
|
|
@ -317,41 +317,6 @@ trait DatabaseBase
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDocument
|
||||
*/
|
||||
public function testListDocumentsFirstAndLast(array $data):array
|
||||
{
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'limit' => 1,
|
||||
'orderField' => 'releaseYear',
|
||||
'orderType' => 'ASC',
|
||||
'orderCast' => 'int',
|
||||
'first' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(1944, $documents['body']['releaseYear']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'limit' => 2,
|
||||
'offset' => 1,
|
||||
'orderField' => 'releaseYear',
|
||||
'orderType' => 'ASC',
|
||||
'orderCast' => 'int',
|
||||
'last' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(2019, $documents['body']['releaseYear']);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDocument
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue