mirror of
https://github.com/appwrite/appwrite
synced 2026-04-21 13:37:16 +00:00
Merge branch '1.9.x' into feat/import-export-json
This commit is contained in:
commit
3bb6a8bcc8
67 changed files with 483 additions and 399 deletions
|
|
@ -64,7 +64,7 @@ return [
|
|||
[
|
||||
'$id' => ID::custom('database'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'size' => 128,
|
||||
'size' => 2000,
|
||||
'required' => false,
|
||||
'signed' => true,
|
||||
'array' => false,
|
||||
|
|
|
|||
|
|
@ -250,26 +250,16 @@ return [
|
|||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'key' => 'markdown',
|
||||
'name' => 'Markdown',
|
||||
'version' => '0.3.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-md.git',
|
||||
'package' => 'https://www.npmjs.com/package/@appwrite.io/docs',
|
||||
'enabled' => true,
|
||||
'beta' => false,
|
||||
'dev' => false,
|
||||
'hidden' => false,
|
||||
'family' => APP_SDK_PLATFORM_CONSOLE,
|
||||
'prism' => 'markdown',
|
||||
'source' => \realpath(__DIR__ . '/../sdks/console-md'),
|
||||
'gitUrl' => 'git@github.com:appwrite/sdk-for-md.git',
|
||||
'gitRepoName' => 'sdk-for-md',
|
||||
'gitUserName' => 'appwrite',
|
||||
'gitBranch' => 'dev',
|
||||
'repoBranch' => 'main',
|
||||
'changelog' => \realpath(__DIR__ . '/../../docs/sdks/md/CHANGELOG.md'),
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
APP_SDK_PLATFORM_STATIC => [
|
||||
'key' => APP_SDK_PLATFORM_STATIC,
|
||||
'name' => 'Static',
|
||||
'description' => 'SDK artifacts for Appwrite integrations that do not require a generated platform API specification.',
|
||||
'enabled' => true,
|
||||
'beta' => false,
|
||||
'sdks' => [
|
||||
[
|
||||
'key' => 'agent-skills',
|
||||
'name' => 'AgentSkills',
|
||||
|
|
@ -279,9 +269,10 @@ return [
|
|||
'beta' => false,
|
||||
'dev' => false,
|
||||
'hidden' => false,
|
||||
'family' => APP_SDK_PLATFORM_CONSOLE,
|
||||
'spec' => 'static',
|
||||
'family' => APP_SDK_PLATFORM_STATIC,
|
||||
'prism' => 'agent-skills',
|
||||
'source' => \realpath(__DIR__ . '/../sdks/console-agent-skills'),
|
||||
'source' => \realpath(__DIR__ . '/../sdks/static-agent-skills'),
|
||||
'gitUrl' => 'git@github.com:appwrite/agent-skills.git',
|
||||
'gitRepoName' => 'agent-skills',
|
||||
'gitUserName' => 'appwrite',
|
||||
|
|
@ -298,9 +289,10 @@ return [
|
|||
'beta' => false,
|
||||
'dev' => false,
|
||||
'hidden' => false,
|
||||
'family' => APP_SDK_PLATFORM_CONSOLE,
|
||||
'spec' => 'static',
|
||||
'family' => APP_SDK_PLATFORM_STATIC,
|
||||
'prism' => 'cursor-plugin',
|
||||
'source' => \realpath(__DIR__ . '/../sdks/console-cursor-plugin'),
|
||||
'source' => \realpath(__DIR__ . '/../sdks/static-cursor-plugin'),
|
||||
'gitUrl' => 'git@github.com:appwrite/cursor-plugin.git',
|
||||
'gitRepoName' => 'cursor-plugin',
|
||||
'gitUserName' => 'appwrite',
|
||||
|
|
|
|||
|
|
@ -28,12 +28,18 @@ use Utopia\Validator\Text;
|
|||
Http::init()
|
||||
->groups(['graphql'])
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('authorization')
|
||||
->action(function (Document $project, Authorization $authorization) {
|
||||
->action(function (Document $project, User $user, Request $request, Response $response, Authorization $authorization) {
|
||||
$response->setUser($user);
|
||||
$request->setUser($user);
|
||||
|
||||
if (
|
||||
array_key_exists('graphql', $project->getAttribute('apis', []))
|
||||
&& !$project->getAttribute('apis', [])['graphql']
|
||||
&& !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
&& !($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1270,7 +1270,16 @@ Http::error()
|
|||
* If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php
|
||||
*/
|
||||
if (!$publish && $project->getId() !== 'console') {
|
||||
if (!DBUser::isPrivileged($authorization->getRoles())) {
|
||||
$errorUser = new DBUser();
|
||||
try {
|
||||
$resolvedUser = $utopia->getResource('user');
|
||||
if ($resolvedUser instanceof DBUser) {
|
||||
$errorUser = $resolvedUser;
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// User resource may not be available in error context
|
||||
}
|
||||
if (!$errorUser->isPrivileged($authorization->getRoles())) {
|
||||
$bus->dispatch(new RequestCompleted(
|
||||
project: $project->getArrayCopy(),
|
||||
request: $request,
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ Http::init()
|
|||
->inject('team')
|
||||
->inject('apiKey')
|
||||
->inject('authorization')
|
||||
->action(function (Http $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) {
|
||||
->action(function (Http $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) {
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
/**
|
||||
|
|
@ -419,7 +419,7 @@ Http::init()
|
|||
if (
|
||||
array_key_exists($namespace, $project->getAttribute('services', []))
|
||||
&& ! $project->getAttribute('services', [])[$namespace]
|
||||
&& ! (User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
&& ! ($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new Exception(Exception::GENERAL_SERVICE_DISABLED);
|
||||
}
|
||||
|
|
@ -483,7 +483,10 @@ Http::init()
|
|||
->inject('telemetry')
|
||||
->inject('platform')
|
||||
->inject('authorization')
|
||||
->action(function (Http $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Context $usage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) {
|
||||
->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Context $usage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) {
|
||||
|
||||
$response->setUser($user);
|
||||
$request->setUser($user);
|
||||
|
||||
$route = $utopia->getRoute();
|
||||
$path = $route->getMatchedPath();
|
||||
|
|
@ -496,7 +499,7 @@ Http::init()
|
|||
if (
|
||||
array_key_exists('rest', $project->getAttribute('apis', []))
|
||||
&& ! $project->getAttribute('apis', [])['rest']
|
||||
&& ! (User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
&& ! ($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
|
||||
}
|
||||
|
|
@ -528,8 +531,8 @@ Http::init()
|
|||
$closestLimit = null;
|
||||
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = User::isPrivileged($roles);
|
||||
$isAppUser = User::isApp($roles);
|
||||
$isPrivilegedUser = $user->isPrivileged($roles);
|
||||
$isAppUser = $user->isApp($roles);
|
||||
|
||||
foreach ($timeLimitArray as $timeLimit) {
|
||||
foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
|
||||
|
|
@ -611,7 +614,7 @@ Http::init()
|
|||
if ($useCache) {
|
||||
$route = $utopia->match($request);
|
||||
$isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview';
|
||||
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && ! User::isPrivileged($authorization->getRoles());
|
||||
$isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && ! $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$key = $request->cacheIdentifier();
|
||||
$cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key));
|
||||
|
|
@ -630,7 +633,7 @@ Http::init()
|
|||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isToken = ! $resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence();
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && ! $isAppUser && ! $isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
@ -663,7 +666,7 @@ Http::init()
|
|||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
// Do not update transformedAt if it's a console user
|
||||
if (! User::isPrivileged($authorization->getRoles())) {
|
||||
if (! $user->isPrivileged($authorization->getRoles())) {
|
||||
$transformedAt = $file->getAttribute('transformedAt', '');
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) {
|
||||
$file->setAttribute('transformedAt', DateTime::now());
|
||||
|
|
@ -697,7 +700,7 @@ Http::init()
|
|||
->groups(['session'])
|
||||
->inject('user')
|
||||
->inject('request')
|
||||
->action(function (Document $user, Request $request) {
|
||||
->action(function (User $user, Request $request) {
|
||||
if (\str_contains($request->getURI(), 'oauth2')) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -984,7 +987,7 @@ Http::shutdown()
|
|||
}
|
||||
|
||||
if ($project->getId() !== 'console') {
|
||||
if (! User::isPrivileged($authorization->getRoles())) {
|
||||
if (! $user->isPrivileged($authorization->getRoles())) {
|
||||
$bus->dispatch(new RequestCompleted(
|
||||
project: $project->getArrayCopy(),
|
||||
request: $request,
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@ Http::init()
|
|||
->inject('request')
|
||||
->inject('project')
|
||||
->inject('geodb')
|
||||
->inject('user')
|
||||
->inject('authorization')
|
||||
->action(function (Http $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) {
|
||||
->action(function (Http $utopia, Request $request, Document $project, Reader $geodb, User $user, Authorization $authorization) {
|
||||
$denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', '');
|
||||
if (!empty($denylist && $project->getId() === 'console')) {
|
||||
$countries = explode(',', $denylist);
|
||||
|
|
@ -50,8 +51,8 @@ Http::init()
|
|||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
$isAppUser = $user->isApp($authorization->getRoles());
|
||||
|
||||
if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ const APP_COMPUTE_DEPLOYMENT_MAX_RETENTION = 100 * 365; // 100 years
|
|||
const APP_SDK_PLATFORM_SERVER = 'server';
|
||||
const APP_SDK_PLATFORM_CLIENT = 'client';
|
||||
const APP_SDK_PLATFORM_CONSOLE = 'console';
|
||||
const APP_SDK_PLATFORM_STATIC = 'static';
|
||||
const APP_VCS_GITHUB_USERNAME = 'Appwrite';
|
||||
const APP_VCS_GITHUB_EMAIL = 'team@appwrite.io';
|
||||
const APP_VCS_GITHUB_URL = 'https://github.com/TeamAppwrite';
|
||||
|
|
|
|||
|
|
@ -432,8 +432,10 @@ Http::setResource('user', function (string $mode, Document $project, Document $c
|
|||
$jwtUserId = $payload['userId'] ?? '';
|
||||
if (! empty($jwtUserId)) {
|
||||
if ($mode === APP_MODE_ADMIN) {
|
||||
/** @var User $user */
|
||||
$user = $dbForPlatform->getDocument('users', $jwtUserId);
|
||||
} else {
|
||||
/** @var User $user */
|
||||
$user = $dbForProject->getDocument('users', $jwtUserId);
|
||||
}
|
||||
}
|
||||
|
|
@ -453,6 +455,7 @@ Http::setResource('user', function (string $mode, Document $project, Document $c
|
|||
throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET);
|
||||
}
|
||||
|
||||
/** @var User $accountKeyUser */
|
||||
$accountKeyUser = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $accountKeyUserId));
|
||||
if (! $accountKeyUser->isEmpty()) {
|
||||
$key = $accountKeyUser->find(
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats,
|
|||
$project = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId));
|
||||
$database = getProjectDB($project);
|
||||
|
||||
/** @var Appwrite\Utopia\Database\Documents\User $user */
|
||||
/** @var User $user */
|
||||
$user = $database->getDocument('users', $userId);
|
||||
|
||||
$roles = $user->getRoles($database->getAuthorization());
|
||||
|
|
@ -642,10 +642,14 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
throw new Exception(Exception::REALTIME_POLICY_VIOLATION, 'Missing or unknown project ID');
|
||||
}
|
||||
|
||||
$timelimit = $app->getResource('timelimit');
|
||||
$user = $app->getResource('user'); /** @var User $user */
|
||||
$logUser = $user;
|
||||
|
||||
if (
|
||||
array_key_exists('realtime', $project->getAttribute('apis', []))
|
||||
&& !$project->getAttribute('apis', [])['realtime']
|
||||
&& !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles()))
|
||||
&& !($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles()))
|
||||
) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED);
|
||||
}
|
||||
|
|
@ -656,10 +660,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Project is not accessible in this region. Please make sure you are using the correct endpoint');
|
||||
}
|
||||
|
||||
$timelimit = $app->getResource('timelimit');
|
||||
$user = $app->getResource('user'); /** @var User $user */
|
||||
$logUser = $user;
|
||||
|
||||
/*
|
||||
* Abuse Check
|
||||
*
|
||||
|
|
|
|||
12
composer.lock
generated
12
composer.lock
generated
|
|
@ -4002,16 +4002,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/dns",
|
||||
"version": "1.6.5",
|
||||
"version": "1.6.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/dns.git",
|
||||
"reference": "574327f0f5fabefa7048030c5634cde33ad10640"
|
||||
"reference": "917901ecfe5f09a540e4f689b6cbb80b9f55035d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/574327f0f5fabefa7048030c5634cde33ad10640",
|
||||
"reference": "574327f0f5fabefa7048030c5634cde33ad10640",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/917901ecfe5f09a540e4f689b6cbb80b9f55035d",
|
||||
"reference": "917901ecfe5f09a540e4f689b6cbb80b9f55035d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4053,9 +4053,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/dns/issues",
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.6.5"
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.6.6"
|
||||
},
|
||||
"time": "2026-02-19T16:06:46+00:00"
|
||||
"time": "2026-03-27T11:13:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
# Change Log
|
||||
|
||||
## 0.3.0
|
||||
|
||||
* Add `bytesMax` and `bytesUsed` properties to Collection and Table documentation
|
||||
* Add `queries` parameter to `listKeys` and `keyId` parameter to `createKey` documentation
|
||||
* Add `dart-3.10` and `flutter-3.38` runtimes
|
||||
* Fix Teams membership docs to use `string[]` instead of `Roles[]`
|
||||
|
||||
## 0.2.0
|
||||
|
||||
* Document array-based enum parameters in Markdown examples (e.g., `permissions: BrowserPermission[]`).
|
||||
* Breaking change: `Output` enum has been removed; use `ImageFormat` instead.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
* Initial release
|
||||
|
|
@ -114,12 +114,6 @@ parameters:
|
|||
count: 1
|
||||
path: app/controllers/mock.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Utopia\\Database\\Document\:\:getRoles\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: app/controllers/shared/api.php
|
||||
|
||||
-
|
||||
message: '#^Variable \$register might not be defined\.$#'
|
||||
identifier: variable.undefined
|
||||
|
|
|
|||
|
|
@ -87,13 +87,14 @@ class Decrement extends Action
|
|||
->inject('usage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization, User $user): void
|
||||
{
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -87,13 +87,14 @@ class Increment extends Action
|
|||
->inject('usage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization, User $user): void
|
||||
{
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ class Create extends Action
|
|||
->inject('eventProcessor')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Document $user, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization, EventProcessor $eventProcessor): void
|
||||
public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, User $user, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization, EventProcessor $eventProcessor): void
|
||||
{
|
||||
$data = \is_string($data)
|
||||
? \json_decode($data, true)
|
||||
|
|
@ -183,8 +183,8 @@ class Create extends Action
|
|||
$documents = [$data];
|
||||
}
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($isBulk && !$isAPIKey && !$isPrivilegedUser) {
|
||||
throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE);
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ class Delete extends Action
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -101,12 +102,13 @@ class Delete extends Action
|
|||
Context $usage,
|
||||
TransactionState $transactionState,
|
||||
array $plan,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
): void {
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
|
|
|
|||
|
|
@ -72,13 +72,14 @@ class Get extends Action
|
|||
->inject('usage')
|
||||
->inject('transactionState')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization, User $user): void
|
||||
{
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
|
|
|
|||
|
|
@ -89,10 +89,11 @@ class Update extends Action
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization, User $user): void
|
||||
{
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
|
|
@ -102,8 +103,8 @@ class Update extends Action
|
|||
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class Upsert extends Action
|
|||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
|
||||
public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?string $transactionId, ?\DateTime $requestTimestamp, UtopiaResponse $response, User $user, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void
|
||||
{
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
|
|
@ -108,8 +108,8 @@ class Upsert extends Action
|
|||
throw new Exception($this->getMissingPayloadException());
|
||||
}
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ class XList extends Action
|
|||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void
|
||||
public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, int $ttl, UtopiaResponse $response, Database $dbForProject, User $user, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void
|
||||
{
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
|
|
|
|||
|
|
@ -65,17 +65,18 @@ class Create extends Action
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization): void
|
||||
public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization, User $user): void
|
||||
{
|
||||
if (empty($operations)) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty');
|
||||
}
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
// API keys and admins can read any transaction, regular users need permissions
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class Update extends Action
|
|||
* @param UtopiaResponse $response
|
||||
* @param Database $dbForProject
|
||||
* @param callable $getDatabasesDB
|
||||
* @param Document $user
|
||||
* @param User $user
|
||||
* @param TransactionState $transactionState
|
||||
* @param Delete $queueForDeletes
|
||||
* @param Event $queueForEvents
|
||||
|
|
@ -109,7 +109,7 @@ class Update extends Action
|
|||
* @throws Structure
|
||||
* @throws \Utopia\Http\Exception
|
||||
*/
|
||||
public function action(string $transactionId, bool $commit, bool $rollback, Document $project, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization, EventProcessor $eventProcessor): void
|
||||
public function action(string $transactionId, bool $commit, bool $rollback, Document $project, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, User $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization, EventProcessor $eventProcessor): void
|
||||
{
|
||||
if (!$commit && !$rollback) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true');
|
||||
|
|
@ -118,8 +118,8 @@ class Update extends Action
|
|||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time');
|
||||
}
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$transaction = ($isAPIKey || $isPrivilegedUser)
|
||||
? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId))
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class Decrement extends DecrementDocumentAttribute
|
|||
->inject('usage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class Increment extends IncrementDocumentAttribute
|
|||
->inject('usage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class Delete extends DocumentDelete
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class Get extends DocumentGet
|
|||
->inject('usage')
|
||||
->inject('transactionState')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class Update extends DocumentUpdate
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class Create extends OperationsCreate
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class Decrement extends DecrementDocumentAttribute
|
|||
->inject('usage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class Increment extends IncrementDocumentAttribute
|
|||
->inject('usage')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class Delete extends DocumentDelete
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class Get extends DocumentGet
|
|||
->inject('usage')
|
||||
->inject('transactionState')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class Update extends DocumentUpdate
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class Create extends OperationsCreate
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class Delete extends DocumentDelete
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class Get extends DocumentGet
|
|||
->inject('usage')
|
||||
->inject('transactionState')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class Update extends DocumentUpdate
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class Create extends OperationsCreate
|
|||
->inject('transactionState')
|
||||
->inject('plan')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class Create extends Base
|
|||
Document $project,
|
||||
Database $dbForProject,
|
||||
Database $dbForPlatform,
|
||||
Document $user,
|
||||
User $user,
|
||||
Event $queueForEvents,
|
||||
Context $usage,
|
||||
Func $queueForFunctions,
|
||||
|
|
@ -171,8 +171,8 @@ class Create extends Base
|
|||
/* @var Document $function */
|
||||
$function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class Get extends Base
|
|||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -61,12 +62,13 @@ class Get extends Base
|
|||
string $executionId,
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class XList extends Base
|
|||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -71,12 +72,13 @@ class XList extends Base
|
|||
bool $includeTotal,
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class Create extends Action
|
|||
Request $request,
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Document $user,
|
||||
User $user,
|
||||
Event $queueForEvents,
|
||||
string $mode,
|
||||
Device $deviceForFiles,
|
||||
|
|
@ -112,8 +112,8 @@ class Create extends Action
|
|||
) {
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ class Delete extends Action
|
|||
->inject('deviceForFiles')
|
||||
->inject('queueForDeletes')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -77,12 +78,13 @@ class Delete extends Action
|
|||
Event $queueForEvents,
|
||||
Device $deviceForFiles,
|
||||
DeleteEvent $queueForDeletes,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class Get extends Action
|
|||
->inject('resourceToken')
|
||||
->inject('deviceForFiles')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -84,12 +85,13 @@ class Get extends Action
|
|||
Document $resourceToken,
|
||||
Device $deviceForFiles,
|
||||
Authorization $authorization,
|
||||
User $user,
|
||||
) {
|
||||
/* @type Document $bucket */
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class Get extends Action
|
|||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -59,12 +60,13 @@ class Get extends Action
|
|||
string $fileId,
|
||||
Response $response,
|
||||
Database $dbForProject,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ class Get extends Action
|
|||
->inject('deviceForLocal')
|
||||
->inject('project')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +118,8 @@ class Get extends Action
|
|||
Device $deviceForFiles,
|
||||
Device $deviceForLocal,
|
||||
Document $project,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
|
|
@ -127,8 +129,8 @@ class Get extends Action
|
|||
/* @type Document $bucket */
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
@ -271,7 +273,7 @@ class Get extends Action
|
|||
$contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg'];
|
||||
|
||||
//Do not update transformedAt if it's a console user
|
||||
if (!User::isPrivileged($authorization->getRoles())) {
|
||||
if (!$user->isPrivileged($authorization->getRoles())) {
|
||||
$transformedAt = $file->getAttribute('transformedAt', '');
|
||||
if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) {
|
||||
$file->setAttribute('transformedAt', DateTime::now());
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class Get extends Action
|
|||
->inject('mode')
|
||||
->inject('deviceForFiles')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +67,8 @@ class Get extends Action
|
|||
Document $project,
|
||||
string $mode,
|
||||
Device $deviceForFiles,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0);
|
||||
|
||||
|
|
@ -88,8 +90,8 @@ class Get extends Action
|
|||
$disposition = $decoded['disposition'] ?? 'inline';
|
||||
$dbForProject = $isInternal ? $dbForPlatform : $dbForProject;
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class Update extends Action
|
|||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -75,12 +76,13 @@ class Update extends Action
|
|||
Response $response,
|
||||
Database $dbForProject,
|
||||
Event $queueForEvents,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
@ -108,7 +110,7 @@ class Update extends Action
|
|||
|
||||
// Users can only manage their own roles, API keys and Admin users can manage any
|
||||
$roles = $authorization->getRoles();
|
||||
if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) {
|
||||
if (!$user->isApp($roles) && !$user->isPrivileged($roles) && !\is_null($permissions)) {
|
||||
foreach (Database::PERMISSIONS as $type) {
|
||||
foreach ($permissions as $permission) {
|
||||
$permission = Permission::parse($permission);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class Get extends Action
|
|||
->inject('resourceToken')
|
||||
->inject('deviceForFiles')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -84,13 +85,14 @@ class Get extends Action
|
|||
string $mode,
|
||||
Document $resourceToken,
|
||||
Device $deviceForFiles,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
/* @type Document $bucket */
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class XList extends Action
|
|||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
|
@ -74,12 +75,13 @@ class XList extends Action
|
|||
Response $response,
|
||||
Database $dbForProject,
|
||||
string $mode,
|
||||
Authorization $authorization
|
||||
Authorization $authorization,
|
||||
User $user
|
||||
) {
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -98,10 +98,10 @@ class Create extends Action
|
|||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, Context $usage, array $plan, Password $proofForPassword, Token $proofForToken)
|
||||
public function action(string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, User $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, Context $usage, array $plan, Password $proofForPassword, Token $proofForToken)
|
||||
{
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if (empty($url)) {
|
||||
if (! $isAppUser && ! $isPrivilegedUser) {
|
||||
|
|
|
|||
|
|
@ -52,10 +52,11 @@ class Get extends Action
|
|||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization)
|
||||
public function action(string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization, User $user)
|
||||
{
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
|
|
@ -76,25 +77,25 @@ class Get extends Action
|
|||
];
|
||||
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = User::isPrivileged($roles);
|
||||
$isAppUser = User::isApp($roles);
|
||||
$isPrivilegedUser = $user->isPrivileged($roles);
|
||||
$isAppUser = $user->isApp($roles);
|
||||
|
||||
$membershipsPrivacy = array_map(function ($privacy) use ($isPrivilegedUser, $isAppUser) {
|
||||
return $privacy || $isPrivilegedUser || $isAppUser;
|
||||
}, $membershipsPrivacy);
|
||||
|
||||
$user = !empty(array_filter($membershipsPrivacy))
|
||||
$memberUser = !empty(array_filter($membershipsPrivacy))
|
||||
? $dbForProject->getDocument('users', $membership->getAttribute('userId'))
|
||||
: new Document();
|
||||
|
||||
if ($membershipsPrivacy['mfa']) {
|
||||
$mfa = $user->getAttribute('mfa', false);
|
||||
$mfa = $memberUser->getAttribute('mfa', false);
|
||||
|
||||
if ($mfa) {
|
||||
$totp = TOTP::getAuthenticatorFromUser($user);
|
||||
$totp = TOTP::getAuthenticatorFromUser($memberUser);
|
||||
$totpEnabled = $totp && $totp->getAttribute('verified', false);
|
||||
$emailEnabled = $user->getAttribute('email', false) && $user->getAttribute('emailVerification', false);
|
||||
$phoneEnabled = $user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false);
|
||||
$emailEnabled = $memberUser->getAttribute('email', false) && $memberUser->getAttribute('emailVerification', false);
|
||||
$phoneEnabled = $memberUser->getAttribute('phone', false) && $memberUser->getAttribute('phoneVerification', false);
|
||||
|
||||
if (!$totpEnabled && !$emailEnabled && !$phoneEnabled) {
|
||||
$mfa = false;
|
||||
|
|
@ -105,11 +106,11 @@ class Get extends Action
|
|||
}
|
||||
|
||||
if ($membershipsPrivacy['userName']) {
|
||||
$membership->setAttribute('userName', $user->getAttribute('name'));
|
||||
$membership->setAttribute('userName', $memberUser->getAttribute('name'));
|
||||
}
|
||||
|
||||
if ($membershipsPrivacy['userEmail']) {
|
||||
$membership->setAttribute('userEmail', $user->getAttribute('email'));
|
||||
$membership->setAttribute('userEmail', $memberUser->getAttribute('email'));
|
||||
}
|
||||
|
||||
$membership->setAttribute('teamName', $team->getAttribute('name'));
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class Update extends Action
|
|||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents)
|
||||
public function action(string $teamId, string $membershipId, array $roles, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents)
|
||||
{
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if ($team->isEmpty()) {
|
||||
|
|
@ -83,8 +83,8 @@ class Update extends Action
|
|||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
$isAppUser = $user->isApp($authorization->getRoles());
|
||||
$isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if ($project->getId() === 'console') {
|
||||
|
|
|
|||
|
|
@ -61,10 +61,11 @@ class XList extends Action
|
|||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->inject('user')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization)
|
||||
public function action(string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization, User $user)
|
||||
{
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
|
|
@ -129,26 +130,26 @@ class XList extends Action
|
|||
];
|
||||
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = User::isPrivileged($roles);
|
||||
$isAppUser = User::isApp($roles);
|
||||
$isPrivilegedUser = $user->isPrivileged($roles);
|
||||
$isAppUser = $user->isApp($roles);
|
||||
|
||||
$membershipsPrivacy = array_map(function ($privacy) use ($isPrivilegedUser, $isAppUser) {
|
||||
return $privacy || $isPrivilegedUser || $isAppUser;
|
||||
}, $membershipsPrivacy);
|
||||
|
||||
$memberships = array_map(function ($membership) use ($dbForProject, $team, $membershipsPrivacy) {
|
||||
$user = !empty(array_filter($membershipsPrivacy))
|
||||
$memberUser = !empty(array_filter($membershipsPrivacy))
|
||||
? $dbForProject->getDocument('users', $membership->getAttribute('userId'))
|
||||
: new Document();
|
||||
|
||||
if ($membershipsPrivacy['mfa']) {
|
||||
$mfa = $user->getAttribute('mfa', false);
|
||||
$mfa = $memberUser->getAttribute('mfa', false);
|
||||
|
||||
if ($mfa) {
|
||||
$totp = TOTP::getAuthenticatorFromUser($user);
|
||||
$totp = TOTP::getAuthenticatorFromUser($memberUser);
|
||||
$totpEnabled = $totp && $totp->getAttribute('verified', false);
|
||||
$emailEnabled = $user->getAttribute('email', false) && $user->getAttribute('emailVerification', false);
|
||||
$phoneEnabled = $user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false);
|
||||
$emailEnabled = $memberUser->getAttribute('email', false) && $memberUser->getAttribute('emailVerification', false);
|
||||
$phoneEnabled = $memberUser->getAttribute('phone', false) && $memberUser->getAttribute('phoneVerification', false);
|
||||
|
||||
if (!$totpEnabled && !$emailEnabled && !$phoneEnabled) {
|
||||
$mfa = false;
|
||||
|
|
@ -159,11 +160,11 @@ class XList extends Action
|
|||
}
|
||||
|
||||
if ($membershipsPrivacy['userName']) {
|
||||
$membership->setAttribute('userName', $user->getAttribute('name'));
|
||||
$membership->setAttribute('userName', $memberUser->getAttribute('name'));
|
||||
}
|
||||
|
||||
if ($membershipsPrivacy['userEmail']) {
|
||||
$membership->setAttribute('userEmail', $user->getAttribute('email'));
|
||||
$membership->setAttribute('userEmail', $memberUser->getAttribute('email'));
|
||||
}
|
||||
|
||||
$membership->setAttribute('teamName', $team->getAttribute('name'));
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@ class Create extends Action
|
|||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents)
|
||||
public function action(string $teamId, string $name, array $roles, Response $response, User $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents)
|
||||
{
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAppUser = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
$isAppUser = $user->isApp($authorization->getRoles());
|
||||
|
||||
$teamId = $teamId == 'unique()' ? ID::unique() : $teamId;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ use Utopia\Platform\Action as UtopiaAction;
|
|||
|
||||
class Action extends UtopiaAction
|
||||
{
|
||||
protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, string $bucketId, string $fileId): array
|
||||
protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, User $user, string $bucketId, string $fileId): array
|
||||
{
|
||||
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
||||
$isAPIKey = User::isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = User::isPrivileged($authorization->getRoles());
|
||||
$isAPIKey = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
|
||||
if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use Appwrite\SDK\AuthType;
|
|||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Auth\Proofs\Token;
|
||||
use Utopia\Database\Database;
|
||||
|
|
@ -64,19 +65,20 @@ class Create extends Action
|
|||
->param('fileId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'File unique ID.', false, ['dbForProject'])
|
||||
->param('expire', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Token expiry date', true)
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
public function action(string $bucketId, string $fileId, ?string $expire, Response $response, User $user, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void
|
||||
{
|
||||
/**
|
||||
* @var Document $bucket
|
||||
* @var Document $file
|
||||
*/
|
||||
['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId);
|
||||
['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $user, $bucketId, $fileId);
|
||||
|
||||
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
|
||||
$bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate()));
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use Appwrite\SDK\AuthType;
|
|||
use Appwrite\SDK\ContentType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\FileTokens;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
|
|
@ -57,14 +58,15 @@ class XList extends Action
|
|||
->param('queries', [], new FileTokens(), '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(', ', FileTokens::ALLOWED_ATTRIBUTES), true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization)
|
||||
public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, User $user, Database $dbForProject, Authorization $authorization)
|
||||
{
|
||||
['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId);
|
||||
['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $user, $bucketId, $fileId);
|
||||
|
||||
$queries = Query::parseQueries($queries);
|
||||
$queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]);
|
||||
|
|
|
|||
|
|
@ -82,12 +82,11 @@ class Create extends Action
|
|||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_DETECTION_RUNTIME,
|
||||
model: [
|
||||
Response::MODEL_DETECTION_RUNTIME,
|
||||
Response::MODEL_DETECTION_FRAMEWORK,
|
||||
],
|
||||
),
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_DETECTION_FRAMEWORK,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('installationId', '', new Text(256), 'Installation Id')
|
||||
|
|
|
|||
|
|
@ -86,12 +86,11 @@ class XList extends Action
|
|||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST,
|
||||
model: [
|
||||
Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST,
|
||||
Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST,
|
||||
],
|
||||
),
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST,
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('installationId', '', new Text(256), 'Installation Id')
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ use Appwrite\SDK\Language\Flutter;
|
|||
use Appwrite\SDK\Language\Go;
|
||||
use Appwrite\SDK\Language\GraphQL;
|
||||
use Appwrite\SDK\Language\Kotlin;
|
||||
use Appwrite\SDK\Language\Markdown;
|
||||
use Appwrite\SDK\Language\Node;
|
||||
use Appwrite\SDK\Language\PHP;
|
||||
use Appwrite\SDK\Language\Python;
|
||||
|
|
@ -25,6 +24,7 @@ use Appwrite\SDK\Language\Rust;
|
|||
use Appwrite\SDK\Language\Swift;
|
||||
use Appwrite\SDK\Language\Web;
|
||||
use Appwrite\SDK\SDK;
|
||||
use Appwrite\Spec\StaticSpec;
|
||||
use Appwrite\Spec\Swagger2;
|
||||
use CzProject\GitPhp\Git;
|
||||
use Utopia\Agents\Adapters\OpenAI;
|
||||
|
|
@ -50,7 +50,10 @@ class SDKs extends Action
|
|||
|
||||
public static function getPlatforms(): array
|
||||
{
|
||||
return Specs::getPlatforms();
|
||||
return [
|
||||
...Specs::getPlatforms(),
|
||||
APP_SDK_PLATFORM_STATIC,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getSdkConfigPath(): string
|
||||
|
|
@ -99,11 +102,14 @@ class SDKs extends Action
|
|||
} else {
|
||||
$sdks = explode(',', $sdks);
|
||||
}
|
||||
$version ??= Console::confirm('Choose an Appwrite version');
|
||||
|
||||
$createRelease = ($release === 'yes');
|
||||
$commitRelease = ($commit === 'yes');
|
||||
|
||||
if ($createRelease && $examplesOnly) {
|
||||
throw new \Exception('Cannot use --release=yes with --mode=examples');
|
||||
}
|
||||
|
||||
if (! $createRelease && ! $examplesOnly) {
|
||||
$git ??= Console::confirm('Should we use git push? (yes/no)');
|
||||
$git = ($git === 'yes');
|
||||
|
|
@ -115,30 +121,34 @@ class SDKs extends Action
|
|||
$prUrls = [];
|
||||
}
|
||||
|
||||
if (! \in_array($version, [
|
||||
'0.6.x',
|
||||
'0.7.x',
|
||||
'0.8.x',
|
||||
'0.9.x',
|
||||
'0.10.x',
|
||||
'0.11.x',
|
||||
'0.12.x',
|
||||
'0.13.x',
|
||||
'0.14.x',
|
||||
'0.15.x',
|
||||
'1.0.x',
|
||||
'1.1.x',
|
||||
'1.2.x',
|
||||
'1.3.x',
|
||||
'1.4.x',
|
||||
'1.5.x',
|
||||
'1.6.x',
|
||||
'1.7.x',
|
||||
'1.8.x',
|
||||
'1.9.x',
|
||||
'latest',
|
||||
])) {
|
||||
throw new \Exception('Unknown version given');
|
||||
if (! $createRelease) {
|
||||
$version ??= Console::confirm('Choose an Appwrite version');
|
||||
|
||||
if (! \in_array($version, [
|
||||
'0.6.x',
|
||||
'0.7.x',
|
||||
'0.8.x',
|
||||
'0.9.x',
|
||||
'0.10.x',
|
||||
'0.11.x',
|
||||
'0.12.x',
|
||||
'0.13.x',
|
||||
'0.14.x',
|
||||
'0.15.x',
|
||||
'1.0.x',
|
||||
'1.1.x',
|
||||
'1.2.x',
|
||||
'1.3.x',
|
||||
'1.4.x',
|
||||
'1.5.x',
|
||||
'1.6.x',
|
||||
'1.7.x',
|
||||
'1.8.x',
|
||||
'1.9.x',
|
||||
'latest',
|
||||
])) {
|
||||
throw new \Exception('Unknown version given');
|
||||
}
|
||||
}
|
||||
|
||||
$selectedPlatforms = ($selectedPlatform === '*' || $selectedPlatform === null) ? null : \array_map('trim', \explode(',', $selectedPlatform));
|
||||
|
|
@ -170,16 +180,140 @@ class SDKs extends Action
|
|||
}
|
||||
|
||||
Console::log('');
|
||||
Console::info("━━━ {$language['name']} SDK ({$platform['name']}, {$version}) ━━━");
|
||||
Console::log(' Fetching API spec...');
|
||||
|
||||
$specPath = __DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $language['family'] . '.json';
|
||||
if ($createRelease && ! $examplesOnly) {
|
||||
Console::info("━━━ {$language['name']} SDK ({$platform['name']}, {$language['version']}) ━━━");
|
||||
$changelog = $language['changelog'] ?? '';
|
||||
$changelog = ($changelog) ? \file_get_contents($changelog) : '# Change Log';
|
||||
|
||||
if (!file_exists($specPath)) {
|
||||
throw new \Exception('Spec file not found: ' . $specPath . '. Please run "docker compose exec appwrite specs --version=' . $version . '" first to generate the specs.');
|
||||
$repoName = $language['gitUserName'] . '/' . $language['gitRepoName'];
|
||||
$releaseVersion = $language['version'];
|
||||
$releaseNotes = $this->extractReleaseNotes($changelog, $releaseVersion);
|
||||
|
||||
if (empty($releaseNotes)) {
|
||||
$releaseNotes = "Release version {$releaseVersion}";
|
||||
}
|
||||
|
||||
$releaseTitle = $releaseVersion;
|
||||
$releaseTarget = $language['repoBranch'] ?? 'main';
|
||||
|
||||
if ($repoName === '/') {
|
||||
Console::warning(' Not a releasable SDK, skipping');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if release already exists
|
||||
$checkReleaseCommand = 'gh release view ' . \escapeshellarg($releaseVersion) . ' --repo ' . \escapeshellarg($repoName) . ' --json url --jq ".url" 2>/dev/null';
|
||||
$existingReleaseUrl = trim(\shell_exec($checkReleaseCommand) ?? '');
|
||||
|
||||
if (! empty($existingReleaseUrl)) {
|
||||
Console::warning(" Release {$releaseVersion} already exists, skipping");
|
||||
Console::log(" {$existingReleaseUrl}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the latest commit on the target branch already has a release
|
||||
$latestCommitCommand = 'gh api repos/' . $repoName . '/commits/' . $releaseTarget . ' --jq ".sha" 2>/dev/null';
|
||||
$latestCommitSha = trim(\shell_exec($latestCommitCommand) ?? '');
|
||||
|
||||
if (! empty($latestCommitSha)) {
|
||||
$latestReleaseTagCommand = 'gh api repos/' . $repoName . '/releases --jq ".[0] | .tag_name" 2>/dev/null';
|
||||
$latestReleaseTag = trim(\shell_exec($latestReleaseTagCommand) ?? '');
|
||||
|
||||
if (! empty($latestReleaseTag)) {
|
||||
$tagCommitCommand = 'gh api repos/' . $repoName . '/git/ref/tags/' . $latestReleaseTag . ' --jq ".object.sha" 2>/dev/null';
|
||||
$tagCommitSha = trim(\shell_exec($tagCommitCommand) ?? '');
|
||||
|
||||
if (! empty($tagCommitSha) && $latestCommitSha === $tagCommitSha) {
|
||||
Console::warning(" Latest commit already released ({$latestReleaseTag}), skipping");
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$previousVersion = '';
|
||||
$tagListCommand = 'gh release list --repo ' . \escapeshellarg($repoName) . ' --limit 1 --json tagName --jq ".[0].tagName" 2>&1';
|
||||
$previousVersion = trim(\shell_exec($tagListCommand) ?? '');
|
||||
|
||||
$formattedNotes = "## What's Changed\n\n";
|
||||
$formattedNotes .= $releaseNotes . "\n\n";
|
||||
|
||||
if (! empty($previousVersion)) {
|
||||
$formattedNotes .= '**Full Changelog**: https://github.com/' . $repoName . '/compare/' . $previousVersion . '...' . $releaseVersion;
|
||||
} else {
|
||||
$formattedNotes .= '**Full Changelog**: https://github.com/' . $repoName . '/releases/tag/' . $releaseVersion;
|
||||
}
|
||||
|
||||
if (! $commitRelease) {
|
||||
Console::info(' [DRY RUN] Would create release:');
|
||||
Console::log(" Repository: {$repoName}");
|
||||
Console::log(" Version: {$releaseVersion}");
|
||||
Console::log(" Title: {$releaseTitle}");
|
||||
Console::log(" Target Branch: {$releaseTarget}");
|
||||
Console::log(' Previous Version: ' . ($previousVersion ?: 'N/A'));
|
||||
Console::log(' Release Notes:');
|
||||
Console::log(' ' . str_replace("\n", "\n ", $formattedNotes));
|
||||
} else {
|
||||
Console::log(" Creating release {$releaseVersion}...");
|
||||
|
||||
$tempNotesFile = \tempnam(\sys_get_temp_dir(), 'release_notes_');
|
||||
\file_put_contents($tempNotesFile, $formattedNotes);
|
||||
|
||||
$releaseCommand = 'gh release create ' . \escapeshellarg($releaseVersion) . ' \
|
||||
--repo ' . \escapeshellarg($repoName) . ' \
|
||||
--title ' . \escapeshellarg($releaseTitle) . ' \
|
||||
--notes-file ' . \escapeshellarg($tempNotesFile) . ' \
|
||||
--target ' . \escapeshellarg($releaseTarget) . ' \
|
||||
2>&1';
|
||||
|
||||
$releaseOutput = [];
|
||||
$releaseReturnCode = 0;
|
||||
\exec($releaseCommand, $releaseOutput, $releaseReturnCode);
|
||||
|
||||
\unlink($tempNotesFile);
|
||||
|
||||
if ($releaseReturnCode === 0) {
|
||||
// Extract release URL from output
|
||||
$releaseUrl = '';
|
||||
foreach ($releaseOutput as $line) {
|
||||
if (strpos($line, 'https://github.com/') !== false) {
|
||||
$releaseUrl = trim($line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Console::success(" Release {$releaseVersion} created");
|
||||
if (! empty($releaseUrl)) {
|
||||
Console::log(" {$releaseUrl}");
|
||||
}
|
||||
} else {
|
||||
$errorMessage = implode("\n", $releaseOutput);
|
||||
Console::error(" Failed to create release: " . $errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$spec = file_get_contents($specPath);
|
||||
Console::info("━━━ {$language['name']} SDK ({$platform['name']}, {$version}) ━━━");
|
||||
$specFormat = $language['spec'] ?? 'swagger2';
|
||||
$spec = null;
|
||||
if ($specFormat === 'static') {
|
||||
Console::log(' Using static SDK spec...');
|
||||
} else {
|
||||
Console::log(' Fetching API spec...');
|
||||
|
||||
$specPath = __DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $language['family'] . '.json';
|
||||
|
||||
if (!file_exists($specPath)) {
|
||||
throw new \Exception('Spec file not found: ' . $specPath . '. Please run "docker compose exec appwrite specs --version=' . $version . '" first to generate the specs.');
|
||||
}
|
||||
|
||||
$spec = file_get_contents($specPath);
|
||||
}
|
||||
|
||||
$cover = 'https://github.com/appwrite/appwrite/raw/main/public/images/github.png';
|
||||
$result = \realpath(__DIR__ . '/../../../../app') . '/sdks/' . $key . '-' . $language['key'];
|
||||
|
|
@ -311,10 +445,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
case 'rest':
|
||||
$config = new REST();
|
||||
break;
|
||||
case 'markdown':
|
||||
$config = new Markdown();
|
||||
$config->setNPMPackage('@appwrite.io/docs');
|
||||
break;
|
||||
case 'agent-skills':
|
||||
$config = new AgentSkills();
|
||||
break;
|
||||
|
|
@ -325,124 +455,22 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
throw new \Exception('Language "' . $language['key'] . '" not supported');
|
||||
}
|
||||
|
||||
if ($createRelease && ! $examplesOnly) {
|
||||
$repoName = $language['gitUserName'] . '/' . $language['gitRepoName'];
|
||||
$releaseVersion = $language['version'];
|
||||
$releaseNotes = $this->extractReleaseNotes($changelog, $releaseVersion);
|
||||
|
||||
if (empty($releaseNotes)) {
|
||||
$releaseNotes = "Release version {$releaseVersion}";
|
||||
}
|
||||
|
||||
$releaseTitle = $releaseVersion;
|
||||
$releaseTarget = $language['repoBranch'] ?? 'main';
|
||||
|
||||
if ($repoName === '/') {
|
||||
Console::warning(' Not a releasable SDK, skipping');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if release already exists
|
||||
$checkReleaseCommand = 'gh release view ' . \escapeshellarg($releaseVersion) . ' --repo ' . \escapeshellarg($repoName) . ' --json url --jq ".url" 2>/dev/null';
|
||||
$existingReleaseUrl = trim(\shell_exec($checkReleaseCommand) ?? '');
|
||||
|
||||
if (! empty($existingReleaseUrl)) {
|
||||
Console::warning(" Release {$releaseVersion} already exists, skipping");
|
||||
Console::log(" {$existingReleaseUrl}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the latest commit on the target branch already has a release
|
||||
$latestCommitCommand = 'gh api repos/' . $repoName . '/commits/' . $releaseTarget . ' --jq ".sha" 2>/dev/null';
|
||||
$latestCommitSha = trim(\shell_exec($latestCommitCommand) ?? '');
|
||||
|
||||
if (! empty($latestCommitSha)) {
|
||||
$latestReleaseTagCommand = 'gh api repos/' . $repoName . '/releases --jq ".[0] | .tag_name" 2>/dev/null';
|
||||
$latestReleaseTag = trim(\shell_exec($latestReleaseTagCommand) ?? '');
|
||||
|
||||
if (! empty($latestReleaseTag)) {
|
||||
$tagCommitCommand = 'gh api repos/' . $repoName . '/git/ref/tags/' . $latestReleaseTag . ' --jq ".object.sha" 2>/dev/null';
|
||||
$tagCommitSha = trim(\shell_exec($tagCommitCommand) ?? '');
|
||||
|
||||
if (! empty($tagCommitSha) && $latestCommitSha === $tagCommitSha) {
|
||||
Console::warning(" Latest commit already released ({$latestReleaseTag}), skipping");
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$previousVersion = '';
|
||||
$tagListCommand = 'gh release list --repo ' . \escapeshellarg($repoName) . ' --limit 1 --json tagName --jq ".[0].tagName" 2>&1';
|
||||
$previousVersion = trim(\shell_exec($tagListCommand) ?? '');
|
||||
|
||||
$formattedNotes = "## What's Changed\n\n";
|
||||
$formattedNotes .= $releaseNotes . "\n\n";
|
||||
|
||||
if (! empty($previousVersion)) {
|
||||
$formattedNotes .= '**Full Changelog**: https://github.com/' . $repoName . '/compare/' . $previousVersion . '...' . $releaseVersion;
|
||||
} else {
|
||||
$formattedNotes .= '**Full Changelog**: https://github.com/' . $repoName . '/releases/tag/' . $releaseVersion;
|
||||
}
|
||||
|
||||
if (! $commitRelease) {
|
||||
Console::info(' [DRY RUN] Would create release:');
|
||||
Console::log(" Repository: {$repoName}");
|
||||
Console::log(" Version: {$releaseVersion}");
|
||||
Console::log(" Title: {$releaseTitle}");
|
||||
Console::log(" Target Branch: {$releaseTarget}");
|
||||
Console::log(' Previous Version: ' . ($previousVersion ?: 'N/A'));
|
||||
Console::log(' Release Notes:');
|
||||
Console::log(' ' . str_replace("\n", "\n ", $formattedNotes));
|
||||
} else {
|
||||
Console::log(" Creating release {$releaseVersion}...");
|
||||
|
||||
$tempNotesFile = \tempnam(\sys_get_temp_dir(), 'release_notes_');
|
||||
\file_put_contents($tempNotesFile, $formattedNotes);
|
||||
|
||||
$releaseCommand = 'gh release create ' . \escapeshellarg($releaseVersion) . ' \
|
||||
--repo ' . \escapeshellarg($repoName) . ' \
|
||||
--title ' . \escapeshellarg($releaseTitle) . ' \
|
||||
--notes-file ' . \escapeshellarg($tempNotesFile) . ' \
|
||||
--target ' . \escapeshellarg($releaseTarget) . ' \
|
||||
2>&1';
|
||||
|
||||
$releaseOutput = [];
|
||||
$releaseReturnCode = 0;
|
||||
\exec($releaseCommand, $releaseOutput, $releaseReturnCode);
|
||||
|
||||
\unlink($tempNotesFile);
|
||||
|
||||
if ($releaseReturnCode === 0) {
|
||||
// Extract release URL from output
|
||||
$releaseUrl = '';
|
||||
foreach ($releaseOutput as $line) {
|
||||
if (strpos($line, 'https://github.com/') !== false) {
|
||||
$releaseUrl = trim($line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Console::success(" Release {$releaseVersion} created");
|
||||
if (! empty($releaseUrl)) {
|
||||
Console::log(" {$releaseUrl}");
|
||||
}
|
||||
} else {
|
||||
$errorMessage = implode("\n", $releaseOutput);
|
||||
Console::error(" Failed to create release: " . $errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Console::log($examplesOnly
|
||||
? ' Generating examples...'
|
||||
: ' Generating SDK...');
|
||||
|
||||
$sdk = new SDK($config, new Swagger2($spec));
|
||||
$sdk = new SDK(
|
||||
$config,
|
||||
$specFormat === 'static'
|
||||
? new StaticSpec(
|
||||
title: 'Appwrite',
|
||||
description: 'Appwrite backend as a service',
|
||||
version: $version,
|
||||
licenseName: 'BSD-3-Clause',
|
||||
licenseURL: 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
|
||||
)
|
||||
: new Swagger2($spec)
|
||||
);
|
||||
|
||||
$sdk
|
||||
->setName($language['name'])
|
||||
|
|
@ -483,6 +511,9 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
|
||||
try {
|
||||
$sdk->generate($result);
|
||||
Console::success($examplesOnly
|
||||
? " Examples generated at {$result}"
|
||||
: " SDK generated at {$result}");
|
||||
} catch (\Throwable $exception) {
|
||||
Console::error($exception->getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,6 +347,13 @@ class Specs extends Action
|
|||
$keys = $this->getKeys();
|
||||
|
||||
$generatedFiles = [];
|
||||
$endpoint = System::getEnv('_APP_HOME', '[HOSTNAME]');
|
||||
$email = System::getEnv('_APP_SYSTEM_TEAM_EMAIL', APP_EMAIL_TEAM);
|
||||
$specsDir = __DIR__ . '/../../../../app/config/specs';
|
||||
|
||||
if (!is_dir($specsDir) && !@mkdir($specsDir, 0755, true) && !is_dir($specsDir)) {
|
||||
throw new Exception('Failed to create specs directory: ' . $specsDir);
|
||||
}
|
||||
|
||||
foreach ($platforms as $platform) {
|
||||
$routes = [];
|
||||
|
|
@ -443,8 +450,6 @@ class Specs extends Action
|
|||
foreach (['swagger2', 'open-api3'] as $format) {
|
||||
$formatInstance = $this->getFormatInstance($format, $arguments);
|
||||
$specs = new Specification($formatInstance);
|
||||
$endpoint = System::getEnv('_APP_HOME', '[HOSTNAME]');
|
||||
$email = System::getEnv('_APP_SYSTEM_TEAM_EMAIL', APP_EMAIL_TEAM);
|
||||
|
||||
$formatInstance
|
||||
->setParam('name', APP_NAME)
|
||||
|
|
@ -463,36 +468,30 @@ class Specs extends Action
|
|||
->setParam('docs.description', 'Full API docs, specs and tutorials')
|
||||
->setParam('docs.url', $endpoint . '/docs');
|
||||
|
||||
$specsDir = __DIR__ . '/../../../../app/config/specs';
|
||||
$path = $mocks
|
||||
? $specsDir . '/' . $format . '-mocks-' . $platform . '.json'
|
||||
: $specsDir . '/' . $format . '-' . $version . '-' . $platform . '.json';
|
||||
|
||||
if (!is_dir($specsDir)) {
|
||||
if (!mkdir($specsDir, 0755, true)) {
|
||||
throw new Exception('Failed to create specs directory: ' . $specsDir);
|
||||
}
|
||||
$parsedSpecs = $specs->parse();
|
||||
$encodedSpecs = \json_encode($parsedSpecs, JSON_PRETTY_PRINT);
|
||||
|
||||
unset($parsedSpecs);
|
||||
|
||||
if ($encodedSpecs === false) {
|
||||
throw new Exception('Failed to encode ' . ($mocks ? 'mocks ' : '') . 'spec file: ' . \json_last_error_msg());
|
||||
}
|
||||
|
||||
if ($mocks) {
|
||||
$path = $specsDir . '/' . $format . '-mocks-' . $platform . '.json';
|
||||
|
||||
if (!file_put_contents($path, json_encode($specs->parse(), JSON_PRETTY_PRINT))) {
|
||||
throw new Exception('Failed to save mocks spec file: ' . $path);
|
||||
}
|
||||
|
||||
$generatedFiles[] = realpath($path);
|
||||
Console::success('Saved mocks spec file: ' . realpath($path));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $specsDir . '/' . $format . '-' . $version . '-' . $platform . '.json';
|
||||
|
||||
if (!file_put_contents($path, json_encode($specs->parse(), JSON_PRETTY_PRINT))) {
|
||||
throw new Exception('Failed to save spec file: ' . $path);
|
||||
if (\file_put_contents($path, $encodedSpecs) === false) {
|
||||
throw new Exception('Failed to save ' . ($mocks ? 'mocks ' : '') . 'spec file: ' . $path);
|
||||
}
|
||||
|
||||
$generatedFiles[] = realpath($path);
|
||||
Console::success('Saved spec file: ' . realpath($path));
|
||||
Console::success('Saved ' . ($mocks ? 'mocks ' : '') . 'spec file: ' . realpath($path));
|
||||
|
||||
unset($encodedSpecs, $specs, $formatInstance);
|
||||
}
|
||||
|
||||
unset($arguments, $models, $routes, $services);
|
||||
}
|
||||
|
||||
if ($git === 'yes') {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class User extends Document
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPrivileged(array $roles): bool
|
||||
public function isPrivileged(array $roles): bool
|
||||
{
|
||||
if (
|
||||
in_array(self::ROLE_OWNER, $roles) ||
|
||||
|
|
@ -122,7 +122,7 @@ class User extends Document
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isApp(array $roles): bool
|
||||
public function isApp(array $roles): bool
|
||||
{
|
||||
if (in_array(self::ROLE_APPS, $roles)) {
|
||||
return true;
|
||||
|
|
@ -175,7 +175,5 @@ class User extends Document
|
|||
}
|
||||
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ class Request extends UtopiaRequest
|
|||
$forwardedUserAgent = $this->getHeader('x-forwarded-user-agent');
|
||||
if (!empty($forwardedUserAgent)) {
|
||||
$roles = $this->authorization->getRoles();
|
||||
$isAppUser = User::isApp($roles);
|
||||
$isAppUser = $this->user?->isApp($roles) ?? false;
|
||||
|
||||
if ($isAppUser) {
|
||||
return $forwardedUserAgent;
|
||||
|
|
@ -239,9 +239,15 @@ class Request extends UtopiaRequest
|
|||
}
|
||||
|
||||
private ?Authorization $authorization = null;
|
||||
private ?User $user = null;
|
||||
|
||||
public function setAuthorization(Authorization $authorization): void
|
||||
{
|
||||
$this->authorization = $authorization;
|
||||
}
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,8 +505,9 @@ class Response extends SwooleResponse
|
|||
|
||||
if ($rule['sensitive']) {
|
||||
$roles = $this->authorization->getRoles();
|
||||
$isPrivilegedUser = DBUser::isPrivileged($roles);
|
||||
$isAppUser = DBUser::isApp($roles);
|
||||
$user = $this->user ?? new DBUser();
|
||||
$isPrivilegedUser = $user->isPrivileged($roles);
|
||||
$isAppUser = $user->isApp($roles);
|
||||
|
||||
if ((!$isPrivilegedUser && !$isAppUser) && !self::$showSensitive) {
|
||||
$data->setAttribute($key, '');
|
||||
|
|
@ -674,9 +675,15 @@ class Response extends SwooleResponse
|
|||
}
|
||||
|
||||
private ?Authorization $authorization = null;
|
||||
private ?DBUser $user = null;
|
||||
|
||||
public function setAuthorization(Authorization $authorization): void
|
||||
{
|
||||
$this->authorization = $authorization;
|
||||
}
|
||||
|
||||
public function setUser(DBUser $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3631,7 +3631,7 @@ trait DatabasesBase
|
|||
]);
|
||||
|
||||
$adapter = getenv('_APP_DB_ADAPTER');
|
||||
if ($adapter === 'mongodb') {
|
||||
if ($adapter === 'mongodb' || !$this->getSupportForAttributes()) {
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
} else {
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
|
|
|||
|
|
@ -171,36 +171,40 @@ class UserTest extends TestCase
|
|||
|
||||
public function testIsPrivilegedUser(): void
|
||||
{
|
||||
$this->assertEquals(false, User::isPrivileged([]));
|
||||
$this->assertEquals(false, User::isPrivileged([Role::guests()->toString()]));
|
||||
$this->assertEquals(false, User::isPrivileged([Role::users()->toString()]));
|
||||
$this->assertEquals(true, User::isPrivileged([User::ROLE_ADMIN]));
|
||||
$this->assertEquals(true, User::isPrivileged([User::ROLE_DEVELOPER]));
|
||||
$this->assertEquals(true, User::isPrivileged([User::ROLE_OWNER]));
|
||||
$this->assertEquals(false, User::isPrivileged([User::ROLE_APPS]));
|
||||
$this->assertEquals(false, User::isPrivileged([User::ROLE_SYSTEM]));
|
||||
$user = new User();
|
||||
|
||||
$this->assertEquals(false, User::isPrivileged([User::ROLE_APPS, User::ROLE_APPS]));
|
||||
$this->assertEquals(false, User::isPrivileged([User::ROLE_APPS, Role::guests()->toString()]));
|
||||
$this->assertEquals(true, User::isPrivileged([User::ROLE_OWNER, Role::guests()->toString()]));
|
||||
$this->assertEquals(true, User::isPrivileged([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER]));
|
||||
$this->assertEquals(false, $user->isPrivileged([]));
|
||||
$this->assertEquals(false, $user->isPrivileged([Role::guests()->toString()]));
|
||||
$this->assertEquals(false, $user->isPrivileged([Role::users()->toString()]));
|
||||
$this->assertEquals(true, $user->isPrivileged([User::ROLE_ADMIN]));
|
||||
$this->assertEquals(true, $user->isPrivileged([User::ROLE_DEVELOPER]));
|
||||
$this->assertEquals(true, $user->isPrivileged([User::ROLE_OWNER]));
|
||||
$this->assertEquals(false, $user->isPrivileged([User::ROLE_APPS]));
|
||||
$this->assertEquals(false, $user->isPrivileged([User::ROLE_SYSTEM]));
|
||||
|
||||
$this->assertEquals(false, $user->isPrivileged([User::ROLE_APPS, User::ROLE_APPS]));
|
||||
$this->assertEquals(false, $user->isPrivileged([User::ROLE_APPS, Role::guests()->toString()]));
|
||||
$this->assertEquals(true, $user->isPrivileged([User::ROLE_OWNER, Role::guests()->toString()]));
|
||||
$this->assertEquals(true, $user->isPrivileged([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER]));
|
||||
}
|
||||
|
||||
public function testIsAppUser(): void
|
||||
{
|
||||
$this->assertEquals(false, User::isApp([]));
|
||||
$this->assertEquals(false, User::isApp([Role::guests()->toString()]));
|
||||
$this->assertEquals(false, User::isApp([Role::users()->toString()]));
|
||||
$this->assertEquals(false, User::isApp([User::ROLE_ADMIN]));
|
||||
$this->assertEquals(false, User::isApp([User::ROLE_DEVELOPER]));
|
||||
$this->assertEquals(false, User::isApp([User::ROLE_OWNER]));
|
||||
$this->assertEquals(true, User::isApp([User::ROLE_APPS]));
|
||||
$this->assertEquals(false, User::isApp([User::ROLE_SYSTEM]));
|
||||
$user = new User();
|
||||
|
||||
$this->assertEquals(true, User::isApp([User::ROLE_APPS, User::ROLE_APPS]));
|
||||
$this->assertEquals(true, User::isApp([User::ROLE_APPS, Role::guests()->toString()]));
|
||||
$this->assertEquals(false, User::isApp([User::ROLE_OWNER, Role::guests()->toString()]));
|
||||
$this->assertEquals(false, User::isApp([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER]));
|
||||
$this->assertEquals(false, $user->isApp([]));
|
||||
$this->assertEquals(false, $user->isApp([Role::guests()->toString()]));
|
||||
$this->assertEquals(false, $user->isApp([Role::users()->toString()]));
|
||||
$this->assertEquals(false, $user->isApp([User::ROLE_ADMIN]));
|
||||
$this->assertEquals(false, $user->isApp([User::ROLE_DEVELOPER]));
|
||||
$this->assertEquals(false, $user->isApp([User::ROLE_OWNER]));
|
||||
$this->assertEquals(true, $user->isApp([User::ROLE_APPS]));
|
||||
$this->assertEquals(false, $user->isApp([User::ROLE_SYSTEM]));
|
||||
|
||||
$this->assertEquals(true, $user->isApp([User::ROLE_APPS, User::ROLE_APPS]));
|
||||
$this->assertEquals(true, $user->isApp([User::ROLE_APPS, Role::guests()->toString()]));
|
||||
$this->assertEquals(false, $user->isApp([User::ROLE_OWNER, Role::guests()->toString()]));
|
||||
$this->assertEquals(false, $user->isApp([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER]));
|
||||
}
|
||||
|
||||
public function testGuestRoles(): void
|
||||
|
|
|
|||
Loading…
Reference in a new issue