Merge branch '1.5.x' into feat-check-certificate-validity
@@ -99,3 +99,4 @@ _APP_ASSISTANT_OPENAI_API_KEY=
|
||||
_APP_MESSAGE_SMS_TEST_DSN=
|
||||
_APP_MESSAGE_EMAIL_TEST_DSN=
|
||||
_APP_MESSAGE_PUSH_TEST_DSN=
|
||||
_APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10
|
||||
@@ -344,13 +344,13 @@ Things to remember when releasing SDKs:
|
||||
|
||||
## Debug
|
||||
|
||||
Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code's [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension.
|
||||
Appwrite uses [XDebug](https://github.com/xdebug/xdebug) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code's [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension.
|
||||
|
||||
If you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection:
|
||||
|
||||
1. Create an init file.
|
||||
2. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php**.
|
||||
3. Set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
|
||||
1. Set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
|
||||
2. If needed edit the **dev/xdebug.ini** file to your needs.
|
||||
3. Launch your Appwrite instance while your debugger is listening for connections.
|
||||
|
||||
### VS Code Launch Configuration
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT
|
||||
RUN npm ci
|
||||
RUN npm run build
|
||||
|
||||
FROM appwrite/base:0.4.3 as final
|
||||
FROM appwrite/base:0.7.2 as final
|
||||
|
||||
LABEL maintainer="team@appwrite.io"
|
||||
|
||||
@@ -56,6 +56,7 @@ COPY ./public /usr/src/code/public
|
||||
COPY ./bin /usr/local/bin
|
||||
COPY ./docs /usr/src/code/docs
|
||||
COPY ./src /usr/src/code/src
|
||||
COPY ./dev /usr/src/code/dev
|
||||
|
||||
# Set Volumes
|
||||
RUN mkdir -p /storage/uploads && \
|
||||
@@ -126,9 +127,10 @@ RUN chmod +x /usr/local/bin/calc-tier-stats && \
|
||||
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
|
||||
|
||||
# Enable Extensions
|
||||
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/src/code/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
|
||||
|
||||
RUN if [ "$DEBUG" == "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi
|
||||
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi
|
||||
RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi
|
||||
RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so; fi
|
||||
RUN echo "opcache.preload_user=www-data" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.preload=/usr/src/code/app/preload.php" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/appwrite.ini
|
||||
|
||||
@@ -72,7 +72,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) {
|
||||
$collections = Config::getParam('collections', [])['console'];
|
||||
$last = \array_key_last($collections);
|
||||
|
||||
if (!($dbForConsole->exists($dbForConsole->getDefaultDatabase(), $last))) { /** TODO cache ready variable using registry */
|
||||
if (!($dbForConsole->exists($dbForConsole->getDatabase(), $last))) { /** TODO cache ready variable using registry */
|
||||
throw new Exception('Tables not ready yet.');
|
||||
}
|
||||
|
||||
|
||||
@@ -1573,17 +1573,6 @@ $commonCollections = [
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('description'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 256,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => '',
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('status'),
|
||||
'type' => Database::VAR_STRING,
|
||||
@@ -1744,17 +1733,6 @@ $commonCollections = [
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('description'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 2048,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('total'),
|
||||
'type' => Database::VAR_INTEGER,
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* List of server wide error codes and their respective messages.
|
||||
*/
|
||||
|
||||
use Appwrite\Enum\MessageStatus;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Messaging\Status as MessageStatus;
|
||||
|
||||
return [
|
||||
/** General Errors */
|
||||
|
||||
@@ -8,7 +8,7 @@ use Appwrite\Auth\Validator\Phone;
|
||||
use Appwrite\Detector\Detector;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Mail;
|
||||
use Appwrite\Auth\SecurityPhrase;
|
||||
use Appwrite\Auth\Phrase;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Utopia\Validator\Host;
|
||||
@@ -169,7 +169,8 @@ App::post('/v1/account')
|
||||
]);
|
||||
$user->setAttribute('targets', [...$user->getAttribute('targets', []), $existingTarget]);
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate) {
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
@@ -273,7 +274,7 @@ App::post('/v1/account/sessions/email')
|
||||
$dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [
|
||||
Permission::read(Role::user($user->getId())),
|
||||
@@ -461,8 +462,6 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
->label('abuse-limit', 50)
|
||||
->label('abuse-key', 'ip:{ip}')
|
||||
->label('docs', false)
|
||||
->label('usage.metric', 'sessions.{scope}.requests.create')
|
||||
->label('usage.params', ['provider:{request.provider}'])
|
||||
->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 provider.')
|
||||
->param('code', '', new Text(2048, 0), 'OAuth2 code. This is a temporary code that the will be later exchanged for an access token.', true)
|
||||
->param('state', '', new Text(2048), 'OAuth2 state params.', true)
|
||||
@@ -607,7 +606,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
$currentDocument = $dbForProject->getDocument('sessions', $current);
|
||||
if (!$currentDocument->isEmpty()) {
|
||||
$dbForProject->deleteDocument('sessions', $currentDocument->getId());
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -867,7 +866,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'));
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$state['success']['query'] = URLParser::unparseQuery($query);
|
||||
$state['success'] = URLParser::unparse($state['success']);
|
||||
@@ -885,7 +884,6 @@ App::get('/v1/account/identities')
|
||||
->desc('List Identities')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'accounts.read')
|
||||
->label('usage.metric', 'users.{scope}.requests.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'listIdentities')
|
||||
@@ -906,7 +904,7 @@ App::get('/v1/account/identities')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -989,7 +987,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the magic URL login. 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.', true, ['clients'])
|
||||
->param('securityPhrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of authentication flow.', true)
|
||||
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
@@ -998,14 +996,14 @@ App::post('/v1/account/tokens/magic-url')
|
||||
->inject('locale')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->action(function (string $userId, string $email, string $url, bool $securityPhrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
|
||||
->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
|
||||
|
||||
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
|
||||
}
|
||||
|
||||
if ($securityPhrase === true) {
|
||||
$securityPhrase = SecurityPhrase::generate();
|
||||
if ($phrase === true) {
|
||||
$phrase = Phrase::generate();
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
@@ -1087,7 +1085,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
if (empty($url)) {
|
||||
$url = $request->getProtocol() . '://' . $request->getHostname() . '/auth/magic-url';
|
||||
@@ -1115,7 +1113,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
->setParam('{{thanks}}', $locale->getText("emails.magicSession.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.magicSession.signature"));
|
||||
|
||||
if (!empty($securityPhrase)) {
|
||||
if (!empty($phrase)) {
|
||||
$message->setParam('{{securityPhrase}}', $locale->getText("emails.magicSession.securityPhrase"));
|
||||
} else {
|
||||
$message->setParam('{{securityPhrase}}', '');
|
||||
@@ -1179,7 +1177,7 @@ App::post('/v1/account/tokens/magic-url')
|
||||
'agentDevice' => '<strong>' . ( $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN') . '</strong>',
|
||||
'agentClient' => '<strong>' . ($agentClient['clientName'] ?? 'UNKNOWN') . '</strong>',
|
||||
'agentOs' => '<strong>' . ($agentOs['osName'] ?? 'UNKNOWN') . '</strong>',
|
||||
'phrase' => '<strong>' . (!empty($securityPhrase) ? $securityPhrase : '') . '</strong>'
|
||||
'phrase' => '<strong>' . (!empty($phrase) ? $phrase : '') . '</strong>'
|
||||
];
|
||||
|
||||
$queueForMails
|
||||
@@ -1199,8 +1197,8 @@ App::post('/v1/account/tokens/magic-url')
|
||||
// Hide secret for clients
|
||||
$token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : '');
|
||||
|
||||
if (!empty($securityPhrase)) {
|
||||
$token->setAttribute('securityPhrase', $securityPhrase);
|
||||
if (!empty($phrase)) {
|
||||
$token->setAttribute('phrase', $phrase);
|
||||
}
|
||||
|
||||
$response
|
||||
@@ -1228,7 +1226,7 @@ App::post('/v1/account/tokens/email')
|
||||
->label('abuse-key', 'url:{url},email:{param-email}')
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('email', '', new Email(), 'User email.')
|
||||
->param('securityPhrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of authentication flow.', true)
|
||||
->param('phrase', false, new Boolean(), 'Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.', true)
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
@@ -1237,13 +1235,13 @@ App::post('/v1/account/tokens/email')
|
||||
->inject('locale')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->action(function (string $userId, string $email, bool $securityPhrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
|
||||
->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
|
||||
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
|
||||
}
|
||||
|
||||
if ($securityPhrase === true) {
|
||||
$securityPhrase = SecurityPhrase::generate();
|
||||
if ($phrase === true) {
|
||||
$phrase = Phrase::generate();
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
@@ -1325,7 +1323,7 @@ App::post('/v1/account/tokens/email')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$subject = $locale->getText("emails.otpSession.subject");
|
||||
$customTemplate = $project->getAttribute('templates', [])['email.otpSession-' . $locale->default] ?? [];
|
||||
@@ -1343,7 +1341,7 @@ App::post('/v1/account/tokens/email')
|
||||
->setParam('{{thanks}}', $locale->getText("emails.otpSession.thanks"))
|
||||
->setParam('{{signature}}', $locale->getText("emails.otpSession.signature"));
|
||||
|
||||
if (!empty($securityPhrase)) {
|
||||
if (!empty($phrase)) {
|
||||
$message->setParam('{{securityPhrase}}', $locale->getText("emails.otpSession.securityPhrase"));
|
||||
} else {
|
||||
$message->setParam('{{securityPhrase}}', '');
|
||||
@@ -1407,7 +1405,7 @@ App::post('/v1/account/tokens/email')
|
||||
'agentDevice' => '<strong>' . ( $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN') . '</strong>',
|
||||
'agentClient' => '<strong>' . ($agentClient['clientName'] ?? 'UNKNOWN') . '</strong>',
|
||||
'agentOs' => '<strong>' . ($agentOs['osName'] ?? 'UNKNOWN') . '</strong>',
|
||||
'phrase' => '<strong>' . (!empty($securityPhrase) ? $securityPhrase : '') . '</strong>'
|
||||
'phrase' => '<strong>' . (!empty($phrase) ? $phrase : '') . '</strong>'
|
||||
];
|
||||
|
||||
$queueForMails
|
||||
@@ -1427,8 +1425,8 @@ App::post('/v1/account/tokens/email')
|
||||
// Hide secret for clients
|
||||
$token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : '');
|
||||
|
||||
if (!empty($securityPhrase)) {
|
||||
$token->setAttribute('securityPhrase', $securityPhrase);
|
||||
if (!empty($phrase)) {
|
||||
$token->setAttribute('phrase', $phrase);
|
||||
}
|
||||
|
||||
$response
|
||||
@@ -1488,9 +1486,9 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId()));
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
if ($verifiedToken->getAttribute('type') === Auth::TOKEN_TYPE_MAGIC_URL) {
|
||||
$user->setAttribute('emailVerification', true);
|
||||
@@ -1543,7 +1541,6 @@ App::put('/v1/account/sessions/magic-url')
|
||||
->label('audits.event', 'session.create')
|
||||
->label('audits.resource', 'user/{response.userId}')
|
||||
->label('audits.userId', '{response.userId}')
|
||||
->label('usage.metric', 'sessions.{scope}.requests.create')
|
||||
->label('sdk.auth', [])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', ['updateMagicURLSession', 'updatePhoneSession'])
|
||||
@@ -1573,7 +1570,6 @@ App::post('/v1/account/sessions/token')
|
||||
->label('audits.event', 'session.create')
|
||||
->label('audits.resource', 'user/{response.userId}')
|
||||
->label('audits.userId', '{response.userId}')
|
||||
->label('usage.metric', 'sessions.{scope}.requests.create')
|
||||
->label('sdk.auth', [])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'createSession')
|
||||
@@ -1687,7 +1683,7 @@ App::post('/v1/account/tokens/phone')
|
||||
]);
|
||||
$user->setAttribute('targets', [...$user->getAttribute('targets', []), $existingTarget]);
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
}
|
||||
|
||||
$secret = Auth::codeGenerator();
|
||||
@@ -1713,7 +1709,7 @@ App::post('/v1/account/tokens/phone')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl');
|
||||
|
||||
@@ -1870,7 +1866,7 @@ App::post('/v1/account/sessions/anonymous')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -2006,7 +2002,7 @@ App::post('/v1/account/targets/push')
|
||||
} catch (Duplicate) {
|
||||
throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS);
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -2021,7 +2017,6 @@ App::get('/v1/account')
|
||||
->desc('Get account')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'accounts.read')
|
||||
->label('usage.metric', 'users.{scope}.requests.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'get')
|
||||
@@ -2034,6 +2029,9 @@ App::get('/v1/account')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->action(function (Response $response, Document $user) {
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($user, Response::MODEL_ACCOUNT);
|
||||
});
|
||||
@@ -2042,7 +2040,6 @@ App::get('/v1/account/prefs')
|
||||
->desc('Get account preferences')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'accounts.read')
|
||||
->label('usage.metric', 'users.{scope}.requests.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'getPrefs')
|
||||
@@ -2065,7 +2062,6 @@ App::get('/v1/account/sessions')
|
||||
->desc('List sessions')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'accounts.read')
|
||||
->label('usage.metric', 'users.{scope}.requests.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'listSessions')
|
||||
@@ -2101,7 +2097,6 @@ App::get('/v1/account/logs')
|
||||
->desc('List logs')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'accounts.read')
|
||||
->label('usage.metric', 'users.{scope}.requests.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'listLogs')
|
||||
@@ -2162,7 +2157,6 @@ App::get('/v1/account/sessions/:sessionId')
|
||||
->desc('Get session')
|
||||
->groups(['api', 'account'])
|
||||
->label('scope', 'accounts.read')
|
||||
->label('usage.metric', 'users.{scope}.requests.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'getSession')
|
||||
@@ -2385,7 +2379,7 @@ App::patch('/v1/account/email')
|
||||
if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email)));
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate) {
|
||||
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
}
|
||||
@@ -2466,7 +2460,7 @@ App::patch('/v1/account/phone')
|
||||
if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) {
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone)));
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception(Exception::USER_PHONE_ALREADY_EXISTS);
|
||||
}
|
||||
@@ -2612,7 +2606,7 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||
;
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -2691,7 +2685,7 @@ App::patch('/v1/account/sessions/:sessionId')
|
||||
|
||||
// Save changes
|
||||
$dbForProject->updateDocument('sessions', $sessionId, $session);
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -2752,7 +2746,7 @@ App::delete('/v1/account/sessions')
|
||||
}
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -2837,7 +2831,7 @@ App::post('/v1/account/recovery')
|
||||
Permission::delete(Role::user($profile->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $profile->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $profile->getId());
|
||||
|
||||
$url = Template::parseURL($url);
|
||||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $profile->getId(), 'secret' => $secret, 'expire' => $expire]);
|
||||
@@ -3013,7 +3007,7 @@ App::put('/v1/account/recovery')
|
||||
* the recovery token but actually we don't need it anymore.
|
||||
*/
|
||||
$dbForProject->deleteDocument('tokens', $verifiedToken->getId());
|
||||
$dbForProject->deleteCachedDocument('users', $profile->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $profile->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $profile->getId())
|
||||
@@ -3084,7 +3078,7 @@ App::post('/v1/account/verification')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$url = Template::parseURL($url);
|
||||
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $verificationSecret, 'expire' => $expire]);
|
||||
@@ -3233,7 +3227,7 @@ App::put('/v1/account/verification')
|
||||
* the verification token but actually we don't need it anymore.
|
||||
*/
|
||||
$dbForProject->deleteDocument('tokens', $verifiedToken->getId());
|
||||
$dbForProject->deleteCachedDocument('users', $profile->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $profile->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $userId)
|
||||
@@ -3306,7 +3300,7 @@ App::post('/v1/account/verification/phone')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl');
|
||||
|
||||
@@ -3402,7 +3396,7 @@ App::put('/v1/account/verification/phone')
|
||||
* We act like we're updating and validating the verification token but actually we don't need it anymore.
|
||||
*/
|
||||
$dbForProject->deleteDocument('tokens', $verifiedToken->getId());
|
||||
$dbForProject->deleteCachedDocument('users', $profile->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $profile->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -3459,7 +3453,7 @@ App::put('/v1/account/targets/:targetId/push')
|
||||
$target->setAttribute('name', "{$device['deviceBrand']} {$device['deviceModel']}");
|
||||
|
||||
$target = $dbForProject->updateDocument('targets', $target->getId(), $target);
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -3476,7 +3470,6 @@ App::delete('/v1/account')
|
||||
->label('scope', 'accounts.write')
|
||||
->label('audits.event', 'user.delete')
|
||||
->label('audits.resource', 'user/{response.$id}')
|
||||
->label('usage.metric', 'users.{scope}.requests.delete')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'account')
|
||||
->label('sdk.method', 'delete')
|
||||
|
||||
@@ -116,7 +116,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro
|
||||
|
||||
Authorization::skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Throwable $err) {
|
||||
$index = 0;
|
||||
do {
|
||||
@@ -521,7 +521,7 @@ App::get('/v1/avatars/initials')
|
||||
// if there is no space, try to split by `_` underscore
|
||||
$words = (count($words) == 1) ? \explode('_', \strtoupper($name)) : $words;
|
||||
|
||||
$initials = null;
|
||||
$initials = '';
|
||||
$code = 0;
|
||||
|
||||
foreach ($words as $key => $w) {
|
||||
|
||||
@@ -28,7 +28,6 @@ use Utopia\Database\Exception\Limit as LimitException;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Exception\Restricted as RestrictedException;
|
||||
use Utopia\Database\Exception\Structure as StructureException;
|
||||
use Utopia\Database\Exception\Timeout as TimeoutException;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
@@ -153,13 +152,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
|
||||
} catch (LimitException) {
|
||||
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded');
|
||||
} catch (\Exception $e) {
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
||||
if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) {
|
||||
$twoWayKey = $options['twoWayKey'];
|
||||
@@ -197,13 +196,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
|
||||
$dbForProject->deleteDocument('attributes', $attribute->getId());
|
||||
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded');
|
||||
} catch (\Exception $e) {
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
}
|
||||
|
||||
$queueForDatabase
|
||||
@@ -358,7 +357,7 @@ function updateAttribute(
|
||||
$relatedOptions = \array_merge($relatedAttribute->getAttribute('options'), $options);
|
||||
$relatedAttribute->setAttribute('options', $relatedOptions);
|
||||
$dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute);
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
}
|
||||
} else {
|
||||
$dbForProject->updateAttribute(
|
||||
@@ -371,7 +370,7 @@ function updateAttribute(
|
||||
}
|
||||
|
||||
$attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute);
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collection->getId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collection->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setContext('collection', $collection)
|
||||
@@ -496,7 +495,7 @@ App::get('/v1/databases')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -703,8 +702,8 @@ App::delete('/v1/databases/:databaseId')
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('databases', $database->getId());
|
||||
$dbForProject->deleteCachedCollection('databases_' . $database->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('databases', $database->getId());
|
||||
$dbForProject->purgeCachedCollection('databases_' . $database->getInternalId());
|
||||
|
||||
$queueForDatabase
|
||||
->setType(DATABASE_TYPE_DELETE_DATABASE)
|
||||
@@ -818,7 +817,7 @@ App::get('/v1/databases/:databaseId/collections')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -901,6 +900,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId());
|
||||
|
||||
@@ -1076,7 +1076,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
||||
$queueForDatabase
|
||||
->setType(DATABASE_TYPE_DELETE_COLLECTION)
|
||||
@@ -1672,7 +1672,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
|
||||
$cursor = \reset($cursor);
|
||||
@@ -2248,8 +2248,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
|
||||
$attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting'));
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
||||
if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) {
|
||||
$options = $attribute->getAttribute('options');
|
||||
@@ -2270,8 +2270,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
|
||||
$dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting'));
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']);
|
||||
$dbForProject->deleteCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']);
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2330,7 +2330,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
||||
->param('databaseId', '', new UID(), 'Database ID.')
|
||||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
|
||||
->param('key', null, new Key(), 'Index Key.')
|
||||
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL, Database::INDEX_ARRAY]), 'Index type.')
|
||||
->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE, Database::INDEX_SPATIAL]), 'Index type.')
|
||||
->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.')
|
||||
->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true)
|
||||
->inject('response')
|
||||
@@ -2453,7 +2453,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
||||
throw new Exception(Exception::INDEX_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
||||
$queueForDatabase
|
||||
->setType(DATABASE_TYPE_CREATE_INDEX)
|
||||
@@ -2509,7 +2509,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
|
||||
@@ -2620,7 +2620,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
|
||||
$index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting'));
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
||||
$queueForDatabase
|
||||
->setType(DATABASE_TYPE_DELETE_INDEX)
|
||||
@@ -2893,13 +2893,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
||||
->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents')
|
||||
->param('databaseId', '', new UID(), 'Database ID.')
|
||||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
|
||||
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
|
||||
->param('queries', [], new JSON(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) {
|
||||
$queries = Query::parseQueries($queries);
|
||||
$database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
||||
@@ -2913,11 +2913,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$queries = Query::parseQueries($queries);
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
|
||||
$cursor = \reset($cursor);
|
||||
@@ -2934,11 +2932,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
||||
$cursor->setValue($cursorDocument);
|
||||
}
|
||||
|
||||
$filters = Query::groupByType($queries)['filters'];
|
||||
|
||||
try {
|
||||
$documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries);
|
||||
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filters, APP_LIMIT_COUNT);
|
||||
$total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT);
|
||||
} catch (AuthorizationException) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (QueryException $e) {
|
||||
@@ -3020,7 +3017,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
||||
->param('databaseId', '', new UID(), 'Database ID.')
|
||||
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
|
||||
->param('documentId', '', new UID(), 'Document ID.')
|
||||
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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 method allowed is select.', true)
|
||||
->param('queries', [], new JSON(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
|
||||
@@ -374,7 +374,7 @@ App::get('/v1/functions')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -1268,7 +1268,7 @@ App::get('/v1/functions/:functionId/deployments')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -1805,7 +1805,7 @@ App::get('/v1/functions/:functionId/executions')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
use Appwrite\Auth\Validator\Phone;
|
||||
use Appwrite\Detector\Detector;
|
||||
use Appwrite\Enum\MessageStatus;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Event\Messaging;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Messaging\Status as MessageStatus;
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use Appwrite\Permission;
|
||||
use Appwrite\Role;
|
||||
@@ -35,6 +35,7 @@ use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Validator\JSON;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Text;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\Database\DateTime;
|
||||
@@ -61,30 +62,20 @@ App::post('/v1/messaging/providers/mailgun')
|
||||
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
||||
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
||||
->param('isEuRegion', null, new Boolean(), 'Set as EU region.', true)
|
||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||
->param('fromName', '', new Text(128, 0), 'Sender Name.', true)
|
||||
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||
->param('replyToName', '', new Text(128, 0), 'Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.', true)
|
||||
->param('replyToEmail', '', new Email(), 'Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.', true)
|
||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $providerId, string $name, string $apiKey, string $domain, ?bool $isEuRegion, ?bool $enabled, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
->action(function (string $providerId, string $name, string $apiKey, string $domain, ?bool $isEuRegion, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
||||
|
||||
$options = [
|
||||
'fromName' => $fromName,
|
||||
'fromEmail' => $fromEmail,
|
||||
];
|
||||
|
||||
if (!empty($replyToName) && !empty($replyToEmail)) {
|
||||
$options['replyToName'] = $replyToName;
|
||||
$options['replyToEmail'] = $replyToEmail;
|
||||
}
|
||||
|
||||
$credentials = [];
|
||||
|
||||
if ($isEuRegion === true || $isEuRegion === false) {
|
||||
if (!\is_null($isEuRegion)) {
|
||||
$credentials['isEuRegion'] = $isEuRegion;
|
||||
}
|
||||
|
||||
@@ -96,12 +87,19 @@ App::post('/v1/messaging/providers/mailgun')
|
||||
$credentials['domain'] = $domain;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'fromName' => $fromName,
|
||||
'fromEmail' => $fromEmail,
|
||||
'replyToName' => $replyToName,
|
||||
'replyToEmail' => $replyToEmail,
|
||||
];
|
||||
|
||||
if (
|
||||
$enabled === true &&
|
||||
\array_key_exists('isEuRegion', $credentials) &&
|
||||
\array_key_exists('apiKey', $credentials) &&
|
||||
\array_key_exists('domain', $credentials) &&
|
||||
\array_key_exists('fromEmail', $options)
|
||||
$enabled === true
|
||||
&& !empty($fromEmail)
|
||||
&& \array_key_exists('isEuRegion', $credentials)
|
||||
&& \array_key_exists('apiKey', $credentials)
|
||||
&& \array_key_exists('domain', $credentials)
|
||||
) {
|
||||
$enabled = true;
|
||||
} else {
|
||||
@@ -149,37 +147,34 @@ App::post('/v1/messaging/providers/sendgrid')
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||
->param('fromName', '', new Text(128, 0), 'Sender Name.', true)
|
||||
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||
->param('replyToName', '', new Text(128, 0), 'Name set in the reply to field for the mail. Default value is sender name.', true)
|
||||
->param('replyToEmail', '', new Email(), 'Email set in the reply to field for the mail. Default value is sender email.', true)
|
||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $providerId, string $name, string $apiKey, ?bool $enabled, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
->action(function (string $providerId, string $name, string $apiKey, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
||||
|
||||
$options = [
|
||||
'fromName' => $fromName,
|
||||
'fromEmail' => $fromEmail,
|
||||
];
|
||||
|
||||
if (!empty($replyToName) && !empty($replyToEmail)) {
|
||||
$options['replyToName'] = $replyToName;
|
||||
$options['replyToEmail'] = $replyToEmail;
|
||||
}
|
||||
|
||||
$credentials = [];
|
||||
|
||||
if (!empty($apiKey)) {
|
||||
$credentials['apiKey'] = $apiKey;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'fromName' => $fromName,
|
||||
'fromEmail' => $fromEmail,
|
||||
'replyToName' => $replyToName,
|
||||
'replyToEmail' => $replyToEmail,
|
||||
];
|
||||
|
||||
if (
|
||||
$enabled === true
|
||||
&& !empty($fromEmail)
|
||||
&& \array_key_exists('apiKey', $credentials)
|
||||
&& \array_key_exists('fromEmail', $options)
|
||||
) {
|
||||
$enabled = true;
|
||||
} else {
|
||||
@@ -210,6 +205,94 @@ App::post('/v1/messaging/providers/sendgrid')
|
||||
->dynamic($provider, Response::MODEL_PROVIDER);
|
||||
});
|
||||
|
||||
App::post('/v1/messaging/providers/smtp')
|
||||
->desc('Create SMTP provider')
|
||||
->groups(['api', 'messaging'])
|
||||
->label('audits.event', 'provider.create')
|
||||
->label('audits.resource', 'provider/{response.$id}')
|
||||
->label('event', 'providers.[providerId].create')
|
||||
->label('scope', 'providers.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'messaging')
|
||||
->label('sdk.method', 'createSMTPProvider')
|
||||
->label('sdk.description', '/docs/references/messaging/create-smtp-provider.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
||||
->param('providerId', '', new CustomId(), 'Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->param('name', '', new Text(128), 'Provider name.')
|
||||
->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host by using this format: [hostname:port] (e.g. "smtp1.example.com:25;smtp2.example.com"). You can also specify encryption type, for example: (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). Hosts will be tried in order.')
|
||||
->param('port', 587, new Range(1, 65535), 'The default SMTP server port.', true)
|
||||
->param('username', '', new Text(0), 'Authentication username.', true)
|
||||
->param('password', '', new Text(0), 'Authentication password.', true)
|
||||
->param('encryption', '', new WhiteList(['none', 'ssl', 'tls']), 'Encryption type. Can be omitted, \'ssl\', or \'tls\'', true)
|
||||
->param('autoTLS', true, new Boolean(), 'Enable SMTP AutoTLS feature.', true)
|
||||
->param('mailer', '', new Text(0), 'The value to use for the X-Mailer header.', true)
|
||||
->param('fromName', '', new Text(128, 0), 'Sender Name.', true)
|
||||
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||
->param('replyToName', '', new Text(128, 0), 'Name set in the reply to field for the mail. Default value is sender name.', true)
|
||||
->param('replyToEmail', '', new Email(), 'Email set in the reply to field for the mail. Default value is sender email.', true)
|
||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $providerId, string $name, string $host, int $port, string $username, string $password, string $encryption, bool $autoTLS, string $mailer, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
||||
|
||||
$credentials = [
|
||||
'port' => $port,
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
];
|
||||
|
||||
if (!empty($host)) {
|
||||
$credentials['host'] = $host;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'fromName' => $fromName,
|
||||
'fromEmail' => $fromEmail,
|
||||
'replyToName' => $replyToName,
|
||||
'replyToEmail' => $replyToEmail,
|
||||
'encryption' => $encryption === 'none' ? '' : $encryption,
|
||||
'autoTLS' => $autoTLS,
|
||||
'mailer' => $mailer,
|
||||
];
|
||||
|
||||
if (
|
||||
$enabled === true
|
||||
&& !empty($fromEmail)
|
||||
&& \array_key_exists('host', $credentials)
|
||||
) {
|
||||
$enabled = true;
|
||||
} else {
|
||||
$enabled = false;
|
||||
}
|
||||
|
||||
$provider = new Document([
|
||||
'$id' => $providerId,
|
||||
'name' => $name,
|
||||
'provider' => 'smtp',
|
||||
'type' => MESSAGE_TYPE_EMAIL,
|
||||
'enabled' => $enabled,
|
||||
'credentials' => $credentials,
|
||||
'options' => $options,
|
||||
]);
|
||||
|
||||
try {
|
||||
$provider = $dbForProject->createDocument('providers', $provider);
|
||||
} catch (DuplicateException) {
|
||||
throw new Exception(Exception::PROVIDER_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$queueForEvents
|
||||
->setParam('providerId', $provider->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($provider, Response::MODEL_PROVIDER);
|
||||
});
|
||||
|
||||
App::post('/v1/messaging/providers/msg91')
|
||||
->desc('Create Msg91 provider')
|
||||
->groups(['api', 'messaging'])
|
||||
@@ -761,7 +844,7 @@ App::get('/v1/messaging/providers')
|
||||
}
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
@@ -1085,6 +1168,125 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId')
|
||||
->dynamic($provider, Response::MODEL_PROVIDER);
|
||||
});
|
||||
|
||||
App::patch('/v1/messaging/providers/smtp/:providerId')
|
||||
->desc('Update SMTP provider')
|
||||
->groups(['api', 'messaging'])
|
||||
->label('audits.event', 'provider.update')
|
||||
->label('audits.resource', 'provider/{response.$id}')
|
||||
->label('event', 'providers.[providerId].update')
|
||||
->label('scope', 'providers.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'messaging')
|
||||
->label('sdk.method', 'updateSMTPProvider')
|
||||
->label('sdk.description', '/docs/references/messaging/update-smtp-provider.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
||||
->param('providerId', '', new UID(), 'Provider ID.')
|
||||
->param('name', '', new Text(128), 'Provider name.', true)
|
||||
->param('host', '', new Text(0), 'SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host by using this format: [hostname:port] (e.g. "smtp1.example.com:25;smtp2.example.com"). You can also specify encryption type, for example: (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). Hosts will be tried in order.', true)
|
||||
->param('port', null, new Range(1, 65535), 'SMTP port.', true)
|
||||
->param('username', '', new Text(0), 'Authentication username.', true)
|
||||
->param('password', '', new Text(0), 'Authentication password.', true)
|
||||
->param('encryption', '', new WhiteList(['none', 'ssl', 'tls']), 'Encryption type. Can be \'ssl\' or \'tls\'', true)
|
||||
->param('autoTLS', null, new Boolean(), 'Enable SMTP AutoTLS feature.', true)
|
||||
->param('fromName', '', new Text(128), 'Sender Name.', true)
|
||||
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||
->param('replyToName', '', new Text(128), 'Name set in the Reply To field for the mail. Default value is Sender Name.', true)
|
||||
->param('replyToEmail', '', new Text(128), 'Email set in the Reply To field for the mail. Default value is Sender Email.', true)
|
||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $providerId, string $name, string $host, ?int $port, string $username, string $password, string $encryption, ?bool $autoTLS, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$provider = $dbForProject->getDocument('providers', $providerId);
|
||||
|
||||
if ($provider->isEmpty()) {
|
||||
throw new Exception(Exception::PROVIDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$providerAttr = $provider->getAttribute('provider');
|
||||
|
||||
if ($providerAttr !== 'smtp') {
|
||||
throw new Exception(Exception::PROVIDER_INCORRECT_TYPE);
|
||||
}
|
||||
|
||||
if (!empty($name)) {
|
||||
$provider->setAttribute('name', $name);
|
||||
}
|
||||
|
||||
$options = $provider->getAttribute('options');
|
||||
|
||||
if (!empty($fromName)) {
|
||||
$options['fromName'] = $fromName;
|
||||
}
|
||||
|
||||
if (!empty($fromEmail)) {
|
||||
$options['fromEmail'] = $fromEmail;
|
||||
}
|
||||
|
||||
if (!empty($replyToName)) {
|
||||
$options['replyToName'] = $replyToName;
|
||||
}
|
||||
|
||||
if (!empty($replyToEmail)) {
|
||||
$options['replyToEmail'] = $replyToEmail;
|
||||
}
|
||||
|
||||
$provider->setAttribute('options', $options);
|
||||
|
||||
$credentials = $provider->getAttribute('credentials');
|
||||
|
||||
if (!empty($host)) {
|
||||
$credentials['host'] = $host;
|
||||
}
|
||||
|
||||
if (!\is_null($port)) {
|
||||
$credentials['port'] = $port;
|
||||
}
|
||||
|
||||
if (!empty($username)) {
|
||||
$credentials['username'] = $username;
|
||||
}
|
||||
|
||||
if (!empty($password)) {
|
||||
$credentials['password'] = $password;
|
||||
}
|
||||
|
||||
if (!empty($encryption)) {
|
||||
$credentials['encryption'] = $encryption === 'none' ? '' : $encryption;
|
||||
}
|
||||
|
||||
if (!\is_null($autoTLS)) {
|
||||
$credentials['autoTLS'] = $autoTLS;
|
||||
}
|
||||
|
||||
$provider->setAttribute('credentials', $credentials);
|
||||
|
||||
if (!\is_null($enabled)) {
|
||||
if ($enabled) {
|
||||
if (
|
||||
!empty($options['fromEmail'])
|
||||
&& \array_key_exists('host', $credentials)
|
||||
) {
|
||||
$provider->setAttribute('enabled', true);
|
||||
} else {
|
||||
throw new Exception(Exception::PROVIDER_MISSING_CREDENTIALS);
|
||||
}
|
||||
} else {
|
||||
$provider->setAttribute('enabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
$provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider);
|
||||
|
||||
$queueForEvents
|
||||
->setParam('providerId', $provider->getId());
|
||||
|
||||
$response
|
||||
->dynamic($provider, Response::MODEL_PROVIDER);
|
||||
});
|
||||
|
||||
App::patch('/v1/messaging/providers/msg91/:providerId')
|
||||
->desc('Update Msg91 provider')
|
||||
->groups(['api', 'messaging'])
|
||||
@@ -1701,17 +1903,15 @@ App::post('/v1/messaging/topics')
|
||||
->label('sdk.response.model', Response::MODEL_TOPIC)
|
||||
->param('topicId', '', new CustomId(), 'Topic ID. Choose a custom Topic ID or a new Topic ID.')
|
||||
->param('name', '', new Text(128), 'Topic Name.')
|
||||
->param('description', '', new Text(2048), 'Topic Description.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $topicId, string $name, string $description, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
->action(function (string $topicId, string $name, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$topicId = $topicId == 'unique()' ? ID::unique() : $topicId;
|
||||
|
||||
$topic = new Document([
|
||||
'$id' => $topicId,
|
||||
'name' => $name,
|
||||
'description' => $description
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -1751,7 +1951,7 @@ App::get('/v1/messaging/topics')
|
||||
}
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
@@ -1898,11 +2098,10 @@ App::patch('/v1/messaging/topics/:topicId')
|
||||
->label('sdk.response.model', Response::MODEL_TOPIC)
|
||||
->param('topicId', '', new UID(), 'Topic ID.')
|
||||
->param('name', '', new Text(128), 'Topic Name.', true)
|
||||
->param('description', '', new Text(2048), 'Topic Description.', true)
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForProject')
|
||||
->inject('response')
|
||||
->action(function (string $topicId, string $name, string $description, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
->action(function (string $topicId, string $name, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||
$topic = $dbForProject->getDocument('topics', $topicId);
|
||||
|
||||
if ($topic->isEmpty()) {
|
||||
@@ -1913,10 +2112,6 @@ App::patch('/v1/messaging/topics/:topicId')
|
||||
$topic->setAttribute('name', $name);
|
||||
}
|
||||
|
||||
if (!empty($description)) {
|
||||
$topic->setAttribute('description', $description);
|
||||
}
|
||||
|
||||
$topic = $dbForProject->updateDocument('topics', $topicId, $topic);
|
||||
|
||||
$queueForEvents
|
||||
@@ -2078,7 +2273,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
|
||||
\array_push($queries, Query::equal('topicInternalId', [$topic->getInternalId()]));
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
@@ -2301,7 +2496,6 @@ App::post('/v1/messaging/messages/email')
|
||||
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('cc', [], new ArrayList(new UID()), 'Array of target IDs to be added as CC.', true)
|
||||
->param('bcc', [], new ArrayList(new UID()), 'Array of target IDs to be added as BCC.', true)
|
||||
->param('description', '', new Text(256), 'Description for message.', true)
|
||||
->param('status', MessageStatus::DRAFT, new WhiteList([MessageStatus::DRAFT, MessageStatus::SCHEDULED, MessageStatus::PROCESSING]), 'Message Status. Value must be one of: ' . implode(', ', [MessageStatus::DRAFT, MessageStatus::SCHEDULED, MessageStatus::PROCESSING]) . '.', true)
|
||||
->param('html', false, new Boolean(), 'Is content of type HTML', true)
|
||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
@@ -2311,7 +2505,7 @@ App::post('/v1/messaging/messages/email')
|
||||
->inject('project')
|
||||
->inject('queueForMessaging')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, string $description, string $status, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, string $status, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
$messageId = $messageId == 'unique()'
|
||||
? ID::unique()
|
||||
: $messageId;
|
||||
@@ -2350,7 +2544,6 @@ App::post('/v1/messaging/messages/email')
|
||||
'topics' => $topics,
|
||||
'users' => $users,
|
||||
'targets' => $targets,
|
||||
'description' => $description,
|
||||
'scheduledAt' => $scheduledAt,
|
||||
'data' => [
|
||||
'subject' => $subject,
|
||||
@@ -2420,7 +2613,6 @@ App::post('/v1/messaging/messages/sms')
|
||||
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
||||
->param('status', MessageStatus::DRAFT, new WhiteList([MessageStatus::DRAFT, MessageStatus::SCHEDULED, MessageStatus::PROCESSING]), 'Message Status. Value must be one of: ' . implode(', ', [MessageStatus::DRAFT, MessageStatus::SCHEDULED, MessageStatus::PROCESSING]) . '.', true)
|
||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
->inject('queueForEvents')
|
||||
@@ -2429,7 +2621,7 @@ App::post('/v1/messaging/messages/sms')
|
||||
->inject('project')
|
||||
->inject('queueForMessaging')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, string $content, array $topics, array $users, array $targets, string $description, string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
->action(function (string $messageId, string $content, array $topics, array $users, array $targets, string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
$messageId = $messageId == 'unique()'
|
||||
? ID::unique()
|
||||
: $messageId;
|
||||
@@ -2466,7 +2658,6 @@ App::post('/v1/messaging/messages/sms')
|
||||
'topics' => $topics,
|
||||
'users' => $users,
|
||||
'targets' => $targets,
|
||||
'description' => $description,
|
||||
'data' => [
|
||||
'content' => $content,
|
||||
],
|
||||
@@ -2532,7 +2723,6 @@ App::post('/v1/messaging/messages/push')
|
||||
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
||||
->param('data', null, new JSON(), 'Additional Data for push notification.', true)
|
||||
->param('action', '', new Text(256), 'Action for push notification.', true)
|
||||
->param('icon', '', new Text(256), 'Icon for push notification. Available only for Android and Web Platform.', true)
|
||||
@@ -2548,7 +2738,7 @@ App::post('/v1/messaging/messages/push')
|
||||
->inject('project')
|
||||
->inject('queueForMessaging')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, string $description, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
$messageId = $messageId == 'unique()'
|
||||
? ID::unique()
|
||||
: $messageId;
|
||||
@@ -2595,7 +2785,6 @@ App::post('/v1/messaging/messages/push')
|
||||
'topics' => $topics,
|
||||
'users' => $users,
|
||||
'targets' => $targets,
|
||||
'description' => $description,
|
||||
'scheduledAt' => $scheduledAt,
|
||||
'data' => $pushData,
|
||||
'status' => $status,
|
||||
@@ -2663,7 +2852,7 @@ App::get('/v1/messaging/messages')
|
||||
}
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
@@ -2806,7 +2995,7 @@ App::get('/v1/messaging/messages/:messageId/targets')
|
||||
$queries[] = Query::equal('$id', $targetIDs);
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
@@ -2869,7 +3058,6 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||
->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', null, new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('subject', null, new Text(998), 'Email Subject.', true)
|
||||
->param('description', null, new Text(256), 'Description for Message.', true)
|
||||
->param('content', null, new Text(64230), 'Email Content.', true)
|
||||
->param('status', MessageStatus::DRAFT, new WhiteList([MessageStatus::DRAFT, MessageStatus::SCHEDULED, MessageStatus::PROCESSING]), 'Message Status. Value must be one of: ' . implode(', ', [MessageStatus::DRAFT, MessageStatus::SCHEDULED, MessageStatus::PROCESSING]) . '.', true)
|
||||
->param('html', null, new Boolean(), 'Is content of type HTML', true)
|
||||
@@ -2882,7 +3070,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||
->inject('project')
|
||||
->inject('queueForMessaging')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $subject, ?string $description, ?string $content, ?string $status, ?bool $html, ?array $cc, ?array $bcc, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $subject, ?string $content, ?string $status, ?bool $html, ?array $cc, ?array $bcc, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
$message = $dbForProject->getDocument('messages', $messageId);
|
||||
|
||||
if ($message->isEmpty()) {
|
||||
@@ -2933,10 +3121,6 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||
|
||||
$message->setAttribute('data', $data);
|
||||
|
||||
if (!\is_null($description)) {
|
||||
$message->setAttribute('description', $description);
|
||||
}
|
||||
|
||||
if (!\is_null($status)) {
|
||||
$message->setAttribute('status', $status);
|
||||
}
|
||||
@@ -3007,7 +3191,6 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||
->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', null, new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('description', null, new Text(256), 'Description for Message.', true)
|
||||
->param('content', null, new Text(64230), 'Email Content.', true)
|
||||
->param('status', null, new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
@@ -3017,7 +3200,7 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||
->inject('project')
|
||||
->inject('queueForMessaging')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $description, ?string $content, ?string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $content, ?string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
$message = $dbForProject->getDocument('messages', $messageId);
|
||||
|
||||
if ($message->isEmpty()) {
|
||||
@@ -3056,10 +3239,6 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||
$message->setAttribute('status', $status);
|
||||
}
|
||||
|
||||
if (!\is_null($description)) {
|
||||
$message->setAttribute('description', $description);
|
||||
}
|
||||
|
||||
if (!\is_null($scheduledAt)) {
|
||||
if (\is_null($message->getAttribute(('scheduleId')))) {
|
||||
$schedule = $dbForConsole->createDocument('schedules', new Document([
|
||||
@@ -3126,7 +3305,6 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||
->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||
->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true)
|
||||
->param('targets', null, new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||
->param('description', null, new Text(256), 'Description for Message.', true)
|
||||
->param('title', null, new Text(256), 'Title for push notification.', true)
|
||||
->param('body', null, new Text(64230), 'Body for push notification.', true)
|
||||
->param('data', null, new JSON(), 'Additional Data for push notification.', true)
|
||||
@@ -3144,7 +3322,7 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||
->inject('project')
|
||||
->inject('queueForMessaging')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $description, ?string $title, ?string $body, ?array $data, ?string $action, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||
$message = $dbForProject->getDocument('messages', $messageId);
|
||||
|
||||
if ($message->isEmpty()) {
|
||||
@@ -3215,10 +3393,6 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||
$message->setAttribute('status', $status);
|
||||
}
|
||||
|
||||
if (!\is_null($description)) {
|
||||
$message->setAttribute('description', $description);
|
||||
}
|
||||
|
||||
if (!\is_null($scheduledAt)) {
|
||||
if (\is_null($message->getAttribute(('scheduleId')))) {
|
||||
$schedule = $dbForConsole->createDocument('schedules', new Document([
|
||||
@@ -3266,3 +3440,59 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||
$response
|
||||
->dynamic($message, Response::MODEL_MESSAGE);
|
||||
});
|
||||
|
||||
App::delete('/v1/messaging/messages/:messageId')
|
||||
->desc('Delete a message')
|
||||
->groups(['api', 'messaging'])
|
||||
->label('audits.event', 'message.delete')
|
||||
->label('audits.resource', 'message/{request.route.messageId}')
|
||||
->label('event', 'messages.[messageId].delete')
|
||||
->label('scope', 'messages.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'messaging')
|
||||
->label('sdk.method', 'delete')
|
||||
->label('sdk.description', '/docs/references/messaging/delete-message.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('messageId', '', new UID(), 'Message ID.')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->inject('response')
|
||||
->action(function (string $messageId, Database $dbForProject, Database $dbForConsole, Response $response) {
|
||||
$message = $dbForProject->getDocument('messages', $messageId);
|
||||
|
||||
if ($message->isEmpty()) {
|
||||
throw new Exception(Exception::MESSAGE_NOT_FOUND);
|
||||
}
|
||||
|
||||
switch ($message->getAttribute('status')) {
|
||||
case MessageStatus::PROCESSING:
|
||||
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
|
||||
case MessageStatus::SCHEDULED:
|
||||
$scheduleId = $message->getAttribute('scheduleId');
|
||||
$scheduledAt = $message->getAttribute('scheduledAt');
|
||||
|
||||
$now = DateTime::now();
|
||||
$scheduledDate = DateTime::formatTz($scheduledAt);
|
||||
|
||||
if ($now > $scheduledDate) {
|
||||
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
|
||||
}
|
||||
|
||||
if (!empty($scheduleId)) {
|
||||
try {
|
||||
$dbForConsole->deleteDocument('schedules', $scheduleId);
|
||||
} catch (Exception) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('messages', $message->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
@@ -392,7 +392,7 @@ App::get('/v1/migrations')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
|
||||
@@ -249,7 +249,7 @@ App::get('/v1/projects')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -825,7 +825,7 @@ App::post('/v1/projects/:projectId/webhooks')
|
||||
|
||||
$webhook = $dbForConsole->createDocument('webhooks', $webhook);
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
@@ -952,7 +952,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
}
|
||||
|
||||
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
|
||||
});
|
||||
@@ -991,7 +991,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
|
||||
$webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64)));
|
||||
|
||||
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
|
||||
});
|
||||
@@ -1028,7 +1028,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
||||
|
||||
$dbForConsole->deleteDocument('webhooks', $webhook->getId());
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
@@ -1078,7 +1078,7 @@ App::post('/v1/projects/:projectId/keys')
|
||||
|
||||
$key = $dbForConsole->createDocument('keys', $key);
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
@@ -1192,7 +1192,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
||||
|
||||
$dbForConsole->updateDocument('keys', $key->getId(), $key);
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->dynamic($key, Response::MODEL_KEY);
|
||||
});
|
||||
@@ -1229,7 +1229,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
|
||||
|
||||
$dbForConsole->deleteDocument('keys', $key->getId());
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
@@ -1279,7 +1279,7 @@ App::post('/v1/projects/:projectId/platforms')
|
||||
|
||||
$platform = $dbForConsole->createDocument('platforms', $platform);
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
@@ -1394,7 +1394,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
||||
|
||||
$dbForConsole->updateDocument('platforms', $platform->getId(), $platform);
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->dynamic($platform, Response::MODEL_PLATFORM);
|
||||
});
|
||||
@@ -1431,7 +1431,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
|
||||
|
||||
$dbForConsole->deleteDocument('platforms', $platformId);
|
||||
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
@@ -164,7 +164,7 @@ App::get('/v1/proxy/rules')
|
||||
$queries[] = Query::equal('projectInternalId', [$project->getInternalId()]);
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
|
||||
@@ -169,7 +169,7 @@ App::get('/v1/storage/buckets')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -451,7 +451,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
||||
}
|
||||
|
||||
$idValidator = new UID();
|
||||
if (!$idValidator->isValid($request->getHeader('x-appwrite-id'))) {
|
||||
if (!$idValidator->isValid($fileId)) {
|
||||
throw new Exception(Exception::STORAGE_INVALID_APPWRITE_ID);
|
||||
}
|
||||
|
||||
@@ -745,7 +745,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -963,7 +963,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
||||
break;
|
||||
}
|
||||
|
||||
$image = new Image($source);
|
||||
try {
|
||||
$image = new Image($source);
|
||||
} catch (ImagickException $e) {
|
||||
throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, $e->getMessage());
|
||||
}
|
||||
|
||||
$image->crop((int) $width, (int) $height, $gravity);
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ App::post('/v1/teams')
|
||||
]);
|
||||
|
||||
$membership = $dbForProject->createDocument('memberships', $membership);
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
}
|
||||
|
||||
$queueForEvents->setParam('teamId', $team->getId());
|
||||
@@ -154,7 +154,7 @@ App::get('/v1/teams')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -537,7 +537,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||
$team->setAttribute('total', $team->getAttribute('total', 0) + 1);
|
||||
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $invitee->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $invitee->getId());
|
||||
} else {
|
||||
try {
|
||||
$membership = $dbForProject->createDocument('memberships', $membership);
|
||||
@@ -710,7 +710,7 @@ App::get('/v1/teams/:teamId/memberships')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -856,7 +856,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
||||
/**
|
||||
* Replace membership on profile
|
||||
*/
|
||||
$dbForProject->deleteCachedDocument('users', $profile->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $profile->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('teamId', $team->getId())
|
||||
@@ -972,13 +972,13 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
Permission::delete(Role::user($user->getId())),
|
||||
]));
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
Authorization::setRole(Role::user($userId)->toString());
|
||||
|
||||
$membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership);
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1)));
|
||||
|
||||
@@ -1057,7 +1057,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
if ($membership->getAttribute('confirm')) { // Count only confirmed members
|
||||
$team->setAttribute('total', \max($team->getAttribute('total', 0) - 1, 0));
|
||||
|
||||
@@ -144,7 +144,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
|
||||
}
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
@@ -507,7 +507,7 @@ App::post('/v1/users/:userId/targets')
|
||||
} catch (Duplicate) {
|
||||
throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS);
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -543,7 +543,7 @@ App::get('/v1/users')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -838,7 +838,7 @@ App::get('/v1/users/:userId/targets')
|
||||
$queries[] = Query::equal('userId', [$userId]);
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
|
||||
if ($cursor) {
|
||||
@@ -883,7 +883,7 @@ App::get('/v1/users/identities')
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
@@ -957,7 +957,7 @@ App::put('/v1/users/:userId/labels')
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_USER)
|
||||
->param('userId', '', new UID(), 'User ID.')
|
||||
->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.')
|
||||
->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_LABELS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_LABELS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
@@ -1183,7 +1183,7 @@ App::patch('/v1/users/:userId/email')
|
||||
if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) {
|
||||
$dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email));
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
}
|
||||
@@ -1245,7 +1245,7 @@ App::patch('/v1/users/:userId/phone')
|
||||
if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) {
|
||||
$dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $number));
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception(Exception::USER_PHONE_ALREADY_EXISTS);
|
||||
}
|
||||
@@ -1407,7 +1407,7 @@ App::patch('/v1/users/:userId/targets/:targetId')
|
||||
}
|
||||
|
||||
$target = $dbForProject->updateDocument('targets', $target->getId(), $target);
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -1417,76 +1417,6 @@ App::patch('/v1/users/:userId/targets/:targetId')
|
||||
->dynamic($target, Response::MODEL_TARGET);
|
||||
});
|
||||
|
||||
App::post('/v1/users/:userId/sessions')
|
||||
->desc('Create session')
|
||||
->groups(['api', 'users'])
|
||||
->label('event', 'users.[userId].sessions.[sessionId].create')
|
||||
->label('scope', 'users.write')
|
||||
->label('audits.event', 'session.create')
|
||||
->label('audits.resource', 'user/{request.userId}')
|
||||
->label('usage.metric', 'sessions.{scope}.requests.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'createSession')
|
||||
->label('sdk.description', '/docs/references/users/create-session.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_SESSION)
|
||||
->param('userId', '', new CustomId(), 'User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $userId, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents) {
|
||||
$user = $dbForProject->getDocument('users', $userId);
|
||||
if ($user === false || $user->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$secret = Auth::codeGenerator();
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
|
||||
$duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration));
|
||||
|
||||
$session = new Document(array_merge(
|
||||
[
|
||||
'$id' => ID::unique(),
|
||||
'userId' => $user->getId(),
|
||||
'userInternalId' => $user->getInternalId(),
|
||||
'provider' => Auth::SESSION_PROVIDER_SERVER,
|
||||
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
],
|
||||
$detector->getOS(),
|
||||
$detector->getClient(),
|
||||
$detector->getDevice()
|
||||
));
|
||||
|
||||
$countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'));
|
||||
|
||||
$session = $dbForProject->createDocument('sessions', $session);
|
||||
$session
|
||||
->setAttribute('secret', $secret)
|
||||
->setAttribute('expire', $expire)
|
||||
->setAttribute('countryName', $countryName);
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
->setParam('sessionId', $session->getId())
|
||||
->setPayload($response->output($session, Response::MODEL_SESSION));
|
||||
|
||||
return $response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($session, Response::MODEL_SESSION);
|
||||
});
|
||||
|
||||
App::post('/v1/users/:userId/tokens')
|
||||
->desc('Create token')
|
||||
->groups(['api', 'users'])
|
||||
@@ -1494,7 +1424,6 @@ App::post('/v1/users/:userId/tokens')
|
||||
->label('scope', 'users.write')
|
||||
->label('audits.event', 'tokens.create')
|
||||
->label('audits.resource', 'user/{request.userId}')
|
||||
->label('usage.metric', 'tokens.requests.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'users')
|
||||
->label('sdk.method', 'createToken')
|
||||
@@ -1531,7 +1460,7 @@ App::post('/v1/users/:userId/tokens')
|
||||
]);
|
||||
|
||||
$token = $dbForProject->createDocument('tokens', $token);
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$token->setAttribute('secret', $secret);
|
||||
|
||||
@@ -1578,7 +1507,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('sessions', $session->getId());
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -1621,7 +1550,7 @@ App::delete('/v1/users/:userId/sessions')
|
||||
//TODO: fix this
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForEvents
|
||||
->setParam('userId', $user->getId())
|
||||
@@ -1710,7 +1639,7 @@ App::delete('/v1/users/:userId/targets/:targetId')
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('targets', $target->getId());
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
$dbForProject->purgeCachedDocument('users', $user->getId());
|
||||
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_TARGET)
|
||||
|
||||
@@ -978,7 +978,7 @@ App::get('/v1/vcs/installations')
|
||||
}
|
||||
|
||||
// Get cursor document if there was a cursor query
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
|
||||
$cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
|
||||
@@ -511,7 +511,7 @@ App::init()
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCCESS)) > $accessedAt) {
|
||||
$key->setAttribute('accessedAt', DateTime::now());
|
||||
$dbForConsole->updateDocument('keys', $key->getId(), $key);
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
|
||||
$sdkValidator = new WhiteList($servers, true);
|
||||
@@ -525,7 +525,7 @@ App::init()
|
||||
/** Update access time as well */
|
||||
$key->setAttribute('accessedAt', Datetime::now());
|
||||
$dbForConsole->updateDocument('keys', $key->getId(), $key);
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -739,7 +739,7 @@ App::error()
|
||||
'code' => $code,
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'trace' => $trace,
|
||||
'trace' => \json_encode($trace, JSON_UNESCAPED_UNICODE) === false ? [] : $trace, // check for failing encode
|
||||
'version' => $version,
|
||||
'type' => $type,
|
||||
] : [
|
||||
|
||||
@@ -410,7 +410,7 @@ App::shutdown()
|
||||
$session = array_shift($sessions);
|
||||
$dbForProject->deleteDocument('sessions', $session->getId());
|
||||
}
|
||||
$dbForProject->deleteCachedDocument('users', $userId);
|
||||
$dbForProject->purgeCachedDocument('users', $userId);
|
||||
});
|
||||
|
||||
App::shutdown()
|
||||
|
||||
@@ -147,7 +147,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
|
||||
$dbForConsole->createCollection($key, $attributes, $indexes);
|
||||
}
|
||||
|
||||
if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDefaultDatabase(), 'bucket_1')) {
|
||||
if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) {
|
||||
Console::success('[Setup] - Creating default bucket...');
|
||||
$dbForConsole->createDocument('buckets', new Document([
|
||||
'$id' => ID::custom('default'),
|
||||
|
||||
@@ -34,6 +34,7 @@ use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\URL\URL as AppwriteURL;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Adapter\SQL;
|
||||
use Utopia\Logger\Logger;
|
||||
use Utopia\Cache\Adapter\Redis as RedisCache;
|
||||
use Utopia\Cache\Cache;
|
||||
@@ -99,6 +100,7 @@ const APP_LIMIT_ANTIVIRUS = 20_000_000; //20MB
|
||||
const APP_LIMIT_ENCRYPTION = 20_000_000; //20MB
|
||||
const APP_LIMIT_COMPRESSION = 20_000_000; //20MB
|
||||
const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value
|
||||
const APP_LIMIT_ARRAY_LABELS_SIZE = 1000; // Default maximum of how many labels elements can there be in API parameter that expects array value
|
||||
const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length.
|
||||
const APP_LIMIT_SUBQUERY = 1000;
|
||||
const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000;
|
||||
@@ -804,10 +806,10 @@ $register->set('pools', function () {
|
||||
$resource = function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
|
||||
return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) {
|
||||
return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array(
|
||||
// No need to set PDO::ATTR_ERRMODE it is overwitten in PDOProxy
|
||||
PDO::ATTR_TIMEOUT => 3, // Seconds
|
||||
PDO::ATTR_PERSISTENT => true,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed
|
||||
PDO::ATTR_EMULATE_PREPARES => true,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => true
|
||||
));
|
||||
@@ -829,12 +831,10 @@ $register->set('pools', function () {
|
||||
|
||||
default:
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid scheme");
|
||||
break;
|
||||
}
|
||||
|
||||
$pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) {
|
||||
// Get Adapter
|
||||
$adapter = null;
|
||||
switch ($type) {
|
||||
case 'database':
|
||||
$adapter = match ($dsn->getScheme()) {
|
||||
@@ -843,7 +843,7 @@ $register->set('pools', function () {
|
||||
default => null
|
||||
};
|
||||
|
||||
$adapter->setDefaultDatabase($dsn->getPath());
|
||||
$adapter->setDatabase($dsn->getPath());
|
||||
break;
|
||||
case 'pubsub':
|
||||
$adapter = $resource();
|
||||
@@ -863,7 +863,6 @@ $register->set('pools', function () {
|
||||
|
||||
default:
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation.");
|
||||
break;
|
||||
}
|
||||
|
||||
return $adapter;
|
||||
@@ -880,22 +879,18 @@ $register->set('pools', function () {
|
||||
|
||||
$register->set('db', function () {
|
||||
// This is usually for our workers or CLI commands scope
|
||||
$dbHost = App::getEnv('_APP_DB_HOST', '');
|
||||
$dbPort = App::getEnv('_APP_DB_PORT', '');
|
||||
$dbUser = App::getEnv('_APP_DB_USER', '');
|
||||
$dbPass = App::getEnv('_APP_DB_PASS', '');
|
||||
$dbScheme = App::getEnv('_APP_DB_SCHEMA', '');
|
||||
$dbHost = App::getEnv('_APP_DB_HOST', '');
|
||||
$dbPort = App::getEnv('_APP_DB_PORT', '');
|
||||
$dbUser = App::getEnv('_APP_DB_USER', '');
|
||||
$dbPass = App::getEnv('_APP_DB_PASS', '');
|
||||
$dbScheme = App::getEnv('_APP_DB_SCHEMA', '');
|
||||
|
||||
$pdo = new PDO("mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4", $dbUser, $dbPass, array(
|
||||
PDO::ATTR_TIMEOUT => 3, // Seconds
|
||||
PDO::ATTR_PERSISTENT => true,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_EMULATE_PREPARES => true,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => true,
|
||||
));
|
||||
|
||||
return $pdo;
|
||||
return new PDO(
|
||||
"mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4",
|
||||
$dbUser,
|
||||
$dbPass,
|
||||
SQL::getPDOAttributes()
|
||||
);
|
||||
});
|
||||
|
||||
$register->set('smtp', function () {
|
||||
|
||||
@@ -15,7 +15,7 @@ $image = $this->getParam('image', '');
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:2.9
|
||||
image: traefik:2.11
|
||||
container_name: appwrite-traefik
|
||||
<<: *x-logging
|
||||
command:
|
||||
@@ -735,7 +735,7 @@ services:
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
container_name: appwrite-mariadb
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -751,7 +751,7 @@ services:
|
||||
command: 'mysqld --innodb-flush-method=fsync'
|
||||
|
||||
redis:
|
||||
image: redis:7.0.4-alpine
|
||||
image: redis:7.2.4-alpine
|
||||
container_name: appwrite-redis
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -43,20 +43,20 @@
|
||||
"ext-sockets": "*",
|
||||
"appwrite/php-runtimes": "0.13.*",
|
||||
"appwrite/php-clamav": "2.0.*",
|
||||
"utopia-php/abuse": "0.33.*",
|
||||
"utopia-php/abuse": "0.36.*",
|
||||
"utopia-php/analytics": "0.10.*",
|
||||
"utopia-php/audit": "0.35.*",
|
||||
"utopia-php/audit": "0.38.*",
|
||||
"utopia-php/cache": "0.9.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.45.*",
|
||||
"utopia-php/database": "0.48.*",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.1.*",
|
||||
"utopia-php/dsn": "0.2.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/image": "0.5.*",
|
||||
"utopia-php/image": "0.6.*",
|
||||
"utopia-php/locale": "0.4.*",
|
||||
"utopia-php/logger": "0.3.*",
|
||||
"utopia-php/messaging": "0.8.*",
|
||||
"utopia-php/messaging": "0.9.*",
|
||||
"utopia-php/migration": "0.3.*",
|
||||
"utopia-php/orchestration": "0.9.*",
|
||||
"utopia-php/platform": "0.5.*",
|
||||
@@ -74,7 +74,7 @@
|
||||
"chillerlan/php-qrcode": "4.3.4",
|
||||
"adhocore/jwt": "1.1.2",
|
||||
"webonyx/graphql-php": "14.11.*",
|
||||
"league/csv": "9.7.1"
|
||||
"league/csv": "^9.14"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
@@ -96,7 +96,7 @@
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.0"
|
||||
"php": "8.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "758fc8f128df402e823dd2cb340bf78b",
|
||||
"content-hash": "4b9b6ff602a179493e0196636d961e9c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -463,34 +463,39 @@
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
"version": "9.7.1",
|
||||
"version": "9.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/csv.git",
|
||||
"reference": "0ec57e8264ec92565974ead0d1724cf1026e10c1"
|
||||
"reference": "34bf0df7340b60824b9449b5c526fcc3325070d5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/0ec57e8264ec92565974ead0d1724cf1026e10c1",
|
||||
"reference": "0ec57e8264ec92565974ead0d1724cf1026e10c1",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/34bf0df7340b60824b9449b5c526fcc3325070d5",
|
||||
"reference": "34bf0df7340b60824b9449b5c526fcc3325070d5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-filter": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.3 || ^8.0"
|
||||
"php": "^8.1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"doctrine/collections": "^2.1.4",
|
||||
"ext-dom": "*",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"phpstan/phpstan": "^0.12.0",
|
||||
"phpstan/phpstan-phpunit": "^0.12.0",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
"ext-xdebug": "*",
|
||||
"friendsofphp/php-cs-fixer": "^v3.22.0",
|
||||
"phpbench/phpbench": "^1.2.15",
|
||||
"phpstan/phpstan": "^1.10.50",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1.4",
|
||||
"phpstan/phpstan-phpunit": "^1.3.15",
|
||||
"phpstan/phpstan-strict-rules": "^1.5.2",
|
||||
"phpunit/phpunit": "^10.5.3",
|
||||
"symfony/var-dumper": "^6.4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "Required to use the XMLConverter and or the HTMLConverter classes",
|
||||
"ext-dom": "Required to use the XMLConverter and the HTMLConverter classes",
|
||||
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -520,7 +525,7 @@
|
||||
}
|
||||
],
|
||||
"description": "CSV data manipulation made easy in PHP",
|
||||
"homepage": "http://csv.thephpleague.com",
|
||||
"homepage": "https://csv.thephpleague.com",
|
||||
"keywords": [
|
||||
"convert",
|
||||
"csv",
|
||||
@@ -543,7 +548,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-04-17T16:32:08+00:00"
|
||||
"time": "2023-12-29T07:34:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "matomo/device-detector",
|
||||
@@ -898,23 +903,23 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/abuse",
|
||||
"version": "0.33.0",
|
||||
"version": "0.36.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/abuse.git",
|
||||
"reference": "1ba8d5f2793885cbf779e3b5b9d886968af43d2c"
|
||||
"reference": "d3d09b4fa0db75935110714ad4b2a87f3ace31ed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/1ba8d5f2793885cbf779e3b5b9d886968af43d2c",
|
||||
"reference": "1ba8d5f2793885cbf779e3b5b9d886968af43d2c",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/d3d09b4fa0db75935110714ad4b2a87f3ace31ed",
|
||||
"reference": "d3d09b4fa0db75935110714ad4b2a87f3ace31ed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-pdo": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "0.45.*"
|
||||
"utopia-php/database": "0.48.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.5.*",
|
||||
@@ -941,9 +946,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/abuse/issues",
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.33.0"
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.36.0"
|
||||
},
|
||||
"time": "2023-11-01T08:51:33+00:00"
|
||||
"time": "2024-01-19T09:32:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/analytics",
|
||||
@@ -993,21 +998,21 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/audit",
|
||||
"version": "0.35.0",
|
||||
"version": "0.38.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/audit.git",
|
||||
"reference": "ed9366ef05556da040de7a8b570f4160c7d8ea4a"
|
||||
"reference": "a9067f4af76e8787f1d29850a8ec94fc32bb6539"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/ed9366ef05556da040de7a8b570f4160c7d8ea4a",
|
||||
"reference": "ed9366ef05556da040de7a8b570f4160c7d8ea4a",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/a9067f4af76e8787f1d29850a8ec94fc32bb6539",
|
||||
"reference": "a9067f4af76e8787f1d29850a8ec94fc32bb6539",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "0.45.*"
|
||||
"utopia-php/database": "0.48.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.5.*",
|
||||
@@ -1034,9 +1039,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/audit/issues",
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.35.0"
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.38.0"
|
||||
},
|
||||
"time": "2023-11-01T08:51:29+00:00"
|
||||
"time": "2024-01-19T09:33:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cache",
|
||||
@@ -1190,16 +1195,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.45.5",
|
||||
"version": "0.48.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "0b66a017f817a910acb83e6aea92bccea9571fe6"
|
||||
"reference": "2651f41b9d3909dc123d26becfb6a3a44fb63077"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/0b66a017f817a910acb83e6aea92bccea9571fe6",
|
||||
"reference": "0b66a017f817a910acb83e6aea92bccea9571fe6",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/2651f41b9d3909dc123d26becfb6a3a44fb63077",
|
||||
"reference": "2651f41b9d3909dc123d26becfb6a3a44fb63077",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1240,9 +1245,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.45.5"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.48.0"
|
||||
},
|
||||
"time": "2024-01-08T17:08:15+00:00"
|
||||
"time": "2024-01-19T08:17:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -1306,16 +1311,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/dsn",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/dsn.git",
|
||||
"reference": "17a5935eab1b89fb4b95600db50a1b6d5faa6cea"
|
||||
"reference": "c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/dsn/zipball/17a5935eab1b89fb4b95600db50a1b6d5faa6cea",
|
||||
"reference": "17a5935eab1b89fb4b95600db50a1b6d5faa6cea",
|
||||
"url": "https://api.github.com/repos/utopia-php/dsn/zipball/c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7",
|
||||
"reference": "c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1347,22 +1352,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/dsn/issues",
|
||||
"source": "https://github.com/utopia-php/dsn/tree/0.1.0"
|
||||
"source": "https://github.com/utopia-php/dsn/tree/0.2.0"
|
||||
},
|
||||
"time": "2022-10-26T10:06:20+00:00"
|
||||
"time": "2023-11-02T12:01:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/framework",
|
||||
"version": "0.33.1",
|
||||
"version": "0.33.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/http.git",
|
||||
"reference": "b745607aa1875554a0ad52e28f6db918da1ce11c"
|
||||
"reference": "b1423ca3e3b61c6c4c2e619d2cb80672809a19f3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/http/zipball/b745607aa1875554a0ad52e28f6db918da1ce11c",
|
||||
"reference": "b745607aa1875554a0ad52e28f6db918da1ce11c",
|
||||
"url": "https://api.github.com/repos/utopia-php/http/zipball/b1423ca3e3b61c6c4c2e619d2cb80672809a19f3",
|
||||
"reference": "b1423ca3e3b61c6c4c2e619d2cb80672809a19f3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1392,22 +1397,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/http/issues",
|
||||
"source": "https://github.com/utopia-php/http/tree/0.33.1"
|
||||
"source": "https://github.com/utopia-php/http/tree/0.33.2"
|
||||
},
|
||||
"time": "2024-01-17T16:48:32+00:00"
|
||||
"time": "2024-01-31T10:35:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/image",
|
||||
"version": "0.5.4",
|
||||
"version": "0.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/image.git",
|
||||
"reference": "ca5f436f9aa22dedaa6648f24f3687733808e336"
|
||||
"reference": "88f7209172bdabd81e76ac981c95fac117dc6e08"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/image/zipball/ca5f436f9aa22dedaa6648f24f3687733808e336",
|
||||
"reference": "ca5f436f9aa22dedaa6648f24f3687733808e336",
|
||||
"url": "https://api.github.com/repos/utopia-php/image/zipball/88f7209172bdabd81e76ac981c95fac117dc6e08",
|
||||
"reference": "88f7209172bdabd81e76ac981c95fac117dc6e08",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1415,6 +1420,8 @@
|
||||
"php": ">=8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.2.*",
|
||||
"phpstan/phpstan": "1.9.x-dev",
|
||||
"phpunit/phpunit": "^9.3",
|
||||
"vimeo/psalm": "4.13.1"
|
||||
},
|
||||
@@ -1428,12 +1435,6 @@
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Eldad Fux",
|
||||
"email": "eldad@appwrite.io"
|
||||
}
|
||||
],
|
||||
"description": "A simple Image manipulation library",
|
||||
"keywords": [
|
||||
"framework",
|
||||
@@ -1444,9 +1445,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/image/issues",
|
||||
"source": "https://github.com/utopia-php/image/tree/0.5.4"
|
||||
"source": "https://github.com/utopia-php/image/tree/0.6.0"
|
||||
},
|
||||
"time": "2022-05-11T12:30:41+00:00"
|
||||
"time": "2024-01-24T06:59:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/locale",
|
||||
@@ -1554,16 +1555,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/messaging",
|
||||
"version": "0.8.1",
|
||||
"version": "0.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/messaging.git",
|
||||
"reference": "bfb5014d3a8752901e50da1ae21bf309a6af5006"
|
||||
"reference": "df54ba51570e886724590edeb03dbd455bb0464d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/bfb5014d3a8752901e50da1ae21bf309a6af5006",
|
||||
"reference": "bfb5014d3a8752901e50da1ae21bf309a6af5006",
|
||||
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/df54ba51570e886724590edeb03dbd455bb0464d",
|
||||
"reference": "df54ba51570e886724590edeb03dbd455bb0464d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1598,9 +1599,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/messaging/issues",
|
||||
"source": "https://github.com/utopia-php/messaging/tree/0.8.1"
|
||||
"source": "https://github.com/utopia-php/messaging/tree/0.9.0"
|
||||
},
|
||||
"time": "2024-01-10T23:55:03+00:00"
|
||||
"time": "2024-01-31T11:51:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
@@ -2473,16 +2474,16 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/deprecations.git",
|
||||
"reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931"
|
||||
"reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
|
||||
"reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab",
|
||||
"reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2514,9 +2515,9 @@
|
||||
"homepage": "https://www.doctrine-project.org/",
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/deprecations/issues",
|
||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.2"
|
||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.3"
|
||||
},
|
||||
"time": "2023-09-27T20:04:15+00:00"
|
||||
"time": "2024-01-30T19:34:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
@@ -5172,7 +5173,7 @@
|
||||
"ext-fileinfo": "*"
|
||||
},
|
||||
"platform-overrides": {
|
||||
"php": "8.0"
|
||||
"php": "8.2"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
zend_extension=xdebug
|
||||
|
||||
[xdebug]
|
||||
xdebug.mode=develop,debug
|
||||
xdebug.client_host=host.docker.internal
|
||||
xdebug.start_with_request=yes
|
||||
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
echo 'execute init_file success' . PHP_EOL;
|
||||
Yasd\Api\setRemoteHost('host.docker.internal'); //Set your development machine's IP
|
||||
@@ -14,7 +14,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:2.9
|
||||
image: traefik:2.11
|
||||
<<: *x-logging
|
||||
container_name: appwrite-traefik
|
||||
command:
|
||||
@@ -297,6 +297,7 @@ services:
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_WEBHOOK_MAX_FAILED_ATTEMPTS
|
||||
|
||||
appwrite-worker-deletes:
|
||||
entrypoint: worker-deletes
|
||||
@@ -885,7 +886,7 @@ services:
|
||||
- OPR_PROXY_HEALTHCHECK=enabled
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
container_name: appwrite-mariadb
|
||||
<<: *x-logging
|
||||
networks:
|
||||
@@ -915,7 +916,7 @@ services:
|
||||
# - SMARTHOST_PORT=587
|
||||
|
||||
redis:
|
||||
image: redis:7.0.4-alpine
|
||||
image: redis:7.2.4-alpine
|
||||
<<: *x-logging
|
||||
container_name: appwrite-redis
|
||||
command: >
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Delete a message by its unique ID.
|
||||
@@ -60,7 +60,8 @@ class Scryptmodified extends Hash
|
||||
$saltBytes = \base64_decode($options['salt']);
|
||||
$saltSeparatorBytes = \base64_decode($options['saltSeparator']);
|
||||
|
||||
$derivedKey = \scrypt(\utf8_encode($password), $saltBytes . $saltSeparatorBytes, 16384, 8, 1, 64);
|
||||
$password = mb_convert_encoding($password, 'UTF-8');
|
||||
$derivedKey = \scrypt($password, $saltBytes . $saltSeparatorBytes, 16384, 8, 1, 64);
|
||||
$derivedKey = \hex2bin($derivedKey);
|
||||
|
||||
return $derivedKey;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Appwrite\Auth;
|
||||
|
||||
class SecurityPhrase
|
||||
class Phrase
|
||||
{
|
||||
public static function generate(): string
|
||||
{
|
||||
@@ -43,10 +43,10 @@ class PersonalData extends Password
|
||||
|
||||
if (!$this->strict) {
|
||||
$password = strtolower($password);
|
||||
$this->userId = strtolower($this->userId);
|
||||
$this->email = strtolower($this->email);
|
||||
$this->name = strtolower($this->name);
|
||||
$this->phone = strtolower($this->phone);
|
||||
$this->userId = strtolower($this->userId ?? '');
|
||||
$this->email = strtolower($this->email ?? '');
|
||||
$this->name = strtolower($this->name ?? '');
|
||||
$this->phone = strtolower($this->phone ?? '');
|
||||
}
|
||||
|
||||
if ($this->userId && strpos($password, $this->userId) !== false) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Enum;
|
||||
namespace Appwrite\Messaging;
|
||||
|
||||
class MessageStatus
|
||||
class Status
|
||||
{
|
||||
/**
|
||||
* Message that is not ready to be sent
|
||||
@@ -397,7 +397,7 @@ abstract class Migration
|
||||
*/
|
||||
protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void
|
||||
{
|
||||
$stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;");
|
||||
$stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;");
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
|
||||
@@ -295,7 +295,7 @@ class V15 extends Migration
|
||||
protected function removeWritePermissions(string $table): void
|
||||
{
|
||||
try {
|
||||
$this->pdo->prepare("DELETE FROM `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute();
|
||||
$this->pdo->prepare("DELETE FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("Remove 'write' permissions from {$table}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -311,7 +311,7 @@ class V15 extends Migration
|
||||
*/
|
||||
protected function getSQLColumnTypes(string $table): array
|
||||
{
|
||||
$query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->projectDB->getDefaultDatabase()}'");
|
||||
$query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->projectDB->getDatabase()}'");
|
||||
$query->execute();
|
||||
|
||||
return array_reduce($query->fetchAll(), function (array $carry, array $item) {
|
||||
@@ -333,8 +333,8 @@ class V15 extends Migration
|
||||
|
||||
if ($columns[$attribute] === 'int') {
|
||||
try {
|
||||
$this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute();
|
||||
$this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute();
|
||||
$this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute();
|
||||
$this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute();
|
||||
$columns[$attribute] = 'varchar';
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning($th->getMessage());
|
||||
@@ -343,7 +343,7 @@ class V15 extends Migration
|
||||
|
||||
if ($columns[$attribute] === 'varchar') {
|
||||
try {
|
||||
$this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute();
|
||||
$this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning($th->getMessage());
|
||||
}
|
||||
@@ -372,7 +372,7 @@ class V15 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($table);
|
||||
$this->projectDB->purgeCachedCollection($table);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,7 +389,7 @@ class V15 extends Migration
|
||||
|
||||
if (!array_key_exists('_permissions', $columns)) {
|
||||
try {
|
||||
$this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute();
|
||||
$this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("Add '_permissions' column to '{$table}': {$th->getMessage()}");
|
||||
}
|
||||
@@ -410,7 +410,7 @@ class V15 extends Migration
|
||||
{
|
||||
$table ??= $document->getCollection();
|
||||
|
||||
$query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'");
|
||||
$query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'");
|
||||
$query->execute();
|
||||
$results = $query->fetchAll();
|
||||
$permissions = [];
|
||||
@@ -479,7 +479,7 @@ class V15 extends Migration
|
||||
$this->createCollection('cache');
|
||||
Console::log('Created new Collection "variables" collection');
|
||||
$this->createCollection('variables');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
break;
|
||||
|
||||
case 'abuse':
|
||||
@@ -1472,9 +1472,9 @@ class V15 extends Migration
|
||||
$from = $this->pdo->quote($from);
|
||||
$to = $this->pdo->quote($to);
|
||||
|
||||
$this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute();
|
||||
$this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("Migrating steps from {$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage());
|
||||
Console::warning("Migrating steps from {$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class V17 extends Migration
|
||||
|
||||
try {
|
||||
$this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false);
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'mimeType' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class V17 extends Migration
|
||||
* Create 'size' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'size');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'size' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -88,7 +88,7 @@ class V17 extends Migration
|
||||
* Update 'mimeType' attribute size (127->255)
|
||||
*/
|
||||
$this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false);
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'mimeType' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -98,7 +98,7 @@ class V17 extends Migration
|
||||
* Create 'bucketInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'bucketInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class V17 extends Migration
|
||||
* Delete 'endTime' attribute (use startTime+duration if needed)
|
||||
*/
|
||||
$this->projectDB->deleteAttribute($id, 'endTime');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'endTime' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class V17 extends Migration
|
||||
* Rename 'outputPath' to 'path'
|
||||
*/
|
||||
$this->projectDB->renameAttribute($id, 'outputPath', 'path');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'path' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -130,7 +130,7 @@ class V17 extends Migration
|
||||
* Create 'deploymentInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class V17 extends Migration
|
||||
* Delete 'type' attribute
|
||||
*/
|
||||
$this->projectDB->deleteAttribute($id, 'type');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'type' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class V17 extends Migration
|
||||
* Create 'resourceInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'resourceInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -166,7 +166,7 @@ class V17 extends Migration
|
||||
* Create 'deploymentInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -176,7 +176,7 @@ class V17 extends Migration
|
||||
* Create 'scheduleInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -186,7 +186,7 @@ class V17 extends Migration
|
||||
* Delete 'scheduleUpdatedAt' attribute
|
||||
*/
|
||||
$this->projectDB->deleteAttribute($id, 'scheduleUpdatedAt');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'scheduleUpdatedAt' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -198,7 +198,7 @@ class V17 extends Migration
|
||||
* Create 'resourceInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'resourceInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -208,7 +208,7 @@ class V17 extends Migration
|
||||
* Create 'buildInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'buildInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'buildInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -220,7 +220,7 @@ class V17 extends Migration
|
||||
* Create 'functionInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'functionInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'functionInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -230,7 +230,7 @@ class V17 extends Migration
|
||||
* Create 'deploymentInternalId' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ class V18 extends Migration
|
||||
* Create 'passwordHistory' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'passwordHistory');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'passwordHistory' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class V18 extends Migration
|
||||
* Create 'prefs' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'prefs');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'prefs' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -128,7 +128,7 @@ class V18 extends Migration
|
||||
* Create 'options' attribute
|
||||
*/
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'options');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'options' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -244,7 +244,7 @@ class V18 extends Migration
|
||||
/**
|
||||
* Create 'documentSecurity' column
|
||||
*/
|
||||
$this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute();
|
||||
$this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning($th->getMessage());
|
||||
}
|
||||
@@ -253,7 +253,7 @@ class V18 extends Migration
|
||||
/**
|
||||
* Set 'documentSecurity' column to 1 if NULL
|
||||
*/
|
||||
$this->pdo->prepare("UPDATE `{$this->projectDB->getDefaultDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute();
|
||||
$this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute();
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning($th->getMessage());
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class V19 extends Migration
|
||||
|
||||
protected function migrateDomains(): void
|
||||
{
|
||||
if ($this->consoleDB->exists($this->consoleDB->getDefaultDatabase(), 'domains')) {
|
||||
if ($this->consoleDB->exists($this->consoleDB->getDatabase(), 'domains')) {
|
||||
foreach ($this->documentsIterator('domains') as $domain) {
|
||||
$status = 'created';
|
||||
if ($domain->getAttribute('verification', false)) {
|
||||
@@ -106,7 +106,7 @@ class V19 extends Migration
|
||||
|
||||
try {
|
||||
$this->createAttributeFromCollection($this->projectDB, $id, 'bucketInternalId', 'files');
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning("'bucketInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
@@ -166,7 +166,7 @@ class V19 extends Migration
|
||||
Console::warning("'error' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'buckets':
|
||||
@@ -194,7 +194,7 @@ class V19 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'builds':
|
||||
@@ -217,7 +217,7 @@ class V19 extends Migration
|
||||
Console::warning("'path' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'certificates':
|
||||
@@ -233,7 +233,7 @@ class V19 extends Migration
|
||||
Console::warning("'logs' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'databases':
|
||||
@@ -243,7 +243,7 @@ class V19 extends Migration
|
||||
Console::warning("'enabled' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'deployments':
|
||||
@@ -306,7 +306,7 @@ class V19 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'executions':
|
||||
@@ -367,7 +367,7 @@ class V19 extends Migration
|
||||
Console::warning("'_key_responseStatusCode' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'files':
|
||||
@@ -394,7 +394,7 @@ class V19 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'functions':
|
||||
@@ -456,7 +456,7 @@ class V19 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'memberships':
|
||||
@@ -466,7 +466,7 @@ class V19 extends Migration
|
||||
Console::warning("'teamInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
// Intentional fall through to update memberships.userInternalId
|
||||
case 'sessions':
|
||||
@@ -477,7 +477,7 @@ class V19 extends Migration
|
||||
Console::warning("'userInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'domains':
|
||||
@@ -490,7 +490,7 @@ class V19 extends Migration
|
||||
Console::warning("'projectInternalId' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'projects':
|
||||
@@ -508,7 +508,7 @@ class V19 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'stats':
|
||||
@@ -521,26 +521,26 @@ class V19 extends Migration
|
||||
// Holding off on these until a future release
|
||||
// try {
|
||||
// $this->projectDB->deleteAttribute($id, 'type');
|
||||
// $this->projectDB->deleteCachedCollection($id);
|
||||
// $this->projectDB->purgeCachedCollection($id);
|
||||
// } catch (\Throwable $th) {
|
||||
// Console::warning("'type' from {$id}: {$th->getMessage()}");
|
||||
// }
|
||||
|
||||
// try {
|
||||
// $this->projectDB->deleteIndex($id, '_key_metric_period_time');
|
||||
// $this->projectDB->deleteCachedCollection($id);
|
||||
// $this->projectDB->purgeCachedCollection($id);
|
||||
// } catch (\Throwable $th) {
|
||||
// Console::warning("'_key_metric_period_time' from {$id}: {$th->getMessage()}");
|
||||
// }
|
||||
|
||||
// try {
|
||||
// $this->createIndexFromCollection($this->projectDB, $id, '_key_metric_period_time');
|
||||
// $this->projectDB->deleteCachedCollection($id);
|
||||
// $this->projectDB->purgeCachedCollection($id);
|
||||
// } catch (\Throwable $th) {
|
||||
// Console::warning("'_key_metric_period_time' from {$id}: {$th->getMessage()}");
|
||||
// }
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'users':
|
||||
@@ -568,7 +568,7 @@ class V19 extends Migration
|
||||
Console::warning("'_key_accessedAt' from {$id}: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
case 'variables':
|
||||
@@ -616,7 +616,7 @@ class V19 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection($id);
|
||||
$this->projectDB->purgeCachedCollection($id);
|
||||
|
||||
break;
|
||||
default:
|
||||
@@ -775,7 +775,7 @@ class V19 extends Migration
|
||||
Console::warning("'domains' from projects: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection('projects');
|
||||
$this->projectDB->purgeCachedCollection('projects');
|
||||
|
||||
try {
|
||||
$this->projectDB->deleteAttribute('builds', 'stderr');
|
||||
@@ -789,7 +789,7 @@ class V19 extends Migration
|
||||
Console::warning("'stdout' from builds: {$th->getMessage()}");
|
||||
}
|
||||
|
||||
$this->projectDB->deleteCachedCollection('builds');
|
||||
$this->projectDB->purgeCachedCollection('builds');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -90,12 +90,12 @@ class DeleteOrphanedProjects extends Action
|
||||
->getResource();
|
||||
|
||||
$dbForProject = new Database($adapter, $cache);
|
||||
$dbForProject->setDefaultDatabase('appwrite');
|
||||
$dbForProject->setDatabase('appwrite');
|
||||
$dbForProject->setNamespace('_' . $project->getInternalId());
|
||||
|
||||
$collectionsCreated = 0;
|
||||
$cnt++;
|
||||
if ($dbForProject->exists($dbForProject->getDefaultDatabase(), Database::METADATA)) {
|
||||
if ($dbForProject->exists($dbForProject->getDatabase(), Database::METADATA)) {
|
||||
$collectionsCreated = $dbForProject->count(Database::METADATA);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ class DeleteOrphanedProjects extends Action
|
||||
foreach ($collections as $collection) {
|
||||
if ($commit) {
|
||||
$dbForProject->deleteCollection($collection->getId());
|
||||
$dbForConsole->deleteCachedCollection($collection->getId());
|
||||
$dbForConsole->purgeCachedCollection($collection->getId());
|
||||
}
|
||||
Console::info('--Deleting collection (' . $collection->getId() . ') project no (' . $project->getInternalId() . ')');
|
||||
}
|
||||
@@ -121,12 +121,12 @@ class DeleteOrphanedProjects extends Action
|
||||
|
||||
if ($commit) {
|
||||
$dbForConsole->deleteDocument('projects', $project->getId());
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
if ($dbForProject->exists($dbForProject->getDefaultDatabase(), Database::METADATA)) {
|
||||
try {
|
||||
$dbForProject->deleteCollection(Database::METADATA);
|
||||
$dbForProject->deleteCachedCollection(Database::METADATA);
|
||||
$dbForProject->purgeCachedCollection(Database::METADATA);
|
||||
} catch (\Throwable $th) {
|
||||
Console::warning('Metadata collection does not exist');
|
||||
}
|
||||
|
||||
@@ -195,10 +195,10 @@ class Databases extends Action
|
||||
}
|
||||
|
||||
if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) {
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,12 +346,12 @@ class Databases extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
||||
if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,7 +413,7 @@ class Databases extends Action
|
||||
$this->trigger($database, $collection, $index, $project, $projectId, $events);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -471,7 +471,7 @@ class Databases extends Action
|
||||
$this->trigger($database, $collection, $index, $project, $projectId, $events);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $database->getInternalId(), $collection->getId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -526,8 +526,8 @@ class Databases extends Action
|
||||
}
|
||||
$relatedCollection = $dbForProject->getDocument('database_' . $databaseInternalId, $relationship['relatedCollection']);
|
||||
$dbForProject->deleteDocument('attributes', $databaseInternalId . '_' . $relatedCollection->getInternalId() . '_' . $relationship['twoWayKey']);
|
||||
$dbForProject->deleteCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId());
|
||||
$dbForProject->deleteCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId());
|
||||
}
|
||||
|
||||
$dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId());
|
||||
|
||||
@@ -411,8 +411,8 @@ class Deletes extends Action
|
||||
}
|
||||
$relatedCollection = $dbForProject->getDocument('database_' . $databaseInternalId, $relationship['relatedCollection']);
|
||||
$dbForProject->deleteDocument('attributes', $databaseInternalId . '_' . $relatedCollection->getInternalId() . '_' . $relationship['twoWayKey']);
|
||||
$dbForProject->deleteCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId());
|
||||
$dbForProject->deleteCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId());
|
||||
$dbForProject->purgeCachedDocument('database_' . $databaseInternalId, $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $databaseInternalId . '_collection_' . $relatedCollection->getInternalId());
|
||||
}
|
||||
|
||||
$dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $document->getInternalId());
|
||||
@@ -468,7 +468,7 @@ class Deletes extends Action
|
||||
$dbForProject,
|
||||
function (Document $membership) use ($dbForProject) {
|
||||
$userId = $membership->getAttribute('userId');
|
||||
$dbForProject->deleteCachedDocument('users', $userId);
|
||||
$dbForProject->purgeCachedDocument('users', $userId);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -603,7 +603,7 @@ class Deletes extends Action
|
||||
Query::equal('userInternalId', [$userInternalId])
|
||||
], $dbForProject);
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $userId);
|
||||
$dbForProject->purgeCachedDocument('users', $userId);
|
||||
|
||||
// Delete Memberships and decrement team membership counts
|
||||
$this->deleteByGroup('memberships', [
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Appwrite\Platform\Workers;
|
||||
|
||||
use Appwrite\Enum\MessageStatus;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Messaging\Status as MessageStatus;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
@@ -18,6 +18,7 @@ use Utopia\Database\Query;
|
||||
use Utopia\Messaging\Adapter\Email as EmailAdapter;
|
||||
use Utopia\Messaging\Adapter\Email\Mailgun;
|
||||
use Utopia\Messaging\Adapter\Email\Sendgrid;
|
||||
use Utopia\Messaging\Adapter\Email\SMTP;
|
||||
use Utopia\Messaging\Adapter\Push as PushAdapter;
|
||||
use Utopia\Messaging\Adapter\Push\APNS;
|
||||
use Utopia\Messaging\Adapter\Push\FCM;
|
||||
@@ -216,8 +217,8 @@ class Messaging extends Action
|
||||
$batches = \array_chunk($identifiers, $maxBatchSize);
|
||||
$batchIndex = 0;
|
||||
|
||||
return batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex, $dbForProject) {
|
||||
return function () use ($batch, $message, $provider, $adapter, $batchIndex, $dbForProject) {
|
||||
return batch(\array_map(function ($batch) use ($message, $provider, $adapter, &$batchIndex, $dbForProject) {
|
||||
return function () use ($batch, $message, $provider, $adapter, &$batchIndex, $dbForProject) {
|
||||
$deliveredTotal = 0;
|
||||
$deliveryErrors = [];
|
||||
$messageData = clone $message;
|
||||
@@ -407,10 +408,24 @@ class Messaging extends Action
|
||||
|
||||
private function email(Document $provider): ?EmailAdapter
|
||||
{
|
||||
$credentials = $provider->getAttribute('credentials');
|
||||
$credentials = $provider->getAttribute('credentials', []);
|
||||
$options = $provider->getAttribute('options', []);
|
||||
return match ($provider->getAttribute('provider')) {
|
||||
'mock' => new Mock('username', 'password'),
|
||||
'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']),
|
||||
'smtp' => new SMTP(
|
||||
$credentials['host'],
|
||||
$credentials['port'],
|
||||
$credentials['username'],
|
||||
$credentials['password'],
|
||||
$options['encryption'],
|
||||
$options['autoTLS'],
|
||||
$options['mailer'],
|
||||
),
|
||||
'mailgun' => new Mailgun(
|
||||
$credentials['apiKey'],
|
||||
$credentials['domain'],
|
||||
$credentials['isEuRegion']
|
||||
),
|
||||
'sendgrid' => new Sendgrid($credentials['apiKey']),
|
||||
default => null
|
||||
};
|
||||
@@ -418,16 +433,10 @@ class Messaging extends Action
|
||||
|
||||
private function buildEmailMessage(Database $dbForProject, Document $message, Document $provider): Email
|
||||
{
|
||||
$fromName = $provider['options']['fromName'];
|
||||
$fromEmail = $provider['options']['fromEmail'];
|
||||
$replyToEmail = null;
|
||||
$replyToName = null;
|
||||
|
||||
if (isset($provider['options']['replyToName']) && isset($provider['options']['replyToEmail'])) {
|
||||
$replyToName = $provider['options']['replyToName'];
|
||||
$replyToEmail = $provider['options']['replyToEmail'];
|
||||
}
|
||||
|
||||
$fromName = $provider['options']['fromName'] ?? null;
|
||||
$fromEmail = $provider['options']['fromEmail'] ?? null;
|
||||
$replyToEmail = $provider['options']['replyToEmail'] ?? null;
|
||||
$replyToName = $provider['options']['replyToName'] ?? null;
|
||||
$data = $message['data'] ?? [];
|
||||
$ccTargets = $data['cc'] ?? [];
|
||||
$bccTargets = $data['bcc'] ?? [];
|
||||
|
||||
@@ -225,7 +225,7 @@ class Migrations extends Action
|
||||
]);
|
||||
|
||||
$this->dbForConsole->createDocument('keys', $key);
|
||||
$this->dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$this->dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ use Utopia\Queue\Message;
|
||||
class Webhooks extends Action
|
||||
{
|
||||
private array $errors = [];
|
||||
private const MAX_FAILED_ATTEMPTS = 10;
|
||||
private const MAX_FILE_SIZE = 5242880; // 5 MB
|
||||
|
||||
public static function getName(): string
|
||||
@@ -157,19 +156,19 @@ class Webhooks extends Action
|
||||
|
||||
$webhook->setAttribute('logs', $logs);
|
||||
|
||||
if ($attempts >= self::MAX_FAILED_ATTEMPTS) {
|
||||
if ($attempts >= \intval(App::getEnv('_APP_WEBHOOK_MAX_FAILED_ATTEMPTS', '10'))) {
|
||||
$webhook->setAttribute('enabled', false);
|
||||
$this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForConsole, $queueForMails);
|
||||
}
|
||||
|
||||
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
|
||||
$this->errors[] = $logs;
|
||||
} else {
|
||||
$webhook->setAttribute('attempts', 0); // Reset attempts on success
|
||||
$dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook);
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
$dbForConsole->purgeCachedDocument('projects', $project->getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class Token extends Model
|
||||
'default' => '',
|
||||
'example' => self::TYPE_DATETIME_EXAMPLE,
|
||||
])
|
||||
->addRule('securityPhrase', [
|
||||
->addRule('phrase', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.',
|
||||
'default' => '',
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Account;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
trait AccountBase
|
||||
{
|
||||
@@ -147,7 +148,7 @@ trait AccountBase
|
||||
$this->assertNotEmpty($response['body']['userId']);
|
||||
$this->assertNotEmpty($response['body']['expire']);
|
||||
$this->assertEmpty($response['body']['secret']);
|
||||
$this->assertEmpty($response['body']['securityPhrase']);
|
||||
$this->assertEmpty($response['body']['phrase']);
|
||||
|
||||
$userId = $response['body']['userId'];
|
||||
|
||||
@@ -207,21 +208,21 @@ trait AccountBase
|
||||
]), [
|
||||
'userId' => ID::unique(),
|
||||
'email' => 'otpuser@appwrite.io',
|
||||
'securityPhrase' => true
|
||||
'phrase' => true
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 201);
|
||||
$this->assertNotEmpty($response['body']['securityPhrase']);
|
||||
$this->assertNotEmpty($response['body']['phrase']);
|
||||
$this->assertEmpty($response['body']['secret']);
|
||||
$this->assertEquals($userId, $response['body']['userId']);
|
||||
|
||||
$securityPhrase = $response['body']['securityPhrase'];
|
||||
$phrase = $response['body']['phrase'];
|
||||
|
||||
$lastEmail = $this->getLastEmail();
|
||||
$this->assertEquals('otpuser@appwrite.io', $lastEmail['to'][0]['address']);
|
||||
$this->assertEquals('OTP for ' . $this->getProject()['name'] . ' Login', $lastEmail['subject']);
|
||||
$this->assertStringContainsStringIgnoringCase('security phrase', $lastEmail['text']);
|
||||
$this->assertStringContainsStringIgnoringCase($securityPhrase, $lastEmail['text']);
|
||||
$this->assertStringContainsStringIgnoringCase($phrase, $lastEmail['text']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/account/tokens/email', array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
|
||||
@@ -9,6 +9,7 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\SideClient;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
use function sleep;
|
||||
@@ -344,7 +345,9 @@ class AccountCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
|
||||
]), [
|
||||
'queries' => [ 'limit(1)' ],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($responseLimit['headers']['status-code'], 200);
|
||||
@@ -361,7 +364,9 @@ class AccountCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
|
||||
]), [
|
||||
'queries' => [ 'offset(1)' ],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($responseOffset['headers']['status-code'], 200);
|
||||
@@ -378,7 +383,10 @@ class AccountCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
|
||||
]), [
|
||||
'queries' => [ 'limit(1)', 'offset(1)' ],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
Query::limit(1)->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($responseLimitOffset['headers']['status-code'], 200);
|
||||
@@ -2323,7 +2331,7 @@ class AccountCustomClientTest extends Scope
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertEmpty($response['body']['secret']);
|
||||
$this->assertEmpty($response['body']['securityPhrase']);
|
||||
$this->assertEmpty($response['body']['phrase']);
|
||||
$this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire']));
|
||||
|
||||
$userId = $response['body']['userId'];
|
||||
@@ -2391,15 +2399,15 @@ class AccountCustomClientTest extends Scope
|
||||
]), [
|
||||
'userId' => ID::unique(),
|
||||
'email' => $email,
|
||||
'securityPhrase' => true
|
||||
'phrase' => true
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['securityPhrase']);
|
||||
$this->assertNotEmpty($response['body']['phrase']);
|
||||
|
||||
$lastEmail = $this->getLastEmail();
|
||||
$this->assertStringContainsStringIgnoringCase($response['body']['securityPhrase'], $lastEmail['text']);
|
||||
$this->assertStringContainsStringIgnoringCase($response['body']['phrase'], $lastEmail['text']);
|
||||
|
||||
$data['token'] = $token;
|
||||
$data['id'] = $userId;
|
||||
|
||||
@@ -120,6 +120,47 @@ class AccountCustomServerTest extends Scope
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateAccountSession
|
||||
*/
|
||||
public function testGetAccount($data): array
|
||||
{
|
||||
$email = $data['email'] ?? '';
|
||||
$name = $data['name'] ?? '';
|
||||
$session = $data['session'] ?? '';
|
||||
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-session' => $session,
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration']));
|
||||
$this->assertEquals($response['body']['email'], $email);
|
||||
$this->assertEquals($response['body']['name'], $name);
|
||||
$this->assertArrayHasKey('accessedAt', $response['body']);
|
||||
$this->assertNotEmpty($response['body']['accessedAt']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function testCreateAnonymousAccount()
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -6,13 +6,152 @@ use Appwrite\Extend\Exception;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
use Utopia\Validator\JSON;
|
||||
|
||||
trait DatabasesBase
|
||||
{
|
||||
/**
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws \Utopia\Database\Exception\Query
|
||||
*/
|
||||
public function testOrQueries(): void
|
||||
{
|
||||
// Create database
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Or queries'
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($database['body']['$id']);
|
||||
$this->assertEquals(201, $database['headers']['status-code']);
|
||||
$this->assertEquals('Or queries', $database['body']['name']);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create Collection
|
||||
$presidents = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'USA Presidents',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $presidents['headers']['status-code']);
|
||||
$this->assertEquals($presidents['body']['name'], 'USA Presidents');
|
||||
|
||||
// Create Attributes
|
||||
$firstName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $presidents['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'first_name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
$this->assertEquals(202, $firstName['headers']['status-code']);
|
||||
|
||||
$lastName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $presidents['body']['$id'] . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'last_name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $lastName['headers']['status-code']);
|
||||
|
||||
// Wait for worker
|
||||
sleep(2);
|
||||
|
||||
$document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $presidents['body']['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'first_name' => 'Donald',
|
||||
'last_name' => 'Trump',
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]);
|
||||
$this->assertEquals(201, $document1['headers']['status-code']);
|
||||
|
||||
$document2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $presidents['body']['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'first_name' => 'George',
|
||||
'last_name' => 'Bush',
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]);
|
||||
$this->assertEquals(201, $document2['headers']['status-code']);
|
||||
|
||||
$document3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $presidents['body']['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'first_name' => 'Joe',
|
||||
'last_name' => 'Biden',
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $document3['headers']['status-code']);
|
||||
|
||||
$documents = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
'/databases/' . $databaseId . '/collections/' . $presidents['body']['$id'] . '/documents',
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()),
|
||||
[
|
||||
'queries' => [
|
||||
Query::select(['first_name', 'last_name'])->toString(),
|
||||
Query::or([
|
||||
Query::equal('first_name', ['Donald']),
|
||||
Query::equal('last_name', ['Bush'])
|
||||
])->toString(),
|
||||
Query::limit(999)->toString(),
|
||||
Query::offset(0)->toString()
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
$this->assertCount(2, $documents['body']['documents']);
|
||||
}
|
||||
|
||||
public function testCreateDatabase(): array
|
||||
{
|
||||
/**
|
||||
@@ -243,6 +382,18 @@ trait DatabasesBase
|
||||
'twoWayKey' => 'movie'
|
||||
]);
|
||||
|
||||
$integers = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/integer', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'integers',
|
||||
'required' => false,
|
||||
'array' => true,
|
||||
'min' => 10,
|
||||
'max' => 99,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $title['headers']['status-code']);
|
||||
$this->assertEquals($title['body']['key'], 'title');
|
||||
$this->assertEquals($title['body']['type'], 'string');
|
||||
@@ -293,6 +444,13 @@ trait DatabasesBase
|
||||
$this->assertEquals($relationship['body']['twoWay'], true);
|
||||
$this->assertEquals($relationship['body']['twoWayKey'], 'movie');
|
||||
|
||||
$this->assertEquals(202, $integers['headers']['status-code']);
|
||||
$this->assertEquals($integers['body']['key'], 'integers');
|
||||
$this->assertEquals($integers['body']['type'], 'integer');
|
||||
$this->assertArrayNotHasKey('size', $integers['body']);
|
||||
$this->assertEquals($integers['body']['required'], false);
|
||||
$this->assertEquals($integers['body']['array'], true);
|
||||
|
||||
// wait for database worker to create attributes
|
||||
sleep(2);
|
||||
|
||||
@@ -303,7 +461,7 @@ trait DatabasesBase
|
||||
]));
|
||||
|
||||
$this->assertIsArray($movies['body']['attributes']);
|
||||
$this->assertCount(8, $movies['body']['attributes']);
|
||||
$this->assertCount(9, $movies['body']['attributes']);
|
||||
$this->assertEquals($movies['body']['attributes'][0]['key'], $title['body']['key']);
|
||||
$this->assertEquals($movies['body']['attributes'][1]['key'], $description['body']['key']);
|
||||
$this->assertEquals($movies['body']['attributes'][2]['key'], $tagline['body']['key']);
|
||||
@@ -312,6 +470,7 @@ trait DatabasesBase
|
||||
$this->assertEquals($movies['body']['attributes'][5]['key'], $actors['body']['key']);
|
||||
$this->assertEquals($movies['body']['attributes'][6]['key'], $datetime['body']['key']);
|
||||
$this->assertEquals($movies['body']['attributes'][7]['key'], $relationship['body']['key']);
|
||||
$this->assertEquals($movies['body']['attributes'][8]['key'], $integers['body']['key']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
@@ -327,7 +486,11 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'queries' => ['equal("type", "string")', 'limit(2)', 'cursorAfter(title)'],
|
||||
'queries' => [
|
||||
Query::equal('type', ['string'])->toString(),
|
||||
Query::limit(2)->toString(),
|
||||
Query::cursorAfter(new Document(['$id' => 'title']))->toString()
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(2, \count($response['body']['attributes']));
|
||||
@@ -336,7 +499,7 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'queries' => ['select(["key"])'],
|
||||
'queries' => [Query::select(['key'])->toString()],
|
||||
]);
|
||||
$this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
@@ -531,6 +694,29 @@ trait DatabasesBase
|
||||
'twoWayKey' => 'twoWayKey'
|
||||
]);
|
||||
|
||||
$strings = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'names',
|
||||
'size' => 512,
|
||||
'required' => false,
|
||||
'array' => true,
|
||||
]);
|
||||
|
||||
$integers = $this->client->call(Client::METHOD_POST, $attributesPath . '/integer', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'numbers',
|
||||
'required' => false,
|
||||
'array' => true,
|
||||
'min' => 1,
|
||||
'max' => 999,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $string['headers']['status-code']);
|
||||
$this->assertEquals('string', $string['body']['key']);
|
||||
$this->assertEquals('string', $string['body']['type']);
|
||||
@@ -615,6 +801,22 @@ trait DatabasesBase
|
||||
$this->assertEquals(true, $relationship['body']['twoWay']);
|
||||
$this->assertEquals('twoWayKey', $relationship['body']['twoWayKey']);
|
||||
|
||||
$this->assertEquals(202, $strings['headers']['status-code']);
|
||||
$this->assertEquals('names', $strings['body']['key']);
|
||||
$this->assertEquals('string', $strings['body']['type']);
|
||||
$this->assertEquals(false, $strings['body']['required']);
|
||||
$this->assertEquals(true, $strings['body']['array']);
|
||||
$this->assertEquals(null, $strings['body']['default']);
|
||||
|
||||
$this->assertEquals(202, $integers['headers']['status-code']);
|
||||
$this->assertEquals('numbers', $integers['body']['key']);
|
||||
$this->assertEquals('integer', $integers['body']['type']);
|
||||
$this->assertEquals(false, $integers['body']['required']);
|
||||
$this->assertEquals(true, $integers['body']['array']);
|
||||
$this->assertEquals(1, $integers['body']['min']);
|
||||
$this->assertEquals(999, $integers['body']['max']);
|
||||
$this->assertEquals(null, $integers['body']['default']);
|
||||
|
||||
// Wait for database worker to create attributes
|
||||
sleep(5);
|
||||
|
||||
@@ -678,6 +880,18 @@ trait DatabasesBase
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$stringsResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $strings['body']['key'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$integersResponse = $this->client->call(Client::METHOD_GET, $attributesPath . '/' . $integers['body']['key'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $stringResponse['headers']['status-code']);
|
||||
$this->assertEquals($string['body']['key'], $stringResponse['body']['key']);
|
||||
$this->assertEquals($string['body']['type'], $stringResponse['body']['type']);
|
||||
@@ -778,11 +992,11 @@ trait DatabasesBase
|
||||
]));
|
||||
|
||||
$this->assertEquals(200, $attributes['headers']['status-code']);
|
||||
$this->assertEquals(10, $attributes['body']['total']);
|
||||
$this->assertEquals(12, $attributes['body']['total']);
|
||||
|
||||
$attributes = $attributes['body']['attributes'];
|
||||
$this->assertIsArray($attributes);
|
||||
$this->assertCount(10, $attributes);
|
||||
$this->assertCount(12, $attributes);
|
||||
|
||||
$this->assertEquals($stringResponse['body']['key'], $attributes[0]['key']);
|
||||
$this->assertEquals($stringResponse['body']['type'], $attributes[0]['type']);
|
||||
@@ -867,6 +1081,22 @@ trait DatabasesBase
|
||||
$this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']);
|
||||
$this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']);
|
||||
|
||||
$this->assertEquals($stringsResponse['body']['key'], $attributes[10]['key']);
|
||||
$this->assertEquals($stringsResponse['body']['type'], $attributes[10]['type']);
|
||||
$this->assertEquals($stringsResponse['body']['status'], $attributes[10]['status']);
|
||||
$this->assertEquals($stringsResponse['body']['required'], $attributes[10]['required']);
|
||||
$this->assertEquals($stringsResponse['body']['array'], $attributes[10]['array']);
|
||||
$this->assertEquals($stringsResponse['body']['default'], $attributes[10]['default']);
|
||||
|
||||
$this->assertEquals($integersResponse['body']['key'], $attributes[11]['key']);
|
||||
$this->assertEquals($integersResponse['body']['type'], $attributes[11]['type']);
|
||||
$this->assertEquals($integersResponse['body']['status'], $attributes[11]['status']);
|
||||
$this->assertEquals($integersResponse['body']['required'], $attributes[11]['required']);
|
||||
$this->assertEquals($integersResponse['body']['array'], $attributes[11]['array']);
|
||||
$this->assertEquals($integersResponse['body']['default'], $attributes[11]['default']);
|
||||
$this->assertEquals($integersResponse['body']['min'], $attributes[11]['min']);
|
||||
$this->assertEquals($integersResponse['body']['max'], $attributes[11]['max']);
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -878,7 +1108,7 @@ trait DatabasesBase
|
||||
$attributes = $collection['body']['attributes'];
|
||||
|
||||
$this->assertIsArray($attributes);
|
||||
$this->assertCount(10, $attributes);
|
||||
$this->assertCount(12, $attributes);
|
||||
|
||||
$this->assertEquals($stringResponse['body']['key'], $attributes[0]['key']);
|
||||
$this->assertEquals($stringResponse['body']['type'], $attributes[0]['type']);
|
||||
@@ -963,6 +1193,22 @@ trait DatabasesBase
|
||||
$this->assertEquals($relationshipResponse['body']['twoWay'], $attributes[9]['twoWay']);
|
||||
$this->assertEquals($relationshipResponse['body']['twoWayKey'], $attributes[9]['twoWayKey']);
|
||||
|
||||
$this->assertEquals($stringsResponse['body']['key'], $attributes[10]['key']);
|
||||
$this->assertEquals($stringsResponse['body']['type'], $attributes[10]['type']);
|
||||
$this->assertEquals($stringsResponse['body']['status'], $attributes[10]['status']);
|
||||
$this->assertEquals($stringsResponse['body']['required'], $attributes[10]['required']);
|
||||
$this->assertEquals($stringsResponse['body']['array'], $attributes[10]['array']);
|
||||
$this->assertEquals($stringsResponse['body']['default'], $attributes[10]['default']);
|
||||
|
||||
$this->assertEquals($integersResponse['body']['key'], $attributes[11]['key']);
|
||||
$this->assertEquals($integersResponse['body']['type'], $attributes[11]['type']);
|
||||
$this->assertEquals($integersResponse['body']['status'], $attributes[11]['status']);
|
||||
$this->assertEquals($integersResponse['body']['required'], $attributes[11]['required']);
|
||||
$this->assertEquals($integersResponse['body']['array'], $attributes[11]['array']);
|
||||
$this->assertEquals($integersResponse['body']['default'], $attributes[11]['default']);
|
||||
$this->assertEquals($integersResponse['body']['min'], $attributes[11]['min']);
|
||||
$this->assertEquals($integersResponse['body']['max'], $attributes[11]['max']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
@@ -1127,6 +1373,56 @@ trait DatabasesBase
|
||||
$this->assertEquals(400, $tooLong['headers']['status-code']);
|
||||
$this->assertStringContainsString('Index length is longer than the maximum', $tooLong['body']['message']);
|
||||
|
||||
$fulltextArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'key' => 'ft',
|
||||
'type' => 'fulltext',
|
||||
'attributes' => ['actors'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $fulltextArray['headers']['status-code']);
|
||||
$this->assertEquals('"Fulltext" index is forbidden on array attributes', $fulltextArray['body']['message']);
|
||||
|
||||
$actorsArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'key' => 'index-actors',
|
||||
'type' => 'key',
|
||||
'attributes' => ['actors'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $actorsArray['headers']['status-code']);
|
||||
|
||||
$twoLevelsArray = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'key' => 'index-ip-actors',
|
||||
'type' => 'key',
|
||||
'attributes' => ['releaseYear', 'actors'], // 2 levels
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $twoLevelsArray['headers']['status-code']);
|
||||
|
||||
$unknown = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'key' => 'index-unknown',
|
||||
'type' => 'key',
|
||||
'attributes' => ['Unknown'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $unknown['headers']['status-code']);
|
||||
$this->assertEquals('Unknown attribute: Unknown', $unknown['body']['message']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -1141,7 +1437,10 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'queries' => ['equal("type", "key")', 'limit(2)'],
|
||||
'queries' => [
|
||||
Query::equal('type', ['key'])->toString(),
|
||||
Query::limit(2)->toString()
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(2, \count($response['body']['indexes']));
|
||||
@@ -1150,7 +1449,9 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), [
|
||||
'queries' => ['select(["key"])'],
|
||||
'queries' => [
|
||||
Query::select(['key'])->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
@@ -1196,7 +1497,8 @@ trait DatabasesBase
|
||||
'Tom Holland',
|
||||
'Zendaya Maree Stoermer',
|
||||
'Samuel Jackson',
|
||||
]
|
||||
],
|
||||
'integers' => [50,60]
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
@@ -1219,6 +1521,7 @@ trait DatabasesBase
|
||||
'Tom Holland',
|
||||
'Zendaya Maree Stoermer',
|
||||
],
|
||||
'integers' => [50]
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
@@ -1269,6 +1572,8 @@ trait DatabasesBase
|
||||
$this->assertEquals($document2['body']['actors'][1], 'Zendaya Maree Stoermer');
|
||||
$this->assertEquals($document2['body']['actors'][2], 'Samuel Jackson');
|
||||
$this->assertEquals($document2['body']['birthDay'], null);
|
||||
$this->assertEquals($document2['body']['integers'][0], 50);
|
||||
$this->assertEquals($document2['body']['integers'][1], 60);
|
||||
|
||||
$this->assertEquals(201, $document3['headers']['status-code']);
|
||||
$this->assertEquals($data['moviesId'], $document3['body']['$collectionId']);
|
||||
@@ -1305,7 +1610,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderAsc('releaseYear')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1327,7 +1634,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderDesc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderDesc('releaseYear')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1377,7 +1686,7 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'select(["title", "releaseYear", "$id"])',
|
||||
Query::select(['title', 'releaseYear', '$id'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -1411,7 +1720,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['documents'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['documents'][0]['$id']]))->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1423,7 +1734,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['documents'][2]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['documents'][2]['$id']]))->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1436,7 +1749,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderAsc('releaseYear')->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $base['headers']['status-code']);
|
||||
@@ -1449,7 +1764,10 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(),
|
||||
Query::orderAsc('releaseYear')->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1463,7 +1781,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderDesc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderDesc('releaseYear')->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $base['headers']['status-code']);
|
||||
@@ -1476,7 +1796,10 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(),
|
||||
Query::orderDesc('releaseYear')->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1490,7 +1813,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("unknown")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $documents['headers']['status-code']);
|
||||
@@ -1522,7 +1847,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['documents'][2]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['documents'][2]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1534,7 +1861,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['documents'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['documents'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1547,7 +1876,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderAsc('releaseYear')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $base['headers']['status-code']);
|
||||
@@ -1560,7 +1891,10 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(),
|
||||
Query::orderAsc('releaseYear')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1574,7 +1908,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderDesc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderDesc('releaseYear')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $base['headers']['status-code']);
|
||||
@@ -1587,7 +1923,10 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['documents'][1]['$id']]))->toString(),
|
||||
Query::orderDesc('releaseYear')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1607,7 +1946,10 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)', 'orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderAsc('releaseYear')->toString(),
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1618,7 +1960,11 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(2)', 'offset(1)', 'orderAsc("releaseYear")'],
|
||||
'queries' => [
|
||||
Query::orderAsc('releaseYear')->toString(),
|
||||
Query::limit(2)->toString(),
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1639,7 +1985,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['search("title", "Captain America")'],
|
||||
'queries' => [
|
||||
Query::search('title', 'Captain America')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1650,7 +1998,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "' . $documents['body']['documents'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::equal('$id', [$documents['body']['documents'][0]['$id']])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1661,7 +2011,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['search("title", "Homecoming")'],
|
||||
'queries' => [
|
||||
Query::search('title', 'Homecoming')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1672,7 +2024,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['search("title", "spider")'],
|
||||
'queries' => [
|
||||
Query::search('title', 'spider')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1684,7 +2038,21 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("releaseYear", 1944)'],
|
||||
'queries' => [
|
||||
Query::contains('title', ['spi'])->toString(), // like query
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
$this->assertEquals(2, $documents['body']['total']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::equal('releaseYear', [1944])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $documents['body']['documents']);
|
||||
@@ -1694,7 +2062,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['notEqual("releaseYear", 1944)'],
|
||||
'queries' => [
|
||||
Query::notEqual('releaseYear', 1944)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(2, $documents['body']['documents']);
|
||||
@@ -1705,7 +2075,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['greaterThan("$createdAt", "1976-06-12")'],
|
||||
'queries' => [
|
||||
Query::greaterThan('$createdAt', '1976-06-12')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(3, $documents['body']['documents']);
|
||||
@@ -1714,7 +2086,9 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['lessThan("$createdAt", "1976-06-12")'],
|
||||
'queries' => [
|
||||
Query::lessThan('$createdAt', '1976-06-12')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(0, $documents['body']['documents']);
|
||||
@@ -1723,15 +2097,45 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("actors", "Tom Holland")'],
|
||||
'queries' => [
|
||||
Query::contains('actors', ['Tom Holland', 'Samuel Jackson'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
$this->assertEquals(3, $documents['body']['total']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['greaterThan("birthDay", "1960-01-01 10:10:10+02:30")'],
|
||||
'queries' => [
|
||||
Query::contains('actors', ['Tom'])->toString(), // Full-match not like
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
$this->assertEquals(0, $documents['body']['total']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::greaterThan('birthDay', '16/01/2024 12:00:00AM')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $documents['headers']['status-code']);
|
||||
$this->assertEquals('Invalid query: Query value is invalid for attribute "birthDay"', $documents['body']['message']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::greaterThan('birthDay', '1960-01-01 10:10:10+02:30')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
@@ -1739,6 +2143,18 @@ trait DatabasesBase
|
||||
$this->assertEquals('1975-06-12T18:12:55.000+00:00', $documents['body']['documents'][1]['birthDay']);
|
||||
$this->assertCount(2, $documents['body']['documents']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::isNull('integers')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $documents['headers']['status-code']);
|
||||
$this->assertEquals(1, $documents['body']['total']);
|
||||
|
||||
/**
|
||||
* Test for Failure
|
||||
*/
|
||||
@@ -1752,34 +2168,41 @@ trait DatabasesBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("releaseYear", [' . implode(',', $conditions) . '])'],
|
||||
'queries' => [
|
||||
Query::equal('releaseYear', $conditions)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $documents['headers']['status-code']);
|
||||
$this->assertEquals('Invalid query: Query on attribute has greater than 100 values: releaseYear', $documents['body']['message']);
|
||||
|
||||
$conditions = [];
|
||||
$value = '';
|
||||
|
||||
for ($i = 0; $i < 101; $i++) {
|
||||
$conditions[] = "[" . $i . "] Too long title to cross 2k chars query limit";
|
||||
$value .= "[" . $i . "] Too long title to cross 2k chars query limit ";
|
||||
}
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['search("title", ' . implode(',', $conditions) . ')'],
|
||||
'queries' => [
|
||||
Query::search('title', $value)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $documents['headers']['status-code']);
|
||||
// Todo: Not sure what to do we with Query length Test VS old? JSON validator will fails if query string will be truncated?
|
||||
//$this->assertEquals(400, $documents['headers']['status-code']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['search("actors", "Tom")'],
|
||||
'queries' => [
|
||||
Query::search('actors', 'Tom')->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(400, $documents['headers']['status-code']);
|
||||
$this->assertEquals('Searching by attribute "actors" requires a fulltext index.', $documents['body']['message']);
|
||||
$this->assertEquals('Invalid query: Cannot query search on attribute "actors" because it is an array.', $documents['body']['message']);
|
||||
|
||||
return [];
|
||||
}
|
||||
@@ -3520,9 +3943,9 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'equal("library", "library1")',
|
||||
'select(["fullName","library.*"])'
|
||||
]
|
||||
Query::select(['fullName', 'library.*'])->toString(),
|
||||
Query::equal('library', ['library1'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(1, $documents['body']['total']);
|
||||
@@ -3534,7 +3957,7 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'equal("library.libraryName", ["Library 1"])',
|
||||
Query::equal('library.libraryName', ['Library 1'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -4040,10 +4463,10 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'isNotNull("$id")',
|
||||
'startsWith("fullName", "Stevie")',
|
||||
'endsWith("fullName", "Wonder")',
|
||||
'between("$createdAt", "1975-12-06", "2050-12-06")',
|
||||
Query::isNotNull('$id')->toString(),
|
||||
Query::startsWith('fullName', 'Stevie')->toString(),
|
||||
Query::endsWith('fullName', 'Wonder')->toString(),
|
||||
Query::between('$createdAt', '1975-12-06', '2050-12-0')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -4058,9 +4481,9 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'isNotNull("$id")',
|
||||
'isNull("fullName")',
|
||||
'select(["fullName"])'
|
||||
Query::isNotNull('$id')->toString(),
|
||||
Query::isNull('fullName')->toString(),
|
||||
Query::select(['fullName'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -4080,8 +4503,8 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'equal("fullName", "Stevie Wonder")',
|
||||
'select(["fullName"])'
|
||||
Query::equal('fullName', ['Stevie Wonder'])->toString(),
|
||||
Query::select(['fullName'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -4093,7 +4516,7 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'select(["libraries.*", "$id"])',
|
||||
Query::select(['libraries.*', '$id'])->toString(),
|
||||
],
|
||||
]);
|
||||
$document = $response['body']['documents'][0];
|
||||
@@ -4105,7 +4528,7 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
'select(["fullName", "$id"])'
|
||||
Query::select(['fullName', '$id'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -4275,7 +4698,9 @@ trait DatabasesBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-timeout' => 1,
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['notEqual("longtext", "appwrite")'],
|
||||
'queries' => [
|
||||
Query::notEqual('longtext', 'appwrite')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(408, $response['headers']['status-code']);
|
||||
|
||||
@@ -9,6 +9,7 @@ use Tests\E2E\Scopes\SideConsole;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class DatabasesConsoleClientTest extends Scope
|
||||
{
|
||||
@@ -279,6 +280,7 @@ class DatabasesConsoleClientTest extends Scope
|
||||
|
||||
/**
|
||||
* @depends testCreateCollection
|
||||
* @throws \Utopia\Database\Exception\Query
|
||||
*/
|
||||
public function testGetCollectionLogs(array $data)
|
||||
{
|
||||
@@ -299,7 +301,7 @@ class DatabasesConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)']
|
||||
'queries' => [Query::limit(1)->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $logs['headers']['status-code']);
|
||||
@@ -311,7 +313,7 @@ class DatabasesConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)']
|
||||
'queries' => [Query::offset(1)->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $logs['headers']['status-code']);
|
||||
@@ -322,7 +324,7 @@ class DatabasesConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)', 'limit(1)']
|
||||
'queries' => [Query::offset(1)->toString(), Query::limit(1)->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $logs['headers']['status-code']);
|
||||
|
||||
@@ -7,9 +7,11 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideServer;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class DatabasesCustomServerTest extends Scope
|
||||
{
|
||||
@@ -57,7 +59,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $databases['headers']['status-code']);
|
||||
$this->assertCount(1, $databases['body']['databases']);
|
||||
@@ -66,7 +70,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)'],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $databases['headers']['status-code']);
|
||||
$this->assertCount(1, $databases['body']['databases']);
|
||||
@@ -75,7 +81,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("name", ["Test 1", "Test 2"])'],
|
||||
'queries' => [
|
||||
Query::equal('name', ['Test 1', 'Test 2'])->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $databases['headers']['status-code']);
|
||||
$this->assertCount(2, $databases['body']['databases']);
|
||||
@@ -84,7 +92,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("name", "Test 2")'],
|
||||
'queries' => [
|
||||
Query::equal('name', ['Test 2'])->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $databases['headers']['status-code']);
|
||||
$this->assertCount(1, $databases['body']['databases']);
|
||||
@@ -93,7 +103,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "first")'],
|
||||
'queries' => [
|
||||
Query::equal('$id', ['first'])->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $databases['headers']['status-code']);
|
||||
$this->assertCount(1, $databases['body']['databases']);
|
||||
@@ -105,7 +117,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderDesc("")'],
|
||||
'queries' => [
|
||||
Query::orderDesc()->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(2, $databases['body']['total']);
|
||||
@@ -124,7 +138,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['databases'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['databases'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $databases['body']['databases']);
|
||||
@@ -134,7 +150,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['databases'][1]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['databases'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(0, $databases['body']['databases']);
|
||||
@@ -152,7 +170,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['databases'][1]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['databases'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $databases['body']['databases']);
|
||||
@@ -162,7 +182,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['databases'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['databases'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(0, $databases['body']['databases']);
|
||||
@@ -208,7 +230,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("unknown")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
@@ -375,7 +399,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)']
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $collections['headers']['status-code']);
|
||||
@@ -385,7 +411,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)']
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $collections['headers']['status-code']);
|
||||
@@ -395,7 +423,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("enabled", true)']
|
||||
'queries' => [
|
||||
Query::equal('enabled', [true])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $collections['headers']['status-code']);
|
||||
@@ -405,7 +435,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("enabled", false)']
|
||||
'queries' => [
|
||||
Query::equal('enabled', [false])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $collections['headers']['status-code']);
|
||||
@@ -418,7 +450,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderDesc("")'],
|
||||
'queries' => [
|
||||
Query::orderDesc()->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(2, $collections['body']['total']);
|
||||
@@ -437,7 +471,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['collections'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['collections'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $collections['body']['collections']);
|
||||
@@ -447,7 +483,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $base['body']['collections'][1]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['collections'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(0, $collections['body']['collections']);
|
||||
@@ -465,7 +503,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['collections'][1]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['collections'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(1, $collections['body']['collections']);
|
||||
@@ -475,7 +515,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("' . $base['body']['collections'][0]['$id'] . '")'],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['collections'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(0, $collections['body']['collections']);
|
||||
@@ -521,7 +563,9 @@ class DatabasesCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("unknown")'],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
@@ -1376,7 +1420,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
// Test indexLimit = 64
|
||||
// MariaDB, MySQL, and MongoDB create 5 indexes per new collection
|
||||
// Add up to the limit, then check if the next index throws IndexLimitException
|
||||
for ($i = 0; $i < 59; $i++) {
|
||||
for ($i = 0; $i < 58; $i++) {
|
||||
// $this->assertEquals(true, static::getDatabase()->createIndex('indexLimit', "index{$i}", Database::INDEX_KEY, ["test{$i}"], [16]));
|
||||
$index = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1405,7 +1449,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertIsArray($collection['body']['attributes']);
|
||||
$this->assertIsArray($collection['body']['indexes']);
|
||||
$this->assertCount(64, $collection['body']['attributes']);
|
||||
$this->assertCount(59, $collection['body']['indexes']);
|
||||
$this->assertCount(58, $collection['body']['indexes']);
|
||||
|
||||
$tooMany = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
||||
@@ -7,8 +7,10 @@ use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideClient;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class FunctionsCustomClientTest extends Scope
|
||||
{
|
||||
@@ -474,7 +476,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $apikey,
|
||||
], [
|
||||
'queries' => [ 'limit(1)' ]
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $executions['headers']['status-code']);
|
||||
@@ -485,7 +489,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $apikey,
|
||||
], [
|
||||
'queries' => [ 'offset(1)' ]
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $executions['headers']['status-code']);
|
||||
@@ -496,7 +502,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $apikey,
|
||||
], [
|
||||
'queries' => [ 'equal("status", ["completed"])' ]
|
||||
'queries' => [
|
||||
Query::equal('status', ['completed'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $executions['headers']['status-code']);
|
||||
@@ -507,7 +515,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $apikey,
|
||||
], [
|
||||
'queries' => [ 'equal("status", ["failed"])' ]
|
||||
'queries' => [
|
||||
Query::equal('status', ['failed'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $executions['headers']['status-code']);
|
||||
@@ -518,7 +528,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $apikey,
|
||||
], [
|
||||
'queries' => [ 'cursorAfter("' . $base['body']['executions'][0]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $base['body']['executions'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(2, $executions['body']['executions']);
|
||||
@@ -529,7 +541,9 @@ class FunctionsCustomClientTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-key' => $apikey,
|
||||
], [
|
||||
'queries' => [ 'cursorBefore("' . $base['body']['executions'][1]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $base['body']['executions'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
// Cleanup : Delete function
|
||||
|
||||
@@ -9,7 +9,9 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideServer;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
class FunctionsCustomServerTest extends Scope
|
||||
@@ -121,7 +123,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ]
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -131,7 +135,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ]
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -141,7 +147,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("enabled", true)' ]
|
||||
'queries' => [
|
||||
Query::equal('enabled', [true])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -151,7 +159,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("enabled", false)' ]
|
||||
'queries' => [
|
||||
Query::equal('enabled', [false])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -244,7 +254,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("' . $functions['body']['functions'][0]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $functions['body']['functions'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -255,7 +267,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorBefore("' . $functions['body']['functions'][1]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $functions['body']['functions'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -269,7 +283,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("unknown")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -532,7 +548,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ]
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($function['headers']['status-code'], 200);
|
||||
@@ -542,7 +560,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ]
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($function['headers']['status-code'], 200);
|
||||
@@ -552,7 +572,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("entrypoint", "index.php")' ]
|
||||
'queries' => [
|
||||
Query::equal('entrypoint', ['index.php'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($function['headers']['status-code'], 200);
|
||||
@@ -562,7 +584,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("entrypoint", "index.js")' ]
|
||||
'queries' => [
|
||||
Query::equal('entrypoint', ['index.js'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($function['headers']['status-code'], 200);
|
||||
@@ -690,7 +714,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ]
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -700,7 +726,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ]
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -710,7 +738,9 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("trigger", "http")' ]
|
||||
'queries' => [
|
||||
Query::equal('trigger', ['http'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -1459,7 +1489,10 @@ class FunctionsCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("resourceId", "' . $functionId . '")', 'equal("resourceType", "function")' ]
|
||||
'queries' => [
|
||||
Query::equal('resourceId', [$functionId])->toString(),
|
||||
Query::equal('resourceType', ['function'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $rules['headers']['status-code']);
|
||||
|
||||
@@ -29,7 +29,7 @@ class AvatarsTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertEquals(18767, \strlen($creditCardIcon['body']));
|
||||
$this->assertEquals(18546, \strlen($creditCardIcon['body']));
|
||||
|
||||
return $creditCardIcon['body'];
|
||||
}
|
||||
@@ -50,7 +50,7 @@ class AvatarsTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertEquals(11100, \strlen($browserIcon['body']));
|
||||
$this->assertEquals(13312, \strlen($browserIcon['body']));
|
||||
|
||||
return $browserIcon['body'];
|
||||
}
|
||||
@@ -71,7 +71,7 @@ class AvatarsTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertEquals(7460, \strlen($countryFlag['body']));
|
||||
$this->assertEquals(8814, \strlen($countryFlag['body']));
|
||||
|
||||
return $countryFlag['body'];
|
||||
}
|
||||
@@ -92,7 +92,7 @@ class AvatarsTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertEquals(36036, \strlen($image['body']));
|
||||
$this->assertEquals(52585, \strlen($image['body']));
|
||||
|
||||
return $image['body'];
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class AvatarsTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertEquals(14771, \strlen($qrCode['body']));
|
||||
$this->assertEquals(29428, \strlen($qrCode['body']));
|
||||
|
||||
return $qrCode['body'];
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class AvatarsTest extends Scope
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertEquals(5041, \strlen($initials['body']));
|
||||
$this->assertEquals(5025, \strlen($initials['body']));
|
||||
|
||||
return $initials['body'];
|
||||
}
|
||||
|
||||
@@ -207,6 +207,7 @@ trait Base
|
||||
// Providers
|
||||
public static string $CREATE_MAILGUN_PROVIDER = 'create_mailgun_provider';
|
||||
public static string $CREATE_SENDGRID_PROVIDER = 'create_sendgrid_provider';
|
||||
public static string $CREATE_SMTP_PROVIDER = 'create_smtp_provider';
|
||||
public static string $CREATE_TWILIO_PROVIDER = 'create_twilio_provider';
|
||||
public static string $CREATE_TELESIGN_PROVIDER = 'create_telesign_provider';
|
||||
public static string $CREATE_TEXTMAGIC_PROVIDER = 'create_textmagic_provider';
|
||||
@@ -218,6 +219,7 @@ trait Base
|
||||
public static string $GET_PROVIDER = 'get_provider';
|
||||
public static string $UPDATE_MAILGUN_PROVIDER = 'update_mailgun_provider';
|
||||
public static string $UPDATE_SENDGRID_PROVIDER = 'update_sendgrid_provider';
|
||||
public static string $UPDATE_SMTP_PROVIDER = 'update_smtp_provider';
|
||||
public static string $UPDATE_TWILIO_PROVIDER = 'update_twilio_provider';
|
||||
public static string $UPDATE_TELESIGN_PROVIDER = 'update_telesign_provider';
|
||||
public static string $UPDATE_TEXTMAGIC_PROVIDER = 'update_textmagic_provider';
|
||||
@@ -1809,6 +1811,16 @@ trait Base
|
||||
enabled
|
||||
}
|
||||
}';
|
||||
case self::$CREATE_SMTP_PROVIDER:
|
||||
return 'mutation createSMTPProvider($providerId: String!, $name: String!, $host: String!, $port: Int!, $username: String!, $password: String!, $encryption: String!, $autoTLS: Boolean! $fromName: String!, $fromEmail: String!, $replyToName: String, $replyToEmail: String) {
|
||||
messagingCreateSMTPProvider(providerId: $providerId, name: $name, host: $host, port: $port, username: $username, password: $password, encryption: $encryption, autoTLS: $autoTLS, fromName: $fromName, fromEmail: $fromEmail, replyToName: $replyToName, replyToEmail: $replyToEmail) {
|
||||
_id
|
||||
name
|
||||
provider
|
||||
type
|
||||
enabled
|
||||
}
|
||||
}';
|
||||
case self::$CREATE_TWILIO_PROVIDER:
|
||||
return 'mutation createTwilioProvider($providerId: String!, $name: String!, $from: String!, $accountSid: String!, $authToken: String!) {
|
||||
messagingCreateTwilioProvider(providerId: $providerId, name: $name, from: $from, accountSid: $accountSid, authToken: $authToken) {
|
||||
@@ -1923,6 +1935,16 @@ trait Base
|
||||
enabled
|
||||
}
|
||||
}';
|
||||
case self::$UPDATE_SMTP_PROVIDER:
|
||||
return 'mutation updateSMTPProvider($providerId: String!, $name: String!, $host: String!, $port: Int!, $username: String!, $password: String!, $encryption: String!, $autoTLS: Boolean!, $fromName: String, $fromEmail: String, $enabled: Boolean) {
|
||||
messagingUpdateSMTPProvider(providerId: $providerId, name: $name, host: $host, port: $port, username: $username, password: $password, encryption: $encryption, autoTLS: $autoTLS, fromName: $fromName, fromEmail: $fromEmail, enabled: $enabled) {
|
||||
_id
|
||||
name
|
||||
provider
|
||||
type
|
||||
enabled
|
||||
}
|
||||
}';
|
||||
case self::$UPDATE_TWILIO_PROVIDER:
|
||||
return 'mutation updateTwilioProvider($providerId: String!, $name: String!, $accountSid: String!, $authToken: String!) {
|
||||
messagingUpdateTwilioProvider(providerId: $providerId, name: $name, accountSid: $accountSid, authToken: $authToken) {
|
||||
@@ -2000,11 +2022,10 @@ trait Base
|
||||
}
|
||||
}';
|
||||
case self::$CREATE_TOPIC:
|
||||
return 'mutation createTopic($topicId: String!, $name: String!, $description: String!) {
|
||||
messagingCreateTopic(topicId: $topicId, name: $name, description: $description) {
|
||||
return 'mutation createTopic($topicId: String!, $name: String!) {
|
||||
messagingCreateTopic(topicId: $topicId, name: $name) {
|
||||
_id
|
||||
name
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$LIST_TOPICS:
|
||||
@@ -2014,7 +2035,6 @@ trait Base
|
||||
topics {
|
||||
_id
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}';
|
||||
@@ -2023,15 +2043,13 @@ trait Base
|
||||
messagingGetTopic(topicId: $topicId) {
|
||||
_id
|
||||
name
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$UPDATE_TOPIC:
|
||||
return 'mutation updateTopic($topicId: String!, $name: String!, $description: String!) {
|
||||
messagingUpdateTopic(topicId: $topicId, name: $name, description: $description) {
|
||||
return 'mutation updateTopic($topicId: String!, $name: String!) {
|
||||
messagingUpdateTopic(topicId: $topicId, name: $name) {
|
||||
_id
|
||||
name
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$DELETE_TOPIC:
|
||||
@@ -2098,8 +2116,8 @@ trait Base
|
||||
}
|
||||
}';
|
||||
case self::$CREATE_EMAIL:
|
||||
return 'mutation createEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String!, $content: String!, $status: String, $description: String, $html: Boolean, $cc: [String], $bcc: [String], $scheduledAt: String) {
|
||||
messagingCreateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, cc: $cc, bcc: $bcc, scheduledAt: $scheduledAt) {
|
||||
return 'mutation createEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String!, $content: String!, $status: String, $html: Boolean, $cc: [String], $bcc: [String], $scheduledAt: String) {
|
||||
messagingCreateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, html: $html, cc: $cc, bcc: $bcc, scheduledAt: $scheduledAt) {
|
||||
_id
|
||||
topics
|
||||
users
|
||||
@@ -2109,12 +2127,11 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$CREATE_SMS:
|
||||
return 'mutation createSMS($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $content: String!, $status: String, $description: String, $scheduledAt: String) {
|
||||
messagingCreateSMS(messageId: $messageId, topics: $topics, users: $users, targets: $targets, content: $content, status: $status, description: $description, scheduledAt: $scheduledAt) {
|
||||
return 'mutation createSMS($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $content: String!, $status: String, $scheduledAt: String) {
|
||||
messagingCreateSMS(messageId: $messageId, topics: $topics, users: $users, targets: $targets, content: $content, status: $status, scheduledAt: $scheduledAt) {
|
||||
_id
|
||||
topics
|
||||
users
|
||||
@@ -2124,12 +2141,11 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$CREATE_PUSH_NOTIFICATION:
|
||||
return 'mutation createPushNotification($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $title: String!, $body: String!, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $description: String, $scheduledAt: String) {
|
||||
messagingCreatePushNotification(messageId: $messageId, topics: $topics, users: $users, targets: $targets, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, description: $description, scheduledAt: $scheduledAt) {
|
||||
return 'mutation createPushNotification($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $title: String!, $body: String!, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $scheduledAt: String) {
|
||||
messagingCreatePushNotification(messageId: $messageId, topics: $topics, users: $users, targets: $targets, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, scheduledAt: $scheduledAt) {
|
||||
_id
|
||||
topics
|
||||
users
|
||||
@@ -2139,7 +2155,6 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$LIST_MESSAGES:
|
||||
@@ -2157,7 +2172,6 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}
|
||||
}';
|
||||
@@ -2174,12 +2188,11 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$UPDATE_EMAIL:
|
||||
return 'mutation updateEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String, $content: String, $status: String, $description: String, $html: Boolean, $cc: [String], $bcc: [String], $scheduledAt: String) {
|
||||
messagingUpdateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, cc: $cc, bcc: $bcc, scheduledAt: $scheduledAt) {
|
||||
return 'mutation updateEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String, $content: String, $status: String, , $html: Boolean, $cc: [String], $bcc: [String], $scheduledAt: String) {
|
||||
messagingUpdateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, html: $html, cc: $cc, bcc: $bcc, scheduledAt: $scheduledAt) {
|
||||
_id
|
||||
topics
|
||||
users
|
||||
@@ -2189,12 +2202,11 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$UPDATE_SMS:
|
||||
return 'mutation updateSMS($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $content: String, $status: String, $description: String, $scheduledAt: String) {
|
||||
messagingUpdateSMS(messageId: $messageId, topics: $topics, users: $users, targets: $targets, content: $content, status: $status, description: $description, scheduledAt: $scheduledAt) {
|
||||
return 'mutation updateSMS($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $content: String, $status: String, $scheduledAt: String) {
|
||||
messagingUpdateSMS(messageId: $messageId, topics: $topics, users: $users, targets: $targets, content: $content, status: $status, scheduledAt: $scheduledAt) {
|
||||
_id
|
||||
topics
|
||||
users
|
||||
@@ -2204,12 +2216,11 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$UPDATE_PUSH_NOTIFICATION:
|
||||
return 'mutation updatePushNotification($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $title: String, $body: String, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $description: String, $scheduledAt: String) {
|
||||
messagingUpdatePushNotification(messageId: $messageId, topics: $topics, users: $users, targets: $targets, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, description: $description, scheduledAt: $scheduledAt) {
|
||||
return 'mutation updatePushNotification($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $title: String, $body: String, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $scheduledAt: String) {
|
||||
messagingUpdatePushNotification(messageId: $messageId, topics: $topics, users: $users, targets: $targets, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, scheduledAt: $scheduledAt) {
|
||||
_id
|
||||
topics
|
||||
users
|
||||
@@ -2219,7 +2230,6 @@ trait Base
|
||||
deliveryErrors
|
||||
deliveredTotal
|
||||
status
|
||||
description
|
||||
}
|
||||
}';
|
||||
case self::$COMPLEX_QUERY:
|
||||
|
||||
@@ -285,7 +285,6 @@ class MessagingTest extends Scope
|
||||
'variables' => [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Active users',
|
||||
],
|
||||
];
|
||||
$response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
@@ -296,7 +295,6 @@ class MessagingTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('topic1', $response['body']['data']['messagingCreateTopic']['name']);
|
||||
$this->assertEquals('Active users', $response['body']['data']['messagingCreateTopic']['description']);
|
||||
|
||||
return $response['body']['data']['messagingCreateTopic'];
|
||||
}
|
||||
@@ -313,7 +311,6 @@ class MessagingTest extends Scope
|
||||
'variables' => [
|
||||
'topicId' => $topicId,
|
||||
'name' => 'topic2',
|
||||
'description' => 'Inactive users',
|
||||
],
|
||||
];
|
||||
$response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
@@ -324,7 +321,6 @@ class MessagingTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('topic2', $response['body']['data']['messagingUpdateTopic']['name']);
|
||||
$this->assertEquals('Inactive users', $response['body']['data']['messagingUpdateTopic']['description']);
|
||||
|
||||
return $topicId;
|
||||
}
|
||||
@@ -368,7 +364,6 @@ class MessagingTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('topic2', $response['body']['data']['messagingGetTopic']['name']);
|
||||
$this->assertEquals('Inactive users', $response['body']['data']['messagingGetTopic']['description']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,7 +589,6 @@ class MessagingTest extends Scope
|
||||
'variables' => [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Active users',
|
||||
],
|
||||
];
|
||||
$topic = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
@@ -801,7 +795,6 @@ class MessagingTest extends Scope
|
||||
'variables' => [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Active users',
|
||||
],
|
||||
];
|
||||
$topic = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
@@ -1006,7 +999,6 @@ class MessagingTest extends Scope
|
||||
'variables' => [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Active users',
|
||||
],
|
||||
];
|
||||
$topic = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
|
||||
@@ -34,7 +34,7 @@ class ScopeTest extends Scope
|
||||
'x-appwrite-key' => $apiKey,
|
||||
], $gqlPayload);
|
||||
|
||||
$message = "app.${projectId}@service.localhost (role: applications) missing scope (databases.write)";
|
||||
$message = "app.{$projectId}@service.localhost (role: applications) missing scope (databases.write)";
|
||||
$this->assertArrayHasKey('errors', $database['body']);
|
||||
$this->assertEquals($message, $database['body']['errors'][0]['message']);
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ class UsersTest extends Scope
|
||||
'query' => $query,
|
||||
'variables' => [
|
||||
'queries' => [
|
||||
'limit(100)',
|
||||
'offset(0)',
|
||||
Query::limit(100)->toString(),
|
||||
Query::offset(0)->toString(),
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
namespace Tests\E2E\Services\Messaging;
|
||||
|
||||
use Appwrite\Enum\MessageStatus;
|
||||
use Appwrite\Messaging\Status as MessageStatus;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\DSN\DSN;
|
||||
|
||||
trait MessagingBase
|
||||
@@ -28,6 +29,17 @@ trait MessagingBase
|
||||
'fromEmail' => 'sender-email@my-domain.com',
|
||||
'isEuRegion' => false,
|
||||
],
|
||||
'smtp' => [
|
||||
'providerId' => ID::unique(),
|
||||
'name' => 'SMTP1',
|
||||
'host' => 'smtp.appwrite.io',
|
||||
'port' => 587,
|
||||
'security' => 'tls',
|
||||
'username' => 'my-username',
|
||||
'password' => 'my-password',
|
||||
'fromName' => 'sender name',
|
||||
'fromEmail' => 'tester@appwrite.io',
|
||||
],
|
||||
'twilio' => [
|
||||
'providerId' => ID::unique(),
|
||||
'name' => 'Twilio1',
|
||||
@@ -114,6 +126,14 @@ trait MessagingBase
|
||||
'apiKey' => 'my-apikey',
|
||||
'domain' => 'my-domain',
|
||||
],
|
||||
'smtp' => [
|
||||
'name' => 'SMTP2',
|
||||
'host' => 'smtp.appwrite.io',
|
||||
'port' => 587,
|
||||
'security' => 'tls',
|
||||
'username' => 'my-username',
|
||||
'password' => 'my-password',
|
||||
],
|
||||
'twilio' => [
|
||||
'name' => 'Twilio2',
|
||||
'accountSid' => 'my-accountSid',
|
||||
@@ -223,7 +243,7 @@ trait MessagingBase
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(10, \count($response['body']['providers']));
|
||||
$this->assertEquals(11, \count($response['body']['providers']));
|
||||
|
||||
return $providers;
|
||||
}
|
||||
@@ -269,7 +289,6 @@ trait MessagingBase
|
||||
]);
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals('my-app', $response['body']['name']);
|
||||
$this->assertEquals('', $response['body']['description']);
|
||||
|
||||
return $response['body'];
|
||||
}
|
||||
@@ -285,11 +304,9 @@ trait MessagingBase
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'name' => 'android-app',
|
||||
'description' => 'updated-description'
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('android-app', $response['body']['name']);
|
||||
$this->assertEquals('updated-description', $response['body']['description']);
|
||||
return $response['body']['$id'];
|
||||
}
|
||||
|
||||
@@ -298,24 +315,13 @@ trait MessagingBase
|
||||
*/
|
||||
public function testListTopic(string $topicId)
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/topics', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'search' => 'updated-description',
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, \count($response['body']['topics']));
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/topics', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => [
|
||||
'equal("total", [0])'
|
||||
Query::equal('total', [0])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -328,7 +334,7 @@ trait MessagingBase
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => [
|
||||
'greaterThan("total", 0)'
|
||||
Query::greaterThan('total', 0)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -350,7 +356,6 @@ trait MessagingBase
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('android-app', $response['body']['name']);
|
||||
$this->assertEquals('updated-description', $response['body']['description']);
|
||||
$this->assertEquals(0, $response['body']['total']);
|
||||
}
|
||||
|
||||
@@ -407,7 +412,6 @@ trait MessagingBase
|
||||
|
||||
$this->assertEquals(200, $topic['headers']['status-code']);
|
||||
$this->assertEquals('android-app', $topic['body']['name']);
|
||||
$this->assertEquals('updated-description', $topic['body']['description']);
|
||||
$this->assertEquals(1, $topic['body']['total']);
|
||||
|
||||
return [
|
||||
@@ -519,7 +523,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['limit(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -532,7 +538,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['offset(1)'],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -544,7 +552,10 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['limit(1)', 'offset(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -560,7 +571,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['limit(-1)']
|
||||
'queries' => [
|
||||
Query::limit(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -570,7 +583,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['offset(-1)']
|
||||
'queries' => [
|
||||
Query::offset(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -580,7 +595,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['equal("$id", "asdf")']
|
||||
'queries' => [
|
||||
Query::equal('$id', ['asdf'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -590,7 +607,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['orderAsc("$id")']
|
||||
'queries' => [
|
||||
Query::orderAsc('$id')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -600,7 +619,9 @@ trait MessagingBase
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'queries' => ['cursorAsc("$id")']
|
||||
'queries' => [
|
||||
'{ "method": "cursorAsc", "attribute": "$id" }'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -626,7 +647,6 @@ trait MessagingBase
|
||||
|
||||
$this->assertEquals(200, $topic['headers']['status-code']);
|
||||
$this->assertEquals('android-app', $topic['body']['name']);
|
||||
$this->assertEquals('updated-description', $topic['body']['description']);
|
||||
$this->assertEquals(0, $topic['body']['total']);
|
||||
}
|
||||
|
||||
@@ -643,6 +663,60 @@ trait MessagingBase
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDraftEmail
|
||||
*/
|
||||
public function testListTargets(array $message)
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/messages/does_not_exist/targets', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $message['$id'] . '/targets', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$targetList = $response['body'];
|
||||
$this->assertEquals(1, $targetList['total']);
|
||||
$this->assertEquals(1, count($targetList['targets']));
|
||||
$this->assertEquals($message['targets'][0], $targetList['targets'][0]['$id']);
|
||||
|
||||
// Test for empty targets
|
||||
$response = $this->client->call(Client::METHOD_POST, '/messaging/messages/email', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'messageId' => ID::unique(),
|
||||
'subject' => 'New blog post',
|
||||
'content' => 'Check out the new blog post at http://localhost',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
$message = $response['body'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $message['$id'] . '/targets', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$targetList = $response['body'];
|
||||
$this->assertEquals(0, $targetList['total']);
|
||||
$this->assertEquals(0, count($targetList['targets']));
|
||||
}
|
||||
|
||||
public function testCreateDraftEmail()
|
||||
{
|
||||
// Create User
|
||||
@@ -660,7 +734,7 @@ trait MessagingBase
|
||||
$this->assertEquals(201, $response['headers']['status-code'], "Error creating user: " . var_export($response['body'], true));
|
||||
|
||||
$user = $response['body'];
|
||||
var_dump($user);
|
||||
|
||||
$this->assertEquals(1, \count($user['targets']));
|
||||
$targetId = $user['targets'][0]['$id'];
|
||||
|
||||
@@ -724,7 +798,6 @@ trait MessagingBase
|
||||
], [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Test Topic'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $topic['headers']['status-code']);
|
||||
@@ -746,7 +819,6 @@ trait MessagingBase
|
||||
// Get target
|
||||
$target = $user['body']['targets'][0];
|
||||
|
||||
|
||||
// Create Subscriber
|
||||
$subscriber = $this->client->call(Client::METHOD_POST, '/messaging/topics/' . $topic['body']['$id'] . '/subscribers', \array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -785,14 +857,19 @@ trait MessagingBase
|
||||
$this->assertEquals(1, $message['body']['deliveredTotal']);
|
||||
$this->assertEquals(0, \count($message['body']['deliveryErrors']));
|
||||
|
||||
return $message;
|
||||
return [
|
||||
'message' => $email['body'],
|
||||
'topic' => $topic['body'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testSendEmail
|
||||
*/
|
||||
public function testUpdateEmail(array $email): void
|
||||
public function testUpdateEmail(array $params): void
|
||||
{
|
||||
$email = $params['message'];
|
||||
|
||||
$message = $this->client->call(Client::METHOD_PATCH, '/messaging/messages/email/' . $email['body']['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -881,7 +958,6 @@ trait MessagingBase
|
||||
], [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Test Topic'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $topic['headers']['status-code']);
|
||||
@@ -1042,7 +1118,6 @@ trait MessagingBase
|
||||
], [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'topic1',
|
||||
'description' => 'Test Topic'
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $topic['headers']['status-code']);
|
||||
@@ -1170,56 +1245,50 @@ trait MessagingBase
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDraftEmail
|
||||
* @depends testSendEmail
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testListTargets(array $message)
|
||||
public function testDeleteMessage(array $params): void
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/messages/does_not_exist/targets', [
|
||||
$message = $params['message'];
|
||||
$topic = $params['topic'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/messaging/messages/' . $message['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $message['$id'] . '/targets', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$targetList = $response['body'];
|
||||
$this->assertEquals(1, $targetList['total']);
|
||||
$this->assertEquals(1, count($targetList['targets']));
|
||||
$this->assertEquals($message['targets'][0], $targetList['targets'][0]['$id']);
|
||||
|
||||
// Test for empty targets
|
||||
// Test for FAILURE
|
||||
$response = $this->client->call(Client::METHOD_POST, '/messaging/messages/email', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'messageId' => ID::unique(),
|
||||
'subject' => 'New blog post',
|
||||
'content' => 'Check out the new blog post at http://localhost',
|
||||
'status' => 'processing',
|
||||
'topics' => [$topic['$id']],
|
||||
'subject' => 'Test subject',
|
||||
'content' => 'Test content',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
$message = $response['body'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $message['$id'] . '/targets', [
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/messaging/messages/' . $response['body']['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
$targetList = $response['body'];
|
||||
$this->assertEquals(0, $targetList['total']);
|
||||
$this->assertEquals(0, count($targetList['targets']));
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/messaging/messages/does_not_exist', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideConsole;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class MessagingConsoleClientTest extends Scope
|
||||
{
|
||||
@@ -67,7 +68,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -79,7 +82,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)'],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -90,7 +95,10 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)', 'offset(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -105,7 +113,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(-1)']
|
||||
'queries' => [
|
||||
Query::limit(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -114,7 +124,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(-1)']
|
||||
'queries' => [
|
||||
Query::offset(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -123,7 +135,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "asdf")']
|
||||
'queries' => [
|
||||
Query::equal('$id', ['asdf'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -132,7 +146,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("$id")']
|
||||
'queries' => [
|
||||
Query::orderAsc('$id')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -141,7 +157,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAsc("$id")']
|
||||
'queries' => [
|
||||
'{ "method": "cursorAsc", "attribute":"$id" }'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -170,7 +188,6 @@ class MessagingConsoleClientTest extends Scope
|
||||
], $this->getHeaders()), [
|
||||
'topicId' => ID::unique(),
|
||||
'name' => 'my-app',
|
||||
'description' => 'web app'
|
||||
]);
|
||||
$this->assertEquals(201, $topic['headers']['status-code']);
|
||||
|
||||
@@ -178,7 +195,7 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'description' => 'updated-description'
|
||||
'name' => 'android-app'
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -197,7 +214,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -209,7 +228,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)'],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -220,7 +241,10 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)', 'offset(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -235,7 +259,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(-1)']
|
||||
'queries' => [
|
||||
Query::limit(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -244,7 +270,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(-1)']
|
||||
'queries' => [
|
||||
Query::offset(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -253,7 +281,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "asdf")']
|
||||
'queries' => [
|
||||
Query::equal('$id', ['asdf'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -262,7 +292,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("$id")']
|
||||
'queries' => [
|
||||
Query::orderAsc('$id')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -271,7 +303,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAsc("$id")']
|
||||
'queries' => [
|
||||
'{"method":"cursorAsc","attribute":"$id","values":[]}'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -331,7 +365,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -343,7 +379,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)'],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -354,7 +392,10 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)', 'offset(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -369,7 +410,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(-1)']
|
||||
'queries' => [
|
||||
Query::limit(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -378,7 +421,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(-1)']
|
||||
'queries' => [
|
||||
Query::offset(-1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -387,7 +432,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "asdf")']
|
||||
'queries' => [
|
||||
Query::equal('$id', ['asdf'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -396,7 +443,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("$id")']
|
||||
'queries' => [
|
||||
Query::orderAsc('$id')->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -405,7 +454,9 @@ class MessagingConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAsc("$id")']
|
||||
'queries' => [
|
||||
'{"method":"cursorAsc","attribute":"$id","values":[]}'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
@@ -10,7 +10,9 @@ use Tests\E2E\Scopes\SideClient;
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\General\UsageTest;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class ProjectsConsoleClientTest extends Scope
|
||||
{
|
||||
@@ -288,7 +290,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("teamId", "' . $team['body']['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::equal('teamId', [$team['body']['$id']])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -300,7 +304,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -312,7 +318,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(3)' ],
|
||||
'queries' => [
|
||||
Query::offset(3)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -324,7 +332,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("name", "Project Test 2")' ],
|
||||
'queries' => [
|
||||
Query::equal('name', ['Project Test 2'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -336,7 +346,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'orderDesc("")' ],
|
||||
'queries' => [
|
||||
Query::orderDesc()->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -360,7 +372,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("' . $response['body']['projects'][0]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $response['body']['projects'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -372,7 +386,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorBefore("' . $response['body']['projects'][0]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => $response['body']['projects'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -387,7 +403,9 @@ class ProjectsConsoleClientTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("unknown")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
@@ -9,6 +9,7 @@ use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
trait StorageBase
|
||||
@@ -27,7 +28,7 @@ trait StorageBase
|
||||
'name' => 'Test Bucket',
|
||||
'fileSecurity' => true,
|
||||
'maximumFileSize' => 2000000, //2MB
|
||||
'allowedFileExtensions' => ["jpg", "png", 'jfif'],
|
||||
'allowedFileExtensions' => ['jpg', 'png', 'jfif'],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::create(Role::any()),
|
||||
@@ -380,7 +381,9 @@ trait StorageBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ]
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $files['headers']['status-code']);
|
||||
$this->assertEquals(1, count($files['body']['files']));
|
||||
@@ -389,7 +392,9 @@ trait StorageBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ]
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $files['headers']['status-code']);
|
||||
$this->assertEquals(0, count($files['body']['files']));
|
||||
@@ -398,7 +403,9 @@ trait StorageBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("mimeType", "image/png")' ]
|
||||
'queries' => [
|
||||
Query::equal('mimeType', ['image/png'])->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $files['headers']['status-code']);
|
||||
$this->assertEquals(1, count($files['body']['files']));
|
||||
@@ -407,7 +414,9 @@ trait StorageBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("mimeType", "image/jpeg")' ]
|
||||
'queries' => [
|
||||
Query::equal('mimeType', ['image/jpeg'])->toString(),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(200, $files['headers']['status-code']);
|
||||
$this->assertEquals(0, count($files['body']['files']));
|
||||
|
||||
@@ -6,7 +6,9 @@ use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideServer;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
class StorageCustomServerTest extends Scope
|
||||
@@ -98,7 +100,9 @@ class StorageCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -108,7 +112,9 @@ class StorageCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -118,7 +124,9 @@ class StorageCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("$id", "bucket1")' ],
|
||||
'queries' => [
|
||||
Query::equal('$id', ['bucket1'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -128,7 +136,9 @@ class StorageCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("fileSecurity", true)' ],
|
||||
'queries' => [
|
||||
Query::equal('fileSecurity', [true])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -138,7 +148,9 @@ class StorageCustomServerTest extends Scope
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("' . $response['body']['buckets'][0]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $response['body']['buckets'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
@@ -4,7 +4,9 @@ namespace Tests\E2E\Services\Teams;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
trait TeamsBase
|
||||
@@ -147,7 +149,9 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(2)' ],
|
||||
'queries' => [
|
||||
Query::limit(2)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -157,7 +161,9 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -167,7 +173,9 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'greaterThanEqual("total", 0)' ],
|
||||
'queries' => [
|
||||
Query::greaterThanEqual('total', 0)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -177,7 +185,9 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("name", ["Arsenal", "Newcastle"])' ],
|
||||
'queries' => [
|
||||
Query::equal('name', ['Arsenal', 'Newcastle'])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -226,7 +236,9 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(2)' ],
|
||||
'queries' => [
|
||||
Query::limit(2)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $teams['headers']['status-code']);
|
||||
@@ -238,7 +250,10 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)', 'cursorAfter("' . $teams['body']['teams'][0]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::cursorAfter(new Document(['$id' => $teams['body']['teams'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -251,7 +266,10 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)', 'cursorBefore("' . $teams['body']['teams'][1]['$id'] . '")' ],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::cursorBefore(new Document(['$id' => $teams['body']['teams'][1]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -267,7 +285,9 @@ trait TeamsBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("unknown")' ],
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
@@ -4,7 +4,9 @@ namespace Tests\E2E\Services\Teams;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
trait TeamsBaseClient
|
||||
@@ -40,7 +42,9 @@ trait TeamsBaseClient
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'limit(1)' ]
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -50,7 +54,9 @@ trait TeamsBaseClient
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'offset(1)' ]
|
||||
'queries' => [
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -60,7 +66,9 @@ trait TeamsBaseClient
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("confirm", true)' ]
|
||||
'queries' => [
|
||||
Query::equal('confirm', [true])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -70,7 +78,9 @@ trait TeamsBaseClient
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'equal("confirm", false)' ]
|
||||
'queries' => [
|
||||
Query::equal('confirm', [false])->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -362,7 +372,9 @@ trait TeamsBaseClient
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [ 'cursorAfter("' . $memberships['body']['memberships'][0]['$id'] . '")' ]
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $memberships['body']['memberships'][0]['$id']]))->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -526,7 +538,7 @@ trait TeamsBaseClient
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
]), [
|
||||
'secret' => $secret,
|
||||
'userId' => ID::custom(''),
|
||||
'userId' => ID::custom('asdf'),
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
@@ -5,7 +5,9 @@ namespace Tests\E2E\Services\Users;
|
||||
use Appwrite\Tests\Retry;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
trait UsersBase
|
||||
{
|
||||
@@ -409,7 +411,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("name", "' . $user1['name'] . '")']
|
||||
'queries' => [
|
||||
Query::equal('name', [$user1['name']])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -418,11 +422,14 @@ trait UsersBase
|
||||
$this->assertCount(1, $response['body']['users']);
|
||||
$this->assertEquals($response['body']['users'][0]['name'], $user1['name']);
|
||||
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("email", "' . $user1['email'] . '")']
|
||||
'queries' => [
|
||||
Query::equal('name', [$user1['name']])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -435,7 +442,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("status", true)']
|
||||
'queries' => [
|
||||
Query::equal('status', [true])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -451,7 +460,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("status", false)']
|
||||
'queries' => [
|
||||
Query::equal('status', [false])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -463,7 +474,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("passwordUpdate", "' . $user1['passwordUpdate'] . '")']
|
||||
'queries' => [
|
||||
Query::equal('passwordUpdate', [$user1['passwordUpdate']])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -476,7 +489,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("registration", "' . $user1['registration'] . '")']
|
||||
'queries' => [
|
||||
Query::equal('registration', [$user1['registration']])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -489,7 +504,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("emailVerification", false)']
|
||||
'queries' => [
|
||||
Query::equal('emailVerification', [false])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -505,7 +522,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("emailVerification", true)']
|
||||
'queries' => [
|
||||
Query::equal('emailVerification', [true])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -517,7 +536,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("phoneVerification", false)']
|
||||
'queries' => [
|
||||
Query::equal('phoneVerification', [false])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -529,7 +550,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("phoneVerification", true)']
|
||||
'queries' => [
|
||||
Query::equal('phoneVerification', [true])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -541,7 +564,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("' . $data['userId'] . '")']
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => $data['userId']]))->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -554,7 +579,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorBefore("user1")']
|
||||
'queries' => [
|
||||
Query::cursorBefore(new Document(['$id' => 'user1']))->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 200);
|
||||
@@ -674,7 +701,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAfter("unknown")']
|
||||
'queries' => [
|
||||
Query::cursorAfter(new Document(['$id' => 'unknown']))->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
@@ -1203,7 +1232,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -1215,7 +1246,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(1)'],
|
||||
'queries' => [
|
||||
Query::offset(1)->toString()
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -1226,7 +1259,10 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(1)', 'offset(1)'],
|
||||
'queries' => [
|
||||
Query::limit(1)->toString(),
|
||||
Query::offset(1)->toString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals($logs['headers']['status-code'], 200);
|
||||
@@ -1241,7 +1277,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['limit(-1)']
|
||||
'queries' => [
|
||||
Query::limit(-1)->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -1250,7 +1288,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['offset(-1)']
|
||||
'queries' => [
|
||||
Query::offset(-1)->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -1259,7 +1299,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['equal("$id", "asdf")']
|
||||
'queries' => [
|
||||
Query::equal('$id', ['asdf'])->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -1268,7 +1310,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['orderAsc("$id")']
|
||||
'queries' => [
|
||||
Query::orderAsc('$id')->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
@@ -1277,7 +1321,9 @@ trait UsersBase
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => ['cursorAsc("$id")']
|
||||
'queries' => [
|
||||
'{ "method": "cursorAsc", "attribute": "$id" }'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($response['headers']['status-code'], 400);
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 11 KiB |
@@ -7,10 +7,7 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CustomIdTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Key
|
||||
*/
|
||||
protected $object = null;
|
||||
protected ?CustomId $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
||||
@@ -7,10 +7,7 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ProjectIdTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Key
|
||||
*/
|
||||
protected $object = null;
|
||||
protected ?ProjectId $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace Tests\Unit\Utopia\Database\Validator\Queries;
|
||||
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Base;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class CollectionTest extends TestCase
|
||||
{
|
||||
@@ -25,17 +27,17 @@ class CollectionTest extends TestCase
|
||||
public function testValid(): void
|
||||
{
|
||||
$validator = new Base('users', ['name', 'search']);
|
||||
$this->assertEquals(true, $validator->isValid(['cursorAfter("asdf")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['equal("name", "value")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['limit(10)']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['offset(10)']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['orderAsc("name")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::cursorAfter(new Document(['$id' => 'asdf']))]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::equal('name', ['value'])]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::limit(10)]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::offset(10)]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::orderAsc('name')]), $validator->getDescription());
|
||||
}
|
||||
|
||||
public function testMissingIndex(): void
|
||||
{
|
||||
$validator = new Base('users', ['name']);
|
||||
$this->assertEquals(false, $validator->isValid(['equal("dne", "value")']), $validator->getDescription());
|
||||
$this->assertEquals(false, $validator->isValid(['orderAsc("dne")']), $validator->getDescription());
|
||||
$this->assertEquals(false, $validator->isValid([Query::equal('dne', ['value'])]), $validator->getDescription());
|
||||
$this->assertEquals(false, $validator->isValid([Query::orderAsc('dne')]), $validator->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Tests\Unit\Utopia\Database\Validator\Queries;
|
||||
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Users;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Utopia\Database\Query;
|
||||
|
||||
class UsersTest extends TestCase
|
||||
{
|
||||
@@ -23,17 +24,17 @@ class UsersTest extends TestCase
|
||||
* Test for Success
|
||||
*/
|
||||
$this->assertEquals(true, $validator->isValid([]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['equal("name", "value")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['equal("email", "value")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['equal("phone", "value")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['greaterThan("passwordUpdate", "2020-10-15 06:38")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['greaterThan("registration", "2020-10-15 06:38")']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['equal("emailVerification", true)']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid(['equal("phoneVerification", true)']), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::equal('name', ['value'])]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::equal('email', ['value'])]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::equal('phone', ['value'])]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::greaterThan('passwordUpdate', '2020-10-15 06:38')]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::greaterThan('registration', '2020-10-15 06:38')]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::equal('emailVerification', [true])]), $validator->getDescription());
|
||||
$this->assertEquals(true, $validator->isValid([Query::equal('phoneVerification', [true])]), $validator->getDescription());
|
||||
|
||||
/**
|
||||
* Test for Failure
|
||||
*/
|
||||
$this->assertEquals(false, $validator->isValid(['equal("password", "value")']), $validator->getDescription());
|
||||
$this->assertEquals(false, $validator->isValid([Query::equal('password', ['value'])]), $validator->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||