1
0
Fork 0
mirror of synced 2024-06-11 23:34:45 +12:00

Finish fixing code QL warnings

This commit is contained in:
Matej Bačo 2024-03-08 13:57:20 +01:00
parent 005a239932
commit db1674811f
79 changed files with 889 additions and 742 deletions

View file

@ -8,7 +8,6 @@ use Appwrite\Event\Delete;
use Appwrite\Event\Func;
use Appwrite\Event\Hamster;
use Appwrite\Platform\Appwrite;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\CLI;
@ -17,6 +16,7 @@ use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Platform\Service;
use Utopia\Pools\Group;
@ -25,8 +25,6 @@ use Utopia\Registry\Registry;
global $register;
$auth->disable();
CLI::setResource('register', fn () => $register);
CLI::setResource('cache', function ($pools) {
@ -48,7 +46,7 @@ CLI::setResource('pools', function (Registry $register) {
return $register->get('pools');
}, ['register']);
CLI::setResource('dbForConsole', function ($pools, $cache) {
CLI::setResource('dbForConsole', function ($pools, $cache, $auth) {
$sleep = 3;
$maxAttempts = 5;
$attempts = 0;
@ -64,6 +62,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) {
->getResource();
$dbForConsole = new Database($dbAdapter, $cache);
$dbForConsole->setAuthorization($auth);
$dbForConsole
->setNamespace('_console')
@ -91,12 +90,12 @@ CLI::setResource('dbForConsole', function ($pools, $cache) {
}
return $dbForConsole;
}, ['pools', 'cache']);
}, ['pools', 'cache', 'auth']);
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) {
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache, $auth) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) {
return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases, $auth) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForConsole;
}
@ -115,6 +114,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
->getResource();
$database = new Database($dbAdapter, $cache);
$database->setAuthorization($auth);
$databases[$databaseName] = $database;
@ -125,7 +125,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
return $database;
};
}, ['pools', 'dbForConsole', 'cache']);
}, ['pools', 'dbForConsole', 'cache', 'auth']);
CLI::setResource('queue', function (Group $pools) {
return $pools->get('queue')->pop()->getResource();
@ -178,11 +178,20 @@ CLI::setResource('logError', function (Registry $register) {
};
}, ['register']);
CLI::setResource('auth', fn () => new Authorization());
$platform = new Appwrite();
$platform->init(Service::TYPE_CLI);
$cli = $platform->getCli();
$cli
->init()
->inject('auth')
->action(function (Authorization $auth) {
$auth->disable();
});
$cli
->error()
->inject('error')

View file

@ -28,7 +28,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Identities;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Audit\Audit as EventAudit;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -45,7 +44,7 @@ use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Locale\Locale;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Assoc;
use Utopia\Http\Validator\Boolean;
@ -53,6 +52,7 @@ use Utopia\Http\Validator\Host;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\Locale\Locale;
$oauthDefaultSuccess = '/auth/oauth2/success';
$oauthDefaultFailure = '/auth/oauth2/failure';
@ -85,7 +85,8 @@ Http::post('/v1/account')
->inject('dbForProject')
->inject('queueForEvents')
->inject('hooks')
->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Hooks $hooks) {
->inject('auth')
->action(function (string $userId, string $email, string $password, string $name, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Hooks $hooks, Authorization $auth) {
$email = \strtolower($email);
if ('console' === $project->getId()) {
@ -186,7 +187,7 @@ Http::post('/v1/account')
throw new Exception(Exception::USER_ALREADY_EXISTS);
}
$auth->unsetRole(Role::guests()->toString());
$auth->removeRole(Role::guests()->toString());
$auth->addRole(Role::user($user->getId())->toString());
$auth->addRole(Role::users()->toString());
@ -227,7 +228,8 @@ Http::post('/v1/account/sessions/email')
->inject('geodb')
->inject('queueForEvents')
->inject('hooks')
->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Hooks $hooks) {
->inject('auth')
->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Hooks $hooks, Authorization $auth) {
$email = \strtolower($email);
$protocol = $request->getProtocol();
@ -551,7 +553,8 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
->inject('dbForProject')
->inject('geodb')
->inject('queueForEvents')
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents) use ($oauthDefaultSuccess) {
->inject('auth')
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $auth) use ($oauthDefaultSuccess) {
$protocol = $request->getProtocol();
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
@ -1098,7 +1101,8 @@ Http::post('/v1/account/tokens/magic-url')
->inject('locale')
->inject('queueForEvents')
->inject('queueForMails')
->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
->inject('Auth')
->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $auth) {
if (empty(Http::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
@ -1340,7 +1344,8 @@ Http::post('/v1/account/tokens/email')
->inject('locale')
->inject('queueForEvents')
->inject('queueForMails')
->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
->inject('auth')
->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $auth) {
if (empty(Http::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
}
@ -1541,7 +1546,7 @@ Http::post('/v1/account/tokens/email')
;
});
$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents) {
$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Authorization $auth) {
$roles = $auth->getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
@ -1676,6 +1681,7 @@ Http::put('/v1/account/sessions/magic-url')
->inject('locale')
->inject('geodb')
->inject('queueForEvents')
->inject('auth')
->action($createSession);
Http::put('/v1/account/sessions/phone')
@ -1706,6 +1712,7 @@ Http::put('/v1/account/sessions/phone')
->inject('locale')
->inject('geodb')
->inject('queueForEvents')
->inject('auth')
->action($createSession);
Http::post('/v1/account/sessions/token')
@ -1735,6 +1742,7 @@ Http::post('/v1/account/sessions/token')
->inject('locale')
->inject('geodb')
->inject('queueForEvents')
->inject('auth')
->action($createSession);
Http::post('/v1/account/tokens/phone')
@ -1765,7 +1773,8 @@ Http::post('/v1/account/tokens/phone')
->inject('queueForEvents')
->inject('queueForMessaging')
->inject('locale')
->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale) {
->inject('auth')
->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, Authorization $auth) {
if (empty(Http::getEnv('_APP_SMS_PROVIDER'))) {
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
}
@ -1933,7 +1942,8 @@ Http::post('/v1/account/sessions/anonymous')
->inject('dbForProject')
->inject('geodb')
->inject('queueForEvents')
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents) {
->inject('auth')
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $auth) {
$protocol = $request->getProtocol();
$roles = $auth->getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
@ -2153,7 +2163,8 @@ Http::get('/v1/account/sessions')
->inject('user')
->inject('locale')
->inject('project')
->action(function (Response $response, Document $user, Locale $locale, Document $project) {
->inject('auth')
->action(function (Response $response, Document $user, Locale $locale, Document $project, Authorization $auth) {
$roles = $auth->getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
@ -2195,7 +2206,8 @@ Http::get('/v1/account/logs')
->inject('locale')
->inject('geodb')
->inject('dbForProject')
->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) {
->inject('auth')
->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject, Authorization $auth) {
try {
$queries = Query::parseQueries($queries);
@ -2207,7 +2219,7 @@ Http::get('/v1/account/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new EventAudit($dbForProject);
$audit = new EventAudit($dbForProject, $auth);
$logs = $audit->getLogsByUser($user->getInternalId(), $limit, $offset);
@ -2261,7 +2273,8 @@ Http::get('/v1/account/sessions/:sessionId')
->inject('user')
->inject('locale')
->inject('project')
->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Document $project) {
->inject('auth')
->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Document $project, Authorization $auth) {
$roles = $auth->getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
@ -2416,7 +2429,8 @@ Http::patch('/v1/account/email')
->inject('queueForEvents')
->inject('project')
->inject('hooks')
->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) {
->inject('auth')
->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, Authorization $auth) {
// passwordUpdate will be empty if the user has never set a password
$passwordUpdate = $user->getAttribute('passwordUpdate');
@ -2508,7 +2522,8 @@ Http::patch('/v1/account/phone')
->inject('queueForEvents')
->inject('project')
->inject('hooks')
->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) {
->inject('auth')
->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, Authorization $auth) {
// passwordUpdate will be empty if the user has never set a password
$passwordUpdate = $user->getAttribute('passwordUpdate');
@ -2888,7 +2903,8 @@ Http::post('/v1/account/recovery')
->inject('locale')
->inject('queueForMails')
->inject('queueForEvents')
->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents) {
->inject('auth')
->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents, Authorization $auth) {
if (empty(Http::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
@ -3065,7 +3081,8 @@ Http::put('/v1/account/recovery')
->inject('project')
->inject('queueForEvents')
->inject('hooks')
->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks) {
->inject('auth')
->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, Authorization $auth) {
$profile = $dbForProject->getDocument('users', $userId);
if ($profile->isEmpty()) {
@ -3149,7 +3166,8 @@ Http::post('/v1/account/verification')
->inject('locale')
->inject('queueForEvents')
->inject('queueForMails')
->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) {
->inject('auth')
->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $auth) {
if (empty(Http::getEnv('_APP_SMTP_HOST'))) {
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
@ -3307,7 +3325,8 @@ Http::put('/v1/account/verification')
->inject('user')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$profile = $auth->skip(fn () => $dbForProject->getDocument('users', $userId));
@ -3370,7 +3389,8 @@ Http::post('/v1/account/verification/phone')
->inject('queueForMessaging')
->inject('project')
->inject('locale')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale) {
->inject('auth')
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, Authorization $auth) {
if (empty(Http::getEnv('_APP_SMS_PROVIDER'))) {
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
}
@ -3479,7 +3499,8 @@ Http::put('/v1/account/verification/phone')
->inject('user')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$profile = $auth->skip(fn () => $dbForProject->getDocument('users', $userId));
@ -4227,7 +4248,8 @@ Http::post('/v1/account/targets/push')
->inject('request')
->inject('response')
->inject('dbForProject')
->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $auth) {
$targetId = $targetId == 'unique()' ? ID::unique() : $targetId;
$provider = $auth->skip(fn () => $dbForProject->getDocument('providers', $providerId));
@ -4299,7 +4321,8 @@ Http::put('/v1/account/targets/:targetId/push')
->inject('request')
->inject('response')
->inject('dbForProject')
->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $targetId, string $identifier, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $auth) {
$target = $auth->skip(fn () => $dbForProject->getDocument('targets', $targetId));
@ -4354,7 +4377,8 @@ Http::delete('/v1/account/targets/:targetId/push')
->inject('request')
->inject('response')
->inject('dbForProject')
->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $targetId, Event $queueForEvents, Delete $queueForDeletes, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $auth) {
$target = $auth->skip(fn () => $dbForProject->getDocument('targets', $targetId));
if ($target->isEmpty()) {

View file

@ -5,7 +5,6 @@ use Appwrite\URL\URL as URLParse;
use Appwrite\Utopia\Response;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -14,15 +13,16 @@ use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\UID;
use Utopia\Domains\Domain;
use Utopia\Image\Image;
use Utopia\Logger\Log;
use Utopia\Logger\Logger;
use Utopia\Http\Http;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\HexColor;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\Image\Image;
use Utopia\Logger\Log;
use Utopia\Logger\Logger;
$avatarCallback = function (string $type, string $code, int $width, int $height, int $quality, Response $response) {
@ -61,7 +61,7 @@ $avatarCallback = function (string $type, string $code, int $width, int $height,
unset($image);
};
$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForConsole, ?Logger $logger) {
$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForConsole, ?Logger $logger, Authorization $auth) {
try {
$user = $auth->skip(fn () => $dbForConsole->getDocument('users', $userId));
@ -593,7 +593,8 @@ Http::get('/v1/cards/cloud')
->inject('contributors')
->inject('employees')
->inject('logger')
->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) {
->inject('authp')
->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $auth) use ($getUserGitHub) {
$user = $auth->skip(fn () => $dbForConsole->getDocument('users', $userId));
if ($user->isEmpty() && empty($mock)) {
@ -605,7 +606,7 @@ Http::get('/v1/cards/cloud')
$email = $user->getAttribute('email', '');
$createdAt = new \DateTime($user->getCreatedAt());
$gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger);
$gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger, $auth);
$githubName = $gitHub['name'] ?? '';
$githubId = $gitHub['id'] ?? '';
@ -800,7 +801,8 @@ Http::get('/v1/cards/cloud-back')
->inject('contributors')
->inject('employees')
->inject('logger')
->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) {
->inject('auth')
->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $auth) use ($getUserGitHub) {
$user = $auth->skip(fn () => $dbForConsole->getDocument('users', $userId));
if ($user->isEmpty() && empty($mock)) {
@ -811,7 +813,7 @@ Http::get('/v1/cards/cloud-back')
$userId = $user->getId();
$email = $user->getAttribute('email', '');
$gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger);
$gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger, $auth);
$githubId = $gitHub['id'] ?? '';
$isHero = \array_key_exists($email, $heroes);
@ -878,7 +880,8 @@ Http::get('/v1/cards/cloud-og')
->inject('contributors')
->inject('employees')
->inject('logger')
->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) {
->inject('auth')
->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger, Authorization $auth) use ($getUserGitHub) {
$user = $auth->skip(fn () => $dbForConsole->getDocument('users', $userId));
if ($user->isEmpty() && empty($mock)) {
@ -894,7 +897,7 @@ Http::get('/v1/cards/cloud-og')
$email = $user->getAttribute('email', '');
$createdAt = new \DateTime($user->getCreatedAt());
$gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger);
$gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger, $auth);
$githubName = $gitHub['name'] ?? '';
$githubId = $gitHub['id'] ?? '';

View file

@ -2,8 +2,8 @@
use Appwrite\Extend\Exception;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Database\Document;
use Utopia\Http\Http;
use Utopia\Http\Validator\Text;
Http::init()

View file

@ -15,7 +15,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Indexes;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -32,6 +31,7 @@ use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Authorization\Input;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Index as IndexValidator;
use Utopia\Database\Validator\Key;
@ -41,7 +41,7 @@ use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\Structure;
use Utopia\Database\Validator\UID;
use Utopia\Locale\Locale;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\FloatValidator;
@ -53,6 +53,7 @@ use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\Locale\Locale;
/**
* * Create attribute of varying type
@ -74,7 +75,7 @@ use Utopia\Http\Validator\WhiteList;
* @throws ConflictException
* @throws Exception
*/
function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents): Document
function createAttribute(string $databaseId, string $collectionId, Document $attribute, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth): Document
{
$key = $attribute->getAttribute('key');
$type = $attribute->getAttribute('type', '');
@ -223,6 +224,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
}
function updateAttribute(
Authorization $auth,
string $databaseId,
string $collectionId,
string $key,
@ -235,7 +237,7 @@ function updateAttribute(
int|float $min = null,
int|float $max = null,
array $elements = null,
array $options = []
array $options = [],
): Document {
$db = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -564,7 +566,8 @@ Http::get('/v1/databases/:databaseId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$database = $dbForProject->getDocument('databases', $databaseId);
@ -582,7 +585,7 @@ Http::get('/v1/databases/:databaseId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'database/' . $databaseId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
@ -750,7 +753,8 @@ Http::post('/v1/databases/:databaseId/collections')
->inject('dbForProject')
->inject('mode')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -811,7 +815,8 @@ Http::get('/v1/databases/:databaseId/collections')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -873,7 +878,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -909,7 +915,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -934,7 +941,7 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'database/' . $databaseId . '/collection/' . $collectionId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
@ -1015,7 +1022,8 @@ Http::put('/v1/databases/:databaseId/collections/:collectionId')
->inject('dbForProject')
->inject('mode')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $name, ?array $permissions, bool $documentSecurity, bool $enabled, Response $response, Database $dbForProject, string $mode, Event $queueForEvents, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1079,7 +1087,8 @@ Http::delete('/v1/databases/:databaseId/collections/:collectionId')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('mode')
->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, string $mode, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1140,7 +1149,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/strin
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
// Ensure attribute default is within required size
$validator = new Text($size, 0);
@ -1162,7 +1172,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/strin
'default' => $default,
'array' => $array,
'filters' => $filters,
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1194,7 +1204,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1204,7 +1215,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_EMAIL,
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1237,7 +1248,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum'
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, array $elements, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
if (!is_null($default) && !in_array($default, $elements)) {
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements');
}
@ -1251,7 +1263,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum'
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_ENUM,
'formatOptions' => ['elements' => $elements],
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1283,7 +1295,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1293,7 +1306,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip')
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_IP,
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1325,7 +1338,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1335,7 +1349,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url')
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_URL,
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1369,7 +1383,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/integ
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
// Ensure attribute default is within range
$min = (is_null($min)) ? PHP_INT_MIN : \intval($min);
@ -1399,7 +1414,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/integ
'min' => $min,
'max' => $max,
],
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$formatOptions = $attribute->getAttribute('formatOptions', []);
@ -1440,7 +1455,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
// Ensure attribute default is within range
$min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min);
@ -1473,7 +1489,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float
'min' => $min,
'max' => $max,
],
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$formatOptions = $attribute->getAttribute('formatOptions', []);
@ -1512,7 +1528,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boole
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$attribute = createAttribute($databaseId, $collectionId, new Document([
'key' => $key,
@ -1521,7 +1538,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boole
'required' => $required,
'default' => $default,
'array' => $array,
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1553,7 +1570,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/datet
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$filters[] = 'datetime';
@ -1565,7 +1583,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/datet
'default' => $default,
'array' => $array,
'filters' => $filters,
]), $response, $dbForProject, $queueForDatabase, $queueForEvents);
]), $response, $dbForProject, $queueForDatabase, $queueForEvents, $auth);
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
@ -1599,6 +1617,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relat
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('auth')
->action(function (
string $databaseId,
string $collectionId,
@ -1611,7 +1630,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relat
Response $response,
Database $dbForProject,
EventDatabase $queueForDatabase,
Event $queueForEvents
Event $queueForEvents,
Authorization $auth
) {
$key ??= $relatedCollectionId;
$twoWayKey ??= $collectionId;
@ -1686,7 +1706,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relat
$response,
$dbForProject,
$queueForDatabase,
$queueForEvents
$queueForEvents,
$auth
);
$options = $attribute->getAttribute('options', []);
@ -1717,7 +1738,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true)
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Authorization $auth) {
/** @var Document $database */
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1805,7 +1827,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
->param('key', '', new Key(), 'Attribute Key.')
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -1874,9 +1897,11 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/stri
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -1913,8 +1938,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/emai
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -1953,8 +1980,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?array $elements, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -1993,8 +2022,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -2032,8 +2063,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -2073,8 +2106,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/inte
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -2122,8 +2157,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/floa
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -2169,8 +2206,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/bool
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -2207,8 +2246,10 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/date
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?string $default, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$attribute = updateAttribute(
auth: $auth,
databaseId: $databaseId,
collectionId: $collectionId,
key: $key,
@ -2244,6 +2285,7 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->inject('auth')
->action(function (
string $databaseId,
string $collectionId,
@ -2251,9 +2293,11 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
?string $onDelete,
Response $response,
Database $dbForProject,
Event $queueForEvents
Event $queueForEvents,
Authorization $auth
) {
$attribute = updateAttribute(
$auth,
$databaseId,
$collectionId,
$key,
@ -2298,7 +2342,8 @@ Http::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:ke
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$db = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2411,7 +2456,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, string $type, array $attributes, array $orders, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$db = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2573,7 +2619,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true)
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Authorization $auth) {
/** @var Document $database */
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2643,7 +2690,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->param('key', null, new Key(), 'Index Key.')
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2686,7 +2734,8 @@ Http::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $auth) {
$db = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -2759,7 +2808,8 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->inject('user')
->inject('queueForEvents')
->inject('mode')
->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Authorization $auth) {
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
@ -2830,17 +2880,16 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/documents')
$data['$permissions'] = $permissions;
$document = new Document($data);
$checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database) {
$checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, $auth) {
$documentSecurity = $collection->getAttribute('documentSecurity', false);
$validator = new Authorization($permission);
$valid = $validator->isValid($collection->getPermissionsByType($permission));
$valid = $auth->isValid(new Input($permission, $collection->getPermissionsByType($permission)));
if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
if ($permission === Database::PERMISSION_UPDATE) {
$valid = $valid || $validator->isValid($document->getUpdate());
$valid = $valid || $auth->isValid($document->getUpdate());
if ($documentSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -2921,7 +2970,7 @@ Http::post('/v1/databases/:databaseId/collections/:collectionId/documents')
}
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $auth) {
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@ -2987,7 +3036,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/documents')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles());
@ -3039,7 +3089,7 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/documents')
}
// Add $collectionId and $databaseId for all documents
$processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool {
$processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $auth): bool {
if ($document->isEmpty()) {
return false;
}
@ -3144,7 +3194,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/documents/:docume
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -3174,7 +3225,7 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/documents/:docume
}
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $auth) {
if ($document->isEmpty()) {
return;
}
@ -3235,7 +3286,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/documents/:docume
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@ -3265,7 +3317,7 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/documents/:docume
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId();
$logs = $audit->getLogsByResource($resource, $limit, $offset);
@ -3349,7 +3401,8 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
->inject('dbForProject')
->inject('queueForEvents')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Authorization $auth) {
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
@ -3416,7 +3469,7 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
$data['$permissions'] = $permissions;
$newDocument = new Document($data);
$setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) {
$setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, $auth) {
$relationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
@ -3502,7 +3555,7 @@ Http::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
}
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $auth) {
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@ -3575,7 +3628,8 @@ Http::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:doc
->inject('queueForDeletes')
->inject('queueForEvents')
->inject('mode')
->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, string $mode) {
->inject('auth')
->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, string $mode, Authorization $auth) {
$database = $auth->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -3612,7 +3666,7 @@ Http::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:doc
});
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, $auth) {
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@ -3674,7 +3728,8 @@ Http::get('/v1/databases/usage')
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $range, Response $response, Database $dbForProject, Authorization $auth) {
$periods = Config::getParam('usage', []);
$stats = $usage = [];
@ -3753,7 +3808,8 @@ Http::get('/v1/databases/:databaseId/usage')
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $databaseId, string $range, Response $response, Database $dbForProject, Authorization $auth) {
$database = $dbForProject->getDocument('databases', $databaseId);
@ -3838,7 +3894,8 @@ Http::get('/v1/databases/:databaseId/collections/:collectionId/usage')
->param('collectionId', '', new UID(), 'Collection ID.')
->inject('response')
->inject('dbForProject')
->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject, Authorization $auth) {
$database = $dbForProject->getDocument('databases', $databaseId);
$collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);

View file

@ -15,11 +15,11 @@ use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Deployments;
use Appwrite\Utopia\Database\Validator\Queries\Executions;
use Appwrite\Utopia\Database\Validator\Queries\Functions;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model\Rule;
use Executor\Executor;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -32,20 +32,21 @@ use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Authorization\Input;
use Utopia\Database\Validator\Roles;
use Utopia\Database\Validator\UID;
use Utopia\Storage\Device;
use Utopia\Storage\Validator\File;
use Utopia\Storage\Validator\FileExt;
use Utopia\Storage\Validator\FileSize;
use Utopia\Storage\Validator\Upload;
use Utopia\Swoole\Request;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Assoc;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Storage\Device;
use Utopia\Storage\Validator\File;
use Utopia\Storage\Validator\FileExt;
use Utopia\Storage\Validator\FileSize;
use Utopia\Storage\Validator\Upload;
use Utopia\VCS\Adapter\Git\GitHub;
use Utopia\VCS\Exception\RepositoryNotFound;
@ -479,7 +480,8 @@ Http::get('/v1/functions/:functionId/usage')
->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $functionId, string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $functionId, string $range, Response $response, Database $dbForProject, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
@ -576,7 +578,8 @@ Http::get('/v1/functions/usage')
->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $range, Response $response, Database $dbForProject, Authorization $auth) {
$periods = Config::getParam('usage', []);
$stats = $usage = [];
@ -694,7 +697,8 @@ Http::put('/v1/functions/:functionId')
->inject('queueForBuilds')
->inject('dbForConsole')
->inject('gitHub')
->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) use ($redeployVcs) {
->inject('auth')
->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github, Authorization $auth) use ($redeployVcs) {
// TODO: If only branch changes, re-deploy
$function = $dbForProject->getDocument('functions', $functionId);
@ -940,7 +944,8 @@ Http::patch('/v1/functions/:functionId/deployments/:deploymentId')
->inject('dbForProject')
->inject('queueForEvents')
->inject('dbForConsole')
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Database $dbForConsole) {
->inject('auth')
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Database $dbForConsole, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
@ -1001,7 +1006,8 @@ Http::delete('/v1/functions/:functionId')
->inject('queueForDeletes')
->inject('queueForEvents')
->inject('dbForConsole')
->action(function (string $functionId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Database $dbForConsole) {
->inject('auth')
->action(function (string $functionId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Database $dbForConsole, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
@ -1451,7 +1457,8 @@ Http::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId'
->inject('project')
->inject('queueForEvents')
->inject('queueForBuilds')
->action(function (string $functionId, string $deploymentId, string $buildId, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds) {
->inject('auth')
->action(function (string $functionId, string $deploymentId, string $buildId, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
@ -1522,7 +1529,8 @@ Http::post('/v1/functions/:functionId/executions')
->inject('mode')
->inject('queueForFunctions')
->inject('geodb')
->action(function (string $functionId, string $body, bool $async, string $path, string $method, array $headers, Response $response, Document $project, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, string $mode, Func $queueForFunctions, Reader $geodb) {
->inject('auth')
->action(function (string $functionId, string $body, bool $async, string $path, string $method, array $headers, Response $response, Document $project, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, string $mode, Func $queueForFunctions, Reader $geodb, Authorization $auth) {
$function = $auth->skip(fn () => $dbForProject->getDocument('functions', $functionId));
@ -1562,10 +1570,8 @@ Http::post('/v1/functions/:functionId/executions')
throw new Exception(Exception::BUILD_NOT_READY);
}
$validator = new Authorization('execute');
if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function
throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription());
if (!$auth->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function
throw new Exception(Exception::USER_UNAUTHORIZED, $auth->getDescription());
}
$jwt = ''; // initialize
@ -1803,7 +1809,8 @@ Http::get('/v1/functions/:functionId/executions')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$function = $auth->skip(fn () => $dbForProject->getDocument('functions', $functionId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -1883,7 +1890,8 @@ Http::get('/v1/functions/:functionId/executions/:executionId')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$function = $auth->skip(fn () => $dbForProject->getDocument('functions', $functionId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -1935,7 +1943,8 @@ Http::post('/v1/functions/:functionId/variables')
->inject('response')
->inject('dbForProject')
->inject('dbForConsole')
->action(function (string $functionId, string $key, string $value, Response $response, Database $dbForProject, Database $dbForConsole) {
->inject('auth')
->action(function (string $functionId, string $key, string $value, Response $response, Database $dbForProject, Database $dbForConsole, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
@ -2066,7 +2075,8 @@ Http::put('/v1/functions/:functionId/variables/:variableId')
->inject('response')
->inject('dbForProject')
->inject('dbForConsole')
->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole) {
->inject('auth')
->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
@ -2124,7 +2134,8 @@ Http::delete('/v1/functions/:functionId/variables/:variableId')
->inject('response')
->inject('dbForProject')
->inject('dbForConsole')
->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject, Database $dbForConsole) {
->inject('auth')
->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject, Database $dbForConsole, Authorization $auth) {
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {

View file

@ -12,8 +12,8 @@ use GraphQL\Validator\Rules\DisableIntrospection;
use GraphQL\Validator\Rules\QueryComplexity;
use GraphQL\Validator\Rules\QueryDepth;
use Swoole\Coroutine\WaitGroup;
use Utopia\Http\Http;
use Utopia\Database\Document;
use Utopia\Http\Http;
use Utopia\Http\Validator\JSON;
use Utopia\Http\Validator\Text;

View file

@ -4,10 +4,15 @@ use Appwrite\ClamAV\Network;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Config\Config;
use Utopia\Database\Document;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\Http\Http;
use Utopia\Http\Validator\Domain;
use Utopia\Http\Validator\Integer;
use Utopia\Http\Validator\Multiple;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Pools\Group;
use Utopia\Queue\Client;
use Utopia\Queue\Connection;
@ -15,11 +20,6 @@ use Utopia\Registry\Registry;
use Utopia\Storage\Device;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Storage;
use Utopia\Http\Validator\Domain;
use Utopia\Http\Validator\Integer;
use Utopia\Http\Validator\Multiple;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
Http::get('/v1/health')
->desc('Get HTTP')

View file

@ -3,9 +3,9 @@
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Config\Config;
use Utopia\Database\Document;
use Utopia\Http\Http;
use Utopia\Locale\Locale;
Http::get('/v1/locale')

View file

@ -19,7 +19,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Targets;
use Appwrite\Utopia\Database\Validator\Queries\Topics;
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
@ -29,6 +28,7 @@ use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Authorization\Input;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
@ -36,7 +36,7 @@ use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\Roles;
use Utopia\Database\Validator\UID;
use Utopia\Domains\Domain;
use Utopia\Locale\Locale;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Integer;
@ -44,6 +44,7 @@ use Utopia\Http\Validator\JSON;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Locale\Locale;
use function Swoole\Coroutine\batch;
@ -846,7 +847,8 @@ Http::get('/v1/messaging/providers')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('dbForProject')
->inject('response')
->action(function (array $queries, string $search, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (array $queries, string $search, Database $dbForProject, Response $response, Authorization $auth) {
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
@ -899,7 +901,8 @@ Http::get('/v1/messaging/providers/:providerId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $providerId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $providerId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$provider = $dbForProject->getDocument('providers', $providerId);
if ($provider->isEmpty()) {
@ -916,7 +919,7 @@ Http::get('/v1/messaging/providers/:providerId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'provider/' . $providerId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
$output = [];
@ -1980,7 +1983,8 @@ Http::get('/v1/messaging/topics')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('dbForProject')
->inject('response')
->action(function (array $queries, string $search, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (array $queries, string $search, Database $dbForProject, Response $response, Authorization $auth) {
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
@ -2033,7 +2037,8 @@ Http::get('/v1/messaging/topics/:topicId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $topicId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $topicId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$topic = $dbForProject->getDocument('topics', $topicId);
if ($topic->isEmpty()) {
@ -2050,7 +2055,7 @@ Http::get('/v1/messaging/topics/:topicId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'topic/' . $topicId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
@ -2236,7 +2241,8 @@ Http::post('/v1/messaging/topics/:topicId/subscribers')
->inject('queueForEvents')
->inject('dbForProject')
->inject('response')
->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (string $subscriberId, string $topicId, string $targetId, Event $queueForEvents, Database $dbForProject, Response $response, Authorization $auth) {
$subscriberId = $subscriberId == 'unique()' ? ID::unique() : $subscriberId;
$topic = $auth->skip(fn () => $dbForProject->getDocument('topics', $topicId));
@ -2245,9 +2251,9 @@ Http::post('/v1/messaging/topics/:topicId/subscribers')
throw new Exception(Exception::TOPIC_NOT_FOUND);
}
$validator = new Authorization('subscribe');
$validator = new Authorization();
if (!$validator->isValid($topic->getAttribute('subscribe'))) {
if (!$validator->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) {
throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription());
}
@ -2328,7 +2334,8 @@ Http::get('/v1/messaging/topics/:topicId/subscribers')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('dbForProject')
->inject('response')
->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Response $response, Authorization $auth) {
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
@ -2368,8 +2375,8 @@ Http::get('/v1/messaging/topics/:topicId/subscribers')
$subscribers = $dbForProject->find('subscribers', $queries);
$subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject) {
return function () use ($subscriber, $dbForProject) {
$subscribers = batch(\array_map(function (Document $subscriber) use ($dbForProject, $auth) {
return function () use ($subscriber, $dbForProject, $auth) {
$target = $auth->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId')));
$user = $auth->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId')));
@ -2403,7 +2410,8 @@ Http::get('/v1/messaging/subscribers/:subscriberId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $subscriberId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $subscriberId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$subscriber = $dbForProject->getDocument('subscribers', $subscriberId);
if ($subscriber->isEmpty()) {
@ -2420,7 +2428,7 @@ Http::get('/v1/messaging/subscribers/:subscriberId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'subscriber/' . $subscriberId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
@ -2490,7 +2498,8 @@ Http::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
->param('subscriberId', '', new UID(), 'Subscriber ID.')
->inject('dbForProject')
->inject('response')
->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response, Authorization $auth) {
$topic = $auth->skip(fn () => $dbForProject->getDocument('topics', $topicId));
if ($topic->isEmpty()) {
@ -2533,7 +2542,8 @@ Http::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId')
->inject('queueForEvents')
->inject('dbForProject')
->inject('response')
->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response, Authorization $auth) {
$topic = $auth->skip(fn () => $dbForProject->getDocument('topics', $topicId));
if ($topic->isEmpty()) {
@ -3022,7 +3032,8 @@ Http::get('/v1/messaging/messages')
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('dbForProject')
->inject('response')
->action(function (array $queries, string $search, Database $dbForProject, Response $response) {
->inject('auth')
->action(function (array $queries, string $search, Database $dbForProject, Response $response, Authorization $auth) {
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
@ -3075,7 +3086,8 @@ Http::get('/v1/messaging/messages/:messageId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$message = $dbForProject->getDocument('messages', $messageId);
if ($message->isEmpty()) {
@ -3092,7 +3104,7 @@ Http::get('/v1/messaging/messages/:messageId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'message/' . $messageId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);

View file

@ -9,7 +9,6 @@ use Appwrite\Role;
use Appwrite\Utopia\Database\Validator\Queries\Migrations;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
@ -17,16 +16,17 @@ use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\UID;
use Utopia\Migration\Sources\Appwrite;
use Utopia\Migration\Sources\Firebase;
use Utopia\Migration\Sources\NHost;
use Utopia\Migration\Sources\Supabase;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Host;
use Utopia\Http\Validator\Integer;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\Migration\Sources\Appwrite;
use Utopia\Migration\Sources\Firebase;
use Utopia\Migration\Sources\NHost;
use Utopia\Migration\Sources\Supabase;
include_once __DIR__ . '/../shared/api.php';

View file

@ -2,7 +2,6 @@
use Appwrite\Extend\Exception;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
@ -13,6 +12,7 @@ use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Datetime as DateTimeValidator;
use Utopia\Database\Validator\UID;
use Utopia\Http\Http;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
@ -31,7 +31,8 @@ Http::get('/v1/project/usage')
->param('period', '1d', new WhiteList(['1h', '1d']), 'Period used', true)
->inject('response')
->inject('dbForProject')
->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject, Authorization $auth) {
$stats = $total = $usage = [];
$format = 'Y-m-d 00:00:00';
$firstDay = (new DateTime($startDate))->format($format);

View file

@ -13,7 +13,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects;
use Appwrite\Utopia\Response;
use PHPMailer\PHPMailer\PHPMailer;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\Cache\Cache;
use Utopia\Config\Config;
@ -25,11 +24,11 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\UID;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\Locale\Locale;
use Utopia\Pools\Group;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Hostname;
@ -39,6 +38,8 @@ use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\Locale\Locale;
use Utopia\Pools\Group;
Http::init()
->groups(['projects'])
@ -76,7 +77,8 @@ Http::post('/v1/projects')
->inject('dbForConsole')
->inject('cache')
->inject('pools')
->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools) {
->inject('auth')
->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole, Cache $cache, Group $pools, Authorization $auth) {
$team = $dbForConsole->getDocument('teams', $teamId);
@ -177,13 +179,14 @@ Http::post('/v1/projects')
}
$dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache);
$dbForProject->setAuthorization($auth);
$dbForProject->setNamespace("_{$project->getInternalId()}");
$dbForProject->create();
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$audit->setup();
$adapter = new TimeLimit('', 0, 1, $dbForProject);
$adapter = new TimeLimit('', 0, 1, $dbForProject, $auth);
$adapter->setup();
/** @var array $collections */

View file

@ -7,7 +7,6 @@ use Appwrite\Extend\Exception;
use Appwrite\Network\Validator\CNAME;
use Appwrite\Utopia\Database\Validator\Queries\Rules;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Query as QueryException;
@ -15,10 +14,11 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\UID;
use Utopia\Domains\Domain;
use Utopia\Logger\Log;
use Utopia\Http\Http;
use Utopia\Http\Validator\Domain as ValidatorDomain;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Logger\Log;
Http::post('/v1/proxy/rules')
->groups(['api', 'proxy'])

View file

@ -9,8 +9,8 @@ use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Buckets;
use Appwrite\Utopia\Database\Validator\Queries\Files;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Document;
@ -24,8 +24,16 @@ use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Authorization\Input;
use Utopia\Database\Validator\Permissions;
use Utopia\Database\Validator\UID;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\HexColor;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Image\Image;
use Utopia\Storage\Compression\Algorithms\GZIP;
use Utopia\Storage\Compression\Algorithms\Zstd;
@ -36,13 +44,6 @@ use Utopia\Storage\Validator\File;
use Utopia\Storage\Validator\FileExt;
use Utopia\Storage\Validator\FileSize;
use Utopia\Storage\Validator\Upload;
use Utopia\Swoole\Request;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\HexColor;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
Http::post('/v1/storage/buckets')
->desc('Create bucket')
@ -361,7 +362,8 @@ Http::post('/v1/storage/buckets/:bucketId/files')
->inject('mode')
->inject('deviceForFiles')
->inject('deviceForLocal')
->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal) {
->inject('auth')
->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@ -372,8 +374,7 @@ Http::post('/v1/storage/buckets/:bucketId/files')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
if (!$auth->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -631,8 +632,7 @@ Http::post('/v1/storage/buckets/:bucketId/files')
* However as with chunk upload even if we are updating, we are essentially creating a file
* adding it's new chunk so we validate create permission instead of update
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
if (!$auth->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = $auth->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
@ -678,8 +678,7 @@ Http::post('/v1/storage/buckets/:bucketId/files')
* However as with chunk upload even if we are updating, we are essentially creating a file
* adding it's new chunk so we validate create permission instead of update
*/
$validator = new Authorization(Database::PERMISSION_CREATE);
if (!$validator->isValid($bucket->getCreate())) {
if (!$auth->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
$file = $auth->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file));
@ -724,7 +723,8 @@ Http::get('/v1/storage/buckets/:bucketId/files')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -735,8 +735,7 @@ Http::get('/v1/storage/buckets/:bucketId/files')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
$valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -808,7 +807,8 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode) {
->inject('auth')
->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -819,8 +819,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
$valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -873,7 +872,8 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
->inject('mode')
->inject('deviceForFiles')
->inject('deviceForLocal')
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal) {
->inject('auth')
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $auth) {
if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
@ -889,8 +889,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
$valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -1033,7 +1032,8 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
->inject('dbForProject')
->inject('mode')
->inject('deviceForFiles')
->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceForFiles) {
->inject('auth')
->action(function (string $bucketId, string $fileId, Request $request, Response $response, Database $dbForProject, string $mode, Device $deviceForFiles, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@ -1045,8 +1045,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
$valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -1173,7 +1172,8 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
->inject('dbForProject')
->inject('mode')
->inject('deviceForFiles')
->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceForFiles) {
->inject('auth')
->action(function (string $bucketId, string $fileId, Response $response, Request $request, Database $dbForProject, string $mode, Device $deviceForFiles, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -1184,8 +1184,7 @@ Http::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
$valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -1333,7 +1332,8 @@ Http::put('/v1/storage/buckets/:bucketId/files/:fileId')
->inject('user')
->inject('mode')
->inject('queueForEvents')
->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents) {
->inject('auth')
->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@ -1345,8 +1345,7 @@ Http::put('/v1/storage/buckets/:bucketId/files/:fileId')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_UPDATE);
$valid = $validator->isValid($bucket->getUpdate());
$valid = $auth->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -1439,7 +1438,8 @@ Http::delete('/v1/storage/buckets/:bucketId/files/:fileId')
->inject('mode')
->inject('deviceForFiles')
->inject('queueForDeletes')
->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes) {
->inject('auth')
->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes, Authorization $auth) {
$bucket = $auth->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
$isAPIKey = Auth::isAppUser($auth->getRoles());
@ -1450,8 +1450,7 @@ Http::delete('/v1/storage/buckets/:bucketId/files/:fileId')
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_DELETE);
$valid = $validator->isValid($bucket->getDelete());
$valid = $auth->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -1464,7 +1463,7 @@ Http::delete('/v1/storage/buckets/:bucketId/files/:fileId')
}
// Make sure we don't delete the file before the document permission check occurs
if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) {
if ($fileSecurity && !$valid && !$auth->isValid($file->getDelete())) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -1524,7 +1523,8 @@ Http::get('/v1/storage/usage')
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $range, Response $response, Database $dbForProject, Authorization $auth) {
$periods = Config::getParam('usage', []);
$stats = $usage = [];
@ -1604,7 +1604,8 @@ Http::get('/v1/storage/:bucketId/usage')
->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true)
->inject('response')
->inject('dbForProject')
->action(function (string $bucketId, string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $bucketId, string $range, Response $response, Database $dbForProject, Authorization $auth) {
$bucket = $dbForProject->getDocument('buckets', $bucketId);
@ -1620,7 +1621,6 @@ Http::get('/v1/storage/:bucketId/usage')
str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE),
];
$auth->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) {
foreach ($metrics as $metric) {
$result = $dbForProject->findOne('stats', [

View file

@ -17,7 +17,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Teams;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -36,11 +35,12 @@ use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Locale\Locale;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Assoc;
use Utopia\Http\Validator\Host;
use Utopia\Http\Validator\Text;
use Utopia\Locale\Locale;
Http::post('/v1/teams')
->desc('Create team')
@ -63,7 +63,8 @@ Http::post('/v1/teams')
->inject('user')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles());
$isAppUser = Auth::isAppUser($auth->getRoles());
@ -396,7 +397,8 @@ Http::post('/v1/teams/:teamId/memberships')
->inject('queueForMails')
->inject('queueForMessaging')
->inject('queueForEvents')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents) {
->inject('auth')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, Authorization $auth) {
$isAPIKey = Auth::isAppUser($auth->getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser($auth->getRoles());
@ -863,7 +865,8 @@ Http::patch('/v1/teams/:teamId/memberships/:membershipId')
->inject('user')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$team = $dbForProject->getDocument('teams', $teamId);
if ($team->isEmpty()) {
@ -938,7 +941,8 @@ Http::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->inject('project')
->inject('geodb')
->inject('queueForEvents')
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents) {
->inject('auth')
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents, Authorization $auth) {
$protocol = $request->getProtocol();
$membership = $dbForProject->getDocument('memberships', $membershipId);
@ -1067,7 +1071,8 @@ Http::delete('/v1/teams/:teamId/memberships/:membershipId')
->inject('response')
->inject('dbForProject')
->inject('queueForEvents')
->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, Event $queueForEvents) {
->inject('auth')
->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $auth) {
$membership = $dbForProject->getDocument('memberships', $membershipId);
@ -1131,7 +1136,8 @@ Http::get('/v1/teams/:teamId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$team = $dbForProject->getDocument('teams', $teamId);
@ -1149,7 +1155,7 @@ Http::get('/v1/teams/:teamId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$resource = 'team/' . $team->getId();
$logs = $audit->getLogsByResource($resource, $limit, $offset);

View file

@ -21,7 +21,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Users;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -38,7 +37,7 @@ use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Locale\Locale;
use Utopia\Http\Http;
use Utopia\Http\Validator\ArrayList;
use Utopia\Http\Validator\Assoc;
use Utopia\Http\Validator\Boolean;
@ -46,6 +45,7 @@ use Utopia\Http\Validator\Integer;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Locale\Locale;
/** TODO: Remove function when we move to using utopia/platform */
function createUser(string $hash, mixed $hashOptions, string $userId, ?string $email, ?string $password, ?string $phone, string $name, Document $project, Database $dbForProject, Event $queueForEvents, Hooks $hooks): Document
@ -777,7 +777,8 @@ Http::get('/v1/users/:userId/logs')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
->inject('auth')
->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $auth) {
$user = $dbForProject->getDocument('users', $userId);
@ -795,7 +796,7 @@ Http::get('/v1/users/:userId/logs')
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$logs = $audit->getLogsByUser($user->getInternalId(), $limit, $offset);
@ -2110,7 +2111,8 @@ Http::get('/v1/users/usage')
->inject('response')
->inject('dbForProject')
->inject('register')
->action(function (string $range, Response $response, Database $dbForProject) {
->inject('auth')
->action(function (string $range, Response $response, Database $dbForProject, Authorization $auth) {
$periods = Config::getParam('usage', []);
$stats = $usage = [];

View file

@ -8,7 +8,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Installations;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Appwrite\Vcs\Comment;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -32,6 +31,7 @@ use Utopia\Detector\Adapter\Python;
use Utopia\Detector\Adapter\Ruby;
use Utopia\Detector\Adapter\Swift;
use Utopia\Detector\Detector;
use Utopia\Http\Http;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Host;
use Utopia\Http\Validator\Text;
@ -40,7 +40,7 @@ use Utopia\VCS\Exception\RepositoryNotFound;
use function Swoole\Coroutine\batch;
$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForConsole, Build $queueForBuilds, callable $getProjectDB, Request $request) {
$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForConsole, Build $queueForBuilds, callable $getProjectDB, Request $request, Authorization $auth) {
foreach ($repositories as $resource) {
$resourceType = $resource->getAttribute('resourceType');
@ -821,8 +821,9 @@ Http::post('/v1/vcs/github/events')
->inject('dbForConsole')
->inject('getProjectDB')
->inject('queueForBuilds')
->inject('auth')
->action(
function (GitHub $github, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) {
function (GitHub $github, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds, Authorization $auth) use ($createGitDeployments) {
$payload = $request->getRawPayload();
$signatureRemote = $request->getHeader('x-hub-signature-256', '');
$signatureLocal = Http::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', '');
@ -863,7 +864,7 @@ Http::post('/v1/vcs/github/events')
// create new deployment only on push and not when branch is created
if (!$providerBranchCreated) {
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForConsole, $queueForBuilds, $getProjectDB, $request);
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForConsole, $queueForBuilds, $getProjectDB, $request, $auth);
}
} elseif ($event == $github::EVENT_INSTALLATION) {
if ($parsedPayload["action"] == "deleted") {
@ -919,7 +920,7 @@ Http::post('/v1/vcs/github/events')
Query::orderDesc('$createdAt')
]));
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForConsole, $queueForBuilds, $getProjectDB, $request);
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForConsole, $queueForBuilds, $getProjectDB, $request, $auth);
} elseif ($parsedPayload["action"] == "closed") {
// Allowed external contributions cleanup
@ -1092,7 +1093,8 @@ Http::patch('/v1/vcs/github/installations/:installationId/repositories/:reposito
->inject('dbForConsole')
->inject('getProjectDB')
->inject('queueForBuilds')
->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) {
->inject('auth')
->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds, Authorization $auth) use ($createGitDeployments) {
$installation = $dbForConsole->getDocument('installations', $installationId);
if ($installation->isEmpty()) {
@ -1140,7 +1142,7 @@ Http::patch('/v1/vcs/github/installations/:installationId/repositories/:reposito
$providerBranch = \explode(':', $pullRequestResponse['head']['label'])[1] ?? '';
$providerCommitHash = $pullRequestResponse['head']['sha'] ?? '';
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForConsole, $queueForBuilds, $getProjectDB, $request);
$createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForConsole, $queueForBuilds, $getProjectDB, $request, $auth);
$response->noContent();
});

View file

@ -26,7 +26,6 @@ use Appwrite\Utopia\View;
use Executor\Executor;
use MaxMind\Db\Reader;
use Swoole\Http\Request as SwooleRequest;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -35,18 +34,19 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Domains\Domain;
use Utopia\Http\Http;
use Utopia\Http\Validator\Hostname;
use Utopia\Http\Validator\Text;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
use Utopia\Logger\Log\User;
use Utopia\Logger\Logger;
use Utopia\Http\Validator\Hostname;
use Utopia\Http\Validator\Text;
Config::setParam('domainVerification', false);
Config::setParam('cookieDomain', 'localhost');
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb)
function router(Http $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Reader $geodb, Authorization $auth)
{
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
@ -382,7 +382,8 @@ Http::init()
->inject('queueForUsage')
->inject('queueForEvents')
->inject('queueForCertificates')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates) {
->inject('auth')
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Authorization $auth) {
/*
* Appwrite Router
*/
@ -390,7 +391,7 @@ Http::init()
$mainDomain = Http::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain) {
if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) {
if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb, $auth)) {
return;
}
}
@ -627,7 +628,8 @@ Http::options()
->inject('queueForEvents')
->inject('queueForUsage')
->inject('geodb')
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb) {
->inject('auth')
->action(function (Http $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Reader $geodb, Authorization $auth) {
/*
* Appwrite Router
*/
@ -635,7 +637,7 @@ Http::options()
$mainDomain = Http::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain) {
if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb)) {
if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $geodb, $auth)) {
return;
}
}
@ -660,7 +662,8 @@ Http::error()
->inject('project')
->inject('logger')
->inject('log')
->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log) {
->inject('auth')
->action(function (Throwable $error, Http $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Authorization $auth) {
$version = Http::getEnv('_APP_VERSION', 'UNKNOWN');
$route = $utopia->getRoute();
@ -734,7 +737,7 @@ Http::error()
}
/** Handle Utopia Errors */
if ($error instanceof Utopia\Exception) {
if ($error instanceof Utopia\Http\Exception) {
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
switch ($code) {
case 400:

View file

@ -5,16 +5,16 @@ global $utopia, $request, $response;
use Appwrite\Extend\Exception;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\UID;
use Utopia\Http\Validator\WhiteList;
use Utopia\Http\Http;
use Utopia\Http\Validator\Host;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\VCS\Adapter\Git\GitHub;
Http::get('/v1/mock/tests/general/oauth2')
@ -218,7 +218,7 @@ Http::shutdown()
->inject('utopia')
->inject('response')
->inject('request')
->action(function (App $utopia, Response $response, Request $request) {
->action(function (Http $utopia, Response $response, Request $request) {
$result = [];
$route = $utopia->getRoute();

View file

@ -16,7 +16,6 @@ use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
use Utopia\Config\Config;
@ -25,7 +24,11 @@ use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Authorization\Input;
use Utopia\Http\Http;
use Utopia\Http\Validator\WhiteList;
use Utopia\Pools\Group;
use Utopia\Pools\Pool;
$parseLabel = function (string $label, array $responsePayload, array $requestParams, Document $user) {
preg_match_all('/{(.*?)}/', $label, $matches);
@ -328,7 +331,7 @@ Http::init()
foreach ($abuseKeyLabel as $abuseKey) {
$start = $request->getContentRangeStart();
$end = $request->getContentRangeEnd();
$timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
$timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject, $auth);
$timeLimit
->setParam('{projectId}', $project->getId())
->setParam('{userId}', $user->getId())
@ -433,8 +436,7 @@ Http::init()
}
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_READ);
$valid = $validator->isValid($bucket->getRead());
$valid = $auth->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()));
if (!$fileSecurity && !$valid) {
throw new Exception(Exception::USER_UNAUTHORIZED);
}
@ -702,8 +704,6 @@ Http::shutdown()
}
}
if ($project->getId() !== 'console') {
if ($mode !== APP_MODE_ADMIN) {
$fileSize = 0;
@ -747,3 +747,16 @@ Http::init()
throw new Exception(Exception::GENERAL_USAGE_DISABLED);
}
});
Http::shutdown()
->inject('pools')
->action(function (Group $pools) {
$pools->reclaim();
});
Http::error()
->inject('pools')
->action(function (Group $pools) {
$pools->reclaim();
});

View file

@ -4,10 +4,10 @@ use Appwrite\Auth\Auth;
use Appwrite\Extend\Exception;
use Appwrite\Utopia\Request;
use MaxMind\Db\Reader;
use Utopia\Http\Http;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
Http::init()
->groups(['mfaProtected'])

View file

@ -1,8 +1,8 @@
<?php
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Config\Config;
use Utopia\Http\Http;
Http::get('/versions')
->desc('Get Version')

View file

@ -4,13 +4,8 @@ require_once __DIR__ . '/../vendor/autoload.php';
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Swoole\Constant;
use Swoole\Http\Request as SwooleRequest;
use Swoole\Http\Response as SwooleResponse;
use Swoole\Http\Server;
use Swoole\Process;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\CLI\Console;
use Utopia\Config\Config;
@ -20,315 +15,198 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\Authorization;
use Utopia\Logger\Log;
use Utopia\Logger\Log\User;
use Utopia\Http\Adapter\Swoole\Request as SwooleRequest;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Http\Adapter\Swoole\Server;
use Utopia\Http\Http;
use Utopia\Pools\Group;
use Utopia\Swoole\Files;
$http = new Server(
host: "0.0.0.0",
port: Http::getEnv('PORT', 80),
mode: SWOOLE_PROCESS,
);
$payloadSize = 6 * (1024 * 1024); // 6MB
$workerNumber = swoole_cpu_num() * intval(Http::getEnv('_APP_WORKER_PER_CORE', 6));
$http
->set([
'worker_num' => $workerNumber,
'open_http2_protocol' => true,
'http_compression' => true,
'http_compression_level' => 6,
'package_max_length' => $payloadSize,
'buffer_output_size' => $payloadSize,
]);
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) {
Console::success('Worker ' . ++$workerId . ' started successfully');
});
$http->on(Constant::EVENT_BEFORE_RELOAD, function ($server, $workerId) {
Console::success('Starting reload...');
});
$http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) {
Console::success('Reload completed...');
});
Files::load(__DIR__ . '/../console');
include __DIR__ . '/controllers/general.php';
$http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) {
$app = new App('UTC');
$http = new Http(new Server('0.0.0.0', Http::getEnv('PORT', 80), [
'open_http2_protocol' => true,
'http_compression' => true,
'http_compression_level' => 6,
'package_max_length' => $payloadSize,
'buffer_output_size' => $payloadSize,
]), 'UTC');
go(function () use ($register, $app) {
$pools = $register->get('pools');
/** @var Group $pools */
Http::setResource('pools', fn () => $pools);
$http->setRequestClass(Request::class);
$http->setResponseClass(Response::class);
// wait for database to be ready
$attempts = 0;
$max = 10;
$sleep = 1;
$http->loadFiles(__DIR__ . '/../console');
do {
try {
$attempts++;
$dbForConsole = $app->getResource('dbForConsole');
$dbForConsole->ping();
/** @var Utopia\Database\Database $dbForConsole */
break; // leave the do-while if successful
} catch (\Throwable $e) {
Console::warning("Database not ready. Retrying connection ({$attempts})...");
if ($attempts >= $max) {
throw new \Exception('Failed to connect to database: ' . $e->getMessage());
}
sleep($sleep);
}
} while ($attempts < $max);
go(function () use ($register, $http, $payloadSize) {
$pools = $register->get('pools');
/** @var Group $pools */
Http::setResource('pools', fn () => $pools);
$auth = new Authorization();
Console::success('[Setup] - Server database init started...');
// wait for database to be ready
$attempts = 0;
$max = 10;
$sleep = 1;
do {
try {
Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create();
$attempts++;
$dbForConsole = $http->getResource('dbForConsole');
$dbForConsole->ping();
/** @var Utopia\Database\Database $dbForConsole */
break; // leave the do-while if successful
} catch (\Throwable $e) {
Console::success('[Setup] - Skip: metadata table already exists');
Console::warning("Database not ready. Retrying connection ({$attempts})...");
if ($attempts >= $max) {
throw new \Exception('Failed to connect to database: ' . $e->getMessage());
}
sleep($sleep);
}
} while ($attempts < $max);
Console::success('[Setup] - Server database init started...');
try {
Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create();
} catch (\Throwable $e) {
Console::success('[Setup] - Skip: metadata table already exists');
}
if ($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) {
$audit = new Audit($dbForConsole, $auth);
$audit->setup();
}
if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $dbForConsole, $auth);
$adapter->setup();
}
/** @var array $collections */
$collections = Config::getParam('collections', []);
$consoleCollections = $collections['console'];
foreach ($consoleCollections as $key => $collection) {
if (($collection['$collection'] ?? '') !== Database::METADATA) {
continue;
}
if (!$dbForConsole->getCollection($key)->isEmpty()) {
continue;
}
if ($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) {
$audit = new Audit($dbForConsole);
$audit->setup();
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');
$attributes = [];
$indexes = [];
foreach ($collection['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => ID::custom($attribute['$id']),
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
'default' => $attribute['default'] ?? null,
'format' => $attribute['format'] ?? ''
]);
}
if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $dbForConsole);
$adapter->setup();
foreach ($collection['indexes'] as $index) {
$indexes[] = new Document([
'$id' => ID::custom($index['$id']),
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
/** @var array $collections */
$collections = Config::getParam('collections', []);
$consoleCollections = $collections['console'];
foreach ($consoleCollections as $key => $collection) {
if (($collection['$collection'] ?? '') !== Database::METADATA) {
continue;
}
if (!$dbForConsole->getCollection($key)->isEmpty()) {
continue;
}
$dbForConsole->createCollection($key, $attributes, $indexes);
}
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');
if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) {
Console::success('[Setup] - Creating default bucket...');
$dbForConsole->createDocument('buckets', new Document([
'$id' => ID::custom('default'),
'$collection' => ID::custom('buckets'),
'name' => 'Default',
'maximumFileSize' => (int) Http::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB
'allowedFileExtensions' => [],
'enabled' => true,
'compression' => 'gzip',
'encryption' => true,
'antivirus' => true,
'fileSecurity' => true,
'$permissions' => [
Permission::create(Role::any()),
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'search' => 'buckets Default',
]));
$attributes = [];
$indexes = [];
$bucket = $dbForConsole->getDocument('buckets', 'default');
foreach ($collection['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => ID::custom($attribute['$id']),
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
'default' => $attribute['default'] ?? null,
'format' => $attribute['format'] ?? ''
]);
}
foreach ($collection['indexes'] as $index) {
$indexes[] = new Document([
'$id' => ID::custom($index['$id']),
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
$dbForConsole->createCollection($key, $attributes, $indexes);
Console::success('[Setup] - Creating files collection for default bucket...');
$files = $collections['buckets']['files'] ?? [];
if (empty($files)) {
throw new Exception('Files collection is not configured.');
}
if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) {
Console::success('[Setup] - Creating default bucket...');
$dbForConsole->createDocument('buckets', new Document([
'$id' => ID::custom('default'),
'$collection' => ID::custom('buckets'),
'name' => 'Default',
'maximumFileSize' => (int) Http::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB
'allowedFileExtensions' => [],
'enabled' => true,
'compression' => 'gzip',
'encryption' => true,
'antivirus' => true,
'fileSecurity' => true,
'$permissions' => [
Permission::create(Role::any()),
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'search' => 'buckets Default',
]));
$attributes = [];
$indexes = [];
$bucket = $dbForConsole->getDocument('buckets', 'default');
Console::success('[Setup] - Creating files collection for default bucket...');
$files = $collections['buckets']['files'] ?? [];
if (empty($files)) {
throw new Exception('Files collection is not configured.');
}
$attributes = [];
$indexes = [];
foreach ($files['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => ID::custom($attribute['$id']),
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
'default' => $attribute['default'] ?? null,
'format' => $attribute['format'] ?? ''
]);
}
foreach ($files['indexes'] as $index) {
$indexes[] = new Document([
'$id' => ID::custom($index['$id']),
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
$dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes);
foreach ($files['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => ID::custom($attribute['$id']),
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
'default' => $attribute['default'] ?? null,
'format' => $attribute['format'] ?? ''
]);
}
$pools->reclaim();
foreach ($files['indexes'] as $index) {
$indexes[] = new Document([
'$id' => ID::custom($index['$id']),
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
Console::success('[Setup] - Server database init completed...');
});
$dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes);
}
$pools->reclaim();
Console::success('[Setup] - Server database init completed...');
Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)');
Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}");
// listen ctrl + c
Process::signal(2, function () use ($http) {
Console::log('Stop by Ctrl+C');
$http->shutdown();
});
Http::init()
->inject('auth')
->action(function (Authorization $auth) {
$auth->cleanRoles();
$auth->addRole(Role::any()->toString());
});
$http->start();
});
$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) {
Http::setResource('swooleRequest', fn () => $swooleRequest);
Http::setResource('swooleResponse', fn () => $swooleResponse);
$request = new Request($swooleRequest);
$response = new Response($swooleResponse);
if (Files::isFileLoaded($request->getURI())) {
$time = (60 * 60 * 24 * 365 * 2); // 45 days cache
$response
->setContentType(Files::getFileMimeType($request->getURI()))
->addHeader('Cache-Control', 'public, max-age=' . $time)
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache
->send(Files::getFileContents($request->getURI()));
return;
}
$app = new App('UTC');
$pools = $register->get('pools');
Http::setResource('pools', fn () => $pools);
try {
$auth->cleanRoles();
$auth->addRole(Role::any()->toString());
$app->run($request, $response);
} catch (\Throwable $th) {
$version = Http::getEnv('_APP_VERSION', 'UNKNOWN');
$logger = $app->getResource("logger");
if ($logger) {
try {
/** @var Utopia\Database\Document $user */
$user = $app->getResource('user');
} catch (\Throwable $_th) {
// All good, user is optional information for logger
}
$route = $app->getRoute();
$log = $app->getResource("log");
if (isset($user) && !$user->isEmpty()) {
$log->setUser(new User($user->getId()));
}
$log->setNamespace("http");
$log->setServer(\gethostname());
$log->setVersion($version);
$log->setType(Log::TYPE_ERROR);
$log->setMessage($th->getMessage());
$log->addTag('method', $route->getMethod());
$log->addTag('url', $route->getPath());
$log->addTag('verboseType', get_class($th));
$log->addTag('code', $th->getCode());
// $log->addTag('projectId', $project->getId()); // TODO: Figure out how to get ProjectID, if it becomes relevant
$log->addTag('hostname', $request->getHostname());
$log->addTag('locale', (string)$request->getParam('locale', $request->getHeader('x-appwrite-locale', '')));
$log->addExtra('file', $th->getFile());
$log->addExtra('line', $th->getLine());
$log->addExtra('trace', $th->getTraceAsString());
$log->addExtra('detailedTrace', $th->getTrace());
$log->addExtra('roles', $auth->getRoles());
$action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD");
$log->setAction($action);
$isProduction = Http::getEnv('_APP_ENV', 'development') === 'production';
$log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING);
$responseCode = $logger->addLog($log);
Console::info('Log pushed with status code: ' . $responseCode);
}
Console::error('[Error] Type: ' . get_class($th));
Console::error('[Error] Message: ' . $th->getMessage());
Console::error('[Error] File: ' . $th->getFile());
Console::error('[Error] Line: ' . $th->getLine());
$swooleResponse->setStatusCode(500);
$output = ((Http::isDevelopment())) ? [
'message' => 'Error: ' . $th->getMessage(),
'code' => 500,
'file' => $th->getFile(),
'line' => $th->getLine(),
'trace' => $th->getTrace(),
'version' => $version,
] : [
'message' => 'Error: Server Error',
'code' => 500,
'version' => $version,
];
$swooleResponse->end(\json_encode($output));
} finally {
$pools->reclaim();
}
});
$http->start();

View file

@ -43,7 +43,6 @@ use Appwrite\URL\URL as AppwriteURL;
use MaxMind\Db\Reader;
use PHPMailer\PHPMailer\PHPMailer;
use Swoole\Database\PDOProxy;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
@ -62,8 +61,14 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Structure;
use Utopia\Domains\Validator\PublicDomain;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Http\Request;
use Utopia\Http\Response;
use Utopia\Http\Validator\Hostname;
use Utopia\Http\Validator\IP;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
use Utopia\Logger\Logger;
@ -80,11 +85,6 @@ use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\Wasabi;
use Utopia\Storage\Storage;
use Utopia\Http\Validator\Hostname;
use Utopia\Http\Validator\IP;
use Utopia\Http\Validator\Range;
use Utopia\Http\Validator\URL;
use Utopia\Http\Validator\WhiteList;
use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub;
const APP_NAME = 'Appwrite';
@ -1307,7 +1307,7 @@ Http::setResource('console', function () {
]);
}, []);
Http::setResource('dbForProject', function (Group $pools, Database $dbForConsole, Cache $cache, Document $project) {
Http::setResource('dbForProject', function (Group $pools, Database $dbForConsole, Cache $cache, Document $project, Authorization $auth) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForConsole;
}
@ -1318,6 +1318,7 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForConsole
->getResource();
$database = new Database($dbAdapter, $cache);
$database->setAuthorization($auth);
$database
->setNamespace('_' . $project->getInternalId())
@ -1326,9 +1327,9 @@ Http::setResource('dbForProject', function (Group $pools, Database $dbForConsole
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS);
return $database;
}, ['pools', 'dbForConsole', 'cache', 'project']);
}, ['pools', 'dbForConsole', 'cache', 'project', 'auth']);
Http::setResource('dbForConsole', function (Group $pools, Cache $cache) {
Http::setResource('dbForConsole', function (Group $pools, Cache $cache, Authorization $auth) {
$dbAdapter = $pools
->get('console')
->pop()
@ -1336,6 +1337,7 @@ Http::setResource('dbForConsole', function (Group $pools, Cache $cache) {
;
$database = new Database($dbAdapter, $cache);
$database->setAuthorization($auth);
$database
->setNamespace('_console')
@ -1344,12 +1346,12 @@ Http::setResource('dbForConsole', function (Group $pools, Cache $cache) {
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS);
return $database;
}, ['pools', 'cache']);
}, ['pools', 'cache', 'auth']);
Http::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) {
Http::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache, Authorization $auth) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
$getProjectDB = function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) {
$getProjectDB = function (Document $project) use ($pools, $dbForConsole, $cache, &$databases, $auth) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForConsole;
}
@ -1374,6 +1376,7 @@ Http::setResource('getProjectDB', function (Group $pools, Database $dbForConsole
->getResource();
$database = new Database($dbAdapter, $cache);
$database->setAuthorization($auth);
$databases[$databaseName] = $database;
@ -1387,7 +1390,7 @@ Http::setResource('getProjectDB', function (Group $pools, Database $dbForConsole
};
return $getProjectDB;
}, ['pools', 'dbForConsole', 'cache']);
}, ['pools', 'dbForConsole', 'cache', 'auth']);
Http::setResource('cache', function (Group $pools) {
$list = Config::getParam('pools-cache', []);
@ -1661,4 +1664,8 @@ Http::setResource('requestTimestamp', function ($request) {
return $requestTimestamp;
}, ['request']);
Http::setResource('auth', fn () => new Authorization());
Http::setResource('auth', fn () => new Authorization());
Http::setResource('pools', function ($register) {
return $register->get('pools');
}, ['pools']);

View file

@ -13,7 +13,6 @@ use Swoole\Table;
use Swoole\Timer;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
@ -26,6 +25,7 @@ use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Adapter\FPM\Server as FPMServer;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\WebSocket\Adapter;
use Utopia\WebSocket\Server;
@ -37,7 +37,7 @@ require_once __DIR__ . '/init.php';
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
function getConsoleDB(): Database
function getConsoleDB(Authorization $auth): Database
{
global $register;
@ -51,6 +51,7 @@ function getConsoleDB(): Database
;
$database = new Database($dbAdapter, getCache());
$database->setAuthorization($auth);
$database
->setNamespace('_console')
@ -60,7 +61,7 @@ function getConsoleDB(): Database
return $database;
}
function getProjectDB(Document $project): Database
function getProjectDB(Document $project, Authorization $auth): Database
{
global $register;
@ -68,7 +69,7 @@ function getProjectDB(Document $project): Database
$pools = $register->get('pools');
if ($project->isEmpty() || $project->getId() === 'console') {
return getConsoleDB();
return getConsoleDB($auth);
}
$dbAdapter = $pools
@ -78,6 +79,7 @@ function getProjectDB(Document $project): Database
;
$database = new Database($dbAdapter, getCache());
$database->setAuthorization($auth);
$database
->setNamespace('_' . $project->getInternalId())
@ -170,15 +172,17 @@ $logError = function (Throwable $error, string $action) use ($register) {
$server->error($logError);
$server->onStart(function () use ($stats, $register, $containerId, &$statsDocument, $logError) {
$auth = new Authorization();
sleep(5); // wait for the initial database schema to be ready
Console::success('Server started successfully');
/**
* Create document for this worker to share stats across Containers.
*/
go(function () use ($register, $containerId, &$statsDocument) {
go(function () use ($register, $containerId, &$statsDocument, $auth) {
$attempts = 0;
$database = getConsoleDB();
$database = getConsoleDB($auth);
do {
try {
@ -206,7 +210,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
/**
* Save current connections to the Database every 5 seconds.
*/
Timer::tick(5000, function () use ($register, $stats, &$statsDocument, $logError) {
Timer::tick(5000, function () use ($register, $stats, &$statsDocument, $logError, $auth) {
$payload = [];
foreach ($stats as $projectId => $value) {
$payload[$projectId] = $stats->get($projectId, 'connectionsTotal');
@ -216,7 +220,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume
}
try {
$database = getConsoleDB();
$database = getConsoleDB($auth);
$statsDocument
->setAttribute('timestamp', DateTime::now())
@ -238,16 +242,17 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
$attempts = 0;
$start = time();
Timer::tick(5000, function () use ($server, $register, $realtime, $stats, $logError) {
$auth = new Authorization();
Timer::tick(5000, function () use ($server, $register, $realtime, $stats, $logError, $auth) {
/**
* Sending current connections to project channels on the console project every 5 seconds.
*/
if ($realtime->hasSubscriber('console', Role::users()->toString(), 'project')) {
$database = getConsoleDB();
$database = getConsoleDB($auth);
$payload = [];
$auth = new Authorization();
$list = $auth->skip(fn () => $database->find('realtime', [
Query::greaterThan('timestamp', DateTime::addSeconds(new \DateTime(), -15)),
]));
@ -334,7 +339,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
Console::error('Pub/sub failed (worker: ' . $workerId . ')');
}
$redis->subscribe(['realtime'], function (Redis $redis, string $channel, string $payload) use ($server, $workerId, $stats, $register, $realtime) {
$redis->subscribe(['realtime'], function (Redis $redis, string $channel, string $payload) use ($server, $workerId, $stats, $register, $realtime, $auth) {
$event = json_decode($payload, true);
if ($event['permissionsChanged'] && isset($event['userId'])) {
@ -343,10 +348,10 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) {
$connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId]));
$consoleDatabase = getConsoleDB();
$consoleDatabase = getConsoleDB($auth);
$auth = new Authorization();
$project = $auth->skip(fn () => $consoleDatabase->getDocument('projects', $projectId));
$database = getProjectDB($project);
$database = getProjectDB($project, $auth);
$user = $database->getDocument('users', $userId);
@ -394,7 +399,9 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
});
$server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $register, $stats, &$realtime, $logError) {
$app = new Http(new FPMServer(), 'UTC');
$auth = new Authorization();
$http = new Http(new FPMServer(), 'UTC');
$request = new Request($request);
$response = new Response(new SwooleResponse());
@ -406,7 +413,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
try {
/** @var Document $project */
$project = $app->getResource('project');
$project = $http->getResource('project');
/*
* Project Check
@ -415,21 +422,22 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, 'Missing or unknown project ID');
}
$dbForProject = getProjectDB($project);
$console = $app->getResource('console'); /** @var Document $console */
$user = $app->getResource('user'); /** @var Document $user */
$dbForProject = getProjectDB($project, $auth);
$console = $http->getResource('console'); /** @var Document $console */
$user = $http->getResource('user'); /** @var Document $user */
$auth = new Authorization();
/*
* Abuse Check
*
* Abuse limits are connecting 128 times per minute and ip address.
*/
$timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject);
$timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject, $auth);
$timeLimit
->setParam('{ip}', $request->getIP())
->setParam('{url}', $request->getURI());
$abuse = new Abuse($timeLimit);
$abuse = new Abuse($timeLimit, $auth);
if (Http::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) {
throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests');
@ -502,15 +510,17 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
});
$server->onMessage(function (int $connection, string $message) use ($server, $register, $realtime, $containerId) {
$auth = new Authorization();
try {
$response = new Response(new SwooleResponse());
$projectId = $realtime->connections[$connection]['projectId'];
$database = getConsoleDB();
$database = getConsoleDB($auth);
if ($projectId !== 'console') {
$auth = new Authorization();
$project = $auth->skip(fn () => $database->getDocument('projects', $projectId));
$database = getProjectDB($project);
$database = getProjectDB($project, $auth);
} else {
$project = null;
}
@ -520,13 +530,13 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
*
* Abuse limits are sending 32 times per minute and connection.
*/
$timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database);
$timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database, $auth);
$timeLimit
->setParam('{connection}', $connection)
->setParam('{container}', $containerId);
$abuse = new Abuse($timeLimit);
$abuse = new Abuse($timeLimit, $auth);
if ($abuse->check() && Http::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many messages.');

View file

@ -17,7 +17,6 @@ use Appwrite\Event\Usage;
use Appwrite\Event\UsageDump;
use Appwrite\Platform\Appwrite;
use Swoole\Runtime;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
@ -26,6 +25,7 @@ use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Logger\Logger;
use Utopia\Platform\Service;
@ -38,12 +38,11 @@ use Utopia\Storage\Device\Local;
global $register;
$auth->disable();
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
Server::setResource('register', fn () => $register);
Server::setResource('dbForConsole', function (Cache $cache, Registry $register) {
Server::setResource('dbForConsole', function (Cache $cache, Registry $register, Authorization $auth) {
$pools = $register->get('pools');
$database = $pools
->get('console')
@ -51,10 +50,11 @@ Server::setResource('dbForConsole', function (Cache $cache, Registry $register)
->getResource();
$adapter = new Database($database, $cache);
$adapter->setAuthorization($auth);
$adapter->setNamespace('_console');
return $adapter;
}, ['cache', 'register']);
}, ['cache', 'register', 'auth']);
Server::setResource('project', function (Message $message, Database $dbForConsole) {
$payload = $message->getPayload() ?? [];
@ -67,7 +67,7 @@ Server::setResource('project', function (Message $message, Database $dbForConsol
return $dbForConsole->getDocument('projects', $project->getId());
}, ['message', 'dbForConsole']);
Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForConsole) {
Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForConsole, Authorization $auth) {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForConsole;
}
@ -79,14 +79,15 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
->getResource();
$adapter = new Database($database, $cache);
$adapter->setAuthorization($auth);
$adapter->setNamespace('_' . $project->getInternalId());
return $adapter;
}, ['cache', 'register', 'message', 'project', 'dbForConsole']);
}, ['cache', 'register', 'message', 'project', 'dbForConsole', 'auth']);
Server::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) {
Server::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache, Authorization $auth) {
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases): Database {
return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases, $auth): Database {
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForConsole;
}
@ -105,6 +106,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
->getResource();
$database = new Database($dbAdapter, $cache);
$database->setAuthorization($auth);
$databases[$databaseName] = $database;
@ -112,7 +114,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
return $database;
};
}, ['pools', 'dbForConsole', 'cache']);
}, ['pools', 'dbForConsole', 'cache', 'auth']);
Server::setResource('abuseRetention', function () {
return DateTime::addSeconds(new \DateTime(), -1 * Http::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400));
@ -228,7 +230,7 @@ Server::setResource('deviceForLocalFiles', function (Document $project) {
return new Local(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
}, ['project']);
Server::setResource('authorization', fn () => new Authorization());
Server::setResource('auth', fn () => new Authorization());
$pools = $register->get('pools');
$platform = new Appwrite();
@ -272,6 +274,13 @@ try {
$worker = $platform->getWorker();
$worker
->init()
->inject('auth')
->action(function (Authorization $auth) {
$auth->disable();
});
$worker
->shutdown()
->inject('pools')

View file

@ -45,16 +45,16 @@
"ext-sockets": "*",
"appwrite/php-runtimes": "0.13.*",
"appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "0.37.*",
"utopia-php/abuse": "dev-feat-framework-v2 as 0.37.99",
"utopia-php/analytics": "dev-feat-framework-v2 as 0.10.99",
"utopia-php/audit": "0.39.*",
"utopia-php/audit": "dev-feat-framework-v2 as 0.39.99",
"utopia-php/cache": "0.9.*",
"utopia-php/cli": "0.17.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "dev-feat-framework-v2 as 0.49.99",
"utopia-php/domains": "0.5.*",
"utopia-php/domains": "dev-feat-framework-v2 as 0.5.99",
"utopia-php/dsn": "0.2.*",
"utopia-php/framework": "0.34.*",
"utopia-php/framework": "dev-feat-framework-v2 as 0.34.99",
"utopia-php/image": "0.6.*",
"utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.3.*",
@ -66,7 +66,7 @@
"utopia-php/view": "0.1.*",
"utopia-php/queue": "dev-feat-framework-v2-v2 as 0.7.99",
"utopia-php/registry": "0.5.*",
"utopia-php/storage": "0.18.*",
"utopia-php/storage": "dev-feat-framework-v2-v2 as 0.18.99",
"utopia-php/vcs": "0.6.*",
"utopia-php/websocket": "0.1.*",
"matomo/device-detector": "6.1.*",

176
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": "98a533604587b5d0f5cc3c52ae177aeb",
"content-hash": "750df68fe066fde9554f4d1ba4a9afb5",
"packages": [
{
"name": "adhocore/jwt",
@ -482,16 +482,16 @@
},
{
"name": "jean85/pretty-package-versions",
"version": "2.0.5",
"version": "2.0.6",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af"
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af",
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4",
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4",
"shasum": ""
},
"require": {
@ -499,9 +499,9 @@
"php": "^7.1|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.17",
"friendsofphp/php-cs-fixer": "^3.2",
"jean85/composer-provided-replaced-stub-package": "^1.0",
"phpstan/phpstan": "^0.12.66",
"phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^7.5|^8.5|^9.4",
"vimeo/psalm": "^4.3"
},
@ -535,9 +535,9 @@
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5"
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6"
},
"time": "2021-10-08T21:21:46+00:00"
"time": "2024-03-08T09:58:59+00:00"
},
{
"name": "league/csv",
@ -771,11 +771,54 @@
"version": "0.6.3",
"source": {
"type": "git",
"url": "https://github.com/mustangostang/spyc",
"url": "https://github.com/mustangostang/spyc.git",
"reference": "4627c838b16550b666d15aeae1e5289dd5b77da0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0",
"reference": "4627c838b16550b666d15aeae1e5289dd5b77da0",
"shasum": ""
},
"require": {
"php": ">=5.3.1"
},
"require-dev": {
"phpunit/phpunit": "4.3.*@dev"
},
"type": "library",
"notification-url": "https://packagist.org/downloads/"
"extra": {
"branch-alias": {
"dev-master": "0.5.x-dev"
}
},
"autoload": {
"files": [
"Spyc.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "mustangostang",
"email": "vlad.andersen@gmail.com"
}
],
"description": "A simple YAML loader/dumper class for PHP",
"homepage": "https://github.com/mustangostang/spyc/",
"keywords": [
"spyc",
"yaml",
"yml"
],
"support": {
"issues": "https://github.com/mustangostang/spyc/issues",
"source": "https://github.com/mustangostang/spyc/tree/0.6.3"
},
"time": "2019-09-10T13:16:29+00:00"
},
{
"name": "paragonie/constant_time_encoding",
@ -1221,23 +1264,23 @@
},
{
"name": "utopia-php/abuse",
"version": "0.37.0",
"version": "dev-feat-framework-v2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "2de5c12886cbd516e511e559afdd9e615d871062"
"reference": "55b34b581c957fc98f912943d94dcdc7079f191e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/2de5c12886cbd516e511e559afdd9e615d871062",
"reference": "2de5c12886cbd516e511e559afdd9e615d871062",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/55b34b581c957fc98f912943d94dcdc7079f191e",
"reference": "55b34b581c957fc98f912943d94dcdc7079f191e",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.49.*"
"utopia-php/database": "dev-feat-framework-v2 as 0.49.99"
},
"require-dev": {
"laravel/pint": "1.5.*",
@ -1264,9 +1307,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.37.0"
"source": "https://github.com/utopia-php/abuse/tree/feat-framework-v2"
},
"time": "2024-03-06T21:20:27+00:00"
"time": "2024-03-08T11:27:58+00:00"
},
{
"name": "utopia-php/analytics",
@ -1316,21 +1359,21 @@
},
{
"name": "utopia-php/audit",
"version": "0.39.0",
"version": "dev-feat-framework-v2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "f0bc15012e05cc0b9dde012ab27d25f193768a2c"
"reference": "59f88d71f9d93603393aeda368a975b10b8ddb17"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/f0bc15012e05cc0b9dde012ab27d25f193768a2c",
"reference": "f0bc15012e05cc0b9dde012ab27d25f193768a2c",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/59f88d71f9d93603393aeda368a975b10b8ddb17",
"reference": "59f88d71f9d93603393aeda368a975b10b8ddb17",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "0.49.*"
"utopia-php/database": "dev-feat-framework-v2 as 0.49.99"
},
"require-dev": {
"laravel/pint": "1.5.*",
@ -1357,9 +1400,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.39.0"
"source": "https://github.com/utopia-php/audit/tree/feat-framework-v2"
},
"time": "2024-03-06T21:20:37+00:00"
"time": "2024-03-08T11:29:31+00:00"
},
{
"name": "utopia-php/cache",
@ -1570,21 +1613,21 @@
},
{
"name": "utopia-php/domains",
"version": "0.5.0",
"version": "dev-feat-framework-v2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/domains.git",
"reference": "bf07f60326f8389f378ddf6fcde86217e5cfe18c"
"reference": "4e7055f0aaba0c16ae60c972faefb9189fa0db1c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/bf07f60326f8389f378ddf6fcde86217e5cfe18c",
"reference": "bf07f60326f8389f378ddf6fcde86217e5cfe18c",
"url": "https://api.github.com/repos/utopia-php/domains/zipball/4e7055f0aaba0c16ae60c972faefb9189fa0db1c",
"reference": "4e7055f0aaba0c16ae60c972faefb9189fa0db1c",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/framework": "0.*.*"
"utopia-php/framework": "0.34.*"
},
"require-dev": {
"laravel/pint": "1.2.*",
@ -1624,9 +1667,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/domains/issues",
"source": "https://github.com/utopia-php/domains/tree/0.5.0"
"source": "https://github.com/utopia-php/domains/tree/feat-framework-v2"
},
"time": "2024-01-03T22:04:27+00:00"
"time": "2024-03-08T09:24:35+00:00"
},
{
"name": "utopia-php/dsn",
@ -1716,16 +1759,16 @@
},
{
"name": "utopia-php/framework",
"version": "0.34.2",
"version": "dev-feat-framework-v2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/http.git",
"reference": "fd126c02b78cc80678c9638f7b335dfb4a841b78"
"reference": "e2e7498aa16cefcdcb474548c3d04ce720ec6430"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/http/zipball/fd126c02b78cc80678c9638f7b335dfb4a841b78",
"reference": "fd126c02b78cc80678c9638f7b335dfb4a841b78",
"url": "https://api.github.com/repos/utopia-php/http/zipball/e2e7498aa16cefcdcb474548c3d04ce720ec6430",
"reference": "e2e7498aa16cefcdcb474548c3d04ce720ec6430",
"shasum": ""
},
"require": {
@ -1758,9 +1801,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/http/issues",
"source": "https://github.com/utopia-php/http/tree/0.34.2"
"source": "https://github.com/utopia-php/http/tree/feat-framework-v2"
},
"time": "2024-02-20T11:36:56+00:00"
"time": "2024-03-08T10:38:48+00:00"
},
{
"name": "utopia-php/image",
@ -2229,12 +2272,12 @@
"source": {
"type": "git",
"url": "https://github.com/utopia-php/queue.git",
"reference": "e613ccc1d4da4219b60576ddfe79dadb182bb74e"
"reference": "0e9ba1b32169d64a78909fd77891db4d64344a63"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/queue/zipball/e613ccc1d4da4219b60576ddfe79dadb182bb74e",
"reference": "e613ccc1d4da4219b60576ddfe79dadb182bb74e",
"url": "https://api.github.com/repos/utopia-php/queue/zipball/0e9ba1b32169d64a78909fd77891db4d64344a63",
"reference": "0e9ba1b32169d64a78909fd77891db4d64344a63",
"shasum": ""
},
"require": {
@ -2282,7 +2325,7 @@
"issues": "https://github.com/utopia-php/queue/issues",
"source": "https://github.com/utopia-php/queue/tree/feat-framework-v2-v2"
},
"time": "2024-03-07T15:43:35+00:00"
"time": "2024-03-08T09:29:41+00:00"
},
{
"name": "utopia-php/registry",
@ -2338,16 +2381,16 @@
},
{
"name": "utopia-php/storage",
"version": "0.18.3",
"version": "dev-feat-framework-v2-v2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "faa0279519ac14f3501e8b138e0865ad9d12bff6"
"reference": "80eafa63cb86b33ce35d48c0189bae6ebdc02734"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/faa0279519ac14f3501e8b138e0865ad9d12bff6",
"reference": "faa0279519ac14f3501e8b138e0865ad9d12bff6",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/80eafa63cb86b33ce35d48c0189bae6ebdc02734",
"reference": "80eafa63cb86b33ce35d48c0189bae6ebdc02734",
"shasum": ""
},
"require": {
@ -2359,7 +2402,7 @@
"ext-zlib": "*",
"ext-zstd": "*",
"php": ">=8.0",
"utopia-php/framework": "0.*.*",
"utopia-php/framework": "0.34.*",
"utopia-php/system": "0.*.*"
},
"require-dev": {
@ -2387,9 +2430,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/0.18.3"
"source": "https://github.com/utopia-php/storage/tree/feat-framework-v2-v2"
},
"time": "2023-12-31T11:45:12+00:00"
"time": "2024-03-08T09:39:46+00:00"
},
{
"name": "utopia-php/system",
@ -5458,18 +5501,42 @@
}
],
"aliases": [
{
"package": "utopia-php/abuse",
"version": "dev-feat-framework-v2",
"alias": "0.37.99",
"alias_normalized": "0.37.99.0"
},
{
"package": "utopia-php/analytics",
"version": "dev-feat-framework-v2",
"alias": "0.10.99",
"alias_normalized": "0.10.99.0"
},
{
"package": "utopia-php/audit",
"version": "dev-feat-framework-v2",
"alias": "0.39.99",
"alias_normalized": "0.39.99.0"
},
{
"package": "utopia-php/database",
"version": "dev-feat-framework-v2",
"alias": "0.49.99",
"alias_normalized": "0.49.99.0"
},
{
"package": "utopia-php/domains",
"version": "dev-feat-framework-v2",
"alias": "0.5.99",
"alias_normalized": "0.5.99.0"
},
{
"package": "utopia-php/framework",
"version": "dev-feat-framework-v2",
"alias": "0.34.99",
"alias_normalized": "0.34.99.0"
},
{
"package": "utopia-php/orchestration",
"version": "dev-feat-framework-v2",
@ -5487,15 +5554,26 @@
"version": "dev-feat-framework-v2-v2",
"alias": "0.7.99",
"alias_normalized": "0.7.99.0"
},
{
"package": "utopia-php/storage",
"version": "dev-feat-framework-v2-v2",
"alias": "0.18.99",
"alias_normalized": "0.18.99.0"
}
],
"minimum-stability": "stable",
"stability-flags": {
"utopia-php/abuse": 20,
"utopia-php/analytics": 20,
"utopia-php/audit": 20,
"utopia-php/database": 20,
"utopia-php/domains": 20,
"utopia-php/framework": 20,
"utopia-php/orchestration": 20,
"utopia-php/platform": 20,
"utopia-php/queue": 20,
"utopia-php/storage": 20,
"appwrite/sdk-generator": 5
},
"prefer-stable": false,

View file

@ -6,8 +6,8 @@ use Appwrite\GraphQL\Exception as GQLException;
use Appwrite\Promises\Swoole;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\Http\Http;
use Utopia\Exception;
use Utopia\Http\Http;
use Utopia\Http\Route;
class Resolvers
@ -15,7 +15,7 @@ class Resolvers
/**
* Create a resolver for a given API {@see Route}.
*
* @param App $utopia
* @param Http $utopia
* @param ?Route $route
* @return callable
*/
@ -25,7 +25,7 @@ class Resolvers
): callable {
return static fn ($type, $args, $context, $info) => new Swoole(
function (callable $resolve, callable $reject) use ($utopia, $route, $args, $context, $info) {
/** @var App $utopia */
/** @var Http $utopia */
/** @var Response $response */
/** @var Request $request */
@ -60,7 +60,7 @@ class Resolvers
/**
* Create a resolver for a document in a specified database and collection with a specific method type.
*
* @param App $utopia
* @param Http $utopia
* @param string $databaseId
* @param string $collectionId
* @param string $methodType
@ -82,7 +82,7 @@ class Resolvers
/**
* Create a resolver for getting a document in a specified database and collection.
*
* @param App $utopia
* @param Http $utopia
* @param string $databaseId
* @param string $collectionId
* @param callable $url
@ -111,7 +111,7 @@ class Resolvers
/**
* Create a resolver for listing documents in a specified database and collection.
*
* @param App $utopia
* @param Http $utopia
* @param string $databaseId
* @param string $collectionId
* @param callable $url
@ -147,7 +147,7 @@ class Resolvers
/**
* Create a resolver for creating a document in a specified database and collection.
*
* @param App $utopia
* @param Http $utopia
* @param string $databaseId
* @param string $collectionId
* @param callable $url
@ -179,7 +179,7 @@ class Resolvers
/**
* Create a resolver for updating a document in a specified database and collection.
*
* @param App $utopia
* @param Http $utopia
* @param string $databaseId
* @param string $collectionId
* @param callable $url
@ -211,7 +211,7 @@ class Resolvers
/**
* Create a resolver for deleting a document in a specified database and collection.
*
* @param App $utopia
* @param Http $utopia
* @param string $databaseId
* @param string $collectionId
* @param callable $url
@ -238,7 +238,7 @@ class Resolvers
}
/**
* @param App $utopia
* @param Http $utopia
* @param Request $request
* @param Response $response
* @param callable $resolve

View file

@ -6,8 +6,8 @@ use Appwrite\GraphQL\Types\Mapper;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema as GQLSchema;
use Utopia\Http\Http;
use Utopia\Exception;
use Utopia\Http\Http;
use Utopia\Http\Route;
class Schema
@ -17,7 +17,7 @@ class Schema
/**
*
* @param App $utopia
* @param Http $utopia
* @param callable $complexity Function to calculate complexity
* @param callable $attributes Function to get attributes
* @param array $urls Array of functions to get urls for specific method types
@ -80,7 +80,7 @@ class Schema
* This function iterates all API routes and builds a GraphQL
* schema defining types and resolvers for all response models.
*
* @param App $utopia
* @param Http $utopia
* @param callable $complexity
* @return array
* @throws Exception
@ -134,7 +134,7 @@ class Schema
* Iterates all of a projects attributes and builds GraphQL
* queries and mutations for the collections they make up.
*
* @param App $utopia
* @param Http $utopia
* @param callable $complexity
* @param callable $attributes
* @param array $urls

View file

@ -205,7 +205,7 @@ class Mapper
/**
* Map a {@see Route} parameter to a GraphQL Type
*
* @param App $utopia
* @param Http $utopia
* @param Validator|callable $validator
* @param bool $required
* @param array $injections

View file

@ -3,11 +3,11 @@
namespace Appwrite\Messaging\Adapter;
use Appwrite\Messaging\Adapter;
use Utopia\Http\Http;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Role;
use Utopia\Http\Http;
class Realtime extends Adapter
{

View file

@ -4,7 +4,6 @@ namespace Appwrite\Migration;
use Exception;
use Swoole\Runtime;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -12,6 +11,7 @@ use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);

View file

@ -4,7 +4,6 @@ namespace Appwrite\Migration\Version;
use Appwrite\Migration\Migration;
use Appwrite\OpenSSL\OpenSSL;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -12,6 +11,7 @@ use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Http\Http;
class V15 extends Migration
{

View file

@ -3,7 +3,6 @@
namespace Appwrite\Migration\Version;
use Appwrite\Migration\Migration;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -11,6 +10,7 @@ use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception;
use Utopia\Database\Query;
use Utopia\Http\Http;
class V19 extends Migration
{

View file

@ -4,17 +4,17 @@ namespace Appwrite\Platform\Tasks;
use League\Csv\Writer;
use PHPMailer\PHPMailer\PHPMailer;
use Utopia\Http\Http;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
use Utopia\Pools\Group;
use Utopia\Registry\Registry;
use Utopia\Http\Validator\Text;
class CalcTierStats extends Action
{

View file

@ -8,8 +8,8 @@ use Utopia\Database\Document;
use Utopia\Database\Exception;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Query;
use Utopia\Platform\Action;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
class CreateInfMetric extends Action
{

View file

@ -2,18 +2,19 @@
namespace Appwrite\Platform\Tasks;
use Utopia\Http\Http;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Adapter\FPM\Server;
use Utopia\Http\Http;
use Utopia\Http\Validator\Boolean;
use Utopia\Platform\Action;
use Utopia\Pools\Group;
use Utopia\Registry\Registry;
use Utopia\Http\Validator\Boolean;
class DeleteOrphanedProjects extends Action
{
@ -32,13 +33,14 @@ class DeleteOrphanedProjects extends Action
->inject('cache')
->inject('dbForConsole')
->inject('register')
->callback(function (bool $commit, Group $pools, Cache $cache, Database $dbForConsole, Registry $register) {
$this->action($commit, $pools, $cache, $dbForConsole, $register);
->inject('auth')
->callback(function (bool $commit, Group $pools, Cache $cache, Database $dbForConsole, Registry $register, Authorization $auth) {
$this->action($commit, $pools, $cache, $dbForConsole, $register, $auth);
});
}
public function action(bool $commit, Group $pools, Cache $cache, Database $dbForConsole, Registry $register): void
public function action(bool $commit, Group $pools, Cache $cache, Database $dbForConsole, Registry $register, Authorization $auth): void
{
Console::title('Delete orphaned projects V1');
@ -59,8 +61,8 @@ class DeleteOrphanedProjects extends Action
], $collectionsConfig);
/* Initialise new Utopia app */
$app = new Http(new Server(), 'UTC');
$console = $app->getResource('console');
$http = new Http(new Server(), 'UTC');
$console = $http->getResource('console');
$projects = [$console];
/** Database connections */
@ -91,6 +93,7 @@ class DeleteOrphanedProjects extends Action
->getResource();
$dbForProject = new Database($adapter, $cache);
$dbForProject->setAuthorization($auth);
$dbForProject->setDatabase('appwrite');
$dbForProject->setNamespace('_' . $project->getInternalId());

View file

@ -6,9 +6,9 @@ use Exception;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Fetch\Client;
use Utopia\Platform\Action;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
class DevGenerateTranslations extends Action
{

View file

@ -3,10 +3,10 @@
namespace Appwrite\Platform\Tasks;
use Appwrite\ClamAV\Network;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Domains\Domain;
use Utopia\Http\Http;
use Utopia\Logger\Logger;
use Utopia\Platform\Action;
use Utopia\Registry\Registry;

View file

@ -5,12 +5,14 @@ namespace Appwrite\Platform\Tasks;
use League\Csv\CannotInsertRecord;
use League\Csv\Writer;
use PHPMailer\PHPMailer\PHPMailer;
use Utopia\Http\Http;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\Exception\Authorization;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization as ValidatorAuthorization;
use Utopia\Http\Adapter\FPM\Server;
use Utopia\Http\Http;
use Utopia\Platform\Action;
use Utopia\Pools\Group;
use Utopia\Registry\Registry;
@ -47,8 +49,9 @@ class GetMigrationStats extends Action
->inject('cache')
->inject('dbForConsole')
->inject('register')
->callback(function (Group $pools, Cache $cache, Database $dbForConsole, Registry $register) {
$this->action($pools, $cache, $dbForConsole, $register);
->inject('auth')
->callback(function (Group $pools, Cache $cache, Database $dbForConsole, Registry $register, ValidatorAuthorization $auth) {
$this->action($pools, $cache, $dbForConsole, $register, $auth);
});
}
@ -56,7 +59,7 @@ class GetMigrationStats extends Action
* @throws \Utopia\Exception
* @throws CannotInsertRecord
*/
public function action(Group $pools, Cache $cache, Database $dbForConsole, Registry $register): void
public function action(Group $pools, Cache $cache, Database $dbForConsole, Registry $register, ValidatorAuthorization $auth): void
{
//docker compose exec -t appwrite get-migration-stats
@ -64,8 +67,8 @@ class GetMigrationStats extends Action
Console::success(APP_NAME . ' Migration stats calculation has started');
/* Initialise new Utopia app */
$app = new Http(new Server(), 'UTC');
$console = $app->getResource('console');
$http = new Http(new Server(), 'UTC');
$console = $http->getResource('console');
/** CSV stuff */
$this->date = date('Y-m-d');
@ -102,6 +105,7 @@ class GetMigrationStats extends Action
->getResource();
$dbForProject = new Database($adapter, $cache);
$dbForProject->setAuthorization($auth);
$dbForProject->setDatabase('appwrite');
$dbForProject->setNamespace('_' . $project->getInternalId());

View file

@ -3,11 +3,11 @@
namespace Appwrite\Platform\Tasks;
use Appwrite\Event\Hamster as EventHamster;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Http\Http;
use Utopia\Platform\Action;
class Hamster extends Action

View file

@ -8,9 +8,9 @@ use Appwrite\Docker\Env;
use Appwrite\Utopia\View;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Platform\Action;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
class Install extends Action
{

View file

@ -4,12 +4,12 @@ namespace Appwrite\Platform\Tasks;
use Appwrite\Event\Certificate;
use Appwrite\Event\Delete;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Http\Http;
use Utopia\Platform\Action;
class Maintenance extends Action

View file

@ -3,7 +3,6 @@
namespace Appwrite\Platform\Tasks;
use Appwrite\Migration\Migration;
use Utopia\Http\Http;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Database\Database;
@ -11,9 +10,10 @@ use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Adapter\FPM\Server;
use Utopia\Http\Http;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
use Utopia\Registry\Registry;
use Utopia\Http\Validator\Text;
class Migrate extends Action
{
@ -54,11 +54,11 @@ class Migrate extends Action
return;
}
$app = new Http(new Server(), 'UTC');
$http = new Http(new Server(), 'UTC');
Console::success('Starting Data Migration to version ' . $version);
$console = $app->getResource('console');
$console = $http->getResource('console');
$limit = 30;
$sum = 30;

View file

@ -9,8 +9,8 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Platform\Action;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
class PatchRecreateRepositoriesDocuments extends Action
{

View file

@ -4,10 +4,10 @@ namespace Appwrite\Platform\Tasks;
use Appwrite\Event\Event;
use Utopia\CLI\Console;
use Utopia\Http\Validator\WhiteList;
use Utopia\Platform\Action;
use Utopia\Queue\Client;
use Utopia\Queue\Connection;
use Utopia\Http\Validator\WhiteList;
class QueueCount extends Action
{

View file

@ -4,11 +4,11 @@ namespace Appwrite\Platform\Tasks;
use Appwrite\Event\Event;
use Utopia\CLI\Console;
use Utopia\Http\Validator\WhiteList;
use Utopia\Http\Validator\Wildcard;
use Utopia\Platform\Action;
use Utopia\Queue\Client;
use Utopia\Queue\Connection;
use Utopia\Http\Validator\WhiteList;
use Utopia\Http\Validator\Wildcard;
class QueueRetry extends Action
{

View file

@ -3,12 +3,12 @@
namespace Appwrite\Platform\Tasks;
use Appwrite\Event\Certificate;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\Document;
use Utopia\Platform\Action;
use Utopia\Http\Http;
use Utopia\Http\Validator\Boolean;
use Utopia\Http\Validator\Hostname;
use Utopia\Platform\Action;
class SSL extends Action
{

View file

@ -3,13 +3,13 @@
namespace Appwrite\Platform\Tasks;
use Swoole\Timer;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception;
use Utopia\Database\Query;
use Utopia\Http\Http;
use Utopia\Platform\Action;
use Utopia\Pools\Group;

View file

@ -9,7 +9,6 @@ use Appwrite\Utopia\Response;
use Exception;
use Swoole\Http\Request;
use Swoole\Http\Response as HttpResponse;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\None;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
@ -17,10 +16,11 @@ use Utopia\Config\Config;
use Utopia\Database\Adapter\MySQL;
use Utopia\Database\Database;
use Utopia\Http\Adapter\FPM\Server;
use Utopia\Platform\Action;
use Utopia\Registry\Registry;
use Utopia\Http\Http;
use Utopia\Http\Validator\Text;
use Utopia\Http\Validator\WhiteList;
use Utopia\Platform\Action;
use Utopia\Registry\Registry;
class Specs extends Action
{

View file

@ -2,9 +2,9 @@
namespace Appwrite\Platform\Tasks;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Http\Http;
use Utopia\Platform\Action;
class Vars extends Action

View file

@ -2,8 +2,8 @@
namespace Appwrite\Platform\Tasks;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Http\Http;
use Utopia\Platform\Action;
class Version extends Action

View file

@ -4,9 +4,9 @@ namespace Appwrite\Platform\Tasks;
use Utopia\CLI\Console;
use Utopia\Database\DateTime;
use Utopia\Platform\Action;
use Utopia\Http\Validator\Integer;
use Utopia\Http\Validator\Text;
use Utopia\Platform\Action;
class VolumeSync extends Action
{

View file

@ -9,6 +9,7 @@ use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Validator\Authorization as ValidatorAuthorization;
use Utopia\Platform\Action;
use Utopia\Queue\Message;
@ -28,7 +29,8 @@ class Audits extends Action
->desc('Audits worker')
->inject('message')
->inject('dbForProject')
->callback(fn ($message, $dbForProject) => $this->action($message, $dbForProject));
->inject('auth')
->callback(fn ($message, $dbForProject, ValidatorAuthorization $auth) => $this->action($message, $dbForProject, $auth));
}
@ -41,7 +43,7 @@ class Audits extends Action
* @throws Authorization
* @throws Structure
*/
public function action(Message $message, Database $dbForProject): void
public function action(Message $message, Database $dbForProject, ValidatorAuthorization $auth): void
{
$payload = $message->getPayload() ?? [];
@ -61,7 +63,7 @@ class Audits extends Action
$userName = $user->getAttribute('name', '');
$userEmail = $user->getAttribute('email', '');
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$audit->log(
userId: $user->getInternalId(),
// Pass first, most verbose event pattern

View file

@ -10,7 +10,6 @@ use Appwrite\Utopia\Response\Model\Deployment;
use Appwrite\Vcs\Comment;
use Executor\Executor;
use Swoole\Coroutine as Co;
use Utopia\Http\Http;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
@ -22,6 +21,7 @@ use Utopia\Database\Exception\Restricted;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Platform\Action;
use Utopia\Queue\Message;

View file

@ -11,7 +11,6 @@ use Appwrite\Template\Template;
use Appwrite\Utopia\Response\Model\Rule;
use Exception;
use Throwable;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
@ -22,6 +21,7 @@ use Utopia\Database\Exception\Structure;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Domains\Domain;
use Utopia\Http\Http;
use Utopia\Locale\Locale;
use Utopia\Logger\Log;
use Utopia\Platform\Action;

View file

@ -8,7 +8,6 @@ use Executor\Executor;
use Throwable;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Http\Http;
use Utopia\Audit\Audit;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
@ -22,6 +21,8 @@ use Utopia\Database\Exception\Conflict;
use Utopia\Database\Exception\Restricted;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization as ValidatorAuthorization;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Platform\Action;
use Utopia\Queue\Message;
@ -52,14 +53,15 @@ class Deletes extends Action
->inject('executionRetention')
->inject('auditRetention')
->inject('log')
->callback(fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $abuseRetention, $executionRetention, $auditRetention, $log));
->inject('auth')
->callback(fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log, ValidatorAuthorization $auth) => $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $abuseRetention, $executionRetention, $auditRetention, $log, $auth));
}
/**
* @throws Exception
* @throws Throwable
*/
public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void
public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log, ValidatorAuthorization $auth): void
{
$payload = $message->getPayload() ?? [];
@ -127,7 +129,7 @@ class Deletes extends Action
break;
case DELETE_TYPE_AUDIT:
if (!$project->isEmpty()) {
$this->deleteAuditLogs($project, $getProjectDB, $auditRetention);
$this->deleteAuditLogs($project, $getProjectDB, $auditRetention, $auth);
}
if (!$document->isEmpty()) {
@ -135,7 +137,7 @@ class Deletes extends Action
}
break;
case DELETE_TYPE_ABUSE:
$this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention);
$this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention, $auth);
break;
case DELETE_TYPE_REALTIME:
$this->deleteRealtimeUsage($dbForConsole, $datetime);
@ -724,12 +726,12 @@ class Deletes extends Action
* @return void
* @throws Exception
*/
private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention): void
private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention, ValidatorAuthorization $auth): void
{
$projectId = $project->getId();
$dbForProject = $getProjectDB($project);
$timeLimit = new TimeLimit("", 0, 1, $dbForProject);
$abuse = new Abuse($timeLimit);
$timeLimit = new TimeLimit("", 0, 1, $dbForProject, $auth);
$abuse = new Abuse($timeLimit, $auth);
$status = $abuse->cleanup($abuseRetention);
if (!$status) {
throw new Exception('Failed to delete Abuse logs for project ' . $projectId);
@ -743,11 +745,11 @@ class Deletes extends Action
* @return void
* @throws Exception
*/
private function deleteAuditLogs(Document $project, callable $getProjectDB, string $auditRetention): void
private function deleteAuditLogs(Document $project, callable $getProjectDB, string $auditRetention, ValidatorAuthorization $auth): void
{
$projectId = $project->getId();
$dbForProject = $getProjectDB($project);
$audit = new Audit($dbForProject);
$audit = new Audit($dbForProject, $auth);
$status = $audit->cleanup($auditRetention);
if (!$status) {
throw new Exception('Failed to delete Audit logs for project' . $projectId);

View file

@ -9,7 +9,6 @@ use Appwrite\Messaging\Adapter\Realtime;
use Appwrite\Utopia\Response\Model\Execution;
use Exception;
use Executor\Executor;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -21,6 +20,7 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Platform\Action;
use Utopia\Queue\Message;

View file

@ -4,10 +4,8 @@ namespace Appwrite\Platform\Workers;
use Appwrite\Event\Hamster as EventHamster;
use Appwrite\Network\Validator\Origin;
use PharIo\Manifest\Author;
use Utopia\Analytics\Adapter\Mixpanel;
use Utopia\Analytics\Event as AnalyticsEvent;
use Utopia\Http\Http;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Config\Config;
@ -15,6 +13,7 @@ use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Http\Http;
use Utopia\Platform\Action;
use Utopia\Pools\Group;
use Utopia\Queue\Message;
@ -123,6 +122,7 @@ class Hamster extends Action
->getResource();
$dbForProject = new Database($adapter, $cache);
$dbForProject->setAuthorization($auth);
$dbForProject->setDatabase('appwrite');
$dbForProject->setNamespace('_' . $project->getInternalId());

View file

@ -4,7 +4,6 @@ namespace Appwrite\Platform\Workers;
use Appwrite\Event\Usage;
use Appwrite\Messaging\Status as MessageStatus;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database;
@ -13,6 +12,7 @@ use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Messaging\Adapter\Email as EmailAdapter;
use Utopia\Messaging\Adapter\Email\Mailgun;

View file

@ -4,10 +4,10 @@ namespace Appwrite\Platform\Workers;
use Appwrite\Event\UsageDump;
use Exception;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Http\Http;
use Utopia\Platform\Action;
use Utopia\Queue\Message;

View file

@ -3,11 +3,11 @@
namespace Appwrite\Platform\Workers;
use Appwrite\Extend\Exception;
use Utopia\Http\Http;
use Utopia\CLI\Console;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Http\Http;
use Utopia\Platform\Action;
use Utopia\Queue\Message;

View file

@ -5,10 +5,10 @@ namespace Appwrite\Platform\Workers;
use Appwrite\Event\Mail;
use Appwrite\Template\Template;
use Exception;
use Utopia\Http\Http;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Platform\Action;
use Utopia\Queue\Message;

View file

@ -3,13 +3,13 @@
namespace Appwrite\Specification;
use Appwrite\Utopia\Response\Model;
use Utopia\Http\Http;
use Utopia\Config\Config;
use Utopia\Http\Http;
use Utopia\Http\Route;
abstract class Format
{
protected Http $app;
protected Http $http;
/**
* @var Route[]
@ -50,9 +50,9 @@ abstract class Format
]
];
public function __construct(Http $app, array $services, array $routes, array $models, array $keys, int $authCount)
public function __construct(Http $http, array $services, array $routes, array $models, array $keys, int $authCount)
{
$this->app = $app;
$this->http = $http;
$this->services = $services;
$this->routes = $routes;
$this->models = $models;

View file

@ -275,7 +275,7 @@ class OpenAPI3 extends Format
/**
* @var \Utopia\Http\Validator $validator
*/
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->http->getResources($param['injections'])) : $param['validator'];
$node = [
'name' => $name,

View file

@ -271,7 +271,7 @@ class Swagger2 extends Format
foreach ($parameters as $name => $param) { // Set params
/** @var Validator $validator */
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->http->getResources($param['injections'])) : $param['validator'];
$node = [
'name' => $name,

View file

@ -11,6 +11,14 @@ class Request extends SwooleRequest
private static ?Filter $filter = null;
private static ?Route $route = null;
/**
* Request constructor.
*/
public function __construct(SwooleRequest $request)
{
parent::__construct($request->getSwooleRequest());
}
/**
* @inheritdoc
*/

View file

@ -102,7 +102,6 @@ use Appwrite\Utopia\Response\Model\User;
use Appwrite\Utopia\Response\Model\Variable;
use Appwrite\Utopia\Response\Model\Webhook;
use Exception;
use Swoole\Http\Response as SwooleHTTPResponse;
// Keep last
use Utopia\Database\Document;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
@ -313,8 +312,10 @@ class Response extends SwooleResponse
*
* @param float $time
*/
public function __construct(SwooleHTTPResponse $response)
public function __construct(SwooleResponse $swooleResponse)
{
$response = $swooleResponse->getSwooleResponse();
$this
// General
->setModel(new None())

View file

@ -2,8 +2,8 @@
namespace Appwrite\Vcs;
use Utopia\Http\Http;
use Utopia\Database\Document;
use Utopia\Http\Http;
class Comment
{

View file

@ -7,10 +7,10 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideNone;
use Utopia\Http\Http;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Http\Http;
class AbuseTest extends Scope
{

View file

@ -6,10 +6,10 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\Http\Http;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Http\Http;
class AbuseTest extends Scope
{

View file

@ -6,9 +6,9 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\Http\Http;
use Utopia\Database\Helpers\ID;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
class MessagingTest extends Scope
{

View file

@ -4,13 +4,13 @@ namespace Tests\E2E\Services\Messaging;
use Appwrite\Messaging\Status as MessageStatus;
use Tests\E2E\Client;
use Utopia\Http\Http;
use Utopia\Database\DateTime;
use Utopia\Database\Document;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
trait MessagingBase
{

View file

@ -6,11 +6,11 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideConsole;
use Utopia\Http\Http;
use Utopia\Cache\Adapter\None;
use Utopia\Cache\Cache;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Role;
use Utopia\Http\Http;
use Utopia\VCS\Adapter\Git\GitHub;
class VCSConsoleClientTest extends Scope

View file

@ -6,8 +6,8 @@ use Appwrite\Event\Event;
use Appwrite\URL\URL;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use Utopia\Http\Http;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Queue;
use Utopia\Queue\Client;

View file

@ -6,7 +6,6 @@ use Appwrite\Auth\Auth;
use Appwrite\Messaging\Adapter\Realtime;
use PHPUnit\Framework\TestCase;
use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Validator\Authorization as ValidatorAuthorization;

View file

@ -4,8 +4,8 @@ namespace Tests\Unit\Usage;
use Appwrite\URL\URL as AppwriteURL;
use PHPUnit\Framework\TestCase;
use Utopia\Http\Http;
use Utopia\DSN\DSN;
use Utopia\Http\Http;
use Utopia\Queue;
use Utopia\Queue\Client;
use Utopia\Queue\Connection;