1
0
Fork 0
mirror of synced 2024-06-15 09:14:50 +12:00

Merge pull request #3652 from appwrite/feat-audits-label

This commit is contained in:
Christy Jacob 2022-08-17 21:29:35 +05:30 committed by GitHub
commit 70f0483f97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 328 additions and 432 deletions

View file

@ -20,7 +20,6 @@ use Appwrite\Utopia\Response;
use Appwrite\Utopia\Database\Validator\CustomId;
use MaxMind\Db\Reader;
use Utopia\App;
use Appwrite\Event\Audit;
use Appwrite\Event\Phone as EventPhone;
use Utopia\Audit\Audit as EventAudit;
use Utopia\Config\Config;
@ -47,6 +46,8 @@ App::post('/v1/account')
->label('event', 'users.[userId].create')
->label('scope', 'public')
->label('auth.type', 'emailPassword')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
->label('sdk.method', 'create')
@ -63,10 +64,10 @@ App::post('/v1/account')
->inject('response')
->inject('project')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $project, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $project, Database $dbForProject, Stats $usage, Event $events) {
$email = \strtolower($email);
if ('console' === $project->getId()) {
$whitelistEmails = $project->getAttribute('authWhitelistEmails');
@ -121,11 +122,6 @@ App::post('/v1/account')
Authorization::setRole('user:' . $user->getId());
Authorization::setRole('role:' . Auth::USER_ROLE_MEMBER);
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$usage->setParam('users.create', 1);
$events->setParam('userId', $user->getId());
@ -140,6 +136,8 @@ App::post('/v1/account/sessions/email')
->label('event', 'users.[userId].sessions.[sessionId].create')
->label('scope', 'public')
->label('auth.type', 'emailPassword')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createEmailSession')
@ -156,10 +154,9 @@ App::post('/v1/account/sessions/email')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $email, string $password, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audits, Stats $usage, Event $events) {
->action(function (string $email, string $password, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Stats $usage, Event $events) {
$email = \strtolower($email);
$protocol = $request->getProtocol();
@ -214,11 +211,6 @@ App::post('/v1/account/sessions/email')
$dbForProject->deleteCachedDocument('users', $profile->getId());
$audits
->setResource('user/' . $profile->getId())
->setUser($profile)
;
if (!Config::getParam('domainVerification')) {
$response
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($profile->getId(), $secret)]))
@ -366,6 +358,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('event', 'users.[userId].sessions.[sessionId].create')
->label('scope', 'public')
->label('audits.resource', 'user/{user.$id}')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->label('docs', false)
@ -378,10 +371,9 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->inject('user')
->inject('dbForProject')
->inject('geodb')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (string $provider, string $code, string $state, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Audit $audits, Event $events, Stats $usage) use ($oauthDefaultSuccess) {
->action(function (string $provider, string $code, string $state, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $events, Stats $usage) use ($oauthDefaultSuccess) {
$protocol = $request->getProtocol();
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
@ -560,11 +552,6 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$dbForProject->deleteCachedDocument('users', $user->getId());
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$usage
->setParam('users.sessions.create', 1)
->setParam('projectId', $project->getId())
@ -602,12 +589,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
;
});
App::post('/v1/account/sessions/magic-url')
->desc('Create Magic URL session')
->groups(['api', 'account'])
->label('scope', 'public')
->label('auth.type', 'magic-url')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createMagicURLSession')
@ -625,10 +613,9 @@ App::post('/v1/account/sessions/magic-url')
->inject('project')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('mails')
->action(function (string $userId, string $email, string $url, Request $request, Response $response, Document $project, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Mail $mails) {
->action(function (string $userId, string $email, string $url, Request $request, Response $response, Document $project, Database $dbForProject, Locale $locale, Event $events, Mail $mails) {
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
@ -723,11 +710,6 @@ App::post('/v1/account/sessions/magic-url')
// Hide secret for clients
$token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $loginSecret : '');
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($token, Response::MODEL_TOKEN)
@ -739,6 +721,8 @@ App::put('/v1/account/sessions/magic-url')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].sessions.[sessionId].create')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateMagicURLSession')
@ -755,9 +739,8 @@ App::put('/v1/account/sessions/magic-url')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('audits')
->inject('events')
->action(function (string $userId, string $secret, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audits, Event $events) {
->action(function (string $userId, string $secret, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Event $events) {
/** @var Utopia\Database\Document $user */
@ -819,8 +802,6 @@ App::put('/v1/account/sessions/magic-url')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed saving user to DB');
}
$audits->setResource('user/' . $user->getId());
$events
->setParam('userId', $user->getId())
->setParam('sessionId', $session->getId())
@ -853,6 +834,8 @@ App::post('/v1/account/sessions/phone')
->groups(['api', 'account'])
->label('scope', 'public')
->label('auth.type', 'phone')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createPhoneSession')
@ -868,10 +851,10 @@ App::post('/v1/account/sessions/phone')
->inject('response')
->inject('project')
->inject('dbForProject')
->inject('audits')
->inject('events')
->inject('messaging')
->action(function (string $userId, string $phone, Request $request, Response $response, Document $project, Database $dbForProject, Audit $audits, Event $events, EventPhone $messaging) {
->action(function (string $userId, string $phone, Request $request, Response $response, Document $project, Database $dbForProject, Event $events, EventPhone $messaging) {
if (empty(App::getEnv('_APP_SMS_PROVIDER'))) {
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
}
@ -954,11 +937,6 @@ App::post('/v1/account/sessions/phone')
// Hide secret for clients
$token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : '');
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($token, Response::MODEL_TOKEN)
@ -966,7 +944,7 @@ App::post('/v1/account/sessions/phone')
});
App::put('/v1/account/sessions/phone')
->desc('Create Phone session (confirmation)')
->desc('Create Phone Session (confirmation)')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].sessions.[sessionId].create')
@ -986,9 +964,8 @@ App::put('/v1/account/sessions/phone')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('audits')
->inject('events')
->action(function (string $userId, string $secret, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Audit $audits, Event $events) {
->action(function (string $userId, string $secret, Request $request, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Event $events) {
$user = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
@ -1046,8 +1023,6 @@ App::put('/v1/account/sessions/phone')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed saving user to DB');
}
$audits->setResource('user/' . $user->getId());
$events
->setParam('userId', $user->getId())
->setParam('sessionId', $session->getId())
@ -1081,6 +1056,8 @@ App::post('/v1/account/sessions/anonymous')
->label('event', 'users.[userId].sessions.[sessionId].create')
->label('scope', 'public')
->label('auth.type', 'anonymous')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createAnonymousSession')
@ -1097,10 +1074,9 @@ App::post('/v1/account/sessions/anonymous')
->inject('project')
->inject('dbForProject')
->inject('geodb')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Audit $audits, Stats $usage, Event $events) {
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Stats $usage, Event $events) {
$protocol = $request->getProtocol();
@ -1175,8 +1151,6 @@ App::post('/v1/account/sessions/anonymous')
$dbForProject->deleteCachedDocument('users', $user->getId());
$audits->setResource('user/' . $user->getId());
$usage
->setParam('users.sessions.create', 1)
->setParam('provider', 'anonymous')
@ -1438,6 +1412,7 @@ App::patch('/v1/account/name')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.name')
->label('scope', 'account')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateName')
@ -1449,20 +1424,14 @@ App::patch('/v1/account/name')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $name, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $name, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
$user = $dbForProject->updateDocument('users', $user->getId(), $user
->setAttribute('name', $name)
->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email', ''), $user->getAttribute('phone', '')])));
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
@ -1474,6 +1443,8 @@ App::patch('/v1/account/password')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.password')
->label('scope', 'account')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePassword')
@ -1486,10 +1457,10 @@ App::patch('/v1/account/password')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $password, string $oldPassword, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $password, string $oldPassword, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
// Check old password only if its an existing user.
if ($user->getAttribute('passwordUpdate') !== 0 && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions'))) { // Double check user password
throw new Exception(Exception::USER_INVALID_CREDENTIALS);
@ -1501,11 +1472,6 @@ App::patch('/v1/account/password')
->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS)
->setAttribute('passwordUpdate', \time()));
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
@ -1517,6 +1483,7 @@ App::patch('/v1/account/email')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.email')
->label('scope', 'account')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateEmail')
@ -1529,10 +1496,9 @@ App::patch('/v1/account/email')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $email, string $password, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $email, string $password, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
$isAnonymousUser = Auth::isAnonymousUser($user); // Check if request is from an anonymous account for converting
if (
@ -1558,11 +1524,6 @@ App::patch('/v1/account/email')
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
}
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
@ -1574,6 +1535,7 @@ App::patch('/v1/account/phone')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.phone')
->label('scope', 'account')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePhone')
@ -1586,10 +1548,9 @@ App::patch('/v1/account/phone')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $phone, string $password, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
$isAnonymousUser = Auth::isAnonymousUser($user); // Check if request is from an anonymous account for converting
@ -1611,11 +1572,6 @@ App::patch('/v1/account/phone')
throw new Exception(Exception::USER_PHONE_ALREADY_EXISTS);
}
$audits
->setResource('user/' . $user->getId())
->setUser($user)
;
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
@ -1627,6 +1583,7 @@ App::patch('/v1/account/prefs')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.prefs')
->label('scope', 'account')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePrefs')
@ -1638,14 +1595,12 @@ App::patch('/v1/account/prefs')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (array $prefs, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (array $prefs, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$audits->setResource('user/' . $user->getId());
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
@ -1657,6 +1612,7 @@ App::patch('/v1/account/status')
->groups(['api', 'account'])
->label('event', 'users.[userId].update.status')
->label('scope', 'account')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateStatus')
@ -1668,17 +1624,12 @@ App::patch('/v1/account/status')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Audit $audits, Event $events, Stats $usage) {
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $events, Stats $usage) {
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('status', false));
$audits
->setResource('user/' . $user->getId())
->setPayload($response->output($user, Response::MODEL_ACCOUNT));
$events
->setParam('userId', $user->getId())
->setPayload($response->output($user, Response::MODEL_ACCOUNT));
@ -1697,6 +1648,7 @@ App::delete('/v1/account/sessions/:sessionId')
->groups(['api', 'account'])
->label('scope', 'account')
->label('event', 'users.[userId].sessions.[sessionId].delete')
->label('audits.resource', 'user/{user.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'deleteSession')
@ -1710,10 +1662,9 @@ App::delete('/v1/account/sessions/:sessionId')
->inject('user')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (?string $sessionId, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Stats $usage) {
->action(function (?string $sessionId, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $events, Stats $usage) {
$protocol = $request->getProtocol();
$sessionId = ($sessionId === 'current')
@ -1728,8 +1679,6 @@ App::delete('/v1/account/sessions/:sessionId')
$dbForProject->deleteDocument('sessions', $session->getId());
$audits->setResource('user/' . $user->getId());
$session->setAttribute('current', false);
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
@ -1774,6 +1723,8 @@ App::patch('/v1/account/sessions/:sessionId')
->groups(['api', 'account'])
->label('scope', 'account')
->label('event', 'users.[userId].sessions.[sessionId].update')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateSession')
@ -1789,10 +1740,9 @@ App::patch('/v1/account/sessions/:sessionId')
->inject('dbForProject')
->inject('project')
->inject('locale')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (?string $sessionId, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Audit $audits, Event $events, Stats $usage) {
->action(function (?string $sessionId, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Event $events, Stats $usage) {
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
@ -1836,8 +1786,6 @@ App::patch('/v1/account/sessions/:sessionId')
$dbForProject->deleteCachedDocument('users', $user->getId());
$audits->setResource('user/' . $user->getId());
$events
->setParam('userId', $user->getId())
->setParam('sessionId', $session->getId())
@ -1861,6 +1809,7 @@ App::delete('/v1/account/sessions')
->groups(['api', 'account'])
->label('scope', 'account')
->label('event', 'users.[userId].sessions.[sessionId].delete')
->label('audits.resource', 'user/{user.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'deleteSessions')
@ -1873,10 +1822,9 @@ App::delete('/v1/account/sessions')
->inject('user')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Stats $usage) {
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $events, Stats $usage) {
$protocol = $request->getProtocol();
$sessions = $user->getAttribute('sessions', []);
@ -1884,8 +1832,6 @@ App::delete('/v1/account/sessions')
foreach ($sessions as $session) {/** @var Document $session */
$dbForProject->deleteDocument('sessions', $session->getId());
$audits->setResource('user/' . $user->getId());
if (!Config::getParam('domainVerification')) {
$response->addHeader('X-Fallback-Cookies', \json_encode([]));
}
@ -1929,6 +1875,8 @@ App::post('/v1/account/recovery')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].recovery.[tokenId].create')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createRecovery')
@ -1946,10 +1894,9 @@ App::post('/v1/account/recovery')
->inject('project')
->inject('locale')
->inject('mails')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (string $email, string $url, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Mail $mails, Audit $audits, Event $events, Stats $usage) {
->action(function (string $email, string $url, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Mail $mails, Event $events, Stats $usage) {
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
@ -2021,7 +1968,6 @@ App::post('/v1/account/recovery')
// Hide secret for clients
$recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : '');
$audits->setResource('user/' . $profile->getId());
$usage->setParam('users.update', 1);
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -2033,6 +1979,8 @@ App::put('/v1/account/recovery')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].recovery.[tokenId].update')
->label('audits.resource', 'user/{response.userId}')
->label('audits.userId', '{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateRecovery')
@ -2048,10 +1996,9 @@ App::put('/v1/account/recovery')
->param('passwordAgain', '', new Password(), 'Repeat new user password. Must be at least 8 chars.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $userId, string $secret, string $password, string $passwordAgain, Response $response, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $userId, string $secret, string $password, string $passwordAgain, Response $response, Database $dbForProject, Stats $usage, Event $events) {
if ($password !== $passwordAgain) {
throw new Exception(Exception::USER_PASSWORD_MISMATCH);
}
@ -2087,8 +2034,6 @@ App::put('/v1/account/recovery')
$dbForProject->deleteDocument('tokens', $recovery);
$dbForProject->deleteCachedDocument('users', $profile->getId());
$audits->setResource('user/' . $profile->getId());
$usage->setParam('users.update', 1);
$events
@ -2104,6 +2049,7 @@ App::post('/v1/account/verification')
->groups(['api', 'account'])
->label('scope', 'account')
->label('event', 'users.[userId].verification.[tokenId].create')
->label('audits.resource', 'user/{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createVerification')
@ -2120,11 +2066,10 @@ App::post('/v1/account/verification')
->inject('user')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('mails')
->inject('usage')
->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Mail $mails, Stats $usage) {
->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $events, Mail $mails, Stats $usage) {
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
@ -2182,7 +2127,6 @@ App::post('/v1/account/verification')
// Hide secret for clients
$verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : '');
$audits->setResource('user/' . $user->getId());
$usage->setParam('users.update', 1);
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -2194,6 +2138,7 @@ App::put('/v1/account/verification')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].verification.[tokenId].update')
->label('audits.resource', 'user/{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateVerification')
@ -2208,10 +2153,9 @@ App::put('/v1/account/verification')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
$profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
@ -2239,8 +2183,6 @@ App::put('/v1/account/verification')
$dbForProject->deleteDocument('tokens', $verification);
$dbForProject->deleteCachedDocument('users', $profile->getId());
$audits->setResource('user/' . $user->getId());
$usage->setParam('users.update', 1);
$events
@ -2256,6 +2198,7 @@ App::post('/v1/account/verification/phone')
->groups(['api', 'account'])
->label('scope', 'account')
->label('event', 'users.[userId].verification.[tokenId].create')
->label('audits.resource', 'user/{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createPhoneVerification')
@ -2269,11 +2212,10 @@ App::post('/v1/account/verification/phone')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('events')
->inject('usage')
->inject('messaging')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Audit $audits, Event $events, Stats $usage, EventPhone $messaging) {
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $events, Stats $usage, EventPhone $messaging) {
if (empty(App::getEnv('_APP_SMS_PROVIDER'))) {
throw new Exception(Exception::GENERAL_PHONE_DISABLED);
@ -2329,7 +2271,6 @@ App::post('/v1/account/verification/phone')
// Hide secret for clients
$verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : '');
$audits->setResource('user/' . $user->getId());
$usage->setParam('users.update', 1);
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -2341,6 +2282,7 @@ App::put('/v1/account/verification/phone')
->groups(['api', 'account'])
->label('scope', 'public')
->label('event', 'users.[userId].verification.[tokenId].update')
->label('audits.resource', 'user/{response.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePhoneVerification')
@ -2355,10 +2297,9 @@ App::put('/v1/account/verification/phone')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Stats $usage, Event $events) {
$profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
@ -2384,8 +2325,6 @@ App::put('/v1/account/verification/phone')
$dbForProject->deleteDocument('tokens', $verification);
$dbForProject->deleteCachedDocument('users', $profile->getId());
$audits->setResource('user/' . $user->getId());
$usage->setParam('users.update', 1);
$events

View file

@ -301,8 +301,6 @@ App::get('/v1/avatars/qr')
->desc('Get QR Code')
->groups(['api', 'avatars'])
->label('scope', 'avatars.read')
->label('cache', true)
->label('cache.resource', 'avatar/qr')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getQR')
@ -336,7 +334,7 @@ App::get('/v1/avatars/qr')
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
->setContentType('image/png')
->file($image->output('png', 9))
->send($image->output('png', 9))
;
});

View file

@ -36,7 +36,6 @@ use Appwrite\Utopia\Database\Validator\Queries as QueriesValidator;
use Appwrite\Utopia\Database\Validator\OrderAttributes;
use Appwrite\Utopia\Response;
use Appwrite\Detector\Detector;
use Appwrite\Event\Audit as EventAudit;
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Event;
use Appwrite\Stats\Stats;
@ -50,7 +49,7 @@ use MaxMind\Db\Reader;
* @return Document Newly created attribute document
* @throws Exception
*/
function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Event $events, Stats $usage): Document
function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $database, Event $events, Stats $usage): Document
{
$key = $attribute->getAttribute('key');
$type = $attribute->getAttribute('type', '');
@ -141,11 +140,6 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
->setParam('attributeId', $attribute->getId())
;
$audits
->setResource('database/' . $db->getId() . '/collection/' . $collectionId)
->setPayload($attribute->getArrayCopy())
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
return $attribute;
@ -156,6 +150,7 @@ App::post('/v1/databases')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].create')
->label('scope', 'databases.write')
->label('audits.resource', 'database/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'create')
@ -167,10 +162,9 @@ App::post('/v1/databases')
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$databaseId = $databaseId == 'unique()' ? $dbForProject->getId() : $databaseId;
@ -218,11 +212,6 @@ App::post('/v1/databases')
throw new Exception(Exception::DATABASE_ALREADY_EXISTS);
}
$audits
->setResource('database/' . $databaseId)
->setPayload($database->getArrayCopy())
;
$events->setParam('databaseId', $database->getId());
$usage->setParam('databases.create', 1);
@ -386,6 +375,7 @@ App::put('/v1/databases/:databaseId')
->groups(['api', 'database'])
->label('scope', 'databases.write')
->label('event', 'databases.[databaseId].update')
->label('audits.resource', 'database/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'update')
@ -397,10 +387,9 @@ App::put('/v1/databases/:databaseId')
->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $name, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$database = $dbForProject->getDocument('databases', $databaseId);
@ -418,11 +407,6 @@ App::put('/v1/databases/:databaseId')
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
}
$audits
->setResource('database/' . $databaseId)
->setPayload($database->getArrayCopy())
;
$usage->setParam('databases.update', 1);
$events->setParam('databaseId', $database->getId());
@ -434,6 +418,7 @@ App::delete('/v1/databases/:databaseId')
->groups(['api', 'database'])
->label('scope', 'databases.write')
->label('event', 'databases.[databaseId].delete')
->label('audits.resource', 'database/{request.databaseId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'delete')
@ -444,10 +429,9 @@ App::delete('/v1/databases/:databaseId')
->inject('response')
->inject('dbForProject')
->inject('events')
->inject('audits')
->inject('deletes')
->inject('usage')
->action(function (string $databaseId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage) {
->action(function (string $databaseId, Response $response, Database $dbForProject, Event $events, Delete $deletes, Stats $usage) {
$database = $dbForProject->getDocument('databases', $databaseId);
@ -471,11 +455,6 @@ App::delete('/v1/databases/:databaseId')
->setPayload($response->output($database, Response::MODEL_DATABASE))
;
$audits
->setResource('database/' . $databaseId)
->setPayload($database->getArrayCopy())
;
$usage->setParam('databases.delete', 1);
$response->noContent();
@ -487,6 +466,7 @@ App::post('/v1/databases/:databaseId/collections')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'createCollection')
@ -502,10 +482,9 @@ App::post('/v1/databases/:databaseId/collections')
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $name, ?string $permission, ?array $read, ?array $write, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $name, ?string $permission, ?array $read, ?array $write, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -536,11 +515,6 @@ App::post('/v1/databases/:databaseId/collections')
throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED);
}
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId)
->setPayload($collection->getArrayCopy())
;
$events
->setContext('database', $database)
->setParam('databaseId', $databaseId)
@ -741,6 +715,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
->groups(['api', 'database'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateCollection')
@ -757,10 +732,9 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
->param('enabled', true, new Boolean(), 'Is collection enabled?', true)
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -791,11 +765,6 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
}
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId)
->setPayload($collection->getArrayCopy())
;
$usage
->setParam('databaseId', $databaseId)
->setParam('databases.collections.update', 1);
@ -814,6 +783,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
->groups(['api', 'database'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'deleteCollection')
@ -825,10 +795,9 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
->inject('response')
->inject('dbForProject')
->inject('events')
->inject('audits')
->inject('deletes')
->inject('usage')
->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage) {
->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, Event $events, Delete $deletes, Stats $usage) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -860,11 +829,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
->setPayload($response->output($collection, Response::MODEL_COLLECTION))
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId)
->setPayload($collection->getArrayCopy())
;
$usage
->setParam('databaseId', $databaseId)
->setParam('databases.collections.delete', 1);
@ -878,6 +842,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'createStringAttribute')
@ -886,7 +851,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_STRING)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Range::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.')
->param('required', null, new Boolean(), 'Is attribute required?')
@ -895,10 +860,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
// Ensure attribute default is within required size
$validator = new Text($size);
@ -913,7 +877,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
'required' => $required,
'default' => $default,
'array' => $array,
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING);
@ -925,6 +889,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email'
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createEmailAttribute')
@ -933,7 +898,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email'
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_EMAIL)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Email(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
@ -941,10 +906,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email'
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -954,7 +918,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email'
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_EMAIL,
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL);
@ -966,6 +930,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createEnumAttribute')
@ -974,7 +939,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('elements', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' elements are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.')
->param('required', null, new Boolean(), 'Is attribute required?')
@ -983,10 +948,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
// use length of longest string as attribute size
$size = 0;
@ -1011,7 +975,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_ENUM,
'formatOptions' => ['elements' => $elements],
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM);
@ -1023,6 +987,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createIpAttribute')
@ -1031,7 +996,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_IP)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new IP(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
@ -1039,10 +1004,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1052,7 +1016,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_IP,
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_IP);
@ -1064,6 +1028,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createUrlAttribute')
@ -1072,7 +1037,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_URL)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new URL(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
@ -1080,10 +1045,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1093,7 +1057,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_URL,
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_URL);
@ -1105,6 +1069,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createIntegerAttribute')
@ -1113,7 +1078,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_INTEGER)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new Integer(), 'Minimum value to enforce on new documents', true)
@ -1123,10 +1088,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
// Ensure attribute default is within range
$min = (is_null($min)) ? PHP_INT_MIN : \intval($min);
@ -1156,7 +1120,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
'min' => $min,
'max' => $max,
],
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$formatOptions = $attribute->getAttribute('formatOptions', []);
@ -1175,6 +1139,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createFloatAttribute')
@ -1183,7 +1148,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_FLOAT)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents', true)
@ -1193,10 +1158,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('events')
->inject('usage')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Event $events, Stats $usage) {
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events, Stats $usage) {
// Ensure attribute default is within range
$min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min);
@ -1229,7 +1193,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
'min' => $min,
'max' => $max,
],
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$formatOptions = $attribute->getAttribute('formatOptions', []);
@ -1248,6 +1212,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.namespace', 'databases')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createBooleanAttribute')
@ -1256,7 +1221,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_BOOLEAN)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Boolean(), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
@ -1264,10 +1229,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1276,7 +1240,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea
'required' => $required,
'default' => $default,
'array' => $array,
]), $response, $dbForProject, $database, $audits, $events, $usage);
]), $response, $dbForProject, $database, $events, $usage);
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_BOOLEAN);
@ -1295,7 +1259,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->inject('response')
->inject('dbForProject')
->inject('usage')
@ -1345,7 +1309,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_STRING,])// needs to be last, since its condition would dominate any other string attribute
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->inject('response')
->inject('dbForProject')
@ -1401,6 +1365,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
->groups(['api', 'database'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'deleteAttribute')
@ -1408,15 +1373,14 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Attribute Key.')
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('events')
->inject('audits')
->inject('usage')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits, Stats $usage) {
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, Stats $usage) {
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1481,11 +1445,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
->setPayload($response->output($attribute, $model))
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId)
->setPayload($attribute->getArrayCopy())
;
$response->noContent();
});
@ -1495,6 +1454,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create')
->label('scope', 'collections.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'createIndex')
@ -1503,7 +1463,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->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('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.')
@ -1511,10 +1471,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, EventAudit $audits, Stats $usage, Event $events) {
->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) {
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1636,11 +1595,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->setContext('database', $db)
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collection->getId())
->setPayload($index->getArrayCopy())
;
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
$response->dynamic($index, Response::MODEL_INDEX);
});
@ -1658,7 +1612,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX_LIST)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->inject('response')
->inject('dbForProject')
->inject('usage')
@ -1700,7 +1654,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_INDEX)
->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('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', null, new Key(), 'Index Key.')
->inject('response')
->inject('dbForProject')
@ -1744,6 +1698,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->groups(['api', 'database'])
->label('scope', 'collections.write')
->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'deleteIndex')
@ -1751,15 +1706,14 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('key', '', new Key(), 'Index Key.')
->inject('response')
->inject('dbForProject')
->inject('database')
->inject('events')
->inject('audits')
->inject('usage')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, EventAudit $audits, Stats $usage) {
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $database, Event $events, Stats $usage) {
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1805,11 +1759,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->setPayload($response->output($index, Response::MODEL_INDEX))
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collection->getId())
->setPayload($index->getArrayCopy())
;
$response->noContent();
});
@ -1819,6 +1768,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create')
->label('scope', 'documents.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'createDocument')
@ -1828,18 +1778,17 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->label('sdk.response.model', Response::MODEL_DOCUMENT)
->param('databaseId', '', new UID(), 'Database ID.')
->param('documentId', '', new CustomId(), 'Document ID. Choose your own unique ID or pass the string "unique()" to auto generate it. 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('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection). Make sure to define attributes before creating documents.')
->param('data', [], new JSON(), 'Document data as JSON object.')
->param('read', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('audits')
->inject('usage')
->inject('events')
->inject('mode')
->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, EventAudit $audits, Stats $usage, Event $events, string $mode) {
->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, Stats $usage, Event $events, string $mode) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1926,11 +1875,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->setParam('collectionId', $collectionId)
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId())
->setPayload($document->getArrayCopy())
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
@ -1948,8 +1892,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST)
->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/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->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/database#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. By default will return maximum 25 results. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' results allowed per request.', true)
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
->param('cursor', '', new UID(), 'ID of the document used as the starting point for the query, excluding the document itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
@ -2062,7 +2006,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('documentId', null, new UID(), 'Document ID.')
->inject('response')
->inject('dbForProject')
@ -2219,6 +2163,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update')
->label('scope', 'documents.write')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'updateDocument')
@ -2234,11 +2179,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->param('write', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.', true)
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, EventAudit $audits, Stats $usage, Event $events, string $mode) {
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $read, ?array $write, Response $response, Database $dbForProject, Stats $usage, Event $events, string $mode) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2344,11 +2288,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->setParam('collectionId', $collectionId)
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId())
->setPayload($document->getArrayCopy())
;
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
@ -2358,6 +2297,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{request.documentId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'databases')
->label('sdk.method', 'deleteDocument')
@ -2365,16 +2305,15 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('collectionId', null, new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).')
->param('documentId', null, new UID(), 'Document ID.')
->inject('response')
->inject('dbForProject')
->inject('events')
->inject('audits')
->inject('deletes')
->inject('usage')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, Response $response, Database $dbForProject, Event $events, EventAudit $audits, Delete $deletes, Stats $usage, string $mode) {
->action(function (string $databaseId, string $collectionId, string $documentId, Response $response, Database $dbForProject, Event $events, Delete $deletes, Stats $usage, string $mode) {
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2444,11 +2383,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
->setPayload($response->output($document, Response::MODEL_DOCUMENT))
;
$audits
->setResource('database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId())
->setPayload($document->getArrayCopy())
;
$response->noContent();
});

View file

@ -43,6 +43,7 @@ App::post('/v1/functions')
->desc('Create Function')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].create')
->label('audits.resource', 'function/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'create')
@ -281,6 +282,7 @@ App::put('/v1/functions/:functionId')
->desc('Update Function')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].update')
->label('audits.resource', 'function/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'update')
@ -345,6 +347,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId')
->desc('Update Function Deployment')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].deployments.[deploymentId].update')
->label('audits.resource', 'function/{request.functionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'updateDeployment')
@ -410,6 +413,7 @@ App::delete('/v1/functions/:functionId')
->desc('Delete Function')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].delete')
->label('audits.resource', 'function/{request.functionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'delete')
@ -447,6 +451,7 @@ App::post('/v1/functions/:functionId/deployments')
->desc('Create Deployment')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].deployments.[deploymentId].create')
->label('audits.resource', 'function/{request.functionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'createDeployment')
@ -728,6 +733,7 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId')
->desc('Delete Deployment')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].deployments.[deploymentId].delete')
->label('audits.resource', 'function/{request.functionId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'deleteDeployment')
@ -1091,6 +1097,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
->desc('Retry Build')
->label('scope', 'functions.write')
->label('event', 'functions.[functionId].deployments.[deploymentId].update')
->label('audits.resource', 'function/{request.functionId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'functions')
->label('sdk.method', 'retryBuild')

View file

@ -2,7 +2,6 @@
use Appwrite\Auth\Auth;
use Appwrite\ClamAV\Network;
use Appwrite\Event\Audit;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Utopia\Database\Validator\CustomId;
@ -44,6 +43,7 @@ App::post('/v1/storage/buckets')
->groups(['api', 'storage'])
->label('scope', 'buckets.write')
->label('event', 'buckets.[bucketId].create')
->label('audits.resource', 'buckets/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'storage')
->label('sdk.method', 'createBucket')
@ -63,10 +63,9 @@ App::post('/v1/storage/buckets')
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $bucketId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $bucketId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$bucketId = $bucketId === 'unique()' ? $dbForProject->getId() : $bucketId;
try {
@ -124,11 +123,6 @@ App::post('/v1/storage/buckets')
throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS);
}
$audits
->setResource('storage/buckets/' . $bucket->getId())
->setPayload($bucket->getArrayCopy())
;
$events
->setParam('bucketId', $bucket->getId())
;
@ -212,6 +206,7 @@ App::put('/v1/storage/buckets/:bucketId')
->groups(['api', 'storage'])
->label('scope', 'buckets.write')
->label('event', 'buckets.[bucketId].update')
->label('audits.resource', 'buckets/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'storage')
->label('sdk.method', 'updateBucket')
@ -231,10 +226,9 @@ App::put('/v1/storage/buckets/:bucketId')
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->inject('events')
->action(function (string $bucketId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
->action(function (string $bucketId, string $name, string $permission, ?array $read, ?array $write, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$bucket = $dbForProject->getDocument('buckets', $bucketId);
if ($bucket->isEmpty()) {
@ -260,11 +254,6 @@ App::put('/v1/storage/buckets/:bucketId')
->setAttribute('permission', $permission)
->setAttribute('antivirus', (bool) filter_var($antivirus, FILTER_VALIDATE_BOOLEAN)));
$audits
->setResource('storage/buckets/' . $bucket->getId())
->setPayload($bucket->getArrayCopy())
;
$events
->setParam('bucketId', $bucket->getId())
;
@ -279,6 +268,7 @@ App::delete('/v1/storage/buckets/:bucketId')
->groups(['api', 'storage'])
->label('scope', 'buckets.write')
->label('event', 'buckets.[bucketId].delete')
->label('audits.resource', 'buckets/{request.bucketId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'storage')
->label('sdk.method', 'deleteBucket')
@ -288,11 +278,10 @@ App::delete('/v1/storage/buckets/:bucketId')
->param('bucketId', '', new UID(), 'Bucket unique ID.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('deletes')
->inject('events')
->inject('usage')
->action(function (string $bucketId, Response $response, Database $dbForProject, Audit $audits, Delete $deletes, Event $events, Stats $usage) {
->action(function (string $bucketId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Stats $usage) {
$bucket = $dbForProject->getDocument('buckets', $bucketId);
if ($bucket->isEmpty()) {
@ -312,11 +301,6 @@ App::delete('/v1/storage/buckets/:bucketId')
->setPayload($response->output($bucket, Response::MODEL_BUCKET))
;
$audits
->setResource('storage/buckets/' . $bucket->getId())
->setPayload($bucket->getArrayCopy())
;
$usage->setParam('storage.buckets.delete', 1);
$response->noContent();
@ -328,6 +312,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
->groups(['api', 'storage'])
->label('scope', 'files.write')
->label('event', 'buckets.[bucketId].files.[fileId].create')
->label('audits.resource', 'files/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'storage')
->label('sdk.method', 'createFile')
@ -346,14 +331,14 @@ App::post('/v1/storage/buckets/:bucketId/files')
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('audits')
->inject('usage')
->inject('events')
->inject('mode')
->inject('deviceFiles')
->inject('deviceLocal')
->inject('deletes')
->action(function (string $bucketId, string $fileId, mixed $file, ?array $read, ?array $write, Request $request, Response $response, Database $dbForProject, Document $user, Audit $audits, Stats $usage, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal, Delete $deletes) {
->action(function (string $bucketId, string $fileId, mixed $file, ?array $read, ?array $write, Request $request, Response $response, Database $dbForProject, Document $user, Stats $usage, Event $events, string $mode, Device $deviceFiles, Device $deviceLocal, Delete $deletes) {
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
if (
@ -439,8 +424,8 @@ App::post('/v1/storage/buckets/:bucketId/files')
}
/**
* Validators
*/
* Validators
*/
// Check if file type is allowed
$allowedFileExtensions = $bucket->getAttribute('allowedFileExtensions', []);
$fileExt = new FileExt($allowedFileExtensions);
@ -593,10 +578,6 @@ App::post('/v1/storage/buckets/:bucketId/files')
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
}
$audits
->setResource('storage/files/' . $file->getId())
;
$usage
->setParam('storage', $sizeActual ?? 0)
->setParam('storage.files.create', 1)
@ -1267,6 +1248,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
->groups(['api', 'storage'])
->label('scope', 'files.write')
->label('event', 'buckets.[bucketId].files.[fileId].update')
->label('audits.resource', 'files/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'storage')
->label('sdk.method', 'updateFile')
@ -1281,11 +1263,10 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('audits')
->inject('usage')
->inject('mode')
->inject('events')
->action(function (string $bucketId, string $fileId, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, Audit $audits, Stats $usage, string $mode, Event $events) {
->action(function (string $bucketId, string $fileId, ?array $read, ?array $write, Response $response, Database $dbForProject, Document $user, Stats $usage, string $mode, Event $events) {
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$read = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? []; // By default set read permissions for user
$write = (is_null($write) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $write ?? [];
@ -1348,8 +1329,6 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
->setContext('bucket', $bucket)
;
$audits->setResource('file/' . $file->getId());
$usage
->setParam('storage.files.update', 1)
->setParam('bucketId', $bucketId)
@ -1364,6 +1343,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
->groups(['api', 'storage'])
->label('scope', 'files.write')
->label('event', 'buckets.[bucketId].files.[fileId].delete')
->label('audits.resource', 'file/{request.fileId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'storage')
->label('sdk.method', 'deleteFile')
@ -1373,15 +1353,13 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
->param('fileId', '', new UID(), 'File ID.')
->inject('response')
->inject('request')
->inject('dbForProject')
->inject('events')
->inject('audits')
->inject('usage')
->inject('mode')
->inject('deviceFiles')
->inject('deletes')
->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, Event $events, Audit $audits, Stats $usage, string $mode, Device $deviceFiles, Delete $deletes) {
->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $events, Stats $usage, string $mode, Device $deviceFiles, Delete $deletes) {
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
if (
@ -1437,8 +1415,6 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to delete file from device');
}
$audits->setResource('file/' . $file->getId());
$usage
->setParam('storage', $file->getAttribute('size', 0) * -1)
->setParam('storage.files.delete', 1)

View file

@ -2,7 +2,6 @@
use Appwrite\Auth\Auth;
use Appwrite\Detector\Detector;
use Appwrite\Event\Audit as EventAudit;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Mail;
@ -36,6 +35,7 @@ App::post('/v1/teams')
->groups(['api', 'teams'])
->label('event', 'teams.[teamId].create')
->label('scope', 'teams.write')
->label('audits.resource', 'team/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'create')
@ -50,8 +50,7 @@ App::post('/v1/teams')
->inject('user')
->inject('dbForProject')
->inject('events')
->inject('audits')
->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $events, Event $audits) {
->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $events) {
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
@ -94,12 +93,6 @@ App::post('/v1/teams')
$events->setParam('userId', $user->getId());
}
$audits
->setParam('event', 'teams.create')
->setParam('resource', 'team/' . $teamId)
->setParam('data', $team->getArrayCopy())
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response->dynamic($team, Response::MODEL_TEAM);
});
@ -178,6 +171,7 @@ App::put('/v1/teams/:teamId')
->groups(['api', 'teams'])
->label('event', 'teams.[teamId].update')
->label('scope', 'teams.write')
->label('audits.resource', 'team/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'update')
@ -190,8 +184,7 @@ App::put('/v1/teams/:teamId')
->inject('response')
->inject('dbForProject')
->inject('events')
->inject('audits')
->action(function (string $teamId, string $name, Response $response, Database $dbForProject, Event $events, EventAudit $audits) {
->action(function (string $teamId, string $name, Response $response, Database $dbForProject, Event $events) {
$team = $dbForProject->getDocument('teams', $teamId);
@ -204,7 +197,6 @@ App::put('/v1/teams/:teamId')
->setAttribute('search', implode(' ', [$teamId, $name])));
$events->setParam('teamId', $team->getId());
$audits->setResource('team/' . $team->getId());
$response->dynamic($team, Response::MODEL_TEAM);
});
@ -214,6 +206,7 @@ App::delete('/v1/teams/:teamId')
->groups(['api', 'teams'])
->label('event', 'teams.[teamId].delete')
->label('scope', 'teams.write')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'delete')
@ -225,8 +218,7 @@ App::delete('/v1/teams/:teamId')
->inject('dbForProject')
->inject('events')
->inject('deletes')
->inject('audits')
->action(function (string $teamId, Response $response, Database $dbForProject, Event $events, Delete $deletes, EventAudit $audits) {
->action(function (string $teamId, Response $response, Database $dbForProject, Event $events, Delete $deletes) {
$team = $dbForProject->getDocument('teams', $teamId);
@ -258,12 +250,6 @@ App::delete('/v1/teams/:teamId')
->setPayload($response->output($team, Response::MODEL_TEAM))
;
$audits
->setParam('event', 'teams.delete')
->setParam('resource', 'team/' . $teamId)
->setParam('data', $team->getArrayCopy())
;
$response->noContent();
});
@ -273,6 +259,8 @@ App::post('/v1/teams/:teamId/memberships')
->label('event', 'teams.[teamId].memberships.[membershipId].create')
->label('scope', 'teams.write')
->label('auth.type', 'invites')
->label('audits.resource', 'team/{request.teamId}')
->label('audits.userId', '{request.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'createMembership')
@ -291,10 +279,9 @@ App::post('/v1/teams/:teamId/memberships')
->inject('user')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('mails')
->inject('events')
->action(function (string $teamId, string $email, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, EventAudit $audits, Mail $mails, Event $events) {
->action(function (string $teamId, string $email, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, Event $events) {
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
@ -416,10 +403,6 @@ App::post('/v1/teams/:teamId/memberships')
;
}
$audits
->setResource('team/' . $teamId)
;
$events
->setParam('teamId', $team->getId())
->setParam('membershipId', $membership->getId())
@ -558,6 +541,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->groups(['api', 'teams'])
->label('event', 'teams.[teamId].memberships.[membershipId].update')
->label('scope', 'teams.write')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'updateMembershipRoles')
@ -572,9 +556,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, EventAudit $audits, Event $events) {
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $events) {
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
@ -610,8 +593,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
*/
$dbForProject->deleteCachedDocument('users', $profile->getId());
$audits->setResource('team/' . $teamId);
$events
->setParam('teamId', $team->getId())
->setParam('membershipId', $membership->getId());
@ -630,6 +611,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->groups(['api', 'teams'])
->label('event', 'teams.[teamId].memberships.[membershipId].update.status')
->label('scope', 'public')
->label('audits.resource', 'team/{request.teamId}')
->label('audits.userId', '{request.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'updateMembershipStatus')
@ -646,9 +629,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->inject('user')
->inject('dbForProject')
->inject('geodb')
->inject('audits')
->inject('events')
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Reader $geodb, EventAudit $audits, Event $events) {
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Reader $geodb, Event $events) {
$protocol = $request->getProtocol();
$membership = $dbForProject->getDocument('memberships', $membershipId);
@ -692,9 +674,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->setAttribute('confirm', true)
;
$user
->setAttribute('emailVerification', true)
;
$user->setAttribute('emailVerification', true);
// Log user in
@ -731,8 +711,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('total', $team->getAttribute('total', 0) + 1)));
$audits->setResource('team/' . $teamId);
$events
->setParam('teamId', $team->getId())
->setParam('membershipId', $membership->getId())
@ -763,6 +741,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
->groups(['api', 'teams'])
->label('event', 'teams.[teamId].memberships.[membershipId].delete')
->label('scope', 'teams.write')
->label('audits.resource', 'team/{request.teamId}')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'deleteMembership')
@ -773,9 +752,8 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
->param('membershipId', '', new UID(), 'Membership ID.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, EventAudit $audits, Event $events) {
->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, Event $events) {
$membership = $dbForProject->getDocument('memberships', $membershipId);
@ -814,8 +792,6 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team));
}
$audits->setResource('team/' . $teamId);
$events
->setParam('teamId', $team->getId())
->setParam('membershipId', $membership->getId())

View file

@ -6,7 +6,6 @@ use Appwrite\Auth\Validator\Phone;
use Appwrite\Detector\Detector;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Audit as EventAudit;
use Appwrite\Network\Validator\Email;
use Appwrite\Stats\Stats;
use Appwrite\Utopia\Database\Validator\CustomId;
@ -68,13 +67,9 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
throw new Exception(Exception::USER_ALREADY_EXISTS);
}
$usage
->setParam('users.create', 1)
;
$usage->setParam('users.create', 1);
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
return $user;
}
@ -84,6 +79,7 @@ App::post('/v1/users')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'create')
@ -112,6 +108,7 @@ App::post('/v1/users/bcrypt')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createBcryptUser')
@ -139,6 +136,7 @@ App::post('/v1/users/md5')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createMD5User')
@ -166,6 +164,7 @@ App::post('/v1/users/argon2')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createArgon2User')
@ -193,6 +192,7 @@ App::post('/v1/users/sha')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createSHAUser')
@ -227,6 +227,7 @@ App::post('/v1/users/phpass')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createPHPassUser')
@ -254,6 +255,7 @@ App::post('/v1/users/scrypt')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createScryptUser')
@ -294,6 +296,7 @@ App::post('/v1/users/scrypt-modified')
->groups(['api', 'users'])
->label('event', 'users.[userId].create')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'createScryptModifiedUser')
@ -355,9 +358,7 @@ App::get('/v1/users')
$queries[] = new Query('search', Query::TYPE_SEARCH, [$search]);
}
$usage
->setParam('users.read', 1)
;
$usage->setParam('users.read', 1);
$response->dynamic(new Document([
'users' => $dbForProject->find('users', $queries, $limit, $offset, [], [$orderType], $cursorUser ?? null, $cursorDirection),
@ -388,12 +389,48 @@ App::get('/v1/users/:userId')
throw new Exception(Exception::USER_NOT_FOUND);
}
$usage
->setParam('users.read', 1)
;
$usage->setParam('users.read', 1);
$response->dynamic($user, Response::MODEL_USER);
});
App::patch('/v1/users/:userId/prefs')
->desc('Update User Preferences')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.prefs')
->label('scope', 'users.write')
->label('audits.resource', 'user/{request.userId}')
->label('audits.userId', '{request.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updatePrefs')
->label('sdk.description', '/docs/references/users/update-user-prefs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PREFERENCES)
->param('userId', '', new UID(), 'User ID.')
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
->inject('response')
->inject('dbForProject')
->inject('usage')
->inject('events')
->action(function (string $userId, array $prefs, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
}
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
$response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES);
});
App::get('/v1/users/:userId/prefs')
->desc('Get User Preferences')
->groups(['api', 'users'])
@ -419,9 +456,8 @@ App::get('/v1/users/:userId/prefs')
$prefs = $user->getAttribute('prefs', new \stdClass());
$usage
->setParam('users.read', 1)
;
$usage->setParam('users.read', 1);
$response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES);
});
@ -461,9 +497,8 @@ App::get('/v1/users/:userId/sessions')
$sessions[$key] = $session;
}
$usage
->setParam('users.read', 1)
;
$usage->setParam('users.read', 1);
$response->dynamic(new Document([
'sessions' => $sessions,
'total' => count($sessions),
@ -581,9 +616,7 @@ App::get('/v1/users/:userId/logs')
}
}
$usage
->setParam('users.read', 1)
;
$usage->setParam('users.read', 1);
$response->dynamic(new Document([
'total' => $audit->countLogsByUser($user->getId()),
@ -596,6 +629,8 @@ App::patch('/v1/users/:userId/status')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.status')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateStatus')
@ -619,13 +654,9 @@ App::patch('/v1/users/:userId/status')
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('status', (bool) $status));
$usage
->setParam('users.update', 1)
;
$usage->setParam('users.update', 1);
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -635,6 +666,7 @@ App::patch('/v1/users/:userId/verification')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.verification')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateEmailVerification')
@ -658,13 +690,9 @@ App::patch('/v1/users/:userId/verification')
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', $emailVerification));
$usage
->setParam('users.update', 1)
;
$usage->setParam('users.update', 1);
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -674,6 +702,7 @@ App::patch('/v1/users/:userId/verification/phone')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.verification')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updatePhoneVerification')
@ -697,13 +726,9 @@ App::patch('/v1/users/:userId/verification/phone')
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('phoneVerification', $phoneVerification));
$usage
->setParam('users.update', 1)
;
$usage->setParam('users.update', 1);
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -713,6 +738,8 @@ App::patch('/v1/users/:userId/name')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.name')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateName')
@ -724,9 +751,8 @@ App::patch('/v1/users/:userId/name')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function (string $userId, string $name, Response $response, Database $dbForProject, EventAudit $audits, Event $events) {
->action(function (string $userId, string $name, Response $response, Database $dbForProject, Event $events) {
$user = $dbForProject->getDocument('users', $userId);
@ -741,13 +767,7 @@ App::patch('/v1/users/:userId/name')
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$audits
->setResource('user/' . $user->getId())
;
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -757,6 +777,8 @@ App::patch('/v1/users/:userId/password')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.password')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updatePassword')
@ -768,9 +790,9 @@ App::patch('/v1/users/:userId/password')
->param('password', '', new Password(), 'New user password. Must be at least 8 chars.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function (string $userId, string $password, Response $response, Database $dbForProject, EventAudit $audits, Event $events) {
->action(function (string $userId, string $password, Response $response, Database $dbForProject, Event $events) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
@ -785,13 +807,7 @@ App::patch('/v1/users/:userId/password')
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$audits
->setResource('user/' . $user->getId())
;
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -801,6 +817,8 @@ App::patch('/v1/users/:userId/email')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.email')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('audits.userId', '{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateEmail')
@ -812,9 +830,8 @@ App::patch('/v1/users/:userId/email')
->param('email', '', new Email(), 'User email.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function (string $userId, string $email, Response $response, Database $dbForProject, EventAudit $audits, Event $events) {
->action(function (string $userId, string $email, Response $response, Database $dbForProject, Event $events) {
$user = $dbForProject->getDocument('users', $userId);
@ -836,14 +853,7 @@ App::patch('/v1/users/:userId/email')
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
}
$audits
->setResource('user/' . $user->getId())
;
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -853,6 +863,7 @@ App::patch('/v1/users/:userId/phone')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.phone')
->label('scope', 'users.write')
->label('audits.resource', 'user/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updatePhone')
@ -864,9 +875,8 @@ App::patch('/v1/users/:userId/phone')
->param('number', '', new Phone(), 'User phone number.')
->inject('response')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function (string $userId, string $number, Response $response, Database $dbForProject, EventAudit $audits, Event $events) {
->action(function (string $userId, string $number, Response $response, Database $dbForProject, Event $events) {
$user = $dbForProject->getDocument('users', $userId);
@ -886,14 +896,44 @@ App::patch('/v1/users/:userId/phone')
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
}
$events->setParam('userId', $user->getId());
$audits
->setResource('user/' . $user->getId())
;
$response->dynamic($user, Response::MODEL_USER);
});
$events
->setParam('userId', $user->getId())
;
App::patch('/v1/users/:userId/verification')
->desc('Update Email Verification')
->groups(['api', 'users'])
->label('event', 'users.[userId].update.verification')
->label('scope', 'users.write')
->label('audits.resource', 'user/{request.userId}')
->label('audits.userId', '{request.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'updateEmailVerification')
->label('sdk.description', '/docs/references/users/update-user-email-verification.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('userId', '', new UID(), 'User ID.')
->param('emailVerification', false, new Boolean(), 'User email verification status.')
->inject('response')
->inject('dbForProject')
->inject('usage')
->inject('events')
->action(function (string $userId, bool $emailVerification, Response $response, Database $dbForProject, Stats $usage, Event $events) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', $emailVerification));
$usage->setParam('users.update', 1);
$events->setParam('userId', $user->getId());
$response->dynamic($user, Response::MODEL_USER);
});
@ -926,13 +966,9 @@ App::patch('/v1/users/:userId/prefs')
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$usage
->setParam('users.update', 1)
;
$usage->setParam('users.update', 1);
$events
->setParam('userId', $user->getId())
;
$events->setParam('userId', $user->getId());
$response->dynamic(new Document($prefs), Response::MODEL_PREFERENCES);
});
@ -942,6 +978,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
->groups(['api', 'users'])
->label('event', 'users.[userId].sessions.[sessionId].delete')
->label('scope', 'users.write')
->label('audits.resource', 'user/{request.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'deleteSession')
@ -990,6 +1027,7 @@ App::delete('/v1/users/:userId/sessions')
->groups(['api', 'users'])
->label('event', 'users.[userId].sessions.[sessionId].delete')
->label('scope', 'users.write')
->label('audits.resource', 'user/{user.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'deleteSessions')
@ -1036,6 +1074,7 @@ App::delete('/v1/users/:userId')
->groups(['api', 'users'])
->label('event', 'users.[userId].delete')
->label('scope', 'users.write')
->label('audits.resource', 'user/{request.userId}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'users')
->label('sdk.method', 'delete')
@ -1071,9 +1110,7 @@ App::delete('/v1/users/:userId')
->setPayload($response->output($clone, Response::MODEL_USER))
;
$usage
->setParam('users.delete', 1)
;
$usage->setParam('users.delete', 1);
$response->noContent();
});

View file

@ -43,7 +43,6 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar
$label = \str_replace($find, $params[$replace], $label);
}
}
return $label;
};
@ -70,7 +69,7 @@ App::init()
throw new Exception(Exception::PROJECT_UNKNOWN);
}
/*
/**
* Abuse Check
*/
$abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}');
@ -282,7 +281,7 @@ App::shutdown()
$bucket = $events->getContext('bucket');
$target = Realtime::fromPayload(
// Pass first, most verbose event pattern
// Pass first, most verbose event pattern
event: $allEvents[0],
payload: $payload,
project: $project,
@ -305,7 +304,38 @@ App::shutdown()
}
}
if (!empty($audits->getResource())) {
$route = $utopia->match($request);
$requestParams = $route->getParamsValues();
$user = $audits->getUser();
/**
* Audit labels
*/
$pattern = $route->getLabel('audits.resource', null);
if (!empty($pattern)) {
$resource = $parseLabel($pattern, $responsePayload, $requestParams, $user);
if (!empty($resource) && $resource !== $pattern) {
$audits->setResource($resource);
}
}
$pattern = $route->getLabel('audits.userId', null);
if (!empty($pattern)) {
$userId = $parseLabel($pattern, $responsePayload, $requestParams, $user);
$user = $dbForProject->getDocument('users', $userId);
$audits->setUser($user);
}
if (!empty($audits->getResource()) && !empty($audits->getUser()->getId())) {
/**
* audits.payload is switched to default true
* in order to auto audit payload for all endpoints
*/
$pattern = $route->getLabel('audits.payload', true);
if (!empty($pattern)) {
$audits->setPayload($responsePayload);
}
foreach ($events->getParams() as $key => $value) {
$audits->setParam($key, $value);
}
@ -320,10 +350,9 @@ App::shutdown()
$database->trigger();
}
$route = $utopia->match($request);
$requestParams = $route->getParamsValues();
$user = $audits->getUser();
/**
* Cache label
*/
$useCache = $route->getLabel('cache', false);
if ($useCache) {
$resource = null;

View file

@ -138,7 +138,7 @@ class DeletesV1 extends Worker
protected function deleteCacheByTimestamp(): void
{
$this->deleteCacheFiles([
new Query('accessedAt', Query::TYPE_LESSER, [$this->args['timestamp']])
new Query('accessedAt', Query::TYPE_LESSER, [$this->args['timestamp']])
]);
}