mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge pull request #6150 from appwrite/fix-global-vars
Fix: Global variables
This commit is contained in:
@@ -1944,6 +1944,17 @@ $projectCollections = array_merge([
|
||||
'array' => false,
|
||||
'filters' => ['subQueryVariables'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('varsProject'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 16384,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => ['subQueryProjectVariables'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('events'),
|
||||
'type' => Database::VAR_STRING,
|
||||
|
||||
@@ -927,10 +927,9 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('events')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $events, Database $dbForConsole) {
|
||||
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Event $events, Database $dbForConsole) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
@@ -990,9 +989,8 @@ App::delete('/v1/functions/:functionId')
|
||||
->inject('dbForProject')
|
||||
->inject('deletes')
|
||||
->inject('events')
|
||||
->inject('project')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $functionId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Document $project, Database $dbForConsole) {
|
||||
->action(function (string $functionId, Response $response, Database $dbForProject, Delete $deletes, Event $events, Database $dbForConsole) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -1434,11 +1432,9 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->inject('project')
|
||||
->inject('gitHub')
|
||||
->inject('events')
|
||||
->action(function (string $functionId, string $deploymentId, string $buildId, Request $request, Response $response, Database $dbForProject, Database $dbForConsole, Document $project, GitHub $github, Event $events) use ($redeployVcs) {
|
||||
->action(function (string $functionId, string $deploymentId, string $buildId, Request $request, Response $response, Database $dbForProject, Document $project, Event $events) use ($redeployVcs) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -1662,15 +1658,14 @@ App::post('/v1/functions/:functionId/executions')
|
||||
$vars = [];
|
||||
|
||||
// Shared vars
|
||||
foreach ($project->getAttribute('variables', []) as $var) {
|
||||
foreach ($function->getAttribute('varsProject', []) as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
|
||||
}
|
||||
|
||||
// Function vars
|
||||
$vars = \array_merge($vars, array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) {
|
||||
$carry[$var->getAttribute('key')] = $var->getAttribute('value') ?? '';
|
||||
return $carry;
|
||||
}, []));
|
||||
foreach ($function->getAttribute('vars', []) as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
|
||||
}
|
||||
|
||||
// Appwrite vars
|
||||
$vars = \array_merge($vars, [
|
||||
@@ -1905,11 +1900,10 @@ App::post('/v1/functions/:functionId/variables')
|
||||
->param('functionId', '', new UID(), 'Function unique ID.', false)
|
||||
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $functionId, string $key, string $value, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) {
|
||||
->action(function (string $functionId, string $key, string $value, Response $response, Database $dbForProject, Database $dbForConsole) {
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
@@ -1938,7 +1932,6 @@ App::post('/v1/functions/:functionId/variables')
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception(Exception::VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false));
|
||||
|
||||
@@ -1950,8 +1943,6 @@ App::post('/v1/functions/:functionId/variables')
|
||||
->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment')));
|
||||
Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule));
|
||||
|
||||
$dbForProject->deleteCachedDocument('functions', $function->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
@@ -1979,8 +1970,8 @@ App::get('/v1/functions/:functionId/variables')
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'variables' => $function->getAttribute('vars'),
|
||||
'total' => \count($function->getAttribute('vars')),
|
||||
'variables' => $function->getAttribute('vars', []),
|
||||
'total' => \count($function->getAttribute('vars', [])),
|
||||
]), Response::MODEL_VARIABLE_LIST);
|
||||
});
|
||||
|
||||
@@ -2040,11 +2031,10 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false)
|
||||
->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $functionId, string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) {
|
||||
->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
@@ -2071,7 +2061,6 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception(Exception::VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false));
|
||||
|
||||
@@ -2083,8 +2072,6 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment')));
|
||||
Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule));
|
||||
|
||||
$dbForProject->deleteCachedDocument('functions', $function->getId());
|
||||
|
||||
$response->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
});
|
||||
|
||||
@@ -2102,11 +2089,10 @@ App::delete('/v1/functions/:functionId/variables/:variableId')
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('functionId', '', new UID(), 'Function unique ID.', false)
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $functionId, string $variableId, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) {
|
||||
->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject, Database $dbForConsole) {
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
@@ -2134,7 +2120,5 @@ App::delete('/v1/functions/:functionId/variables/:variableId')
|
||||
->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment')));
|
||||
Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule));
|
||||
|
||||
$dbForProject->deleteCachedDocument('functions', $function->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
@@ -161,7 +161,6 @@ App::post('/v1/project/variables')
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception(Exception::VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$functions = $dbForProject->find('functions', [
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
@@ -171,8 +170,6 @@ App::post('/v1/project/variables')
|
||||
$dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false));
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
@@ -261,7 +258,6 @@ App::put('/v1/project/variables/:variableId')
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception(Exception::VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
$dbForConsole->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$functions = $dbForProject->find('functions', [
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
@@ -271,8 +267,6 @@ App::put('/v1/project/variables/:variableId')
|
||||
$dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false));
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
});
|
||||
|
||||
@@ -296,6 +290,8 @@ App::delete('/v1/project/variables/:variableId')
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('variables', $variable->getId());
|
||||
|
||||
$functions = $dbForProject->find('functions', [
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
]);
|
||||
@@ -304,8 +300,5 @@ App::delete('/v1/project/variables/:variableId')
|
||||
$dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false));
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('variables', $variable->getId());
|
||||
$dbForProject->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
@@ -228,6 +228,7 @@ App::get('/v1/vcs/github/authorize')
|
||||
->groups(['api', 'vcs'])
|
||||
->label('scope', 'vcs.read')
|
||||
->label('sdk.namespace', 'vcs')
|
||||
->label('error', __DIR__ . '/../../views/general/error.phtml')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.method', 'createGitHubInstallation')
|
||||
->label('sdk.description', '')
|
||||
@@ -248,6 +249,11 @@ App::get('/v1/vcs/github/authorize')
|
||||
]);
|
||||
|
||||
$appName = App::getEnv('_APP_VCS_GITHUB_APP_NAME');
|
||||
|
||||
if (empty($appName)) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'GitHub App name is not configured. Please configure VCS (Version Control System) variables in .env file.');
|
||||
}
|
||||
|
||||
$url = "https://github.com/apps/$appName/installations/new?" . \http_build_query([
|
||||
'state' => $state,
|
||||
'redirect_uri' => $request->getProtocol() . '://' . $request->getHostname() . "/v1/vcs/github/callback"
|
||||
|
||||
@@ -493,7 +493,6 @@ Database::addFilter(
|
||||
}
|
||||
);
|
||||
|
||||
// READ-ONLY! TO update, write directly to 'variables' collection. After update to vars, make sure to deleteCachedDocument()
|
||||
Database::addFilter(
|
||||
'subQueryProjectVariables',
|
||||
function (mixed $value) {
|
||||
|
||||
+6
-12
@@ -321,21 +321,15 @@ class BuildsV1 extends Worker
|
||||
|
||||
$vars = [];
|
||||
|
||||
// Global vars
|
||||
$varsFromProject = $dbForProject->find('variables', [
|
||||
Query::equal('resourceType', ['project']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
]);
|
||||
|
||||
foreach ($varsFromProject as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value') ?? '';
|
||||
// Shared vars
|
||||
foreach ($function->getAttribute('varsProject', []) as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
|
||||
}
|
||||
|
||||
// Function vars
|
||||
$vars = \array_merge($vars, array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) {
|
||||
$carry[$var->getAttribute('key')] = $var->getAttribute('value');
|
||||
return $carry;
|
||||
}, []));
|
||||
foreach ($function->getAttribute('vars', []) as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
|
||||
}
|
||||
|
||||
// Appwrite vars
|
||||
$vars = \array_merge($vars, [
|
||||
|
||||
@@ -143,17 +143,14 @@ Server::setResource('execute', function () {
|
||||
$vars = [];
|
||||
|
||||
// Shared vars
|
||||
$varsShared = $project->getAttribute('variables', []);
|
||||
$vars = \array_merge($vars, \array_reduce($varsShared, function (array $carry, Document $var) {
|
||||
$carry[$var->getAttribute('key')] = $var->getAttribute('value') ?? '';
|
||||
return $carry;
|
||||
}, []));
|
||||
foreach ($function->getAttribute('varsProject', []) as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
|
||||
}
|
||||
|
||||
// Function vars
|
||||
$vars = \array_merge($vars, array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) {
|
||||
$carry[$var->getAttribute('key')] = $var->getAttribute('value');
|
||||
return $carry;
|
||||
}, []));
|
||||
foreach ($function->getAttribute('vars', []) as $var) {
|
||||
$vars[$var->getAttribute('key')] = $var->getAttribute('value', '');
|
||||
}
|
||||
|
||||
// Appwrite vars
|
||||
$vars = \array_merge($vars, [
|
||||
|
||||
@@ -17,14 +17,17 @@ class Exception extends AppwriteException
|
||||
$decoded = json_decode($response, true);
|
||||
if (\is_array($decoded)) {
|
||||
if (\is_array($decoded['error'] ?? '')) {
|
||||
$this->error = $decoded['error']['status'];
|
||||
$this->errorDescription = $decoded['error']['message'];
|
||||
$this->message = $this->error . ': ' . $this->errorDescription;
|
||||
$this->error = $decoded['error']['status'] ?? 'Unknown error';
|
||||
$this->errorDescription = $decoded['error']['message'] ?? 'No description';
|
||||
} elseif (\is_array($decoded['errors'] ?? '')) {
|
||||
$this->error = $decoded['error'] ?? $decoded['message'] ?? 'Unknown error';
|
||||
$this->errorDescription = $decoded['errors'][0]['message'] ?? 'No description';
|
||||
} else {
|
||||
$this->error = $decoded['error'] ?? $decoded['message'] ?? 'Unknown error';
|
||||
$this->errorDescription = $decoded['error_description'] ?? 'No description';
|
||||
$this->message = $this->error . ': ' . $this->errorDescription;
|
||||
}
|
||||
|
||||
$this->message = $this->error . ': ' . $this->errorDescription;
|
||||
}
|
||||
$type = match ($code) {
|
||||
400 => AppwriteException::USER_OAUTH2_BAD_REQUEST,
|
||||
|
||||
@@ -408,6 +408,7 @@ class V19 extends Migration
|
||||
'version',
|
||||
'entrypoint',
|
||||
'commands',
|
||||
'varsProject'
|
||||
];
|
||||
foreach ($attributesToCreate as $attribute) {
|
||||
try {
|
||||
|
||||
@@ -343,6 +343,24 @@ class FunctionsCustomServerTest extends Scope
|
||||
$this->assertEquals('0 0 1 1 *', $response1['body']['schedule']);
|
||||
$this->assertEquals(15, $response1['body']['timeout']);
|
||||
|
||||
/**
|
||||
* Create global variable to test in execution later
|
||||
*/
|
||||
$headers = [
|
||||
'content-type' => 'application/json',
|
||||
'origin' => 'http://localhost',
|
||||
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-mode' => 'admin',
|
||||
];
|
||||
|
||||
$variable = $this->client->call(Client::METHOD_POST, '/project/variables', $headers, [
|
||||
'key' => 'GLOBAL_VARIABLE',
|
||||
'value' => 'Global Variable Value',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $variable['headers']['status-code']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
@@ -640,6 +658,7 @@ class FunctionsCustomServerTest extends Scope
|
||||
$this->assertStringContainsString('http', $execution['body']['responseBody']);
|
||||
$this->assertStringContainsString('PHP', $execution['body']['responseBody']);
|
||||
$this->assertStringContainsString('8.0', $execution['body']['responseBody']);
|
||||
$this->assertStringContainsString('Global Variable Value', $execution['body']['responseBody']);
|
||||
// $this->assertStringContainsString('êä', $execution['body']['responseBody']); // tests unknown utf-8 chars
|
||||
$this->assertEquals('', $execution['body']['errors']);
|
||||
$this->assertEquals('', $execution['body']['logs']);
|
||||
|
||||
@@ -8,6 +8,7 @@ return function ($context) {
|
||||
'APPWRITE_FUNCTION_TRIGGER' => $context->req->headers['x-appwrite-trigger'] ?? '',
|
||||
'APPWRITE_FUNCTION_RUNTIME_NAME' => \getenv('APPWRITE_FUNCTION_RUNTIME_NAME') ?: '',
|
||||
'APPWRITE_FUNCTION_RUNTIME_VERSION' => \getenv('APPWRITE_FUNCTION_RUNTIME_VERSION') ?: '',
|
||||
'UNICODE_TEST' => "êä"
|
||||
'UNICODE_TEST' => "êä",
|
||||
'GLOBAL_VARIABLE' => \getenv('GLOBAL_VARIABLE') ?: ''
|
||||
]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user