1
0
Fork 0
mirror of synced 2024-05-20 12:42:39 +12:00

Merge pull request #2523 from appwrite/feat-prepend-collection-name-to-id

feat(refactor-db): add prefix to external collections
This commit is contained in:
Torsten Dittmann 2021-12-28 13:15:55 +01:00 committed by GitHub
commit dbf8b2e1d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 902 additions and 911 deletions

2
.env
View file

@ -18,7 +18,7 @@ _APP_REDIS_PORT=6379
_APP_DB_HOST=mariadb
_APP_DB_PORT=3306
_APP_DB_SCHEMA=appwrite
_APP_DB_USER=root
_APP_DB_USER=user
_APP_DB_PASS=password
_APP_STORAGE_ANTIVIRUS=disabled
_APP_STORAGE_ANTIVIRUS_HOST=clamav

View file

@ -729,7 +729,7 @@ $collections = [
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
@ -740,7 +740,7 @@ $collections = [
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
@ -751,7 +751,7 @@ $collections = [
'format' => '',
'size' => 0,
'signed' => true,
'required' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
@ -1001,7 +1001,7 @@ $collections = [
'size' => 16384,
'signed' => true,
'required' => false,
'default' => [],
'default' => new \stdClass(),
'array' => false,
'filters' => ['json'],
],

View file

@ -51,14 +51,14 @@ App::post('/v1/account')
->inject('request')
->inject('response')
->inject('project')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($userId, $email, $password, $name, $request, $response, $project, $dbForInternal, $audits, $usage) {
->action(function ($userId, $email, $password, $name, $request, $response, $project, $dbForProject, $audits, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -79,7 +79,7 @@ App::post('/v1/account')
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [
$sum = $dbForProject->count('users', [
new Query('deleted', Query::TYPE_EQUAL, [false]),
], APP_LIMIT_USERS);
@ -89,8 +89,8 @@ App::post('/v1/account')
}
try {
$userId = $userId == 'unique()' ? $dbForInternal->getId() : $userId;
$user = Authorization::skip(fn() => $dbForInternal->createDocument('users', new Document([
$userId = $userId == 'unique()' ? $dbForProject->getId() : $userId;
$user = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:' . $userId],
@ -102,7 +102,7 @@ App::post('/v1/account')
'registration' => \time(),
'reset' => false,
'name' => $name,
'prefs' => [],
'prefs' => new \stdClass(),
'sessions' => [],
'tokens' => [],
'memberships' => [],
@ -149,15 +149,15 @@ App::post('/v1/account/sessions')
->param('password', '', new Password(), 'User password. Must be at least 8 chars.')
->inject('request')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('audits')
->inject('usage')
->action(function ($email, $password, $request, $response, $dbForInternal, $locale, $geodb, $audits, $usage) {
->action(function ($email, $password, $request, $response, $dbForProject, $locale, $geodb, $audits, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Event\Event $audits */
@ -166,7 +166,7 @@ App::post('/v1/account/sessions')
$email = \strtolower($email);
$protocol = $request->getProtocol();
$profile = $dbForInternal->findOne('users', [new Query('deleted', Query::TYPE_EQUAL, [false]), new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
$profile = $dbForProject->findOne('users', [new Query('deleted', Query::TYPE_EQUAL, [false]), new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if (!$profile || !Auth::passwordVerify($password, $profile->getAttribute('password'))) {
$audits
@ -188,7 +188,7 @@ App::post('/v1/account/sessions')
$secret = Auth::tokenGenerator();
$session = new Document(array_merge(
[
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $profile->getId(),
'provider' => Auth::SESSION_PROVIDER_EMAIL,
'providerUid' => $email,
@ -202,13 +202,13 @@ App::post('/v1/account/sessions')
Authorization::setRole('user:' . $profile->getId());
$session = $dbForInternal->createDocument('sessions', $session
$session = $dbForProject->createDocument('sessions', $session
->setAttribute('$read', ['user:' . $profile->getId()])
->setAttribute('$write', ['user:' . $profile->getId()])
);
$profile->setAttribute('sessions', $session, Document::SET_TYPE_APPEND);
$profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile);
$profile = $dbForProject->updateDocument('users', $profile->getId(), $profile);
$audits
->setParam('userId', $profile->getId())
@ -376,17 +376,17 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->inject('response')
->inject('project')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('geodb')
->inject('audits')
->inject('events')
->inject('usage')
->action(function ($provider, $code, $state, $request, $response, $project, $user, $dbForInternal, $geodb, $audits, $events, $usage) use ($oauthDefaultSuccess) {
->action(function ($provider, $code, $state, $request, $response, $project, $user, $dbForProject, $geodb, $audits, $events, $usage) use ($oauthDefaultSuccess) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -458,13 +458,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
if ($current === $session['$id']) {
unset($sessions[$key]);
$dbForInternal->deleteDocument('sessions', $session->getId());
$dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('sessions', $sessions));
$dbForProject->deleteDocument('sessions', $session->getId());
$dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('sessions', $sessions));
}
}
}
$user = ($user->isEmpty()) ? $dbForInternal->findOne('sessions', [ // Get user by provider id
$user = ($user->isEmpty()) ? $dbForProject->findOne('sessions', [ // Get user by provider id
new Query('provider', QUERY::TYPE_EQUAL, [$provider]),
new Query('providerUid', QUERY::TYPE_EQUAL, [$oauth2ID]),
]) : $user;
@ -473,13 +473,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$name = $oauth2->getUserName($accessToken);
$email = $oauth2->getUserEmail($accessToken);
$user = $dbForInternal->findOne('users', [new Query('deleted', Query::TYPE_EQUAL, [false]), new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
$user = $dbForProject->findOne('users', [new Query('deleted', Query::TYPE_EQUAL, [false]), new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if ($user === false || $user->isEmpty()) { // Last option -> create the user, generate random password
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [ new Query('deleted', Query::TYPE_EQUAL, [false]),], APP_LIMIT_COUNT);
$sum = $dbForProject->count('users', [ new Query('deleted', Query::TYPE_EQUAL, [false]),], APP_LIMIT_COUNT);
if ($sum >= $limit) {
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
@ -487,8 +487,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
}
try {
$userId = $dbForInternal->getId();
$user = Authorization::skip(fn() => $dbForInternal->createDocument('users', new Document([
$userId = $dbForProject->getId();
$user = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:' . $userId],
@ -500,7 +500,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
'registration' => \time(),
'reset' => false,
'name' => $name,
'prefs' => [],
'prefs' => new \stdClass(),
'sessions' => [],
'tokens' => [],
'memberships' => [],
@ -524,7 +524,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$secret = Auth::tokenGenerator();
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
$session = new Document(array_merge([
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $user->getId(),
'provider' => $provider,
'providerUid' => $oauth2ID,
@ -552,12 +552,12 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
Authorization::setRole('user:' . $user->getId());
$session = $dbForInternal->createDocument('sessions', $session
$session = $dbForProject->createDocument('sessions', $session
->setAttribute('$read', ['user:' . $user->getId()])
->setAttribute('$write', ['user:' . $user->getId()])
);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$audits
->setParam('userId', $user->getId())
@ -621,16 +621,16 @@ App::post('/v1/account/sessions/magic-url')
->inject('request')
->inject('response')
->inject('project')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('mails')
->action(function ($userId, $email, $url, $request, $response, $project, $dbForInternal, $locale, $audits, $events, $mails) {
->action(function ($userId, $email, $url, $request, $response, $project, $dbForProject, $locale, $audits, $events, $mails) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
@ -644,13 +644,13 @@ App::post('/v1/account/sessions/magic-url')
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
$user = $dbForInternal->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]);
$user = $dbForProject->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]);
if (!$user) {
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [
$sum = $dbForProject->count('users', [
new Query('deleted', Query::TYPE_EQUAL, [false]),
], APP_LIMIT_COUNT);
@ -659,9 +659,9 @@ App::post('/v1/account/sessions/magic-url')
}
}
$userId = $userId == 'unique()' ? $dbForInternal->getId() : $userId;
$userId = $userId == 'unique()' ? $dbForProject->getId() : $userId;
$user = Authorization::skip(fn () => $dbForInternal->createDocument('users', new Document([
$user = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:' . $userId],
@ -672,7 +672,7 @@ App::post('/v1/account/sessions/magic-url')
'passwordUpdate' => \time(),
'registration' => \time(),
'reset' => false,
'prefs' => [],
'prefs' => new \stdClass(),
'sessions' => [],
'tokens' => [],
'memberships' => [],
@ -689,7 +689,7 @@ App::post('/v1/account/sessions/magic-url')
$expire = \time() + Auth::TOKEN_EXPIRATION_CONFIRM;
$token = new Document([
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $user->getId(),
'type' => Auth::TOKEN_TYPE_MAGIC_URL,
'secret' => Auth::hash($loginSecret), // One way hash encryption to protect DB leak
@ -702,7 +702,7 @@ App::post('/v1/account/sessions/magic-url')
$user->setAttribute('tokens', $token, Document::SET_TYPE_APPEND);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
if (false === $user) {
throw new Exception('Failed to save user to DB', 500);
@ -766,21 +766,21 @@ App::put('/v1/account/sessions/magic-url')
->param('secret', '', new Text(256), 'Valid verification token.')
->inject('request')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('audits')
->action(function ($userId, $secret, $request, $response, $dbForInternal, $locale, $geodb, $audits) {
->action(function ($userId, $secret, $request, $response, $dbForProject, $locale, $geodb, $audits) {
/** @var string $userId */
/** @var string $secret */
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Event\Event $audits */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -798,7 +798,7 @@ App::put('/v1/account/sessions/magic-url')
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
$session = new Document(array_merge(
[
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $user->getId(),
'provider' => Auth::SESSION_PROVIDER_MAGIC_URL,
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
@ -814,7 +814,7 @@ App::put('/v1/account/sessions/magic-url')
Authorization::setRole('user:' . $user->getId());
$session = $dbForInternal->createDocument('sessions', $session
$session = $dbForProject->createDocument('sessions', $session
->setAttribute('$read', ['user:' . $user->getId()])
->setAttribute('$write', ['user:' . $user->getId()])
);
@ -836,7 +836,7 @@ App::put('/v1/account/sessions/magic-url')
->setAttribute('tokens', $tokens);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
if (false === $user) {
throw new Exception('Failed saving user to DB', 500);
@ -894,17 +894,17 @@ App::post('/v1/account/sessions/anonymous')
->inject('locale')
->inject('user')
->inject('project')
->inject('dbForInternal')
->inject('dbForProject')
->inject('geodb')
->inject('audits')
->inject('usage')
->action(function ($request, $response, $locale, $user, $project, $dbForInternal, $geodb, $audits, $usage) {
->action(function ($request, $response, $locale, $user, $project, $dbForProject, $geodb, $audits, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Locale\Locale $locale */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -922,7 +922,7 @@ App::post('/v1/account/sessions/anonymous')
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [
$sum = $dbForProject->count('users', [
new Query('deleted', Query::TYPE_EQUAL, [false]),
], APP_LIMIT_COUNT);
@ -931,8 +931,8 @@ App::post('/v1/account/sessions/anonymous')
}
}
$userId = $dbForInternal->getId();
$user = Authorization::skip(fn() => $dbForInternal->createDocument('users', new Document([
$userId = $dbForProject->getId();
$user = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:' . $userId],
@ -944,7 +944,7 @@ App::post('/v1/account/sessions/anonymous')
'registration' => \time(),
'reset' => false,
'name' => null,
'prefs' => [],
'prefs' => new \stdClass(),
'sessions' => [],
'tokens' => [],
'memberships' => [],
@ -960,7 +960,7 @@ App::post('/v1/account/sessions/anonymous')
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
$session = new Document(array_merge(
[
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $user->getId(),
'provider' => Auth::SESSION_PROVIDER_ANONYMOUS,
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
@ -976,12 +976,12 @@ App::post('/v1/account/sessions/anonymous')
Authorization::setRole('user:' . $user->getId());
$session = $dbForInternal->createDocument('sessions', $session
$session = $dbForProject->createDocument('sessions', $session
->setAttribute('$read', ['user:' . $user->getId()])
->setAttribute('$write', ['user:' . $user->getId()])
);
$user = $dbForInternal->updateDocument('users', $user->getId(),
$user = $dbForProject->updateDocument('users', $user->getId(),
$user->setAttribute('sessions', $session, Document::SET_TYPE_APPEND));
$audits
@ -1178,18 +1178,18 @@ App::get('/v1/account/logs')
->inject('user')
->inject('locale')
->inject('geodb')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($limit, $offset, $response, $user, $locale, $geodb, $dbForInternal, $usage) {
->action(function ($limit, $offset, $response, $user, $locale, $geodb, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
/** @var MaxMind\Db\Reader $geodb */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$audit = new Audit($dbForInternal);
$audit = new Audit($dbForProject);
$auditEvents = [
'account.create',
'account.delete',
@ -1262,13 +1262,13 @@ App::get('/v1/account/sessions/:sessionId')
->inject('response')
->inject('user')
->inject('locale')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($sessionId, $response, $user, $locale, $dbForInternal, $usage) {
->action(function ($sessionId, $response, $user, $locale, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Locale\Locale $locale */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$sessions = $user->getAttribute('sessions', []);
@ -1314,17 +1314,17 @@ App::patch('/v1/account/name')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($name, $response, $user, $dbForInternal, $audits, $usage) {
->action(function ($name, $response, $user, $dbForProject, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->updateDocument('users', $user->getId(), $user
$user = $dbForProject->updateDocument('users', $user->getId(), $user
->setAttribute('name', $name)
->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email')]))
);
@ -1358,13 +1358,13 @@ App::patch('/v1/account/password')
->param('oldPassword', '', new Password(), 'Current user password. Must be at least 8 chars.', true)
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($password, $oldPassword, $response, $user, $dbForInternal, $audits, $usage) {
->action(function ($password, $oldPassword, $response, $user, $dbForProject, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -1373,7 +1373,7 @@ App::patch('/v1/account/password')
throw new Exception('Invalid credentials', 401);
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user
$user = $dbForProject->updateDocument('users', $user->getId(), $user
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time())
);
@ -1406,13 +1406,13 @@ App::patch('/v1/account/email')
->param('password', '', new Password(), 'User password. Must be at least 8 chars.')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($email, $password, $response, $user, $dbForInternal, $audits, $usage) {
->action(function ($email, $password, $response, $user, $dbForProject, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -1426,14 +1426,14 @@ App::patch('/v1/account/email')
}
$email = \strtolower($email);
$profile = $dbForInternal->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
$profile = $dbForProject->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if ($profile) {
throw new Exception('User already registered', 409);
}
try {
$user = $dbForInternal->updateDocument('users', $user->getId(), $user
$user = $dbForProject->updateDocument('users', $user->getId(), $user
->setAttribute('password', $isAnonymousUser ? Auth::passwordHash($password) : $user->getAttribute('password', ''))
->setAttribute('email', $email)
->setAttribute('emailVerification', false) // After this user needs to confirm mail again
@ -1470,17 +1470,17 @@ App::patch('/v1/account/prefs')
->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($prefs, $response, $user, $dbForInternal, $audits, $usage) {
->action(function ($prefs, $response, $user, $dbForProject, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$audits
->setParam('event', 'account.update.prefs')
@ -1507,21 +1507,21 @@ App::delete('/v1/account')
->inject('request')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('events')
->inject('usage')
->action(function ($request, $response, $user, $dbForInternal, $audits, $events, $usage) {
->action(function ($request, $response, $user, $dbForProject, $audits, $events, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Stats\Stats $usage */
$protocol = $request->getProtocol();
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('status', false));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('status', false));
// TODO Seems to be related to users.php/App::delete('/v1/users/:userId'). Can we share code between these two? Do todos below apply to users.php?
@ -1576,16 +1576,16 @@ App::delete('/v1/account/sessions/:sessionId')
->inject('request')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('usage')
->action(function ($sessionId, $request, $response, $user, $dbForInternal, $locale, $audits, $events, $usage) {
->action(function ($sessionId, $request, $response, $user, $dbForProject, $locale, $audits, $events, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
@ -1602,7 +1602,7 @@ App::delete('/v1/account/sessions/:sessionId')
if ($sessionId == $session->getId()) {
unset($sessions[$key]);
$dbForInternal->deleteDocument('sessions', $session->getId());
$dbForProject->deleteDocument('sessions', $session->getId());
$audits
->setParam('userId', $user->getId())
@ -1630,7 +1630,7 @@ App::delete('/v1/account/sessions/:sessionId')
;
}
$dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('sessions', $sessions));
$dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('sessions', $sessions));
$events
->setParam('eventData', $response->output($session, Response::MODEL_SESSION))
@ -1662,16 +1662,16 @@ App::delete('/v1/account/sessions')
->inject('request')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('usage')
->action(function ($request, $response, $user, $dbForInternal, $locale, $audits, $events, $usage) {
->action(function ($request, $response, $user, $dbForProject, $locale, $audits, $events, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
@ -1681,7 +1681,7 @@ App::delete('/v1/account/sessions')
$sessions = $user->getAttribute('sessions', []);
foreach ($sessions as $session) {/** @var Document $session */
$dbForInternal->deleteDocument('sessions', $session->getId());
$dbForProject->deleteDocument('sessions', $session->getId());
$audits
->setParam('userId', $user->getId())
@ -1709,7 +1709,7 @@ App::delete('/v1/account/sessions')
}
}
$dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('sessions', []));
$dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('sessions', []));
$numOfSessions = count($sessions);
@ -1745,17 +1745,17 @@ App::post('/v1/account/recovery')
->param('url', '', function ($clients) {return new Host($clients);}, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients'])
->inject('request')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('project')
->inject('locale')
->inject('mails')
->inject('audits')
->inject('events')
->inject('usage')
->action(function ($email, $url, $request, $response, $dbForInternal, $project, $locale, $mails, $audits, $events, $usage) {
->action(function ($email, $url, $request, $response, $dbForProject, $project, $locale, $mails, $audits, $events, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $mails */
@ -1772,7 +1772,7 @@ App::post('/v1/account/recovery')
$isAppUser = Auth::isAppUser($roles);
$email = \strtolower($email);
$profile = $dbForInternal->findOne('users', [new Query('deleted', Query::TYPE_EQUAL, [false]), new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
$profile = $dbForProject->findOne('users', [new Query('deleted', Query::TYPE_EQUAL, [false]), new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if (!$profile) {
throw new Exception('User not found', 404);
@ -1786,7 +1786,7 @@ App::post('/v1/account/recovery')
$secret = Auth::tokenGenerator();
$recovery = new Document([
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $profile->getId(),
'type' => Auth::TOKEN_TYPE_RECOVERY,
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
@ -1799,7 +1799,7 @@ App::post('/v1/account/recovery')
$profile->setAttribute('tokens', $recovery, Document::SET_TYPE_APPEND);
$profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile);
$profile = $dbForProject->updateDocument('users', $profile->getId(), $profile);
$url = Template::parseURL($url);
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $profile->getId(), 'secret' => $secret, 'expire' => $expire]);
@ -1860,12 +1860,12 @@ App::put('/v1/account/recovery')
->param('password', '', new Password(), 'New user password. Must be at least 8 chars.')
->param('passwordAgain', '', new Password(), 'Repeat new user password. Must be at least 8 chars.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($userId, $secret, $password, $passwordAgain, $response, $dbForInternal, $audits, $usage) {
->action(function ($userId, $secret, $password, $passwordAgain, $response, $dbForProject, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -1873,7 +1873,7 @@ App::put('/v1/account/recovery')
throw new Exception('Passwords must match', 400);
}
$profile = $dbForInternal->getDocument('users', $userId);
$profile = $dbForProject->getDocument('users', $userId);
if ($profile->isEmpty() || $profile->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -1888,7 +1888,7 @@ App::put('/v1/account/recovery')
Authorization::setRole('user:' . $profile->getId());
$profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile
$profile = $dbForProject->updateDocument('users', $profile->getId(), $profile
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time())
->setAttribute('emailVerification', true)
@ -1905,7 +1905,7 @@ App::put('/v1/account/recovery')
}
}
$dbForInternal->updateDocument('users', $profile->getId(), $profile->setAttribute('tokens', $tokens));
$dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('tokens', $tokens));
$audits
->setParam('userId', $profile->getId())
@ -1938,18 +1938,18 @@ App::post('/v1/account/verification')
->inject('response')
->inject('project')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('events')
->inject('mails')
->inject('usage')
->action(function ($url, $request, $response, $project, $user, $dbForInternal, $locale, $audits, $events, $mails, $usage) {
->action(function ($url, $request, $response, $project, $user, $dbForProject, $locale, $audits, $events, $mails, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
@ -1969,7 +1969,7 @@ App::post('/v1/account/verification')
$expire = \time() + Auth::TOKEN_EXPIRATION_CONFIRM;
$verification = new Document([
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $user->getId(),
'type' => Auth::TOKEN_TYPE_VERIFICATION,
'secret' => Auth::hash($verificationSecret), // One way hash encryption to protect DB leak
@ -1982,7 +1982,7 @@ App::post('/v1/account/verification')
$user->setAttribute('tokens', $verification, Document::SET_TYPE_APPEND);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$url = Template::parseURL($url);
$url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $verificationSecret, 'expire' => $expire]);
@ -2042,17 +2042,17 @@ App::put('/v1/account/verification')
->param('secret', '', new Text(256), 'Valid verification token.')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('usage')
->action(function ($userId, $secret, $response, $user, $dbForInternal, $audits, $usage) {
->action(function ($userId, $secret, $response, $user, $dbForProject, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
$profile = $dbForInternal->getDocument('users', $userId);
$profile = $dbForProject->getDocument('users', $userId);
if ($profile->isEmpty()) {
throw new Exception('User not found', 404);
@ -2067,7 +2067,7 @@ App::put('/v1/account/verification')
Authorization::setRole('user:' . $profile->getId());
$profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true));
$profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true));
/**
* We act like we're updating and validating
@ -2080,7 +2080,7 @@ App::put('/v1/account/verification')
}
}
$dbForInternal->updateDocument('users', $profile->getId(), $profile->setAttribute('tokens', $tokens));
$dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('tokens', $tokens));
$audits
->setParam('userId', $profile->getId())

File diff suppressed because it is too large Load diff

View file

@ -48,13 +48,13 @@ App::post('/v1/functions')
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
->param('timeout', 15, new Range(1, 900), 'Function maximum execution time in seconds.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($functionId, $name, $execute, $runtime, $vars, $events, $schedule, $timeout, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($functionId, $name, $execute, $runtime, $vars, $events, $schedule, $timeout, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$functionId = ($functionId == 'unique()') ? $dbForInternal->getId() : $functionId;
$function = $dbForInternal->createDocument('functions', new Document([
$functionId = ($functionId == 'unique()') ? $dbForProject->getId() : $functionId;
$function = $dbForProject->createDocument('functions', new Document([
'$id' => $functionId,
'execute' => $execute,
'dateCreated' => time(),
@ -94,13 +94,13 @@ App::get('/v1/functions')
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
if (!empty($cursor)) {
$cursorFunction = $dbForInternal->getDocument('functions', $cursor);
$cursorFunction = $dbForProject->getDocument('functions', $cursor);
if ($cursorFunction->isEmpty()) {
throw new Exception("Function '{$cursor}' for the 'cursor' value not found.", 400);
@ -114,8 +114,8 @@ App::get('/v1/functions')
}
$response->dynamic(new Document([
'functions' => $dbForInternal->find('functions', $queries, $limit, $offset, [], [$orderType], $cursorFunction ?? null, $cursorDirection),
'sum' => $dbForInternal->count('functions', $queries, APP_LIMIT_COUNT),
'functions' => $dbForProject->find('functions', $queries, $limit, $offset, [], [$orderType], $cursorFunction ?? null, $cursorDirection),
'sum' => $dbForProject->count('functions', $queries, APP_LIMIT_COUNT),
]), Response::MODEL_FUNCTION_LIST);
});
@ -160,12 +160,12 @@ App::get('/v1/functions/:functionId')
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new UID(), 'Function ID.')
->inject('response')
->inject('dbForInternal')
->action(function ($functionId, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($functionId, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
@ -187,16 +187,14 @@ App::get('/v1/functions/:functionId/usage')
->param('functionId', '', new UID(), 'Function ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true)
->inject('response')
->inject('project')
->inject('dbForInternal')
->inject('register')
->action(function ($functionId, $range, $response, $project, $dbForInternal, $register) {
->inject('dbForProject')
->action(function ($functionId, $range, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Registry\Registry $register */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
@ -231,12 +229,12 @@ App::get('/v1/functions/:functionId/usage')
$stats = [];
Authorization::skip(function() use ($dbForInternal, $periods, $range, $metrics, &$stats) {
Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForInternal->find('stats', [
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
@ -298,14 +296,14 @@ App::put('/v1/functions/:functionId')
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
->param('timeout', 15, new Range(1, 900), 'Maximum execution time in seconds.', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('project')
->action(function ($functionId, $name, $execute, $vars, $events, $schedule, $timeout, $response, $dbForInternal, $project) {
->action(function ($functionId, $name, $execute, $vars, $events, $schedule, $timeout, $response, $dbForProject, $project) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $project */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
@ -315,7 +313,7 @@ App::put('/v1/functions/:functionId')
$cron = (!empty($function->getAttribute('tag', null)) && !empty($schedule)) ? new CronExpression($schedule) : null;
$next = (!empty($function->getAttribute('tag', null)) && !empty($schedule)) ? $cron->getNextRunDate()->format('U') : 0;
$function = $dbForInternal->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
$function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
'execute' => $execute,
'dateUpdated' => time(),
'name' => $name,
@ -355,15 +353,15 @@ App::patch('/v1/functions/:functionId/tag')
->param('functionId', '', new UID(), 'Function ID.')
->param('tag', '', new UID(), 'Tag ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('project')
->action(function ($functionId, $tag, $response, $dbForInternal, $project) {
->action(function ($functionId, $tag, $response, $dbForProject, $project) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $project */
$function = $dbForInternal->getDocument('functions', $functionId);
$tag = $dbForInternal->getDocument('tags', $tag);
$function = $dbForProject->getDocument('functions', $functionId);
$tag = $dbForProject->getDocument('tags', $tag);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
@ -377,7 +375,7 @@ App::patch('/v1/functions/:functionId/tag')
$cron = (empty($function->getAttribute('tag')) && !empty($schedule)) ? new CronExpression($schedule) : null;
$next = (empty($function->getAttribute('tag')) && !empty($schedule)) ? $cron->getNextRunDate()->format('U') : 0;
$function = $dbForInternal->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
$function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
'tag' => $tag->getId(),
'scheduleNext' => (int)$next,
])));
@ -408,20 +406,20 @@ App::delete('/v1/functions/:functionId')
->label('sdk.response.model', Response::MODEL_NONE)
->param('functionId', '', new UID(), 'Function ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('deletes')
->action(function ($functionId, $response, $dbForInternal, $deletes) {
->action(function ($functionId, $response, $dbForProject, $deletes) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $deletes */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
if (!$dbForInternal->deleteDocument('functions', $function->getId())) {
if (!$dbForProject->deleteDocument('functions', $function->getId())) {
throw new Exception('Failed to remove function from DB', 500);
}
@ -452,15 +450,15 @@ App::post('/v1/functions/:functionId/tags')
->param('code', [], new File(), 'Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.', false)
->inject('request')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($functionId, $command, $file, $request, $response, $dbForInternal, $usage) {
->action(function ($functionId, $command, $file, $request, $response, $dbForProject, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $usage */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
@ -501,8 +499,8 @@ App::post('/v1/functions/:functionId/tags')
throw new Exception('Failed moving file', 500);
}
$tagId = $dbForInternal->getId();
$tag = $dbForInternal->createDocument('tags', new Document([
$tagId = $dbForProject->getId();
$tag = $dbForProject->createDocument('tags', new Document([
'$id' => $tagId,
'$read' => [],
'$write' => [],
@ -541,19 +539,19 @@ App::get('/v1/functions/:functionId/tags')
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($functionId, $search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($functionId, $search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
if (!empty($cursor)) {
$cursorTag = $dbForInternal->getDocument('tags', $cursor);
$cursorTag = $dbForProject->getDocument('tags', $cursor);
if ($cursorTag->isEmpty()) {
throw new Exception("Tag '{$cursor}' for the 'cursor' value not found.", 400);
@ -568,8 +566,8 @@ App::get('/v1/functions/:functionId/tags')
$queries[] = new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]);
$results = $dbForInternal->find('tags', $queries, $limit, $offset, [], [$orderType], $cursorTag ?? null, $cursorDirection);
$sum = $dbForInternal->count('tags', $queries, APP_LIMIT_COUNT);
$results = $dbForProject->find('tags', $queries, $limit, $offset, [], [$orderType], $cursorTag ?? null, $cursorDirection);
$sum = $dbForProject->count('tags', $queries, APP_LIMIT_COUNT);
$response->dynamic(new Document([
'tags' => $results,
@ -591,18 +589,18 @@ App::get('/v1/functions/:functionId/tags/:tagId')
->param('functionId', '', new UID(), 'Function ID.')
->param('tagId', '', new UID(), 'Tag ID.')
->inject('response')
->inject('dbForInternal')
->action(function ($functionId, $tagId, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($functionId, $tagId, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
$tag = $dbForInternal->getDocument('tags', $tagId);
$tag = $dbForProject->getDocument('tags', $tagId);
if ($tag->getAttribute('functionId') !== $function->getId()) {
throw new Exception('Tag not found', 404);
@ -629,20 +627,20 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
->param('functionId', '', new UID(), 'Function ID.')
->param('tagId', '', new UID(), 'Tag ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($functionId, $tagId, $response, $dbForInternal, $usage) {
->action(function ($functionId, $tagId, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $usage */
$function = $dbForInternal->getDocument('functions', $functionId);
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
$tag = $dbForInternal->getDocument('tags', $tagId);
$tag = $dbForProject->getDocument('tags', $tagId);
if ($tag->getAttribute('functionId') !== $function->getId()) {
throw new Exception('Tag not found', 404);
@ -655,13 +653,13 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
$device = Storage::getDevice('functions');
if ($device->delete($tag->getAttribute('path', ''))) {
if (!$dbForInternal->deleteDocument('tags', $tag->getId())) {
if (!$dbForProject->deleteDocument('tags', $tag->getId())) {
throw new Exception('Failed to remove tag from DB', 500);
}
}
if($function->getAttribute('tag') === $tag->getId()) { // Reset function tag
$function = $dbForInternal->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
$function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
'tag' => '',
])));
}
@ -692,21 +690,21 @@ App::post('/v1/functions/:functionId/executions')
// ->param('async', 1, new Range(0, 1), 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
->inject('response')
->inject('project')
->inject('dbForInternal')
->inject('dbForProject')
->inject('user')
->action(function ($functionId, $data, /*$async,*/ $response, $project, $dbForInternal, $user) {
->action(function ($functionId, $data, /*$async,*/ $response, $project, $dbForProject, $user) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $user */
$function = Authorization::skip(fn() => $dbForInternal->getDocument('functions', $functionId));
$function = Authorization::skip(fn() => $dbForProject->getDocument('functions', $functionId));
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
$tag = Authorization::skip(fn() => $dbForInternal->getDocument('tags', $function->getAttribute('tag')));
$tag = Authorization::skip(fn() => $dbForProject->getDocument('tags', $function->getAttribute('tag')));
if ($tag->getAttribute('functionId') !== $function->getId()) {
throw new Exception('Tag not found. Deploy tag before trying to execute a function', 404);
@ -722,9 +720,9 @@ App::post('/v1/functions/:functionId/executions')
throw new Exception($validator->getDescription(), 401);
}
$executionId = $dbForInternal->getId();
$executionId = $dbForProject->getId();
$execution = Authorization::skip(fn() => $dbForInternal->createDocument('executions', new Document([
$execution = Authorization::skip(fn() => $dbForProject->createDocument('executions', new Document([
'$id' => $executionId,
'$read' => (!$user->isEmpty()) ? ['user:' . $user->getId()] : [],
'$write' => [],
@ -794,19 +792,19 @@ App::get('/v1/functions/:functionId/executions')
->param('cursor', '', new UID(), 'ID of the execution used as the starting point for the query, excluding the execution itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($functionId, $limit, $offset, $search, $cursor, $cursorDirection, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($functionId, $limit, $offset, $search, $cursor, $cursorDirection, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$function = Authorization::skip(fn() => $dbForInternal->getDocument('functions', $functionId));
$function = Authorization::skip(fn() => $dbForProject->getDocument('functions', $functionId));
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
if (!empty($cursor)) {
$cursorExecution = $dbForInternal->getDocument('executions', $cursor);
$cursorExecution = $dbForProject->getDocument('executions', $cursor);
if ($cursorExecution->isEmpty()) {
throw new Exception("Execution '{$cursor}' for the 'cursor' value not found.", 400);
@ -821,8 +819,8 @@ App::get('/v1/functions/:functionId/executions')
$queries[] = new Query('search', Query::TYPE_SEARCH, [$search]);
}
$results = $dbForInternal->find('executions', $queries, $limit, $offset, [], [Database::ORDER_DESC], $cursorExecution ?? null, $cursorDirection);
$sum = $dbForInternal->count('executions', $queries, APP_LIMIT_COUNT);
$results = $dbForProject->find('executions', $queries, $limit, $offset, [], [Database::ORDER_DESC], $cursorExecution ?? null, $cursorDirection);
$sum = $dbForProject->count('executions', $queries, APP_LIMIT_COUNT);
$response->dynamic(new Document([
'executions' => $results,
@ -844,18 +842,18 @@ App::get('/v1/functions/:functionId/executions/:executionId')
->param('functionId', '', new UID(), 'Function ID.')
->param('executionId', '', new UID(), 'Execution ID.')
->inject('response')
->inject('dbForInternal')
->action(function ($functionId, $executionId, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($functionId, $executionId, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$function = Authorization::skip(fn() => $dbForInternal->getDocument('functions', $functionId));
$function = Authorization::skip(fn() => $dbForProject->getDocument('functions', $functionId));
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
$execution = $dbForInternal->getDocument('executions', $executionId);
$execution = $dbForProject->getDocument('executions', $executionId);
if ($execution->getAttribute('functionId') !== $function->getId()) {
throw new Exception('Execution not found', 404);

View file

@ -224,9 +224,7 @@ App::get('/v1/locale/currencies')
$list = Config::getParam('locale-currencies');
$list = array_map(function($node) {
return new Document($node);
}, $list);
$list = array_map(fn($node) => new Document($node), $list);
$response->dynamic(new Document(['currencies' => $list, 'sum' => \count($list)]), Response::MODEL_CURRENCY_LIST);
});
@ -249,9 +247,7 @@ App::get('/v1/locale/languages')
$list = Config::getParam('locale-languages');
$list = array_map(function($node) {
return new Document($node);
}, $list);
$list = array_map(fn ($node) => new Document($node), $list);
$response->dynamic(new Document(['languages' => $list, 'sum' => \count($list)]), Response::MODEL_LANGUAGE_LIST);
});

View file

@ -57,13 +57,11 @@ App::post('/v1/projects')
->param('legalTaxId', '', new Text(256), 'Project legal Tax ID. Max length: 256 chars.', true)
->inject('response')
->inject('dbForConsole')
->inject('dbForInternal')
->inject('dbForExternal')
->action(function ($projectId, $name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId, $response, $dbForConsole, $dbForInternal, $dbForExternal) {
->inject('dbForProject')
->action(function ($projectId, $name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId, $response, $dbForConsole, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForConsole */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForExternal */
/** @var Utopia\Database\Database $dbForProject */
$team = $dbForConsole->getDocument('teams', $teamId);
@ -106,15 +104,13 @@ App::post('/v1/projects')
$collections = Config::getParam('collections', []); /** @var array $collections */
$dbForInternal->setNamespace('project_' . $project->getId() . '_internal');
$dbForInternal->create();
$dbForExternal->setNamespace('project_' . $project->getId() . '_external');
$dbForExternal->create();
$dbForProject->setNamespace('_project_' . $project->getId());
$dbForProject->create('appwrite');
$audit = new Audit($dbForInternal);
$audit = new Audit($dbForProject);
$audit->setup();
$adapter = new TimeLimit('', 0, 1, $dbForInternal);
$adapter = new TimeLimit('', 0, 1, $dbForProject);
$adapter->setup();
foreach ($collections as $key => $collection) {
@ -143,7 +139,7 @@ App::post('/v1/projects')
]);
}
$dbForInternal->createCollection($key, $attributes, $indexes);
$dbForProject->createCollection($key, $attributes, $indexes);
}
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -235,12 +231,12 @@ App::get('/v1/projects/:projectId/usage')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForConsole')
->inject('dbForInternal')
->inject('dbForProject')
->inject('register')
->action(function ($projectId, $range, $response, $dbForConsole, $dbForInternal, $register) {
->action(function ($projectId, $range, $response, $dbForConsole, $dbForProject, $register) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForConsole */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Registry\Registry $register */
$project = $dbForConsole->getDocument('projects', $projectId);
@ -270,11 +266,11 @@ App::get('/v1/projects/:projectId/usage')
],
];
$dbForInternal->setNamespace('project_' . $projectId . '_internal');
$dbForProject->setNamespace('_project_' . $projectId);
$metrics = [
'requests',
'network',
'requests',
'network',
'executions',
'users.count',
'database.documents.count',
@ -284,12 +280,12 @@ App::get('/v1/projects/:projectId/usage')
$stats = [];
Authorization::skip(function() use ($dbForInternal, $periods, $range, $metrics, &$stats) {
Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForInternal->find('stats', [
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);

View file

@ -47,14 +47,14 @@ App::post('/v1/storage/files')
->param('write', null, new ArrayList(new Text(64)), '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('request')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('user')
->inject('audits')
->inject('usage')
->action(function ($fileId, $file, $read, $write, $request, $response, $dbForInternal, $user, $audits, $usage) {
->action(function ($fileId, $file, $read, $write, $request, $response, $dbForProject, $user, $audits, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $user */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
@ -146,8 +146,8 @@ App::post('/v1/storage/files')
$sizeActual = $device->getFileSize($path);
$fileId = ($fileId == 'unique()') ? $dbForInternal->getId() : $fileId;
$file = $dbForInternal->createDocument('files', new Document([
$fileId = ($fileId == 'unique()') ? $dbForProject->getId() : $fileId;
$file = $dbForProject->createDocument('files', new Document([
'$id' => $fileId,
'$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 ?? [], // By default set write permissions for user
@ -202,15 +202,15 @@ App::get('/v1/storage/files')
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal, $usage) {
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
if (!empty($cursor)) {
$cursorFile = $dbForInternal->getDocument('files', $cursor);
$cursorFile = $dbForProject->getDocument('files', $cursor);
if ($cursorFile->isEmpty()) {
throw new Exception("File '{$cursor}' for the 'cursor' value not found.", 400);
@ -229,8 +229,8 @@ App::get('/v1/storage/files')
;
$response->dynamic(new Document([
'files' => $dbForInternal->find('files', $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection),
'sum' => $dbForInternal->count('files', $queries, APP_LIMIT_COUNT),
'files' => $dbForProject->find('files', $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection),
'sum' => $dbForProject->count('files', $queries, APP_LIMIT_COUNT),
]), Response::MODEL_FILE_LIST);
});
@ -247,14 +247,14 @@ App::get('/v1/storage/files/:fileId')
->label('sdk.response.model', Response::MODEL_FILE)
->param('fileId', '', new UID(), 'File ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($fileId, $response, $dbForInternal, $usage) {
->action(function ($fileId, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$file = $dbForInternal->getDocument('files', $fileId);
$file = $dbForProject->getDocument('files', $fileId);
if (empty($file->getId())) {
throw new Exception('File not found', 404);
@ -292,13 +292,13 @@ App::get('/v1/storage/files/:fileId/preview')
->inject('request')
->inject('response')
->inject('project')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($fileId, $width, $height, $gravity, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output, $request, $response, $project, $dbForInternal, $usage) {
->action(function ($fileId, $width, $height, $gravity, $quality, $borderWidth, $borderColor, $borderRadius, $opacity, $rotation, $background, $output, $request, $response, $project, $dbForProject, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $stats */
$storage = 'files';
@ -322,7 +322,7 @@ App::get('/v1/storage/files/:fileId/preview')
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5($fileId.$width.$height.$gravity.$quality.$borderWidth.$borderColor.$borderRadius.$opacity.$rotation.$background.$storage.$output);
$file = $dbForInternal->getDocument('files', $fileId);
$file = $dbForProject->getDocument('files', $fileId);
if (empty($file->getId())) {
throw new Exception('File not found', 404);
@ -440,14 +440,14 @@ App::get('/v1/storage/files/:fileId/download')
->label('sdk.methodType', 'location')
->param('fileId', '', new UID(), 'File ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($fileId, $response, $dbForInternal, $usage) {
->action(function ($fileId, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$file = $dbForInternal->getDocument('files', $fileId);
$file = $dbForProject->getDocument('files', $fileId);
if (empty($file->getId())) {
throw new Exception('File not found', 404);
@ -505,14 +505,14 @@ App::get('/v1/storage/files/:fileId/view')
->label('sdk.methodType', 'location')
->param('fileId', '', new UID(), 'File ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($fileId, $response, $dbForInternal, $usage) {
->action(function ($fileId, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$file = $dbForInternal->getDocument('files', $fileId);
$file = $dbForProject->getDocument('files', $fileId);
$mimes = Config::getParam('storage-mimes');
if (empty($file->getId())) {
@ -583,13 +583,13 @@ App::put('/v1/storage/files/:fileId')
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.')
->param('write', [], new ArrayList(new Text(64)), '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('dbForInternal')
->inject('dbForProject')
->inject('user')
->inject('audits')
->inject('usage')
->action(function ($fileId, $read, $write, $response, $dbForInternal, $user, $audits, $usage) {
->action(function ($fileId, $read, $write, $response, $dbForProject, $user, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $user */
/** @var Appwrite\Event\Event $audits */
@ -612,13 +612,13 @@ App::put('/v1/storage/files/:fileId')
}
}
$file = $dbForInternal->getDocument('files', $fileId);
$file = $dbForProject->getDocument('files', $fileId);
if (empty($file->getId())) {
throw new Exception('File not found', 404);
}
$file = $dbForInternal->updateDocument('files', $fileId, new Document(\array_merge($file->getArrayCopy(), [
$file = $dbForProject->updateDocument('files', $fileId, new Document(\array_merge($file->getArrayCopy(), [
'$read' => $read,
'$write' => $write,
'bucketId' => '',
@ -650,18 +650,18 @@ App::delete('/v1/storage/files/:fileId')
->label('sdk.response.model', Response::MODEL_NONE)
->param('fileId', '', new UID(), 'File ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('events')
->inject('audits')
->inject('usage')
->action(function ($fileId, $response, $dbForInternal, $events, $audits, $usage) {
->action(function ($fileId, $response, $dbForProject, $events, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
$file = $dbForInternal->getDocument('files', $fileId);
$file = $dbForProject->getDocument('files', $fileId);
if (empty($file->getId())) {
throw new Exception('File not found', 404);
@ -670,7 +670,7 @@ App::delete('/v1/storage/files/:fileId')
$device = Storage::getDevice('files');
if ($device->delete($file->getAttribute('path', ''))) {
if (!$dbForInternal->deleteDocument('files', $fileId)) {
if (!$dbForProject->deleteDocument('files', $fileId)) {
throw new Exception('Failed to remove file from DB', 500);
}
}
@ -705,10 +705,10 @@ App::get('/v1/storage/usage')
->label('sdk.response.model', Response::MODEL_USAGE_STORAGE)
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($range, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($range, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
@ -738,12 +738,12 @@ App::get('/v1/storage/usage')
$stats = [];
Authorization::skip(function() use ($dbForInternal, $periods, $range, $metrics, &$stats) {
Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForInternal->find('stats', [
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);
@ -797,10 +797,10 @@ App::get('/v1/storage/:bucketId/usage')
->param('bucketId', '', new UID(), 'Bucket ID.')
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($bucketId, $range, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($bucketId, $range, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
// TODO: Check if the storage bucket exists else throw 404
@ -835,12 +835,12 @@ App::get('/v1/storage/:bucketId/usage')
$stats = [];
Authorization::skip(function() use ($dbForInternal, $periods, $range, $metrics, &$stats) {
Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForInternal->find('stats', [
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);

View file

@ -39,19 +39,19 @@ App::post('/v1/teams')
->param('roles', ['owner'], new ArrayList(new Key()), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.', true)
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('events')
->action(function ($teamId, $name, $roles, $response, $user, $dbForInternal, $events) {
->action(function ($teamId, $name, $roles, $response, $user, $dbForProject, $events) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $events */
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
$teamId = $teamId == 'unique()' ? $dbForInternal->getId() : $teamId;
$team = Authorization::skip(fn() => $dbForInternal->createDocument('teams', new Document([
$teamId = $teamId == 'unique()' ? $dbForProject->getId() : $teamId;
$team = Authorization::skip(fn() => $dbForProject->createDocument('teams', new Document([
'$id' => $teamId ,
'$read' => ['team:'.$teamId],
'$write' => ['team:'.$teamId .'/owner'],
@ -74,11 +74,11 @@ App::post('/v1/teams')
'secret' => '',
]);
$membership = $dbForInternal->createDocument('memberships', $membership);
$membership = $dbForProject->createDocument('memberships', $membership);
// Attach user to team
$user->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
}
if (!empty($user->getId())) {
@ -107,13 +107,13 @@ App::get('/v1/teams')
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
if (!empty($cursor)) {
$cursorTeam = $dbForInternal->getDocument('teams', $cursor);
$cursorTeam = $dbForProject->getDocument('teams', $cursor);
if ($cursorTeam->isEmpty()) {
throw new Exception("Team '{$cursor}' for the 'cursor' value not found.", 400);
@ -126,8 +126,8 @@ App::get('/v1/teams')
$queries[] = new Query('search', Query::TYPE_SEARCH, [$search]);
}
$results = $dbForInternal->find('teams', $queries, $limit, $offset, [], [$orderType], $cursorTeam ?? null, $cursorDirection);
$sum = $dbForInternal->count('teams', $queries, APP_LIMIT_COUNT);
$results = $dbForProject->find('teams', $queries, $limit, $offset, [], [$orderType], $cursorTeam ?? null, $cursorDirection);
$sum = $dbForProject->count('teams', $queries, APP_LIMIT_COUNT);
$response->dynamic(new Document([
'teams' => $results,
@ -148,12 +148,12 @@ App::get('/v1/teams/:teamId')
->label('sdk.response.model', Response::MODEL_TEAM)
->param('teamId', '', new UID(), 'Team ID.')
->inject('response')
->inject('dbForInternal')
->action(function ($teamId, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($teamId, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
@ -177,18 +177,18 @@ App::put('/v1/teams/:teamId')
->param('teamId', '', new UID(), 'Team ID.')
->param('name', null, new Text(128), 'New team name. Max length: 128 chars.')
->inject('response')
->inject('dbForInternal')
->action(function ($teamId, $name, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($teamId, $name, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$team = $dbForInternal->updateDocument('teams', $team->getId(),$team
$team = $dbForProject->updateDocument('teams', $team->getId(),$team
->setAttribute('name', $name)
->setAttribute('search', implode(' ', [$teamId, $name]))
);
@ -209,33 +209,33 @@ App::delete('/v1/teams/:teamId')
->label('sdk.response.model', Response::MODEL_NONE)
->param('teamId', '', new UID(), 'Team ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('events')
->inject('deletes')
->action(function ($teamId, $response, $dbForInternal, $events, $deletes) {
->action(function ($teamId, $response, $dbForProject, $events, $deletes) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $deletes */
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$memberships = $dbForInternal->find('memberships', [
$memberships = $dbForProject->find('memberships', [
new Query('teamId', Query::TYPE_EQUAL, [$teamId]),
], 2000, 0); // TODO fix members limit
// TODO delete all members individually from the user object
foreach ($memberships as $membership) {
if (!$dbForInternal->deleteDocument('memberships', $membership->getId())) {
if (!$dbForProject->deleteDocument('memberships', $membership->getId())) {
throw new Exception('Failed to remove membership for team from DB', 500);
}
}
if (!$dbForInternal->deleteDocument('teams', $teamId)) {
if (!$dbForProject->deleteDocument('teams', $teamId)) {
throw new Exception('Failed to remove team from DB', 500);
}
@ -273,15 +273,15 @@ App::post('/v1/teams/:teamId/memberships')
->inject('response')
->inject('project')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('audits')
->inject('mails')
->action(function ($teamId, $email, $roles, $url, $name, $response, $project, $user, $dbForInternal, $locale, $audits, $mails) {
->action(function ($teamId, $email, $roles, $url, $name, $response, $project, $user, $dbForProject, $locale, $audits, $mails) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $mails */
@ -294,20 +294,20 @@ App::post('/v1/teams/:teamId/memberships')
$email = \strtolower($email);
$name = (empty($name)) ? $email : $name;
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$invitee = $dbForInternal->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
$invitee = $dbForProject->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if (empty($invitee)) { // Create new user if no user with same email found
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0 && $project->getId() !== 'console') { // check users limit, console invites are allways allowed.
$sum = $dbForInternal->count('users', [], APP_LIMIT_USERS);
$sum = $dbForProject->count('users', [], APP_LIMIT_USERS);
if($sum >= $limit) {
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
@ -315,8 +315,8 @@ App::post('/v1/teams/:teamId/memberships')
}
try {
$userId = $dbForInternal->getId();
$invitee = Authorization::skip(fn() => $dbForInternal->createDocument('users', new Document([
$userId = $dbForProject->getId();
$invitee = Authorization::skip(fn() => $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['user:'.$userId, 'role:all'],
'$write' => ['user:'.$userId],
@ -333,7 +333,7 @@ App::post('/v1/teams/:teamId/memberships')
'registration' => \time(),
'reset' => false,
'name' => $name,
'prefs' => [],
'prefs' => new \stdClass(),
'sessions' => [],
'tokens' => [],
'memberships' => [],
@ -353,7 +353,7 @@ App::post('/v1/teams/:teamId/memberships')
$secret = Auth::tokenGenerator();
$membership = new Document([
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'$read' => ['role:all'],
'$write' => ['user:'.$invitee->getId(), 'team:'.$team->getId().'/owner'],
'userId' => $invitee->getId(),
@ -367,20 +367,20 @@ App::post('/v1/teams/:teamId/memberships')
if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership
try {
$membership = Authorization::skip(fn() => $dbForInternal->createDocument('memberships', $membership));
$membership = Authorization::skip(fn() => $dbForProject->createDocument('memberships', $membership));
} catch (Duplicate $th) {
throw new Exception('User has already been invited or is already a member of this team', 409);
}
$team->setAttribute('sum', $team->getAttribute('sum', 0) + 1);
$team = Authorization::skip(fn() => $dbForInternal->updateDocument('teams', $team->getId(), $team));
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team));
// Attach user to team
$invitee->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND);
$invitee = Authorization::skip(fn() => $dbForInternal->updateDocument('users', $invitee->getId(), $invitee));
$invitee = Authorization::skip(fn() => $dbForProject->updateDocument('users', $invitee->getId(), $invitee));
} else {
try {
$membership = $dbForInternal->createDocument('memberships', $membership);
$membership = $dbForProject->createDocument('memberships', $membership);
} catch (Duplicate $th) {
throw new Exception('User has already been invited or is already a member of this team', 409);
}
@ -438,32 +438,32 @@ App::get('/v1/teams/:teamId/memberships')
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($teamId, $search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($teamId, $search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
if (!empty($cursor)) {
$cursorMembership = $dbForInternal->getDocument('memberships', $cursor);
$cursorMembership = $dbForProject->getDocument('memberships', $cursor);
if ($cursorMembership->isEmpty()) {
throw new Exception("Membership '{$cursor}' for the 'cursor' value not found.", 400);
}
}
$memberships = $dbForInternal->find('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], $limit, $offset, [], [$orderType], $cursorMembership ?? null, $cursorDirection);
$sum = $dbForInternal->count('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], APP_LIMIT_COUNT);
$memberships = $dbForProject->find('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], $limit, $offset, [], [$orderType], $cursorMembership ?? null, $cursorDirection);
$sum = $dbForProject->count('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], APP_LIMIT_COUNT);
$memberships = array_filter($memberships, fn(Document $membership) => !empty($membership->getAttribute('userId')));
$memberships = array_map(function($membership) use ($dbForInternal) {
$user = $dbForInternal->getDocument('users', $membership->getAttribute('userId'));
$memberships = array_map(function($membership) use ($dbForProject) {
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
$membership
->setAttribute('name', $user->getAttribute('name'))
@ -493,24 +493,24 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
->param('teamId', '', new UID(), 'Team ID.')
->param('membershipId', '', new UID(), 'Membership ID.')
->inject('response')
->inject('dbForInternal')
->action(function ($teamId, $membershipId, $response, $dbForInternal) {
->inject('dbForProject')
->action(function ($teamId, $membershipId, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$membership = $dbForInternal->getDocument('memberships', $membershipId);
$membership = $dbForProject->getDocument('memberships', $membershipId);
if($membership->isEmpty() || empty($membership->getAttribute('userId'))) {
throw new Exception('Membership not found', 404);
}
$user = $dbForInternal->getDocument('users', $membership->getAttribute('userId'));
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
$membership
->setAttribute('name', $user->getAttribute('name'))
@ -538,26 +538,26 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->inject('request')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->action(function ($teamId, $membershipId, $roles, $request, $response, $user, $dbForInternal, $audits) {
->action(function ($teamId, $membershipId, $roles, $request, $response, $user, $dbForProject, $audits) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$membership = $dbForInternal->getDocument('memberships', $membershipId);
$membership = $dbForProject->getDocument('memberships', $membershipId);
if ($membership->isEmpty()) {
throw new Exception('Membership not found', 404);
}
$profile = $dbForInternal->getDocument('users', $membership->getAttribute('userId'));
$profile = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
if ($profile->isEmpty()) {
throw new Exception('User not found', 404);
}
@ -572,7 +572,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
// Update the roles
$membership->setAttribute('roles', $roles);
$membership = $dbForInternal->updateDocument('memberships', $membership->getId(), $membership);
$membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership);
// TODO sync updated membership in the user $profile object using TYPE_REPLACE
@ -604,20 +604,20 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->inject('request')
->inject('response')
->inject('user')
->inject('dbForInternal')
->inject('dbForProject')
->inject('geodb')
->inject('audits')
->action(function ($teamId, $membershipId, $userId, $secret, $request, $response, $user, $dbForInternal, $geodb, $audits) {
->action(function ($teamId, $membershipId, $userId, $secret, $request, $response, $user, $dbForProject, $geodb, $audits) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Event\Event $audits */
$protocol = $request->getProtocol();
$membership = $dbForInternal->getDocument('memberships', $membershipId);
$membership = $dbForProject->getDocument('memberships', $membershipId);
if ($membership->isEmpty()) {
throw new Exception('Membership not found', 404);
@ -627,7 +627,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
throw new Exception('Team IDs don\'t match', 404);
}
$team = Authorization::skip(fn() => $dbForInternal->getDocument('teams', $teamId));
$team = Authorization::skip(fn() => $dbForProject->getDocument('teams', $teamId));
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
@ -642,7 +642,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
}
if ($user->isEmpty()) {
$user = $dbForInternal->getDocument('users', $userId); // Get user
$user = $dbForProject->getDocument('users', $userId); // Get user
}
if ($membership->getAttribute('userId') !== $user->getId()) {
@ -668,7 +668,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
$secret = Auth::tokenGenerator();
$session = new Document(array_merge([
'$id' => $dbForInternal->getId(),
'$id' => $dbForProject->getId(),
'userId' => $user->getId(),
'provider' => Auth::SESSION_PROVIDER_EMAIL,
'providerUid' => $user->getAttribute('email'),
@ -679,7 +679,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
], $detector->getOS(), $detector->getClient(), $detector->getDevice()));
$session = $dbForInternal->createDocument('sessions', $session
$session = $dbForProject->createDocument('sessions', $session
->setAttribute('$read', ['user:'.$user->getId()])
->setAttribute('$write', ['user:'.$user->getId()])
);
@ -688,10 +688,10 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
Authorization::setRole('user:'.$userId);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$membership = $dbForInternal->updateDocument('memberships', $membership->getId(), $membership);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership);
$team = Authorization::skip(fn() => $dbForInternal->updateDocument('teams', $team->getId(), $team->setAttribute('sum', $team->getAttribute('sum', 0) + 1)));
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team->setAttribute('sum', $team->getAttribute('sum', 0) + 1)));
$audits
->setParam('userId', $user->getId())
@ -730,16 +730,16 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
->param('teamId', '', new UID(), 'Team ID.')
->param('membershipId', '', new UID(), 'Membership ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->inject('events')
->action(function ($teamId, $membershipId, $response, $dbForInternal, $audits, $events) {
->action(function ($teamId, $membershipId, $response, $dbForProject, $audits, $events) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
$membership = $dbForInternal->getDocument('memberships', $membershipId);
$membership = $dbForProject->getDocument('memberships', $membershipId);
if ($membership->isEmpty()) {
throw new Exception('Invite not found', 404);
@ -749,19 +749,19 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception('Team IDs don\'t match', 404);
}
$user = $dbForInternal->getDocument('users', $membership->getAttribute('userId'));
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
if ($user->isEmpty()) {
throw new Exception('User not found', 404);
}
$team = $dbForInternal->getDocument('teams', $teamId);
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
if (!$dbForInternal->deleteDocument('memberships', $membership->getId())) {
if (!$dbForProject->deleteDocument('memberships', $membership->getId())) {
throw new Exception('Failed to remove membership from DB', 500);
}
@ -778,11 +778,11 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
$user->setAttribute('memberships', $memberships);
Authorization::skip(fn() => $dbForInternal->updateDocument('users', $user->getId(), $user));
Authorization::skip(fn() => $dbForProject->updateDocument('users', $user->getId(), $user));
if ($membership->getAttribute('confirm')) { // Count only confirmed members
$team->setAttribute('sum', \max($team->getAttribute('sum', 0) - 1, 0));
$team = $dbForInternal->updateDocument('teams', $team->getId(), $team);
$team = $dbForProject->updateDocument('teams', $team->getId(), $team);
}
$audits

View file

@ -39,18 +39,18 @@ App::post('/v1/users')
->param('password', '', new Password(), 'User password. Must be at least 8 chars.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($userId, $email, $password, $name, $response, $dbForInternal, $usage) {
->action(function ($userId, $email, $password, $name, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$email = \strtolower($email);
try {
$userId = $userId == 'unique()' ? $dbForInternal->getId() : $userId;
$user = $dbForInternal->createDocument('users', new Document([
$userId = $userId == 'unique()' ? $dbForProject->getId() : $userId;
$user = $dbForProject->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:'.$userId],
@ -62,7 +62,7 @@ App::post('/v1/users')
'registration' => \time(),
'reset' => false,
'name' => $name,
'prefs' => [],
'prefs' => new \stdClass(),
'sessions' => [],
'tokens' => [],
'memberships' => [],
@ -99,15 +99,15 @@ App::get('/v1/users')
->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true)
->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForInternal, $usage) {
->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
if (!empty($cursor)) {
$cursorUser = $dbForInternal->getDocument('users', $cursor);
$cursorUser = $dbForProject->getDocument('users', $cursor);
if ($cursorUser->isEmpty()) {
throw new Exception("User '{$cursor}' for the 'cursor' value not found.", 400);
@ -127,8 +127,8 @@ App::get('/v1/users')
;
$response->dynamic(new Document([
'users' => $dbForInternal->find('users', $queries, $limit, $offset, [], [$orderType], $cursorUser ?? null, $cursorDirection),
'sum' => $dbForInternal->count('users', $queries, APP_LIMIT_COUNT),
'users' => $dbForProject->find('users', $queries, $limit, $offset, [], [$orderType], $cursorUser ?? null, $cursorDirection),
'sum' => $dbForProject->count('users', $queries, APP_LIMIT_COUNT),
]), Response::MODEL_USER_LIST);
});
@ -145,14 +145,14 @@ App::get('/v1/users/:userId')
->label('sdk.response.model', Response::MODEL_USER)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($userId, $response, $dbForInternal, $usage) {
->action(function ($userId, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -177,14 +177,14 @@ App::get('/v1/users/:userId/prefs')
->label('sdk.response.model', Response::MODEL_PREFERENCES)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($userId, $response, $dbForInternal, $usage) {
->action(function ($userId, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -211,16 +211,16 @@ App::get('/v1/users/:userId/sessions')
->label('sdk.response.model', Response::MODEL_SESSION_LIST)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('usage')
->action(function ($userId, $response, $dbForInternal, $locale, $usage) {
->action(function ($userId, $response, $dbForProject, $locale, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -245,7 +245,7 @@ App::get('/v1/users/:userId/sessions')
'sessions' => $sessions,
'sum' => count($sessions),
]), Response::MODEL_SESSION_LIST);
}, ['response', 'dbForInternal', 'locale']);
});
App::get('/v1/users/:userId/logs')
->desc('Get User Logs')
@ -262,25 +262,25 @@ App::get('/v1/users/:userId/logs')
->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->inject('usage')
->action(function ($userId, $limit, $offset, $response, $dbForInternal, $locale, $geodb, $usage) {
->action(function ($userId, $limit, $offset, $response, $dbForProject, $locale, $geodb, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Locale\Locale $locale */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
}
$audit = new Audit($dbForInternal);
$audit = new Audit($dbForProject);
$auditEvents = [
'account.create',
'account.delete',
@ -367,20 +367,20 @@ App::patch('/v1/users/:userId/status')
->param('userId', '', new UID(), 'User ID.')
->param('status', null, new Boolean(true), 'User Status. To activate the user pass `true` and to block the user pass `false`.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($userId, $status, $response, $dbForInternal, $usage) {
->action(function ($userId, $status, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('status', (bool) $status));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('status', (bool) $status));
$usage
->setParam('users.update', 1)
@ -403,20 +403,20 @@ App::patch('/v1/users/:userId/verification')
->param('userId', '', new UID(), 'User ID.')
->param('emailVerification', false, new Boolean(), 'User email verification status.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($userId, $emailVerification, $response, $dbForInternal, $usage) {
->action(function ($userId, $emailVerification, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', $emailVerification));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', $emailVerification));
$usage
->setParam('users.update', 1)
@ -439,20 +439,20 @@ App::patch('/v1/users/:userId/name')
->param('userId', '', new UID(), 'User ID.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->action(function ($userId, $name, $response, $dbForInternal, $audits) {
->action(function ($userId, $name, $response, $dbForProject, $audits) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('name', $name));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('name', $name));
$audits
->setParam('userId', $user->getId())
@ -478,14 +478,14 @@ App::patch('/v1/users/:userId/password')
->param('userId', '', new UID(), 'User ID.')
->param('password', '', new Password(), 'New user password. Must be at least 8 chars.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->action(function ($userId, $password, $response, $dbForInternal, $audits) {
->action(function ($userId, $password, $response, $dbForProject, $audits) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -495,7 +495,7 @@ App::patch('/v1/users/:userId/password')
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time());
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$audits
->setParam('userId', $user->getId())
@ -521,14 +521,14 @@ App::patch('/v1/users/:userId/email')
->param('userId', '', new UID(), 'User ID.')
->param('email', '', new Email(), 'User email.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('audits')
->action(function ($userId, $email, $response, $dbForInternal, $audits) {
->action(function ($userId, $email, $response, $dbForProject, $audits) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $audits */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -542,7 +542,7 @@ App::patch('/v1/users/:userId/email')
$email = \strtolower($email);
try {
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('email', $email));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('email', $email));
} catch(Duplicate $th) {
throw new Exception('Email already exists', 409);
}
@ -571,20 +571,20 @@ App::patch('/v1/users/:userId/prefs')
->param('userId', '', new UID(), 'User ID.')
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('usage')
->action(function ($userId, $prefs, $response, $dbForInternal, $usage) {
->action(function ($userId, $prefs, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
$usage
->setParam('users.update', 1)
@ -606,16 +606,16 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
->param('userId', '', new UID(), 'User ID.')
->param('sessionId', null, new UID(), 'Session ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('events')
->inject('usage')
->action(function ($userId, $sessionId, $response, $dbForInternal, $events, $usage) {
->action(function ($userId, $sessionId, $response, $dbForProject, $events, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -628,7 +628,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
if ($sessionId == $session->getId()) {
unset($sessions[$key]);
$dbForInternal->deleteDocument('sessions', $session->getId());
$dbForProject->deleteDocument('sessions', $session->getId());
$user->setAttribute('sessions', $sessions);
@ -636,7 +636,7 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
->setParam('eventData', $response->output($user, Response::MODEL_USER))
;
$dbForInternal->updateDocument('users', $user->getId(), $user);
$dbForProject->updateDocument('users', $user->getId(), $user);
}
}
@ -661,16 +661,16 @@ App::delete('/v1/users/:userId/sessions')
->label('sdk.response.model', Response::MODEL_NONE)
->param('userId', '', new UID(), 'User ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('events')
->inject('usage')
->action(function ($userId, $response, $dbForInternal, $events, $usage) {
->action(function ($userId, $response, $dbForProject, $events, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -679,10 +679,10 @@ App::delete('/v1/users/:userId/sessions')
$sessions = $user->getAttribute('sessions', []);
foreach ($sessions as $key => $session) { /** @var Document $session */
$dbForInternal->deleteDocument('sessions', $session->getId());
$dbForProject->deleteDocument('sessions', $session->getId());
}
$dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('sessions', []));
$dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('sessions', []));
$events
->setParam('eventData', $response->output($user, Response::MODEL_USER))
@ -708,18 +708,18 @@ App::delete('/v1/users/:userId')
->label('sdk.response.model', Response::MODEL_NONE)
->param('userId', '', function () {return new UID();}, 'User ID.')
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('events')
->inject('deletes')
->inject('usage')
->action(function ($userId, $response, $dbForInternal, $events, $deletes, $usage) {
->action(function ($userId, $response, $dbForProject, $events, $deletes, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Stats\Stats $usage */
$user = $dbForInternal->getDocument('users', $userId);
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty() || $user->getAttribute('deleted')) {
throw new Exception('User not found', 404);
@ -735,7 +735,7 @@ App::delete('/v1/users/:userId')
->setAttribute("deleted", true)
;
$dbForInternal->updateDocument('users', $userId, $user);
$dbForProject->updateDocument('users', $userId, $user);
$deletes
->setParam('type', DELETE_TYPE_DOCUMENT)
@ -764,13 +764,13 @@ App::get('/v1/users/usage')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USAGE_USERS)
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
->param('provider', '', new WhiteList(\array_merge(['email', 'anonymous'], \array_map(function($value) { return "oauth-".$value; }, \array_keys(Config::getParam('providers', [])))), true), 'Provider Name.', true)
->param('provider', '', new WhiteList(\array_merge(['email', 'anonymous'], \array_map(fn($value) => "oauth-".$value, \array_keys(Config::getParam('providers', [])))), true), 'Provider Name.', true)
->inject('response')
->inject('dbForInternal')
->inject('dbForProject')
->inject('register')
->action(function ($range, $provider, $response, $dbForInternal) {
->action(function ($range, $provider, $response, $dbForProject) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
$usage = [];
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
@ -806,12 +806,12 @@ App::get('/v1/users/usage')
$stats = [];
Authorization::skip(function() use ($dbForInternal, $periods, $range, $metrics, &$stats) {
Authorization::skip(function() use ($dbForProject, $periods, $range, $metrics, &$stats) {
foreach ($metrics as $metric) {
$limit = $periods[$range]['limit'];
$period = $periods[$range]['period'];
$requestDocs = $dbForInternal->find('stats', [
$requestDocs = $dbForProject->find('stats', [
new Query('period', Query::TYPE_EQUAL, [$period]),
new Query('metric', Query::TYPE_EQUAL, [$metric]),
], $limit, 0, ['time'], [Database::ORDER_DESC]);

View file

@ -47,20 +47,25 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons
} else {
Authorization::disable();
$certificate = $dbForConsole->findOne('certificates', [
$domainDocument = $dbForConsole->findOne('domains', [
new Query('domain', QUERY::TYPE_EQUAL, [$domain->get()])
]);
if (empty($certificate)) {
$certificate = new Document([
if (!$domainDocument) {
$domainDocument = new Document([
'domain' => $domain->get(),
'tld' => $domain->getSuffix(),
'registerable' => $domain->getRegisterable(),
'verification' => false,
'certificateId' => null,
]);
$certificate = $dbForConsole->createDocument('certificates', $certificate);
$domainDocument = $dbForConsole->createDocument('domains', $domainDocument);
Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in a few seconds...');
Resque::enqueue('v1-certificates', 'CertificatesV1', [
'document' => $certificate,
'document' => $domainDocument,
'domain' => $domain->get(),
'validateTarget' => false,
'validateCNAME' => false,
@ -74,7 +79,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons
Config::setParam('domains', $domains);
}
$localeParam = (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));
$localeParam = (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));
if (\in_array($localeParam, Config::getParam('locale-codes'))) {
$locale->setDefault($localeParam);

View file

@ -11,7 +11,7 @@ use Utopia\Database\Document;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Storage;
App::init(function ($utopia, $request, $response, $project, $user, $events, $audits, $usage, $deletes, $database, $dbForInternal, $mode) {
App::init(function ($utopia, $request, $response, $project, $user, $events, $audits, $usage, $deletes, $database, $dbForProject, $mode) {
/** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
@ -24,7 +24,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $database */
/** @var Appwrite\Event\Event $functions */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
Storage::setDevice('files', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
Storage::setDevice('functions', new Local(APP_STORAGE_FUNCTIONS.'/app-'.$project->getId()));
@ -38,7 +38,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud
/*
* Abuse Check
*/
$timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForInternal);
$timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
$timeLimit
->setParam('{userId}', $user->getId())
->setParam('{userAgent}', $request->getUserAgent(''))
@ -120,7 +120,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud
$database
->setParam('projectId', $project->getId())
;
}, ['utopia', 'request', 'response', 'project', 'user', 'events', 'audits', 'usage', 'deletes', 'database', 'dbForInternal', 'mode'], 'api');
}, ['utopia', 'request', 'response', 'project', 'user', 'events', 'audits', 'usage', 'deletes', 'database', 'dbForProject', 'mode'], 'api');
App::init(function ($utopia, $request, $project) {
/** @var Utopia\App $utopia */

View file

@ -78,54 +78,70 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
$dbForConsole = $app->getResource('dbForConsole'); /** @var Utopia\Database\Database $dbForConsole */
if(!$dbForConsole->exists()) {
Console::success('[Setup] - Server database init started...');
$collections = Config::getParam('collections', []); /** @var array $collections */
Console::success('[Setup] - Server database init started...');
$collections = Config::getParam('collections', []); /** @var array $collections */
if(!$dbForConsole->exists(App::getEnv('_APP_DB_SCHEMA', 'appwrite'))) {
$redis->flushAll();
$dbForConsole->create();
Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
}
try {
Console::success('[Setup] - Creating metadata table: appwrite...');
$dbForConsole->createMetadata();
} catch (\Throwable $th) {
Console::success('[Setup] - Skip: metadata table already exists');
}
if($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) {
$audit = new Audit($dbForConsole);
$audit->setup();
}
if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $dbForConsole);
$adapter->setup();
}
foreach ($collections as $key => $collection) {
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');
$attributes = [];
$indexes = [];
foreach ($collection['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => $attribute['$id'],
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
]);
}
foreach ($collection['indexes'] as $index) {
$indexes[] = new Document([
'$id' => $index['$id'],
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
$dbForConsole->createCollection($key, $attributes, $indexes);
foreach ($collections as $key => $collection) {
if(!$dbForConsole->getCollection($key)->isEmpty()) {
continue;
}
Console::success('[Setup] - Server database init completed...');
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');
$attributes = [];
$indexes = [];
foreach ($collection['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => $attribute['$id'],
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
]);
}
foreach ($collection['indexes'] as $index) {
$indexes[] = new Document([
'$id' => $index['$id'],
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
$dbForConsole->createCollection($key, $attributes, $indexes);
}
Console::success('[Setup] - Server database init completed...');
});
Console::success('Server started successfully (max payload is '.number_format($payloadSize).' bytes)');

View file

@ -392,7 +392,7 @@ $register->set('dbPool', function () { // Register DB connection
->withOptions([
PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed
])
, 16);
, 64);
return $pool;
});
@ -412,7 +412,7 @@ $register->set('redisPool', function () {
->withPort($redisPort)
->withAuth($redisAuth)
->withDbIndex(0)
, 16);
, 64);
return $pool;
});
@ -602,7 +602,7 @@ App::setResource('usage', function($register) {
return new Stats($register->get('statsd'));
}, ['register']);
App::setResource('clients', function($request, $console, $project) {
App::setResource('clients', function ($request, $console, $project) {
$console->setAttribute('platforms', [ // Always allow current host
'$collection' => 'platforms',
'name' => 'Current Host',
@ -614,34 +614,35 @@ App::setResource('clients', function($request, $console, $project) {
* Get All verified client URLs for both console and current projects
* + Filter for duplicated entries
*/
$clientsConsole = \array_map(function ($node) {
return $node['hostname'];
}, \array_filter($console->getAttribute('platforms', []), function ($node) {
if (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname'])) {
return true;
}
$clientsConsole = \array_map(
fn ($node) => $node['hostname'],
\array_filter(
$console->getAttribute('platforms', []),
fn ($node) => (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname']))
)
);
return false;
}));
$clients = \array_unique(\array_merge($clientsConsole, \array_map(function ($node) {
return $node['hostname'];
}, \array_filter($project->getAttribute('platforms', []), function ($node) {
if (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname'])) {
return true;
}
return false;
}))));
$clients = \array_unique(
\array_merge(
$clientsConsole,
\array_map(
fn ($node) => $node['hostname'],
\array_filter(
$project->getAttribute('platforms', []),
fn ($node) => (isset($node['type']) && $node['type'] === 'web' && isset($node['hostname']) && !empty($node['hostname']))
)
)
)
);
return $clients;
}, ['request', 'console', 'project']);
App::setResource('user', function($mode, $project, $console, $request, $response, $dbForInternal, $dbForConsole) {
App::setResource('user', function($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Database $dbForConsole */
/** @var string $mode */
@ -675,7 +676,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response
$user = new Document(['$id' => '', '$collection' => 'users']);
}
else {
$user = $dbForInternal->getDocument('users', Auth::$unique);
$user = $dbForProject->getDocument('users', Auth::$unique);
}
}
else {
@ -710,7 +711,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response
$jwtSessionId = $payload['sessionId'] ?? '';
if($jwtUserId && $jwtSessionId) {
$user = $dbForInternal->getDocument('users', $jwtUserId);
$user = $dbForProject->getDocument('users', $jwtUserId);
}
if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token
@ -719,7 +720,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response
}
return $user;
}, ['mode', 'project', 'console', 'request', 'response', 'dbForInternal', 'dbForConsole']);
}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForConsole']);
App::setResource('project', function($dbForConsole, $request, $console) {
/** @var Utopia\Swoole\Request $request */
@ -781,20 +782,12 @@ App::setResource('console', function() {
]);
}, []);
App::setResource('dbForInternal', function($db, $cache, $project) {
App::setResource('dbForProject', function($db, $cache, $project) {
$cache = new Cache(new RedisCache($cache));
$database = new Database(new MariaDB($db), $cache);
$database->setNamespace('project_'.$project->getId().'_internal');
return $database;
}, ['db', 'cache', 'project']);
App::setResource('dbForExternal', function($db, $cache, $project) {
$cache = new Cache(new RedisCache($cache));
$database = new Database(new MariaDB($db), $cache);
$database->setNamespace('project_'.$project->getId().'_external');
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace('_project_'.$project->getId());
return $database;
}, ['db', 'cache', 'project']);
@ -803,7 +796,8 @@ App::setResource('dbForConsole', function($db, $cache) {
$cache = new Cache(new RedisCache($cache));
$database = new Database(new MariaDB($db), $cache);
$database->setNamespace('project_console_internal');
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace('_project_console');
return $database;
}, ['db', 'cache']);

View file

@ -58,6 +58,7 @@ function getDatabase(Registry &$register, string $namespace)
$cache = new Cache(new RedisCache($redis));
$database = new Database(new MariaDB($db), $cache);
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace($namespace);
return [
@ -77,7 +78,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
*/
go(function () use ($register, $containerId, &$statsDocument) {
try {
[$database, $returnDatabase] = getDatabase($register, 'project_console_internal');
[$database, $returnDatabase] = getDatabase($register, '_project_console');
$document = new Document([
'$id' => $database->getId(),
'$collection' => 'realtime',
@ -133,7 +134,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
}
try {
[$database, $returnDatabase] = getDatabase($register, 'project_console_internal');
[$database, $returnDatabase] = getDatabase($register, '_project_console');
$statsDocument
->setAttribute('timestamp', time())
@ -163,7 +164,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
*/
if ($realtime->hasSubscriber('console', 'role:member', 'project')) {
[$database, $returnDatabase] = getDatabase($register, 'project_console_internal');
[$database, $returnDatabase] = getDatabase($register, '_project_console');
$payload = [];
@ -267,7 +268,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
return;
}
[$database, $returnDatabase] = getDatabase($register, 'project_' . $projectId . '_internal');
[$database, $returnDatabase] = getDatabase($register, '_project_' . $projectId);
$user = $database->getDocument('users', $userId);
@ -340,7 +341,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
$cache = new Cache(new RedisCache($redis));
$database = new Database(new MariaDB($db), $cache);
$database->setNamespace('project_' . $project->getId() . '_internal');
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace('_project_' . $project->getId());
/*
* Project Check
@ -444,7 +446,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
$cache = new Cache(new RedisCache($redis));
$database = new Database(new MariaDB($db), $cache);
$database->setNamespace('project_' . $realtime->connections[$connection]['projectId'] . '_internal');
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace('_project_' . $realtime->connections[$connection]['projectId']);
/*
* Abuse Check

View file

@ -223,7 +223,9 @@ $cli
$cacheAdapter = new Cache(new Redis($redis));
$dbForProject = new Database(new MariaDB($db), $cacheAdapter);
$dbForConsole = new Database(new MariaDB($db), $cacheAdapter);
$dbForConsole->setNamespace('project_console_internal');
$dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$dbForConsole->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$dbForConsole->setNamespace('_project_console');
$latestTime = [];
@ -276,9 +278,7 @@ $cli
$filters = $options['filters'] ?? []; // Some metrics might have additional filters, like function's status
if (!empty($filters)) {
$filters = ' AND ' . implode(' AND ', array_map(function ($filter, $value) {
return "\"{$filter}\"='{$value}'";
}, array_keys($filters), array_values($filters)));
$filters = ' AND ' . implode(' AND ', array_map(fn ($filter, $value) => "\"{$filter}\"='{$value}'", array_keys($filters), array_values($filters)));
} else {
$filters = '';
}
@ -291,7 +291,7 @@ $cli
$projectId = $point['projectId'];
if (!empty($projectId) && $projectId !== 'console') {
$dbForProject->setNamespace('project_' . $projectId . '_internal');
$dbForProject->setNamespace('_project_' . $projectId);
$metricUpdated = $metric;
if (!empty($groupBy)) {
@ -371,7 +371,7 @@ $cli
$projectId = $project->getId();
// Get total storage
$dbForProject->setNamespace('project_' . $projectId . '_internal');
$dbForProject->setNamespace('_project_' . $projectId);
$storageTotal = $dbForProject->sum('files', 'sizeOriginal') + $dbForProject->sum('tags', 'size');
$time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes
@ -435,9 +435,8 @@ $cli
foreach ($collections as $collection => $options) {
try {
$dbForProject->setNamespace("project_{$projectId}_{$options['namespace']}");
$dbForProject->setNamespace("_project_{$projectId}");
$count = $dbForProject->count($collection);
$dbForProject->setNamespace("project_{$projectId}_internal");
$metricPrefix = $options['metricPrefix'] ?? '';
$metric = empty($metricPrefix) ? "{$collection}.count" : "{$metricPrefix}.{$collection}.count";
@ -491,7 +490,7 @@ $cli
$subCollectionCounts = []; //total project level count of sub collections
do { // Loop over all the parent collection document for each sub collection
$dbForProject->setNamespace("project_{$projectId}_{$options['namespace']}");
$dbForProject->setNamespace("_project_{$projectId}");
$parents = $dbForProject->find($collection, [], 100, cursor: $latestParent); // Get all the parents for the sub collections for example for documents, this will get all the collections
if (empty($parents)) {
@ -502,12 +501,12 @@ $cli
foreach ($parents as $parent) {
foreach ($subCollections as $subCollection => $subOptions) { // Sub collection counts, like database.collections.collectionId.documents.count
$dbForProject->setNamespace("project_{$projectId}_{$subOptions['namespace']}");
$dbForProject->setNamespace("_project_{$projectId}");
$count = $dbForProject->count($parent->getId());
$subCollectionCounts[$subCollection] = ($subCollectionCounts[$subCollection] ?? 0) + $count; // Project level counts for sub collections like database.documents.count
$dbForProject->setNamespace("project_{$projectId}_internal");
$dbForProject->setNamespace("_project_{$projectId}");
$metric = empty($metricPrefix) ? "{$collection}.{$parent->getId()}.{$subCollection}.count" : "{$metricPrefix}.{$collection}.{$parent->getId()}.{$subCollection}.count";
$time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes
@ -557,7 +556,7 @@ $cli
* Inserting project level counts for sub collections like database.documents.count
*/
foreach ($subCollectionCounts as $subCollection => $count) {
$dbForProject->setNamespace("project_{$projectId}_internal");
$dbForProject->setNamespace("_project_{$projectId}");
$metric = empty($metricPrefix) ? "{$subCollection}.count" : "{$metricPrefix}.{$subCollection}.count";

View file

@ -380,7 +380,7 @@ services:
- _APP_REDIS_PASS
mariadb:
image: appwrite/mariadb:1.2.0 # fix issues when upgrading using: mysql_upgrade -u root -p
image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p
container_name: appwrite-mariadb
restart: unless-stopped
networks:

View file

@ -28,8 +28,8 @@ class AuditsV1 extends Worker
$ip = $this->args['ip'];
$data = $this->args['data'];
$dbForInternal = $this->getInternalDB($projectId);
$audit = new Audit($dbForInternal);
$dbForProject = $this->getProjectDB($projectId);
$audit = new Audit($dbForProject);
$audit->log($userId, $event, $resource, $userAgent, $ip, '', [
'userName' => $userName,

View file

@ -160,7 +160,7 @@ class CertificatesV1 extends Worker
'certificateId' => $certificate->getId(),
]));
$certificate = $dbForConsole->updateDocument('certificates', $certificate->getId(), $certificate);
$certificate = $dbForConsole->updateDocument('domains', $certificate->getId(), $certificate);
if(!$certificate) {
throw new Exception('Failed saving domain to DB');

View file

@ -69,8 +69,7 @@ class DatabaseV1 extends Worker
protected function createAttribute(Document $collection, Document $attribute, string $projectId): void
{
$dbForConsole = $this->getConsoleDB();
$dbForInternal = $this->getInternalDB($projectId);
$dbForExternal = $this->getExternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
$event = 'database.attributes.update';
$collectionId = $collection->getId();
@ -87,13 +86,13 @@ class DatabaseV1 extends Worker
$project = $dbForConsole->getDocument('projects', $projectId);
try {
if(!$dbForExternal->createAttribute($collectionId, $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) {
if(!$dbForProject->createAttribute('collection_' . $collectionId, $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) {
throw new Exception('Failed to create Attribute');
}
$dbForInternal->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available'));
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available'));
} catch (\Throwable $th) {
Console::error($th->getMessage());
$dbForInternal->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'failed'));
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'failed'));
} finally {
$target = Realtime::fromPayload($event, $attribute, $project);
@ -110,7 +109,7 @@ class DatabaseV1 extends Worker
);
}
$dbForInternal->deleteCachedDocument('collections', $collectionId);
$dbForProject->deleteCachedDocument('collections', $collectionId);
}
/**
@ -121,8 +120,7 @@ class DatabaseV1 extends Worker
protected function deleteAttribute(Document $collection, Document $attribute, string $projectId): void
{
$dbForConsole = $this->getConsoleDB();
$dbForInternal = $this->getInternalDB($projectId);
$dbForExternal = $this->getExternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
$event = 'database.attributes.delete';
$collectionId = $collection->getId();
@ -137,13 +135,13 @@ class DatabaseV1 extends Worker
// - failed: attribute was never created
// - stuck: attribute was available but cannot be removed
try {
if($status !== 'failed' && !$dbForExternal->deleteAttribute($collectionId, $key)) {
if($status !== 'failed' && !$dbForProject->deleteAttribute('collection_' . $collectionId, $key)) {
throw new Exception('Failed to delete Attribute');
}
$dbForInternal->deleteDocument('attributes', $attribute->getId());
$dbForProject->deleteDocument('attributes', $attribute->getId());
} catch (\Throwable $th) {
Console::error($th->getMessage());
$dbForInternal->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'stuck'));
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'stuck'));
} finally {
$target = Realtime::fromPayload($event, $attribute, $project);
@ -182,7 +180,7 @@ class DatabaseV1 extends Worker
$orders = \array_values(\array_diff($orders, [$orders[$found]]));
if (empty($attributes)) {
$dbForInternal->deleteDocument('indexes', $index->getId());
$dbForProject->deleteDocument('indexes', $index->getId());
} else {
$index
->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN)
@ -205,13 +203,13 @@ class DatabaseV1 extends Worker
if ($exists) { // Delete the duplicate if created, else update in db
$this->deleteIndex($collection, $index, $projectId);
} else {
$dbForInternal->updateDocument('indexes', $index->getId(), $index);
$dbForProject->updateDocument('indexes', $index->getId(), $index);
}
}
}
}
$dbForInternal->deleteCachedDocument('collections', $collectionId);
$dbForProject->deleteCachedDocument('collections', $collectionId);
}
/**
@ -222,8 +220,7 @@ class DatabaseV1 extends Worker
protected function createIndex(Document $collection, Document $index, string $projectId): void
{
$dbForConsole = $this->getConsoleDB();
$dbForInternal = $this->getInternalDB($projectId);
$dbForExternal = $this->getExternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
$event = 'database.indexes.update';
$collectionId = $collection->getId();
@ -235,13 +232,13 @@ class DatabaseV1 extends Worker
$project = $dbForConsole->getDocument('projects', $projectId);
try {
if(!$dbForExternal->createIndex($collectionId, $key, $type, $attributes, $lengths, $orders)) {
if(!$dbForProject->createIndex('collection_' . $collectionId, $key, $type, $attributes, $lengths, $orders)) {
throw new Exception('Failed to create Index');
}
$dbForInternal->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available'));
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available'));
} catch (\Throwable $th) {
Console::error($th->getMessage());
$dbForInternal->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'failed'));
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'failed'));
} finally {
$target = Realtime::fromPayload($event, $index, $project);
@ -258,7 +255,7 @@ class DatabaseV1 extends Worker
);
}
$dbForInternal->deleteCachedDocument('collections', $collectionId);
$dbForProject->deleteCachedDocument('collections', $collectionId);
}
/**
@ -269,8 +266,7 @@ class DatabaseV1 extends Worker
protected function deleteIndex(Document $collection, Document $index, string $projectId): void
{
$dbForConsole = $this->getConsoleDB();
$dbForInternal = $this->getInternalDB($projectId);
$dbForExternal = $this->getExternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
$collectionId = $collection->getId();
$key = $index->getAttribute('key');
@ -279,13 +275,13 @@ class DatabaseV1 extends Worker
$project = $dbForConsole->getDocument('projects', $projectId);
try {
if($status !== 'failed' && !$dbForExternal->deleteIndex($collectionId, $key)) {
if($status !== 'failed' && !$dbForProject->deleteIndex('collection_' . $collectionId, $key)) {
throw new Exception('Failed to delete index');
}
$dbForInternal->deleteDocument('indexes', $index->getId());
$dbForProject->deleteDocument('indexes', $index->getId());
} catch (\Throwable $th) {
Console::error($th->getMessage());
$dbForInternal->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'stuck'));
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'stuck'));
} finally {
$target = Realtime::fromPayload($event, $index, $project);
@ -302,6 +298,6 @@ class DatabaseV1 extends Worker
);
}
$dbForInternal->deleteCachedDocument('collections', $collectionId);
$dbForProject->deleteCachedDocument('collections', $collectionId);
}
}

View file

@ -100,18 +100,17 @@ class DeletesV1 extends Worker
{
$collectionId = $document->getId();
$dbForInternal = $this->getInternalDB($projectId);
$dbForExternal = $this->getExternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
$dbForExternal->deleteCollection($collectionId);
$dbForProject->deleteCollection($collectionId);
$this->deleteByGroup('attributes', [
new Query('collectionId', Query::TYPE_EQUAL, [$collectionId])
], $dbForInternal);
], $dbForProject);
$this->deleteByGroup('indexes', [
new Query('collectionId', Query::TYPE_EQUAL, [$collectionId])
], $dbForInternal);
], $dbForProject);
}
/**
@ -121,17 +120,17 @@ class DeletesV1 extends Worker
protected function deleteUsageStats(int $timestamp1d, int $timestamp30m)
{
$this->deleteForProjectIds(function (string $projectId) use ($timestamp1d, $timestamp30m) {
$dbForInternal = $this->getInternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
// Delete Usage stats
$this->deleteByGroup('stats', [
new Query('time', Query::TYPE_LESSER, [$timestamp1d]),
new Query('period', Query::TYPE_EQUAL, ['1d']),
], $dbForInternal);
], $dbForProject);
$this->deleteByGroup('stats', [
new Query('time', Query::TYPE_LESSER, [$timestamp30m]),
new Query('period', Query::TYPE_EQUAL, ['30m']),
], $dbForInternal);
], $dbForProject);
});
}
@ -146,7 +145,7 @@ class DeletesV1 extends Worker
// Delete Memberships
$this->deleteByGroup('memberships', [
new Query('teamId', Query::TYPE_EQUAL, [$teamId])
], $this->getInternalDB($projectId));
], $this->getProjectDB($projectId));
}
/**
@ -157,8 +156,7 @@ class DeletesV1 extends Worker
$projectId = $document->getId();
// Delete all DBs
$this->getExternalDB($projectId)->delete();
$this->getInternalDB($projectId)->delete();
$this->getProjectDB($projectId)->delete($projectId);
// Delete all storage directories
$uploads = new Local(APP_STORAGE_UPLOADS . '/app-' . $document->getId());
@ -180,13 +178,13 @@ class DeletesV1 extends Worker
// Delete Memberships and decrement team membership counts
$this->deleteByGroup('memberships', [
new Query('userId', Query::TYPE_EQUAL, [$userId])
], $this->getInternalDB($projectId), function (Document $document) use ($projectId) {
], $this->getProjectDB($projectId), function (Document $document) use ($projectId) {
if ($document->getAttribute('confirm')) { // Count only confirmed members
$teamId = $document->getAttribute('teamId');
$team = $this->getInternalDB($projectId)->getDocument('teams', $teamId);
$team = $this->getProjectDB($projectId)->getDocument('teams', $teamId);
if (!$team->isEmpty()) {
$team = $this->getInternalDB($projectId)->updateDocument('teams', $teamId, new Document(\array_merge($team->getArrayCopy(), [
$team = $this->getProjectDB($projectId)->updateDocument('teams', $teamId, new Document(\array_merge($team->getArrayCopy(), [
'sum' => \max($team->getAttribute('sum', 0) - 1, 0), // Ensure that sum >= 0
])));
}
@ -200,11 +198,11 @@ class DeletesV1 extends Worker
protected function deleteExecutionLogs(int $timestamp): void
{
$this->deleteForProjectIds(function (string $projectId) use ($timestamp) {
$dbForInternal = $this->getInternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
// Delete Executions
$this->deleteByGroup('executions', [
new Query('dateCreated', Query::TYPE_LESSER, [$timestamp])
], $dbForInternal);
], $dbForProject);
});
}
@ -214,11 +212,11 @@ class DeletesV1 extends Worker
protected function deleteRealtimeUsage(int $timestamp): void
{
$this->deleteForProjectIds(function (string $projectId) use ($timestamp) {
$dbForInternal = $this->getInternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
// Delete Dead Realtime Logs
$this->deleteByGroup('realtime', [
new Query('timestamp', Query::TYPE_LESSER, [$timestamp])
], $dbForInternal);
], $dbForProject);
});
}
@ -232,8 +230,8 @@ class DeletesV1 extends Worker
}
$this->deleteForProjectIds(function (string $projectId) use ($timestamp) {
$dbForInternal = $this->getInternalDB($projectId);
$timeLimit = new TimeLimit("", 0, 1, $dbForInternal);
$dbForProject = $this->getProjectDB($projectId);
$timeLimit = new TimeLimit("", 0, 1, $dbForProject);
$abuse = new Abuse($timeLimit);
$status = $abuse->cleanup($timestamp);
@ -252,8 +250,8 @@ class DeletesV1 extends Worker
throw new Exception('Failed to delete audit logs. No timestamp provided');
}
$this->deleteForProjectIds(function (string $projectId) use ($timestamp) {
$dbForInternal = $this->getInternalDB($projectId);
$audit = new Audit($dbForInternal);
$dbForProject = $this->getProjectDB($projectId);
$audit = new Audit($dbForProject);
$status = $audit->cleanup($timestamp);
if (!$status) {
throw new Exception('Failed to delete Audit logs for project' . $projectId);
@ -267,13 +265,13 @@ class DeletesV1 extends Worker
*/
protected function deleteFunction(Document $document, string $projectId): void
{
$dbForInternal = $this->getInternalDB($projectId);
$dbForProject = $this->getProjectDB($projectId);
$device = new Local(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
// Delete Tags
$this->deleteByGroup('tags', [
new Query('functionId', Query::TYPE_EQUAL, [$document->getId()])
], $dbForInternal, function (Document $document) use ($device) {
], $dbForProject, function (Document $document) use ($device) {
if ($device->delete($document->getAttribute('path', ''))) {
Console::success('Delete code tag: ' . $document->getAttribute('path', ''));
@ -285,7 +283,7 @@ class DeletesV1 extends Worker
// Delete Executions
$this->deleteByGroup('executions', [
new Query('functionId', Query::TYPE_EQUAL, [$document->getId()])
], $dbForInternal);
], $dbForProject);
}

View file

@ -118,7 +118,7 @@ class FunctionsV1 extends Worker
$userId = $this->args['userId'] ?? '';
$jwt = $this->args['jwt'] ?? '';
$database = $this->getInternalDB($projectId);
$database = $this->getProjectDB($projectId);
switch ($trigger) {
case 'event':

View file

@ -39,13 +39,13 @@
"appwrite/php-runtimes": "0.6.*",
"utopia-php/framework": "0.19.*",
"utopia-php/abuse": "0.6.*",
"utopia-php/abuse": "0.7.*",
"utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.7.*",
"utopia-php/audit": "0.8.*",
"utopia-php/cache": "0.4.*",
"utopia-php/cli": "0.11.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.12.*",
"utopia-php/database": "0.13.*",
"utopia-php/locale": "0.4.*",
"utopia-php/orchestration": "0.2.*",
"utopia-php/registry": "0.5.*",

44
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c755b0ae991777da3e44b0442690fa46",
"content-hash": "2b1ed15e618832ee86b69cff2dcdd6ac",
"packages": [
{
"name": "adhocore/jwt",
@ -1820,22 +1820,22 @@
},
{
"name": "utopia-php/abuse",
"version": "0.6.3",
"version": "0.7.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "d63e928c2c50b367495a499a85ba9806ee274c5e"
"reference": "52fb20e39e2e9619948bc0a73b52e10caa71350d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/d63e928c2c50b367495a499a85ba9806ee274c5e",
"reference": "d63e928c2c50b367495a499a85ba9806ee274c5e",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/52fb20e39e2e9619948bc0a73b52e10caa71350d",
"reference": "52fb20e39e2e9619948bc0a73b52e10caa71350d",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"php": ">=7.4",
"utopia-php/database": ">=0.6 <1.0"
"php": ">=8.0",
"utopia-php/database": ">=0.11 <1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.4",
@ -1867,9 +1867,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.6.3"
"source": "https://github.com/utopia-php/abuse/tree/0.7.0"
},
"time": "2021-08-16T18:38:31+00:00"
"time": "2021-12-27T13:06:45+00:00"
},
{
"name": "utopia-php/analytics",
@ -1928,21 +1928,21 @@
},
{
"name": "utopia-php/audit",
"version": "0.7.0",
"version": "0.8.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "485cdd2354db7eb8f7aa74bbe39c39b583e99c04"
"reference": "b46dc42614a69437c45eb229249b6a6d000122c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/485cdd2354db7eb8f7aa74bbe39c39b583e99c04",
"reference": "485cdd2354db7eb8f7aa74bbe39c39b583e99c04",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/b46dc42614a69437c45eb229249b6a6d000122c1",
"reference": "b46dc42614a69437c45eb229249b6a6d000122c1",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"php": ">=7.4",
"php": ">=8.0",
"utopia-php/database": ">=0.11 <1.0"
},
"require-dev": {
@ -1975,9 +1975,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.7.0"
"source": "https://github.com/utopia-php/audit/tree/0.8.0"
},
"time": "2021-11-17T17:23:42+00:00"
"time": "2021-12-27T13:05:56+00:00"
},
{
"name": "utopia-php/cache",
@ -2138,16 +2138,16 @@
},
{
"name": "utopia-php/database",
"version": "0.12.1",
"version": "0.13.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "af512b7a00cc7c6e30fa03efbc5fd7e77a93e2df"
"reference": "2e13987364f4966ec8a36784d4fb5df3a84e4e78"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/af512b7a00cc7c6e30fa03efbc5fd7e77a93e2df",
"reference": "af512b7a00cc7c6e30fa03efbc5fd7e77a93e2df",
"url": "https://api.github.com/repos/utopia-php/database/zipball/2e13987364f4966ec8a36784d4fb5df3a84e4e78",
"reference": "2e13987364f4966ec8a36784d4fb5df3a84e4e78",
"shasum": ""
},
"require": {
@ -2195,9 +2195,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.12.1"
"source": "https://github.com/utopia-php/database/tree/0.13.0"
},
"time": "2021-12-13T14:57:32+00:00"
"time": "2021-12-27T12:59:50+00:00"
},
{
"name": "utopia-php/domains",

View file

@ -288,6 +288,7 @@ services:
- mariadb
environment:
- _APP_ENV
- _APP_DOMAIN_TARGET
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@ -441,7 +442,7 @@ services:
- _APP_REDIS_PASS
mariadb:
image: appwrite/mariadb:1.2.0 # fix issues when upgrading using: mysql_upgrade -u root -p
image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p
container_name: appwrite-mariadb
networks:
- appwrite

View file

@ -11,6 +11,7 @@ use Redis;
use Swoole\Runtime;
use Throwable;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
@ -29,8 +30,7 @@ global $register;
class V11 extends Migration
{
protected Database $dbInternal;
protected Database $dbExternal;
protected Database $dbProject;
protected Database $dbConsole;
protected array $oldCollections;
@ -43,10 +43,12 @@ class V11 extends Migration
if (!is_null($cache)) {
$cacheAdapter = new Cache(new RedisCache($this->cache));
$this->dbInternal = new Database(new MariaDB($this->db), $cacheAdapter); // namespace is set on execution
$this->dbExternal = new Database(new MariaDB($this->db), $cacheAdapter); // namespace is set on execution
$this->dbProject = new Database(new MariaDB($this->db), $cacheAdapter); // namespace is set on execution
$this->dbConsole = new Database(new MariaDB($this->db), $cacheAdapter);
$this->dbConsole->setNamespace('project_console_internal');
$this->dbProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$this->dbConsole->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$this->dbConsole->setNamespace('_project_console');
}
$this->newCollections = Config::getParam('collections', []);
@ -60,8 +62,7 @@ class V11 extends Migration
$oldProject = $this->project;
$this->dbInternal->setNamespace('project_' . $oldProject->getId() . '_internal');
$this->dbExternal->setNamespace('project_' . $oldProject->getId() . '_external');
$this->dbProject->setNamespace('_project_' . $oldProject->getId());
Console::info('');
Console::info('------------------------------------');
@ -85,26 +86,18 @@ class V11 extends Migration
}
/**
* Create internal DB tables
* Create internal tables
*/
if (!$this->dbInternal->exists()) {
$this->dbInternal->create();
if (!$this->dbProject->exists('appwrite')) {
$this->dbProject->create('appwrite');
Console::log('Created internal tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
/**
* Create external DB tables
*/
if (!$this->dbExternal->exists()) {
$this->dbExternal->create();
Console::log('Created external tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
/**
* Create Audit tables
*/
if ($this->dbInternal->getCollection(Audit::COLLECTION)->isEmpty()) {
$audit = new Audit($this->dbInternal);
if ($this->dbProject->getCollection(Audit::COLLECTION)->isEmpty()) {
$audit = new Audit($this->dbProject);
$audit->setup();
Console::log('Created audit tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
@ -112,8 +105,8 @@ class V11 extends Migration
/**
* Create Abuse tables
*/
if ($this->dbInternal->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $this->dbInternal);
if ($this->dbProject->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $this->dbProject);
$adapter->setup();
Console::log('Created abuse tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
@ -122,7 +115,7 @@ class V11 extends Migration
* Create internal collections for Project
*/
foreach ($this->newCollections as $key => $collection) {
if (!$this->dbInternal->getCollection($key)->isEmpty()) continue; // Skip if project collection already exists
if (!$this->dbProject->getCollection($key)->isEmpty()) continue; // Skip if project collection already exists
$attributes = [];
$indexes = [];
@ -149,7 +142,7 @@ class V11 extends Migration
]);
}
$this->dbInternal->createCollection($key, $attributes, $indexes);
$this->dbProject->createCollection($key, $attributes, $indexes);
}
if ($this->options['migrateCollections']) {
$this->migrateExternalCollections();
@ -198,8 +191,8 @@ class V11 extends Migration
}
try {
if ($this->dbInternal->getDocument($new->getCollection(), $new->getId())->isEmpty()) {
$this->dbInternal->createDocument($new->getCollection(), $new);
if ($this->dbProject->getDocument($new->getCollection(), $new->getId())->isEmpty()) {
$this->dbProject->createDocument($new->getCollection(), $new);
}
} catch (\Throwable $th) {
Console::error('Failed to update document: ' . $th->getMessage());
@ -249,10 +242,10 @@ class V11 extends Migration
$id = $oldCollection->getId();
$permissions = $oldCollection->getPermissions();
$name = $oldCollection->getAttribute('name');
$newCollection = $this->dbExternal->getCollection($id);
$newCollection = $this->dbProject->getCollection('collection_' . $id);
if ($newCollection->isEmpty()) {
$this->dbExternal->createCollection($id);
$this->dbProject->createCollection('collection_' . $id);
/**
* Migrate permissions
*/
@ -263,13 +256,13 @@ class V11 extends Migration
* Suffix collection name with a subsequent number to make it unique if possible.
*/
$suffix = 1;
while ($this->dbInternal->findOne('collections', [
while ($this->dbProject->findOne('collections', [
new Query('name', Query::TYPE_EQUAL, [$name])
])) {
$name .= ' - ' . $suffix++;
}
$this->dbInternal->createDocument('collections', new Document([
$this->dbProject->createDocument('collections', new Document([
'$id' => $id,
'$read' => [],
'$write' => [],
@ -290,7 +283,7 @@ class V11 extends Migration
foreach ($attributes as $attribute) {
try {
$this->dbExternal->createAttribute(
$this->dbProject->createAttribute(
collection: $attribute['$collection'],
id: $attribute['$id'],
type: $attribute['type'],
@ -304,7 +297,7 @@ class V11 extends Migration
filters: $attribute['filters']
);
$this->dbInternal->createDocument('attributes', new Document([
$this->dbProject->createDocument('attributes', new Document([
'$id' => $attribute['$collection'] . '_' . $attribute['$id'],
'key' => $attribute['$id'],
'collectionId' => $attribute['$collection'],
@ -361,7 +354,7 @@ class V11 extends Migration
Console::log('Migrating External Documents for Collection ' . $collection . ': ' . $offset . ' / ' . $this->oldProjectDB->getSum());
foreach ($allDocs as $document) {
if (!$this->dbExternal->getDocument($collection, $document->getId())->isEmpty()) {
if (!$this->dbProject->getDocument('collection_' . $collection, $document->getId())->isEmpty()) {
continue;
}
go(function ($document) {
@ -398,7 +391,7 @@ class V11 extends Migration
}, $document);
$document = new Document($document->getArrayCopy());
$document = $this->migratePermissions($document);
$this->dbExternal->createDocument($collection, $document);
$this->dbProject->createDocument('collection_' . $collection, $document);
}
$offset += $this->limit;
}
@ -522,7 +515,7 @@ class V11 extends Migration
* Set default values for arrays if not set.
*/
if (empty($document->getAttribute('prefs', []))) {
$document->setAttribute('prefs', []);
$document->setAttribute('prefs', new \stdClass());
}
if (empty($document->getAttribute('sessions', []))) {
$document->setAttribute('sessions', []);

View file

@ -2,6 +2,7 @@
namespace Appwrite\Resque;
use Utopia\App;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\CLI\Console;
@ -21,8 +22,7 @@ abstract class Worker
const MAX_ATTEMPTS = 10;
const SLEEP_TIME = 2;
const DATABASE_INTERNAL = 'internal';
const DATABASE_EXTERNAL = 'external';
const DATABASE_PROJECT = 'project';
const DATABASE_CONSOLE = 'console';
public function setUp(): void
@ -44,19 +44,9 @@ abstract class Worker
* @param string $projectId
* @return Database
*/
protected function getInternalDB(string $projectId): Database
protected function getProjectDB(string $projectId): Database
{
return $this->getDB(self::DATABASE_INTERNAL, $projectId);
}
/**
* Get external project database
* @param string $projectId
* @return Database
*/
protected function getExternalDB(string $projectId): Database
{
return $this->getDB(self::DATABASE_EXTERNAL, $projectId);
return $this->getDB(self::DATABASE_PROJECT, $projectId);
}
/**
@ -82,20 +72,14 @@ abstract class Worker
$sleep = self::SLEEP_TIME; // overwritten when necessary
switch ($type) {
case self::DATABASE_INTERNAL:
case self::DATABASE_PROJECT:
if (!$projectId) {
throw new \Exception('ProjectID not provided - cannot get database');
}
$namespace = "project_{$projectId}_internal";
break;
case self::DATABASE_EXTERNAL:
if (!$projectId) {
throw new \Exception('ProjectID not provided - cannot get database');
}
$namespace = "project_{$projectId}_external";
$namespace = "_project_{$projectId}";
break;
case self::DATABASE_CONSOLE:
$namespace = "project_console_internal";
$namespace = "_project_console";
$sleep = 5; // ConsoleDB needs extra sleep time to ensure tables are created
break;
default:
@ -110,9 +94,10 @@ abstract class Worker
$attempts++;
$cache = new Cache(new RedisCache($register->get('cache')));
$database = new Database(new MariaDB($register->get('db')), $cache);
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace($namespace); // Main DB
if (!$database->exists()) {
throw new \Exception("Table does not exist: {$database->getNamespace()}");
if (!empty($projectId) && !$database->getDocument('projects', $projectId)->isEmpty()) {
throw new \Exception("Project does not exist: {$projectId}");
}
break; // leave loop if successful
} catch(\Exception $e) {

View file

@ -343,49 +343,49 @@ trait DatabaseBase
// wait for database worker to create attributes
sleep(30);
$stringResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$string['body']['key']}",array_merge([
$stringResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$string['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$emailResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$email['body']['key']}",array_merge([
$emailResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$email['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$enumResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$enum['body']['key']}",array_merge([
$enumResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$enum['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$ipResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$ip['body']['key']}",array_merge([
$ipResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$ip['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$urlResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$url['body']['key']}",array_merge([
$urlResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$url['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$integerResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$integer['body']['key']}",array_merge([
$integerResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$integer['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$floatResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$float['body']['key']}",array_merge([
$floatResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$float['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$booleanResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$boolean['body']['key']}",array_merge([
$booleanResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$boolean['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
@ -827,6 +827,10 @@ trait DatabaseBase
$this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']);
$this->assertCount(3, $documents['body']['documents']);
foreach ($documents['body']['documents'] as $document) {
$this->assertEquals($data['moviesId'], $document['$collection']);
}
$documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -841,7 +845,28 @@ trait DatabaseBase
$this->assertEquals(2019, $documents['body']['documents'][0]['releaseYear']);
$this->assertCount(3, $documents['body']['documents']);
return [];
return $documents['body']['documents'];
}
/**
* @depends testListDocuments
*/
public function testGetDocument(array $documents): void
{
foreach ($documents as $document) {
$response = $this->client->call(Client::METHOD_GET, '/database/collections/' . $document['$collection'] . '/documents/' . $document['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertEquals($response['body']['$id'], $document['$id']);
$this->assertEquals($response['body']['$collection'], $document['$collection']);
$this->assertEquals($response['body']['title'], $document['title']);
$this->assertEquals($response['body']['releaseYear'], $document['releaseYear']);
$this->assertEquals($response['body']['$read'], $document['$read']);
$this->assertEquals($response['body']['$write'], $document['$write']);
}
}
/**
@ -1218,6 +1243,8 @@ trait DatabaseBase
]);
$this->assertEquals($document['headers']['status-code'], 200);
$this->assertEquals($document['body']['$id'], $id);
$this->assertEquals($document['body']['$collection'], $data['moviesId']);
$this->assertEquals($document['body']['title'], 'Thor: Ragnarok');
$this->assertEquals($document['body']['releaseYear'], 2017);
$this->assertEquals('role:member', $document['body']['$read'][0]);
@ -1280,7 +1307,7 @@ trait DatabaseBase
], $this->getHeaders()));
$this->assertEquals($document['headers']['status-code'], 404);
return $data;
}