mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.9.x' into feat/migrate-di-container
Resolve conflicts keeping DI container migration (container->set pattern) while incorporating 1.9.x fixes: PHPStan unused variable cleanup in GraphQL Resolvers, (int) casts in Builds.php, and phpstan-baseline removal.
This commit is contained in:
@@ -285,7 +285,7 @@ class Event
|
||||
*
|
||||
* @param string $key
|
||||
* @param Document $context
|
||||
* @return self
|
||||
* @return static
|
||||
*/
|
||||
public function setContext(string $key, Document $context): self
|
||||
{
|
||||
@@ -309,7 +309,7 @@ class Event
|
||||
/**
|
||||
* Set class used for this event.
|
||||
* @param string $class
|
||||
* @return self
|
||||
* @return static
|
||||
*/
|
||||
public function setClass(string $class): self
|
||||
{
|
||||
@@ -647,10 +647,8 @@ class Event
|
||||
*
|
||||
* @param Event $event
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
*/
|
||||
public function from(Event $event): self
|
||||
public function from(Event $event): static
|
||||
{
|
||||
$this->project = $event->getProject();
|
||||
$this->user = $event->getUser();
|
||||
|
||||
@@ -25,11 +25,7 @@ class Resolvers
|
||||
?Route $route,
|
||||
): callable {
|
||||
return static fn ($type, $args, $context, $info) => new Swoole(
|
||||
function (callable $resolve, callable $reject) use ($utopia, $route, $args, $context, $info) {
|
||||
/** @var Http $utopia */
|
||||
/** @var Response $response */
|
||||
/** @var Request $request */
|
||||
|
||||
function (callable $resolve, callable $reject) use ($utopia, $route, $args) {
|
||||
$utopia = $utopia->getResource('utopia:graphql');
|
||||
$request = $utopia->getResource('request');
|
||||
$response = $utopia->getResource('response');
|
||||
@@ -96,7 +92,7 @@ class Resolvers
|
||||
callable $url,
|
||||
): callable {
|
||||
return static fn ($type, $args, $context, $info) => new Swoole(
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $type, $args) {
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $args) {
|
||||
$utopia = $utopia->getResource('utopia:graphql');
|
||||
$request = $utopia->getResource('request');
|
||||
$response = $utopia->getResource('response');
|
||||
@@ -127,7 +123,7 @@ class Resolvers
|
||||
callable $params,
|
||||
): callable {
|
||||
return static fn ($type, $args, $context, $info) => new Swoole(
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) {
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) {
|
||||
$utopia = $utopia->getResource('utopia:graphql');
|
||||
$request = $utopia->getResource('request');
|
||||
$response = $utopia->getResource('response');
|
||||
@@ -163,7 +159,7 @@ class Resolvers
|
||||
callable $params,
|
||||
): callable {
|
||||
return static fn ($type, $args, $context, $info) => new Swoole(
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) {
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) {
|
||||
$utopia = $utopia->getResource('utopia:graphql');
|
||||
$request = $utopia->getResource('request');
|
||||
$response = $utopia->getResource('response');
|
||||
@@ -195,7 +191,7 @@ class Resolvers
|
||||
callable $params,
|
||||
): callable {
|
||||
return static fn ($type, $args, $context, $info) => new Swoole(
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $type, $args) {
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $params, $args) {
|
||||
$utopia = $utopia->getResource('utopia:graphql');
|
||||
$request = $utopia->getResource('request');
|
||||
$response = $utopia->getResource('response');
|
||||
@@ -225,7 +221,7 @@ class Resolvers
|
||||
callable $url,
|
||||
): callable {
|
||||
return static fn ($type, $args, $context, $info) => new Swoole(
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $type, $args) {
|
||||
function (callable $resolve, callable $reject) use ($utopia, $databaseId, $collectionId, $url, $args) {
|
||||
$utopia = $utopia->getResource('utopia:graphql');
|
||||
$request = $utopia->getResource('request');
|
||||
$response = $utopia->getResource('response');
|
||||
|
||||
@@ -48,7 +48,7 @@ final class Cors
|
||||
/**
|
||||
* Build CORS headers for a given request origin.
|
||||
*
|
||||
* @return array<string,string>
|
||||
* @return array<string, int|string>
|
||||
*/
|
||||
public function headers(string $origin): array
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ class OpenSSL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encrypt($data, $method, $key, $options = 0, $iv = '', &$tag = null, $aad = '', $tag_length = 16)
|
||||
public static function encrypt($data, $method, $key, $options = 0, $iv = '', ?string &$tag = null, $aad = '', $tag_length = 16)
|
||||
{
|
||||
return \openssl_encrypt($data, $method, $key, $options, $iv, $tag, $aad, $tag_length);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ class Action extends PlatformAction
|
||||
|
||||
$image = new Image(\file_get_contents($path));
|
||||
$image->crop((int) $width, (int) $height);
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
$data = $image->output($output, $quality);
|
||||
$response
|
||||
->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days
|
||||
|
||||
@@ -204,7 +204,6 @@ class Get extends Action
|
||||
|
||||
$image = new Image($data);
|
||||
$image->crop((int) $width, (int) $height);
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
$data = $image->output($output, $quality);
|
||||
|
||||
$response
|
||||
|
||||
@@ -95,7 +95,6 @@ class Get extends Action
|
||||
}
|
||||
|
||||
$image->crop((int) $width, (int) $height);
|
||||
$output = (empty($output)) ? $type : $output;
|
||||
$data = $image->output($output, $quality);
|
||||
|
||||
$response
|
||||
|
||||
@@ -90,7 +90,7 @@ class Get extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$rand = \substr($code, -1);
|
||||
$rand = (int) \substr((string) $code, -1);
|
||||
|
||||
$rand = ($rand > \count($themes) - 1) ? $rand % \count($themes) : $rand;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Action extends AppwriteAction
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
public function setHttpPath(string $path): AppwriteAction
|
||||
public function setHttpPath(string $path): self
|
||||
{
|
||||
if (\str_contains($path, '/tablesdb')) {
|
||||
$this->context = DATABASE_TYPE_TABLESDB;
|
||||
@@ -28,7 +28,8 @@ class Action extends AppwriteAction
|
||||
if (\str_contains($path, '/vectorsdb')) {
|
||||
$this->context = DATABASE_TYPE_VECTORSDB;
|
||||
}
|
||||
return parent::setHttpPath($path);
|
||||
parent::setHttpPath($path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-4
@@ -24,7 +24,7 @@ abstract class Action extends DatabasesAction
|
||||
*/
|
||||
abstract protected function getResponseModel(): string;
|
||||
|
||||
public function setHttpPath(string $path): DatabasesAction
|
||||
public function setHttpPath(string $path): self
|
||||
{
|
||||
if (str_contains($path, '/tablesdb/')) {
|
||||
$this->context = ROWS;
|
||||
@@ -47,7 +47,8 @@ abstract class Action extends DatabasesAction
|
||||
],
|
||||
];
|
||||
|
||||
return parent::setHttpPath($path);
|
||||
parent::setHttpPath($path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getDatabasesOperationReadMetric(): string
|
||||
@@ -406,8 +407,6 @@ abstract class Action extends DatabasesAction
|
||||
|
||||
if (\is_array($related)) {
|
||||
$document->setAttribute($relationship->getAttribute('key'), \array_values($relations));
|
||||
} elseif (empty($relations)) {
|
||||
$document->setAttribute($relationship->getAttribute('key'), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -209,7 +209,7 @@ class Create extends Action
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() . ' with relationship ' . $this->getStructureContext());
|
||||
}
|
||||
|
||||
$setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) {
|
||||
$setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $authorization) {
|
||||
$allowedPermissions = [
|
||||
Database::PERMISSION_READ,
|
||||
Database::PERMISSION_UPDATE,
|
||||
|
||||
-1
@@ -122,7 +122,6 @@ class Update extends Action
|
||||
|
||||
$dbForDatabases = $getDatabasesDB($database);
|
||||
// Read permission should not be required for update
|
||||
/** @var Document $document */
|
||||
$collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence();
|
||||
|
||||
if ($transactionId !== null) {
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ class XList extends Action
|
||||
$cacheKeyBase = \sprintf(
|
||||
'%s-cache-%s:%s:%s:collection:%s:%s:user:%s:%s',
|
||||
$dbForProject->getCacheName(),
|
||||
$hostname ?? '',
|
||||
$hostname,
|
||||
$dbForProject->getNamespace(),
|
||||
$dbForProject->getTenant(),
|
||||
$collectionId,
|
||||
|
||||
@@ -99,8 +99,6 @@ class Update extends Action
|
||||
// Map aggregate permissions into the multiple permissions they represent.
|
||||
$permissions = Permission::aggregate($permissions);
|
||||
|
||||
$enabled ??= $collection->getAttribute('enabled', true);
|
||||
|
||||
$collection = $dbForProject->updateDocument(
|
||||
'database_' . $database->getSequence(),
|
||||
$collectionId,
|
||||
|
||||
@@ -103,6 +103,9 @@ class XList extends Action
|
||||
$os = $detector->getOS();
|
||||
$client = $detector->getClient();
|
||||
$device = $detector->getDevice();
|
||||
$deviceName = \is_array($device) ? ($device['deviceName'] ?? '') : '';
|
||||
$deviceBrand = \is_array($device) ? ($device['deviceBrand'] ?? '') : '';
|
||||
$deviceModel = \is_array($device) ? ($device['deviceModel'] ?? '') : '';
|
||||
|
||||
$output[$i] = new Document([
|
||||
'event' => $log['event'],
|
||||
@@ -121,9 +124,9 @@ class XList extends Action
|
||||
'clientVersion' => $client['clientVersion'],
|
||||
'clientEngine' => $client['clientEngine'],
|
||||
'clientEngineVersion' => $client['clientEngineVersion'],
|
||||
'deviceName' => $device['deviceName'],
|
||||
'deviceBrand' => $device['deviceBrand'],
|
||||
'deviceModel' => $device['deviceModel'],
|
||||
'deviceName' => $deviceName,
|
||||
'deviceBrand' => $deviceBrand,
|
||||
'deviceModel' => $deviceModel,
|
||||
]);
|
||||
|
||||
$record = $geodb->get($log['ip']);
|
||||
|
||||
@@ -33,7 +33,7 @@ abstract class Action extends DatabasesAction
|
||||
return $this->databaseType.'.'.METRIC_DATABASE_ID_OPERATIONS_WRITES;
|
||||
}
|
||||
|
||||
public function setHttpPath(string $path): DatabasesAction
|
||||
public function setHttpPath(string $path): self
|
||||
{
|
||||
switch (true) {
|
||||
case str_contains($path, '/tablesdb'):
|
||||
@@ -50,7 +50,8 @@ abstract class Action extends DatabasesAction
|
||||
$this->databaseType = VECTORSDB;
|
||||
break;
|
||||
}
|
||||
return parent::setHttpPath($path);
|
||||
parent::setHttpPath($path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -239,7 +239,7 @@ class Create extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) {
|
||||
$transaction = $authorization->skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $operations) {
|
||||
$dbForProject->createDocuments('transactionLogs', $staged);
|
||||
return $dbForProject->increaseDocumentAttribute(
|
||||
'transactions',
|
||||
|
||||
@@ -105,8 +105,7 @@ class Update extends Action
|
||||
* @throws Exception
|
||||
* @throws \Throwable
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws Authorization
|
||||
* @throws Structure
|
||||
* @throws StructureException
|
||||
* @throws \Utopia\Http\Exception
|
||||
*/
|
||||
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
|
||||
@@ -183,7 +182,7 @@ class Update extends Action
|
||||
$dbForDatabases = $getDatabasesDB($databaseDoc);
|
||||
|
||||
try {
|
||||
$dbForDatabases->withTransaction(function () use ($dbForDatabases, $dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $queueForEvents, $usage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) {
|
||||
$dbForDatabases->withTransaction(function () use ($dbForDatabases, $dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $authorization) {
|
||||
$authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([
|
||||
'status' => 'committing',
|
||||
])));
|
||||
|
||||
@@ -97,6 +97,9 @@ class XList extends Action
|
||||
$os = $detector->getOS();
|
||||
$client = $detector->getClient();
|
||||
$device = $detector->getDevice();
|
||||
$deviceName = \is_array($device) ? ($device['deviceName'] ?? '') : '';
|
||||
$deviceBrand = \is_array($device) ? ($device['deviceBrand'] ?? '') : '';
|
||||
$deviceModel = \is_array($device) ? ($device['deviceModel'] ?? '') : '';
|
||||
|
||||
$output[$i] = new Document([
|
||||
'event' => $log['event'],
|
||||
@@ -115,9 +118,9 @@ class XList extends Action
|
||||
'clientVersion' => $client['clientVersion'],
|
||||
'clientEngine' => $client['clientEngine'],
|
||||
'clientEngineVersion' => $client['clientEngineVersion'],
|
||||
'deviceName' => $device['deviceName'],
|
||||
'deviceBrand' => $device['deviceBrand'],
|
||||
'deviceModel' => $device['deviceModel'],
|
||||
'deviceName' => $deviceName,
|
||||
'deviceBrand' => $deviceBrand,
|
||||
'deviceModel' => $deviceModel,
|
||||
]);
|
||||
|
||||
$record = $geodb->get($log['ip']);
|
||||
|
||||
@@ -130,9 +130,11 @@ class Create extends CollectionAction
|
||||
$indexes[] = new Document($index);
|
||||
}
|
||||
try {
|
||||
// passing null in creates only creates the metadata collection
|
||||
if (!$dbForDatabases->exists(null, Database::METADATA)) {
|
||||
$dbForDatabases->create();
|
||||
try {
|
||||
$dbForDatabases->create();
|
||||
} catch (DuplicateException) {
|
||||
}
|
||||
}
|
||||
$dbForDatabases->createCollection(
|
||||
id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
|
||||
@@ -213,7 +213,10 @@ class Create extends Base
|
||||
$current = new Document();
|
||||
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Utopia\Database\Document $session */
|
||||
if (!$session instanceof Document) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($proofForToken->verify($store->getProperty('secret', ''), $session->getAttribute('secret'))) { // Find most recent active session for user ID and JWT headers
|
||||
$current = $session;
|
||||
}
|
||||
@@ -237,11 +240,11 @@ class Create extends Base
|
||||
]);
|
||||
|
||||
$executionId = ID::unique();
|
||||
$headers['x-appwrite-execution-id'] = $executionId ?? '';
|
||||
$headers['x-appwrite-execution-id'] = $executionId;
|
||||
$headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey;
|
||||
$headers['x-appwrite-trigger'] = 'http';
|
||||
$headers['x-appwrite-user-id'] = $user->getId() ?? '';
|
||||
$headers['x-appwrite-user-jwt'] = $jwt ?? '';
|
||||
$headers['x-appwrite-user-id'] = $user->getId();
|
||||
$headers['x-appwrite-user-jwt'] = $jwt;
|
||||
$headers['x-appwrite-country-code'] = '';
|
||||
$headers['x-appwrite-continent-code'] = '';
|
||||
$headers['x-appwrite-continent-eu'] = 'false';
|
||||
@@ -350,16 +353,18 @@ class Create extends Base
|
||||
}
|
||||
}
|
||||
|
||||
$this->enqueueDeletes(
|
||||
$project,
|
||||
$function->getSequence(),
|
||||
$executionsRetentionCount,
|
||||
if ($executionsRetentionCount > 0 && ENABLE_EXECUTIONS_LIMIT_ON_ROUTE) {
|
||||
$queueForDeletes
|
||||
);
|
||||
->setProject($project)
|
||||
->setResource($function->getSequence())
|
||||
->setResourceType(RESOURCE_TYPE_FUNCTIONS)
|
||||
->setType(DELETE_TYPE_EXECUTIONS_LIMIT)
|
||||
->trigger();
|
||||
}
|
||||
|
||||
return $response
|
||||
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
|
||||
->dynamic($execution, Response::MODEL_EXECUTION);
|
||||
$response->setStatusCode(Response::STATUS_CODE_ACCEPTED);
|
||||
$response->dynamic($execution, Response::MODEL_EXECUTION);
|
||||
return;
|
||||
}
|
||||
|
||||
$durationStart = \microtime(true);
|
||||
@@ -370,7 +375,7 @@ class Create extends Base
|
||||
if ($version === 'v2') {
|
||||
$vars = \array_merge($vars, [
|
||||
'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '',
|
||||
'APPWRITE_FUNCTION_DATA' => $body ?? '',
|
||||
'APPWRITE_FUNCTION_DATA' => $body,
|
||||
'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '',
|
||||
'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? ''
|
||||
]);
|
||||
@@ -537,32 +542,18 @@ class Create extends Base
|
||||
}
|
||||
}
|
||||
|
||||
$this->enqueueDeletes(
|
||||
$project,
|
||||
$function->getSequence(),
|
||||
$executionsRetentionCount,
|
||||
if ($executionsRetentionCount > 0 && ENABLE_EXECUTIONS_LIMIT_ON_ROUTE) {
|
||||
$queueForDeletes
|
||||
);
|
||||
->setProject($project)
|
||||
->setResource($function->getSequence())
|
||||
->setResourceType(RESOURCE_TYPE_FUNCTIONS)
|
||||
->setType(DELETE_TYPE_EXECUTIONS_LIMIT)
|
||||
->trigger();
|
||||
}
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($execution, Response::MODEL_EXECUTION);
|
||||
}
|
||||
|
||||
private function enqueueDeletes(
|
||||
Document $project,
|
||||
string $resourceId,
|
||||
int $executionsRetentionCount,
|
||||
DeleteEvent $queueForDeletes
|
||||
): void {
|
||||
/* cleanup */
|
||||
if ($executionsRetentionCount > 0 && ENABLE_EXECUTIONS_LIMIT_ON_ROUTE) {
|
||||
$queueForDeletes
|
||||
->setProject($project)
|
||||
->setResource($resourceId)
|
||||
->setResourceType(RESOURCE_TYPE_FUNCTIONS)
|
||||
->setType(DELETE_TYPE_EXECUTIONS_LIMIT)
|
||||
->trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,8 +424,8 @@ class Create extends Base
|
||||
|
||||
/** Trigger Realtime Events */
|
||||
$queueForRealtime
|
||||
->from($ruleCreate)
|
||||
->setSubscribers(['console', $project->getId()])
|
||||
->from($ruleCreate)
|
||||
->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ class Builds extends Action
|
||||
|
||||
$providerCommitHash = \trim($stdout);
|
||||
|
||||
$deployment->setAttribute('providerCommitHash', $providerCommitHash ?? '');
|
||||
$deployment->setAttribute('providerCommitHash', $providerCommitHash);
|
||||
$deployment->setAttribute('providerCommitAuthorUrl', APP_VCS_GITHUB_URL);
|
||||
$deployment->setAttribute('providerCommitAuthor', APP_VCS_GITHUB_USERNAME);
|
||||
$deployment->setAttribute('providerCommitMessage', "Create '" . $resource->getAttribute('name', '') . "' function");
|
||||
@@ -862,7 +862,7 @@ class Builds extends Action
|
||||
if (\str_contains($logs, '{APPWRITE_DETECTION_SEPARATOR_START}')) {
|
||||
[$logsBefore, $detectionLogsStart] = \explode('{APPWRITE_DETECTION_SEPARATOR_START}', $logs, 2);
|
||||
[$detectionLogs, $logsAfter] = \explode('{APPWRITE_DETECTION_SEPARATOR_END}', $detectionLogsStart, 2);
|
||||
$logs = ($logsBefore ?? '') . ($logsAfter ?? '');
|
||||
$logs = $logsBefore . $logsAfter;
|
||||
}
|
||||
|
||||
$deployment->setAttribute('buildLogs', $logs);
|
||||
@@ -1203,8 +1203,8 @@ class Builds extends Action
|
||||
protected function sendUsage(Document $resource, Document $deployment, Document $project, Context $usage, UsagePublisher $publisherForUsage): void
|
||||
{
|
||||
$spec = Config::getParam('specifications')[$resource->getAttribute('buildSpecification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
|
||||
$cpus = $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT;
|
||||
$memory = $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT;
|
||||
$cpus = (int) ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT);
|
||||
$memory = (int) ($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT);
|
||||
|
||||
switch ($deployment->getAttribute('status')) {
|
||||
case 'ready':
|
||||
@@ -1366,6 +1366,8 @@ class Builds extends Action
|
||||
Realtime $queueForRealtime,
|
||||
array $platform
|
||||
): void {
|
||||
$deployment = new Document();
|
||||
|
||||
try {
|
||||
if ($resource->getAttribute('providerSilentMode', false) === true) {
|
||||
return;
|
||||
@@ -1446,7 +1448,7 @@ class Builds extends Action
|
||||
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https';
|
||||
$previewUrl = match ($resource->getCollection()) {
|
||||
'functions' => '',
|
||||
'sites' => ! empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : '',
|
||||
'sites' => !$rule->isEmpty() ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : '',
|
||||
default => throw new \Exception('Invalid resource type')
|
||||
};
|
||||
|
||||
|
||||
@@ -83,7 +83,8 @@ class Update extends Action
|
||||
|
||||
// If rule is already verified or in certificate generation state, don't queue for verification again
|
||||
if ($rule->getAttribute('status') === RULE_STATUS_VERIFIED || $rule->getAttribute('status') === RULE_STATUS_CERTIFICATE_GENERATING) {
|
||||
return $response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
$response->dynamic($rule, Response::MODEL_PROXY_RULE);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -286,6 +286,8 @@ class Create extends Action
|
||||
$mimeType = $deviceForFiles->getFileMimeType($path); // Get mime-type before compression and encryption
|
||||
$fileHash = $deviceForFiles->getFileHash($path); // Get file hash before compression and encryption
|
||||
$data = '';
|
||||
$iv = '';
|
||||
$tag = null;
|
||||
// Compression
|
||||
$algorithm = $bucket->getAttribute('compression', Compression::NONE);
|
||||
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != Compression::NONE) {
|
||||
|
||||
@@ -17,6 +17,7 @@ use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use libphonenumber\NumberParseException;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use Throwable;
|
||||
use Utopia\Auth\Proofs\Password;
|
||||
use Utopia\Auth\Proofs\Token;
|
||||
use Utopia\Database\Database;
|
||||
@@ -102,6 +103,8 @@ class Create extends Action
|
||||
{
|
||||
$isAppUser = $user->isApp($authorization->getRoles());
|
||||
$isPrivilegedUser = $user->isPrivileged($authorization->getRoles());
|
||||
$invitee = new Document();
|
||||
$hash = '';
|
||||
|
||||
if (empty($url)) {
|
||||
if (! $isAppUser && ! $isPrivilegedUser) {
|
||||
@@ -145,9 +148,6 @@ class Create extends Action
|
||||
}
|
||||
} elseif (! empty($phone)) {
|
||||
$invitee = $dbForProject->findOne('users', [Query::equal('phone', [$phone])]);
|
||||
if (! $invitee->isEmpty() && ! empty($email) && $invitee->getAttribute('email', '') !== $email) {
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS, 'Given phone and email doesn\'t match', 409);
|
||||
}
|
||||
}
|
||||
|
||||
if ($invitee->isEmpty()) { // Create new user if no user with same email found
|
||||
|
||||
@@ -124,7 +124,7 @@ class Doctor extends Action
|
||||
$providerConfig = System::getEnv('_APP_LOGGING_CONFIG', '');
|
||||
|
||||
try {
|
||||
$loggingProvider = new DSN($providerConfig ?? '');
|
||||
$loggingProvider = new DSN($providerConfig);
|
||||
|
||||
$providerName = $loggingProvider->getScheme();
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ class Install extends Action
|
||||
// Fall back to CLI mode
|
||||
$enableAssistant = false;
|
||||
$assistantExistsInOldCompose = false;
|
||||
if ($existingInstallation && isset($compose)) {
|
||||
if ($existingInstallation) {
|
||||
try {
|
||||
$assistantService = $compose->getService('appwrite-assistant');
|
||||
$assistantExistsInOldCompose = $assistantService !== null;
|
||||
|
||||
@@ -566,6 +566,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
|
||||
$repoBranch = $language['repoBranch'] ?? 'main';
|
||||
if ($git && !empty($gitUrl)) {
|
||||
$prUrls = [];
|
||||
|
||||
// Generate commit message: use provided message, AI changelog, or fallback
|
||||
if (! empty($message)) {
|
||||
$commitMessage = $message;
|
||||
|
||||
@@ -60,7 +60,7 @@ class StatsResources extends Action
|
||||
|
||||
$interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600');
|
||||
|
||||
Console::loop(function () use ($queueForStatsResources, $dbForPlatform) {
|
||||
Console::loop(function () use ($queueForStatsResources) {
|
||||
|
||||
$last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours'));
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,6 @@ use Exception;
|
||||
use Throwable;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Authorization;
|
||||
use Utopia\Database\Exception\Structure;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
@@ -51,13 +50,11 @@ class Audits extends Action
|
||||
|
||||
/**
|
||||
* @param Message $message
|
||||
* @param callable $getProjectDB
|
||||
* @param Document $project
|
||||
* @param callable $getAudit
|
||||
* @param callable(Document): \Utopia\Audit\Audit $getAudit
|
||||
* @return Commit|NoCommit
|
||||
* @throws Throwable
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws Authorization
|
||||
* @throws Structure
|
||||
*/
|
||||
public function action(Message $message, Document $project, callable $getAudit): Commit|NoCommit
|
||||
|
||||
@@ -24,7 +24,6 @@ use Utopia\Database\Exception\Conflict;
|
||||
use Utopia\Database\Exception\Restricted;
|
||||
use Utopia\Database\Exception\Structure;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\DSN\DSN;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
@@ -363,7 +362,6 @@ class Deletes extends Action
|
||||
/**
|
||||
* @param Document $project
|
||||
* @param callable $getProjectDB
|
||||
* @param Document $target
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
@@ -438,7 +436,6 @@ class Deletes extends Action
|
||||
* @param string $resource
|
||||
* @param string|null $resourceType
|
||||
* @return void
|
||||
* @throws Authorization
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, ?string $resourceType = null): void
|
||||
@@ -518,7 +515,6 @@ class Deletes extends Action
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Database $dbForPlatform
|
||||
* @param callable $getProjectDB
|
||||
* @param string $hourlyUsageRetentionDatetime
|
||||
* @return void
|
||||
@@ -586,7 +582,6 @@ class Deletes extends Action
|
||||
* @param Database $dbForPlatform
|
||||
* @param Document $document
|
||||
* @return void
|
||||
* @throws Authorization
|
||||
* @throws DatabaseException
|
||||
* @throws Conflict
|
||||
* @throws Restricted
|
||||
@@ -623,7 +618,6 @@ class Deletes extends Action
|
||||
* @param Document $document
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws Authorization
|
||||
* @throws DatabaseException
|
||||
*/
|
||||
protected function deleteProject(Database $dbForPlatform, callable $getProjectDB, callable $getDatabasesDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void
|
||||
@@ -952,7 +946,7 @@ class Deletes extends Action
|
||||
// fast path, no need to list anything!
|
||||
$delete($dbForProject, $resourceInternalId, $resourceType);
|
||||
} else {
|
||||
$processResource = function (string $type) use ($dbForProject, $delete, $resourceType) {
|
||||
$processResource = function (string $type) use ($dbForProject, $delete) {
|
||||
$this->listByGroup(
|
||||
collection: $type,
|
||||
queries: [Query::select(['$id', '$sequence'])],
|
||||
@@ -1109,7 +1103,7 @@ class Deletes extends Action
|
||||
Query::equal('resourceInternalId', [$siteInternalId]),
|
||||
Query::equal('resourceType', ['sites']),
|
||||
Query::orderAsc()
|
||||
], $dbForProject, function (Document $document) use ($project, $certificates, $deviceForSites, $deviceForBuilds, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) {
|
||||
], $dbForProject, function (Document $document) use ($deviceForSites, $deviceForBuilds, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds, &$deploymentIds) {
|
||||
$deploymentInternalIds[] = $document->getSequence();
|
||||
$deploymentIds[] = $document->getId();
|
||||
$this->deleteBuildFiles($deviceForBuilds, $document);
|
||||
@@ -1172,7 +1166,7 @@ class Deletes extends Action
|
||||
Query::equal('deploymentResourceInternalId', [$functionInternalId]),
|
||||
Query::equal('projectInternalId', [$project->getSequence()]),
|
||||
Query::orderAsc()
|
||||
], $dbForPlatform, function (Document $document) use ($project, $dbForPlatform, $certificates) {
|
||||
], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) {
|
||||
$this->deleteRule($dbForPlatform, $document, $certificates);
|
||||
});
|
||||
|
||||
@@ -1196,7 +1190,7 @@ class Deletes extends Action
|
||||
Query::equal('resourceInternalId', [$functionInternalId]),
|
||||
Query::equal('resourceType', ['functions']),
|
||||
Query::orderAsc()
|
||||
], $dbForProject, function (Document $document) use ($dbForPlatform, $project, $certificates, $deviceForFunctions, $deviceForBuilds, &$deploymentInternalIds) {
|
||||
], $dbForProject, function (Document $document) use ($deviceForFunctions, $deviceForBuilds, &$deploymentInternalIds) {
|
||||
$deploymentInternalIds[] = $document->getSequence();
|
||||
$this->deleteDeploymentFiles($deviceForFunctions, $document);
|
||||
$this->deleteBuildFiles($deviceForBuilds, $document);
|
||||
@@ -1321,7 +1315,7 @@ class Deletes extends Action
|
||||
|
||||
/**
|
||||
* @param Device $device
|
||||
* @param Document $build
|
||||
* @param Document $deployment
|
||||
* @return void
|
||||
*/
|
||||
private function deleteBuildFiles(Device $device, Document $deployment): void
|
||||
@@ -1631,9 +1625,9 @@ class Deletes extends Action
|
||||
try {
|
||||
$dbForProject->deleteDocuments('transactions', [
|
||||
Query::lessThan('expiresAt', DateTime::format(new \DateTime())),
|
||||
], onNext: function (Document $transaction) use ($dbForProject, $project, &$transactionInternalIds) {
|
||||
], onNext: function (Document $transaction) use (&$transactionInternalIds) {
|
||||
$transactionInternalIds[] = $transaction->getSequence();
|
||||
}, onError: function (Throwable $th) use ($project) {
|
||||
}, onError: function (Throwable $th) {
|
||||
// Swallow errors to avoid breaking the cleanup process
|
||||
});
|
||||
} catch (Throwable $th) {
|
||||
@@ -1646,7 +1640,7 @@ class Deletes extends Action
|
||||
|
||||
$dbForProject->deleteDocuments('transactionLogs', [
|
||||
Query::equal('transactionInternalId', $transactionInternalIds),
|
||||
], onError: function (Throwable $th) use ($project) {
|
||||
], onError: function (Throwable $th) {
|
||||
// Swallow errors to avoid breaking the cleanup process
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class Functions extends Action
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -256,7 +256,7 @@ class Functions extends Action
|
||||
* @param Document $user
|
||||
* @param string|null $jwt
|
||||
* @param string|null $event
|
||||
* @throws Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function fail(
|
||||
string $message,
|
||||
@@ -271,10 +271,10 @@ class Functions extends Action
|
||||
?string $event = null,
|
||||
): void {
|
||||
$executionId = ID::unique();
|
||||
$headers['x-appwrite-execution-id'] = $executionId ?? '';
|
||||
$headers['x-appwrite-execution-id'] = $executionId;
|
||||
$headers['x-appwrite-trigger'] = $trigger;
|
||||
$headers['x-appwrite-event'] = $event ?? '';
|
||||
$headers['x-appwrite-user-id'] = $user->getId() ?? '';
|
||||
$headers['x-appwrite-user-id'] = $user->getId();
|
||||
$headers['x-appwrite-user-jwt'] = $jwt ?? '';
|
||||
|
||||
$headersFiltered = [];
|
||||
@@ -458,8 +458,8 @@ class Functions extends Action
|
||||
if ($version === 'v2') {
|
||||
$vars = \array_merge($vars, [
|
||||
'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '',
|
||||
'APPWRITE_FUNCTION_DATA' => $body ?? '',
|
||||
'APPWRITE_FUNCTION_EVENT_DATA' => $body ?? '',
|
||||
'APPWRITE_FUNCTION_DATA' => $body,
|
||||
'APPWRITE_FUNCTION_EVENT_DATA' => $body,
|
||||
'APPWRITE_FUNCTION_EVENT' => $headers['x-appwrite-event'] ?? '',
|
||||
'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '',
|
||||
'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? ''
|
||||
@@ -508,6 +508,9 @@ class Functions extends Action
|
||||
]);
|
||||
|
||||
/** Execute function */
|
||||
$error = null;
|
||||
$errorCode = 0;
|
||||
|
||||
try {
|
||||
$version = $function->getAttribute('version', 'v2');
|
||||
$command = $runtime['startCommand'];
|
||||
|
||||
@@ -285,7 +285,7 @@ class Messaging extends Action
|
||||
|
||||
try {
|
||||
$response = $adapter->send($data);
|
||||
$deliveredTotal += $response['deliveredTo'];
|
||||
$deliveredTotal += (int) $response['deliveredTo'];
|
||||
foreach ($response['results'] as $result) {
|
||||
if ($result['status'] === 'failure') {
|
||||
$deliveryErrors[] = "Failed sending to target {$result['recipient']} with error: {$result['error']}";
|
||||
@@ -380,7 +380,7 @@ class Messaging extends Action
|
||||
]));
|
||||
|
||||
// Delete any attachments that were downloaded to local storage
|
||||
if ($provider->getAttribute('type') === MESSAGE_TYPE_EMAIL) {
|
||||
if ($providerType === MESSAGE_TYPE_EMAIL) {
|
||||
if ($deviceForFiles->getType() === Storage::DEVICE_LOCAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -408,6 +408,7 @@ class Migrations extends Action
|
||||
$tempAPIKey = $this->generateAPIKey($project);
|
||||
|
||||
$transfer = $source = $destination = null;
|
||||
$aggregatedResources = [];
|
||||
|
||||
$host = System::getEnv('_APP_MIGRATION_HOST');
|
||||
if (empty($host)) {
|
||||
@@ -444,7 +445,6 @@ class Migrations extends Action
|
||||
$destination
|
||||
);
|
||||
|
||||
$aggregatedResources = [];
|
||||
/** Start Transfer */
|
||||
if (empty($source->getErrors())) {
|
||||
$migration->setAttribute('stage', 'migrating');
|
||||
|
||||
@@ -208,7 +208,7 @@ class StatsResources extends Action
|
||||
{
|
||||
$totalFiles = 0;
|
||||
$totalStorage = 0;
|
||||
$this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $dbForLogs, $region, &$totalFiles, &$totalStorage) {
|
||||
$this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $region, &$totalFiles, &$totalStorage) {
|
||||
try {
|
||||
$files = $dbForProject->count('bucket_' . $bucket->getSequence());
|
||||
} catch (Throwable $th) {
|
||||
|
||||
@@ -140,7 +140,7 @@ class StatsUsage extends Action
|
||||
|
||||
/**
|
||||
* @param Message $message
|
||||
* @param callable(): Database $getProjectDB
|
||||
* @param callable(Document): Database $getProjectDB
|
||||
* @param callable(): Database $getLogsDB
|
||||
* @param Registry $register
|
||||
* @return void
|
||||
@@ -212,7 +212,7 @@ class StatsUsage extends Action
|
||||
* @param Document $project
|
||||
* @param Document $document
|
||||
* @param array $metrics
|
||||
* @param callable(): Database $getProjectDB
|
||||
* @param callable(Document): Database $getProjectDB
|
||||
* @param string $databaseType Database type from context
|
||||
* @return void
|
||||
*/
|
||||
@@ -394,7 +394,7 @@ class StatsUsage extends Action
|
||||
|
||||
/**
|
||||
* Commit stats to DB
|
||||
* @param callable(): Database $getProjectDB
|
||||
* @param callable(Document): Database $getProjectDB
|
||||
* @return void
|
||||
*/
|
||||
public function commitToDb(callable $getProjectDB): void
|
||||
@@ -459,7 +459,7 @@ class StatsUsage extends Action
|
||||
/**
|
||||
* Sort by unique index key reduce locks/deadlocks
|
||||
*/
|
||||
usort($projectStats['stats'], function ($a, $b) use ($sequence) {
|
||||
usort($projectStats['stats'], function ($a, $b) {
|
||||
// Metric DESC
|
||||
$cmp = strcmp($b['metric'], $a['metric']);
|
||||
if ($cmp !== 0) {
|
||||
|
||||
@@ -233,7 +233,7 @@ class Webhooks extends Action
|
||||
$template->setParam('{{webhook}}', $webhook->getAttribute('name'));
|
||||
$template->setParam('{{project}}', $project->getAttribute('name'));
|
||||
$template->setParam('{{url}}', $webhook->getAttribute('url'));
|
||||
$template->setParam('{{error}}', $curlError ?? 'The server returned ' . $statusCode . ' status code');
|
||||
$template->setParam('{{error}}', 'The server returned ' . $statusCode . ' status code');
|
||||
$template->setParam('{{path}}', "/console/project-$region-$projectId/settings/webhooks/$webhookId");
|
||||
$template->setParam('{{attempts}}', $attempts);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Appwrite\Promises;
|
||||
|
||||
/** @phpstan-consistent-constructor */
|
||||
abstract class Promise
|
||||
{
|
||||
protected const STATE_PENDING = 1;
|
||||
|
||||
@@ -197,7 +197,7 @@ class Method
|
||||
|
||||
public function isHidden(): bool|array
|
||||
{
|
||||
return $this->hide ?? false;
|
||||
return $this->hide;
|
||||
}
|
||||
|
||||
public function isPackaging(): bool
|
||||
|
||||
@@ -86,7 +86,6 @@ class User extends Document
|
||||
/**
|
||||
* Check if user is anonymous.
|
||||
*
|
||||
* @param Document $this
|
||||
* @return bool
|
||||
*/
|
||||
public function isAnonymous(): bool
|
||||
@@ -153,7 +152,6 @@ class User extends Document
|
||||
/**
|
||||
* Verify session and check that its not expired.
|
||||
*
|
||||
* @param array<Document> $sessions
|
||||
* @param string $secret
|
||||
*
|
||||
* @return bool|string
|
||||
|
||||
Reference in New Issue
Block a user