mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Shared variables
This commit is contained in:
@@ -3715,7 +3715,18 @@ $collections = [
|
||||
'name' => 'variables',
|
||||
'attributes' => [
|
||||
[
|
||||
'$id' => 'functionInternalId',
|
||||
'$id' => ID::custom('resourceType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 100,
|
||||
'signed' => true,
|
||||
'required' => true,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resourceInternalId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
@@ -3726,7 +3737,7 @@ $collections = [
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => 'functionId',
|
||||
'$id' => ID::custom('resourceId'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => Database::LENGTH_KEY,
|
||||
@@ -3772,18 +3783,32 @@ $collections = [
|
||||
],
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_key_function',
|
||||
'$id' => '_key_resourceInternalId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['functionInternalId'],
|
||||
'attributes' => ['resourceInternalId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_resourceId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['resourceId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_resourceType',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['resourceType'],
|
||||
'lengths' => [100],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_uniqueKey',
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'attributes' => ['functionInternalId', 'key'],
|
||||
'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
'attributes' => ['resourceId', 'key', 'resourceType'],
|
||||
'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY, 100],
|
||||
'orders' => [Database::ORDER_ASC, Database::ORDER_ASC, Database::ORDER_ASC],
|
||||
],
|
||||
[
|
||||
'$id' => '_key_key',
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -47,6 +47,8 @@ use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
|
||||
include_once __DIR__ . '/../shared/api.php';
|
||||
|
||||
// TODO: @Meldiron Changes to variables must delete runtime on executor
|
||||
|
||||
App::post('/v1/functions')
|
||||
->groups(['api', 'functions'])
|
||||
->desc('Create Function')
|
||||
@@ -1270,11 +1272,24 @@ App::post('/v1/functions/:functionId/executions')
|
||||
->dynamic($execution, Response::MODEL_EXECUTION);
|
||||
}
|
||||
|
||||
$vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) {
|
||||
$vars = [];
|
||||
|
||||
// Shared vars
|
||||
$vars = \array_merge($vars, \array_reduce($dbForProject->find('variables', [
|
||||
Query::equal('resourceType', ['project']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
]), function (array $carry, Document $var) {
|
||||
$carry[$var->getAttribute('key')] = $var->getAttribute('value') ?? '';
|
||||
return $carry;
|
||||
}, []);
|
||||
}, []));
|
||||
|
||||
// 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;
|
||||
}, []));
|
||||
|
||||
// Appwrite vars
|
||||
$vars = \array_merge($vars, [
|
||||
'APPWRITE_FUNCTION_ID' => $function->getId(),
|
||||
'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'),
|
||||
@@ -1507,11 +1522,12 @@ App::post('/v1/functions/:functionId/variables')
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
'functionInternalId' => $function->getInternalId(),
|
||||
'functionId' => $function->getId(),
|
||||
'resourceInternalId' => $function->getInternalId(),
|
||||
'resourceId' => $function->getId(),
|
||||
'resourceType' => 'function',
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'search' => implode(' ', [$variableId, $function->getId(), $key]),
|
||||
'search' => implode(' ', [$variableId, $function->getId(), $key, 'function']),
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -1578,7 +1594,8 @@ App::get('/v1/functions/:functionId/variables/:variableId')
|
||||
|
||||
$variable = $dbForProject->findOne('variables', [
|
||||
Query::equal('$id', [$variableId]),
|
||||
Query::equal('functionInternalId', [$function->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$function->getInternalId()]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
]);
|
||||
|
||||
if ($variable === false || $variable->isEmpty()) {
|
||||
@@ -1617,7 +1634,8 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
|
||||
$variable = $dbForProject->findOne('variables', [
|
||||
Query::equal('$id', [$variableId]),
|
||||
Query::equal('functionInternalId', [$function->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$function->getInternalId()]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
]);
|
||||
|
||||
if ($variable === false || $variable->isEmpty()) {
|
||||
@@ -1627,7 +1645,7 @@ App::put('/v1/functions/:functionId/variables/:variableId')
|
||||
$variable
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('value', $value ?? $variable->getAttribute('value'))
|
||||
->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key]))
|
||||
->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key, 'function']))
|
||||
;
|
||||
|
||||
try {
|
||||
@@ -1666,7 +1684,8 @@ App::delete('/v1/functions/:functionId/variables/:variableId')
|
||||
|
||||
$variable = $dbForProject->findOne('variables', [
|
||||
Query::equal('$id', [$variableId]),
|
||||
Query::equal('functionInternalId', [$function->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$function->getInternalId()]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
]);
|
||||
|
||||
if ($variable === false || $variable->isEmpty()) {
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
<?php
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
use Utopia\Database\ID;
|
||||
use Utopia\Database\Permission;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
// TODO: @Meldiron Changes to variables must delete runtime on executor
|
||||
|
||||
App::get('/v1/project/usage')
|
||||
->desc('Get usage stats for a project')
|
||||
->groups(['api'])
|
||||
@@ -110,3 +119,180 @@ App::get('/v1/project/usage')
|
||||
|
||||
$response->dynamic($usage, Response::MODEL_USAGE_PROJECT);
|
||||
});
|
||||
|
||||
|
||||
// Variables
|
||||
|
||||
App::post('/v1/project/variables')
|
||||
->desc('Create Variable')
|
||||
->groups(['api'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('audits.event', 'variable.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'project')
|
||||
->label('sdk.method', 'createVariable')
|
||||
->label('sdk.description', '/docs/references/project/create-variable.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_VARIABLE)
|
||||
->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false)
|
||||
->param('value', null, new Text(8192), 'Variable value. Max length: 8192 chars.', false)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $key, string $value, Document $project, Response $response, Database $dbForProject) {
|
||||
$variableId = ID::unique();
|
||||
|
||||
$variable = new Document([
|
||||
'$id' => $variableId,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
],
|
||||
'resourceInternalId' => '',
|
||||
'resourceId' => '',
|
||||
'resourceType' => 'project',
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'search' => implode(' ', [$variableId, $key, 'project']),
|
||||
]);
|
||||
|
||||
try {
|
||||
$variable = $dbForProject->createDocument('variables', $variable);
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception(Exception::VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
});
|
||||
|
||||
App::get('/v1/project/variables')
|
||||
->desc('List Variables')
|
||||
->groups(['api'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'project')
|
||||
->label('sdk.method', 'listVariables')
|
||||
->label('sdk.description', '/docs/references/project/list-variables.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_VARIABLE_LIST)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (Response $response, Database $dbForProject) {
|
||||
$variables = $dbForProject->find('variables', [
|
||||
Query::equal('resourceType', ['project']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
]);
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'variables' => $variables,
|
||||
'total' => \count($variables),
|
||||
]), Response::MODEL_VARIABLE_LIST);
|
||||
});
|
||||
|
||||
App::get('/v1/project/variables/:variableId')
|
||||
->desc('Get Variable')
|
||||
->groups(['api'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'project')
|
||||
->label('sdk.method', 'getVariable')
|
||||
->label('sdk.description', '/docs/references/project/get-variable.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_VARIABLE)
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $variableId, Response $response, Database $dbForProject) {
|
||||
$variable = $dbForProject->findOne('variables', [
|
||||
Query::equal('$id', [$variableId]),
|
||||
Query::equal('resourceType', ['project']),
|
||||
]);
|
||||
|
||||
if ($variable === false || $variable->isEmpty()) {
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
});
|
||||
|
||||
App::put('/v1/project/variables/:variableId')
|
||||
->desc('Update Variable')
|
||||
->groups(['api'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'project')
|
||||
->label('sdk.method', 'updateVariable')
|
||||
->label('sdk.description', '/docs/references/project/update-variable.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_VARIABLE)
|
||||
->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), 'Variable value. Max length: 8192 chars.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject) {
|
||||
$variable = $dbForProject->findOne('variables', [
|
||||
Query::equal('$id', [$variableId]),
|
||||
Query::equal('resourceType', ['project']),
|
||||
]);
|
||||
|
||||
if ($variable === false || $variable->isEmpty()) {
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$variable
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('value', $value ?? $variable->getAttribute('value'))
|
||||
->setAttribute('search', implode(' ', [$variableId, $key, 'project']))
|
||||
;
|
||||
|
||||
try {
|
||||
$dbForProject->updateDocument('variables', $variable->getId(), $variable);
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception(Exception::VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->dynamic($variable, Response::MODEL_VARIABLE);
|
||||
});
|
||||
|
||||
App::delete('/v1/project/variables/:variableId')
|
||||
->desc('Delete Variable')
|
||||
->groups(['api'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'project')
|
||||
->label('sdk.method', 'deleteVariable')
|
||||
->label('sdk.description', '/docs/references/project/delete-variable.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('variableId', '', new UID(), 'Variable unique ID.', false)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(function (string $variableId, Document $project, Response $response, Database $dbForProject) {
|
||||
$variable = $dbForProject->findOne('variables', [
|
||||
Query::equal('$id', [$variableId]),
|
||||
Query::equal('resourceType', ['project']),
|
||||
]);
|
||||
|
||||
if ($variable === false || $variable->isEmpty()) {
|
||||
throw new Exception(Exception::VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('variables', $variable->getId());
|
||||
$dbForProject->deleteCachedDocument('projects', $project->getId());
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
|
||||
+2
-1
@@ -399,7 +399,8 @@ Database::addFilter(
|
||||
function (mixed $value, Document $document, Database $database) {
|
||||
return $database
|
||||
->find('variables', [
|
||||
Query::equal('functionInternalId', [$document->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$document->getInternalId()]),
|
||||
Query::equal('resourceType', ['function']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -467,7 +467,8 @@ class DeletesV1 extends Worker
|
||||
*/
|
||||
Console::info("Deleting variables for function " . $functionId);
|
||||
$this->deleteByGroup('variables', [
|
||||
Query::equal('functionId', [$functionId])
|
||||
Query::equal('resourceType', ['function']),
|
||||
Query::equal('resourceInternalId', [$document->getInternalId()])
|
||||
], $dbForProject);
|
||||
|
||||
/**
|
||||
@@ -512,7 +513,7 @@ class DeletesV1 extends Worker
|
||||
Query::equal('functionId', [$functionId])
|
||||
], $dbForProject);
|
||||
|
||||
// TODO: Request executor to delete runtime
|
||||
// TODO: @Meldiron Request executor to delete runtime
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,7 +553,7 @@ class DeletesV1 extends Worker
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Request executor to delete runtime
|
||||
// TODO: @Meldiron Request executor to delete runtime
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -124,12 +124,24 @@ Server::setResource('execute', function () {
|
||||
}
|
||||
}
|
||||
|
||||
$vars = array_reduce($function->getAttribute('vars', []), function (array $carry, Document $var) {
|
||||
$vars = [];
|
||||
|
||||
// Shared vars
|
||||
$vars = \array_merge($vars, \array_reduce($dbForProject->find('variables', [
|
||||
Query::equal('resourceType', ['project']),
|
||||
Query::limit(APP_LIMIT_SUBQUERY)
|
||||
]), function (array $carry, Document $var) {
|
||||
$carry[$var->getAttribute('key')] = $var->getAttribute('value') ?? '';
|
||||
return $carry;
|
||||
}, []));
|
||||
|
||||
// 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;
|
||||
}, []);
|
||||
}, []));
|
||||
|
||||
/** Collect environment variables */
|
||||
// Appwrite vars
|
||||
$vars = \array_merge($vars, [
|
||||
'APPWRITE_FUNCTION_ID' => $functionId,
|
||||
'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'),
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Create a new project variable. These variables can be accessed by every function.
|
||||
@@ -0,0 +1 @@
|
||||
Delete a project variable by its unique ID.
|
||||
@@ -0,0 +1 @@
|
||||
Get a project variable by its unique ID.
|
||||
@@ -0,0 +1 @@
|
||||
Get a list of all project variables.
|
||||
@@ -0,0 +1 @@
|
||||
Update project variable by its unique ID.
|
||||
@@ -7,7 +7,9 @@ use Appwrite\Utopia\Database\Validator\Queries\Base;
|
||||
class Variables extends Base
|
||||
{
|
||||
public const ALLOWED_ATTRIBUTES = [
|
||||
'key'
|
||||
'key',
|
||||
'resourceType',
|
||||
'resourceId'
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,7 +44,7 @@ class Rule extends Model
|
||||
])
|
||||
->addRule('resourceId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'ID of resource for the action type. If resourceType is "api" or "url", leave empty. If resourceType is "function", provide ID of the function.',
|
||||
'description' => 'ID of resource for the action type. If resourceType is "api" or "url", it is empty. If resourceType is "function", it is ID of the function.',
|
||||
'default' => '',
|
||||
'example' => 'myAwesomeFunction',
|
||||
])
|
||||
|
||||
@@ -41,11 +41,17 @@ class Variable extends Model
|
||||
'default' => '',
|
||||
'example' => 'myPa$$word1',
|
||||
])
|
||||
->addRule('functionId', [
|
||||
->addRule('resourceType', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Function ID.',
|
||||
'description' => 'Service to which the variable belongs. Possible values are "project", "function"',
|
||||
'default' => '',
|
||||
'example' => '5e5ea5c16897e',
|
||||
'example' => 'function',
|
||||
])
|
||||
->addRule('resourceId', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'ID of resource to which the variable belongs. If resourceType is "project", it is empty. If resourceType is "function", it is ID of the function.',
|
||||
'default' => '',
|
||||
'example' => 'myAwesomeFunction',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user