1
0
Fork 0
mirror of synced 2024-06-29 19:50:26 +12:00

Merge branch '1.5.x' of https://github.com/appwrite/appwrite into feat-mailgun-provider

This commit is contained in:
Prateek Banga 2023-09-20 16:59:07 +05:30
commit a2e34b5b64
126 changed files with 1099 additions and 443 deletions

2
.env
View file

@ -71,7 +71,7 @@ _APP_FUNCTIONS_MAINTENANCE_INTERVAL=600
_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes
_APP_EXECUTOR_SECRET=your-secret-key
_APP_EXECUTOR_HOST=http://proxy/v1
_APP_FUNCTIONS_RUNTIMES=
_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1
_APP_MAINTENANCE_INTERVAL=86400
_APP_MAINTENANCE_RETENTION_CACHE=2592000
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600

39
.github/workflows/cleanup-cache.yml vendored Normal file
View file

@ -0,0 +1,39 @@
name: Cleanup Cache
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
while true
do
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
if [ -z "$cacheKeysForPR" ]
then
break
fi
## Setting this to not fail the workflow while deleting cache keys.
set +e
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
done
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2
.gitmodules vendored
View file

@ -1,4 +1,4 @@
[submodule "app/console"]
path = app/console
url = https://github.com/appwrite/console
branch = 3.0.2
branch = 3.0.4

View file

@ -1,3 +1,26 @@
# Version 1.4.2
## Fixes
- Fix create phone session abuse key [#6134](https://github.com/appwrite/appwrite/pull/6134)
- Fix CLI backwards compatibility [#6125](https://github.com/appwrite/appwrite/pull/6125)
- Fix Not Found error when deploying function from git [#6133](https://github.com/appwrite/appwrite/pull/6133)
- Fix _APP_EXECUTOR_HOST for upgrades [#6141](https://github.com/appwrite/appwrite/pull/6141)
- Fix create execution request filter from previous SDK version [#6146](https://github.com/appwrite/appwrite/pull/6146)
- Fix migrations worker [#6116](https://github.com/appwrite/appwrite/pull/6116)
- Fix: Global variables by [#6150](https://github.com/appwrite/appwrite/pull/6150)
- Fix webhook secret validation and executor path validation [#6162](https://github.com/appwrite/appwrite/pull/6162)
- Fix: Untrusted custom domains + auto-ssl [#6155](https://github.com/appwrite/appwrite/pull/6155)
- Fix: AI Assistant [#6153](https://github.com/appwrite/appwrite/pull/6153)
## Changes
- Add required params for scheduled functions [#6148](https://github.com/appwrite/appwrite/pull/6148)
- Update the error message for router_domain_not_configured [#6145](https://github.com/appwrite/appwrite/pull/6145)
- Override forEachDocument() to skip the cache collection [#6144](https://github.com/appwrite/appwrite/pull/6144)
- Support for v2 functions [#6142](https://github.com/appwrite/appwrite/pull/6142)
- Change executor hostname back to appwrite-executor [#6160](https://github.com/appwrite/appwrite/pull/6160)
- Make URL optional for Create Membership API and Serverside Requests [#6157](https://github.com/appwrite/appwrite/pull/6157)
# Version 1.4.1
## Features

View file

@ -66,7 +66,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.4.1
appwrite/appwrite:1.4.2
```
### Windows
@ -78,7 +78,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:1.4.1
appwrite/appwrite:1.4.2
```
#### PowerShell
@ -88,7 +88,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" `
appwrite/appwrite:1.4.1
appwrite/appwrite:1.4.2
```
运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。

View file

@ -75,7 +75,7 @@ docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.4.1
appwrite/appwrite:1.4.2
```
### Windows
@ -87,7 +87,7 @@ docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
--entrypoint="install" ^
appwrite/appwrite:1.4.1
appwrite/appwrite:1.4.2
```
#### PowerShell
@ -97,7 +97,7 @@ docker run -it --rm `
--volume /var/run/docker.sock:/var/run/docker.sock `
--volume ${pwd}/appwrite:/usr/src/code/appwrite:rw `
--entrypoint="install" `
appwrite/appwrite:1.4.1
appwrite/appwrite:1.4.2
```
Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation.

View file

@ -2493,6 +2493,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,

View file

@ -653,7 +653,7 @@ return [
],
Exception::ROUTER_DOMAIN_NOT_CONFIGURED => [
'name' => Exception::ROUTER_DOMAIN_NOT_CONFIGURED,
'description' => 'Domain environment variables not configured. Please configure domain environment variables before using Appwrite outside of localhost.',
'description' => '_APP_DOMAIN, _APP_DOMAIN_TARGET, and _APP_DOMAIN_FUNCTIONS environment variables have not been configured. Please configure the domain environment variables before accessing the Appwrite Console via any IP address or hostname other than localhost. This value could be an IP like 203.0.113.0 or a hostname like example.com.',
'code' => 500,
],
Exception::RULE_RESOURCE_NOT_FOUND => [

View file

@ -258,20 +258,6 @@ return [
'create' => [
'$description' => 'This event triggers when a message is created.',
],
'providers' => [
'$model' => Response::MODEL_PROVIDER,
'$resource' => true,
'$description' => 'This event triggers on any provider event.',
'create' => [
'$description' => 'This event triggers when a provider is created.',
],
'update' => [
'$description' => 'This event triggers when a provider is updated.',
],
'delete' => [
'$description' => 'This event triggers when a provider is deleted.'
],
],
'topics' => [
'$model' => Response::MODEL_TOPIC,
'$resource' => true,
@ -296,6 +282,20 @@ return [
],
],
'providers' => [
'$model' => Response::MODEL_PROVIDER,
'$resource' => true,
'$description' => 'This event triggers on any provider event.',
'create' => [
'$description' => 'This event triggers when a provider is created.',
],
'update' => [
'$description' => 'This event triggers when a provider is updated.',
],
'delete' => [
'$description' => 'This event triggers when a provider is deleted.'
],
],
'rules' => [
'$model' => Response::MODEL_PROXY_RULE,
'$resource' => true,

View file

@ -15,7 +15,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '12.0.0',
'version' => '13.0.0',
'url' => 'https://github.com/appwrite/sdk-for-web',
'package' => 'https://www.npmjs.com/package/appwrite',
'enabled' => true,
@ -63,7 +63,7 @@ return [
[
'key' => 'flutter',
'name' => 'Flutter',
'version' => '10.0.0',
'version' => '11.0.0',
'url' => 'https://github.com/appwrite/sdk-for-flutter',
'package' => 'https://pub.dev/packages/appwrite',
'enabled' => true,
@ -81,7 +81,7 @@ return [
[
'key' => 'apple',
'name' => 'Apple',
'version' => '3.0.0',
'version' => '4.0.0',
'url' => 'https://github.com/appwrite/sdk-for-apple',
'package' => 'https://github.com/appwrite/sdk-for-apple',
'enabled' => true,
@ -116,7 +116,7 @@ return [
[
'key' => 'android',
'name' => 'Android',
'version' => '3.0.0',
'version' => '4.0.0',
'url' => 'https://github.com/appwrite/sdk-for-android',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android',
'enabled' => true,
@ -203,7 +203,7 @@ return [
[
'key' => 'cli',
'name' => 'Command Line',
'version' => '3.0.0',
'version' => '4.0.0',
'url' => 'https://github.com/appwrite/sdk-for-cli',
'package' => 'https://www.npmjs.com/package/appwrite-cli',
'enabled' => true,
@ -231,7 +231,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '10.0.0',
'version' => '11.0.0',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@ -249,7 +249,7 @@ return [
[
'key' => 'deno',
'name' => 'Deno',
'version' => '8.0.0',
'version' => '9.0.0',
'url' => 'https://github.com/appwrite/sdk-for-deno',
'package' => 'https://deno.land/x/appwrite',
'enabled' => true,
@ -267,7 +267,7 @@ return [
[
'key' => 'php',
'name' => 'PHP',
'version' => '9.0.0',
'version' => '10.0.0',
'url' => 'https://github.com/appwrite/sdk-for-php',
'package' => 'https://packagist.org/packages/appwrite/appwrite',
'enabled' => true,
@ -285,7 +285,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '3.0.0',
'version' => '4.0.0',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@ -303,7 +303,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '9.0.0',
'version' => '10.0.0',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
@ -321,7 +321,7 @@ return [
[
'key' => 'go',
'name' => 'Go',
'version' => '2.0.0',
'version' => '3.0.0',
'url' => 'https://github.com/appwrite/sdk-for-go',
'package' => '',
'enabled' => false,
@ -339,7 +339,7 @@ return [
[
'key' => 'java',
'name' => 'Java',
'version' => '2.0.0',
'version' => '3.0.0',
'url' => 'https://github.com/appwrite/sdk-for-java',
'package' => '',
'enabled' => false,
@ -357,7 +357,7 @@ return [
[
'key' => 'dotnet',
'name' => '.NET',
'version' => '0.5.0',
'version' => '0.6.0',
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
'package' => 'https://www.nuget.org/packages/Appwrite',
'enabled' => true,
@ -375,7 +375,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '9.0.0',
'version' => '10.0.0',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
@ -393,7 +393,7 @@ return [
[
'key' => 'kotlin',
'name' => 'Kotlin',
'version' => '3.0.0',
'version' => '4.0.0',
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
'enabled' => true,
@ -415,7 +415,7 @@ return [
[
'key' => 'swift',
'name' => 'Swift',
'version' => '3.0.0',
'version' => '4.0.0',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,

View file

@ -24,7 +24,8 @@ $member = [
'targets.read',
'targets.write',
'subscribers.write',
'subscribers.read'
'subscribers.read',
'assistant.read',
];
$admins = [
@ -69,7 +70,6 @@ $admins = [
'messages.read',
'vcs.read',
'vcs.write',
'assistant.read',
'targets.read',
'targets.write',
'providers.write',
@ -86,6 +86,7 @@ return [
Auth::USER_ROLE_GUESTS => [
'label' => 'Guests',
'scopes' => [
'global',
'public',
'home',
'console',

View file

@ -0,0 +1,16 @@
<?php
/**
* List of Appwrite Cloud Functions supported runtimes
*/
use Utopia\App;
use Appwrite\Runtimes\Runtimes;
$runtimes = new Runtimes('v2');
$allowList = empty(App::getEnv('_APP_FUNCTIONS_RUNTIMES')) ? [] : \explode(',', App::getEnv('_APP_FUNCTIONS_RUNTIMES'));
$runtimes = $runtimes->getAll(true, $allowList);
return $runtimes;

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

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

View file

@ -750,6 +750,7 @@ return [
'introduction' => '0.13.0',
'default' => 'http://appwrite-executor/v1',
'required' => false,
'overwrite' => true,
'question' => '',
'filter' => ''
],

@ -1 +1 @@
Subproject commit 88b6d59051992ed86183ee83d77bf678d1cb73bf
Subproject commit e07f0379f4124a202772bcd4bd38a3c8e2662eea

View file

@ -146,6 +146,7 @@ App::post('/v1/account')
'search' => implode(' ', [$userId, $email, $name]),
'accessedAt' => DateTime::now(),
]);
$user->removeAttribute('$internalId');
Authorization::skip(fn() => $dbForProject->createDocument('users', $user));
} catch (Duplicate) {
throw new Exception(Exception::USER_ALREADY_EXISTS);
@ -653,6 +654,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
'search' => implode(' ', [$userId, $email, $name]),
'accessedAt' => DateTime::now(),
]);
$user->removeAttribute('$internalId');
Authorization::skip(fn() => $dbForProject->createDocument('users', $user));
} catch (Duplicate) {
$failureRedirect(Exception::USER_ALREADY_EXISTS);
@ -955,6 +957,7 @@ App::post('/v1/account/sessions/magic-url')
'accessedAt' => DateTime::now(),
]);
$user->removeAttribute('$internalId');
Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
}
@ -1224,7 +1227,7 @@ App::post('/v1/account/sessions/phone')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TOKEN)
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-phone}')
->label('abuse-key', 'url:{url},phone:{param-phone}')
->param('userId', '', new CustomId(), 'Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.')
->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true)
@ -1288,6 +1291,7 @@ App::post('/v1/account/sessions/phone')
'accessedAt' => DateTime::now(),
]);
$user->removeAttribute('$internalId');
Authorization::skip(fn () => $dbForProject->createDocument('users', $user));
}
@ -1549,6 +1553,7 @@ App::post('/v1/account/sessions/anonymous')
'search' => $userId,
'accessedAt' => DateTime::now(),
]);
$user->removeAttribute('$internalId');
Authorization::skip(fn() => $dbForProject->createDocument('users', $user));
// Create session token

View file

@ -660,7 +660,7 @@ App::put('/v1/functions/:functionId')
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new UID(), 'Function ID.')
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.')
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.', true)
->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true)
->param('events', [], new ArrayList(new ValidatorEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true)
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
@ -704,6 +704,10 @@ App::put('/v1/functions/:functionId')
throw new Exception(Exception::FUNCTION_NOT_FOUND);
}
if (empty($runtime)) {
$runtime = $function->getAttribute('runtime');
}
$enabled ??= $function->getAttribute('enabled', true);
$repositoryId = $function->getAttribute('repositoryId', '');
@ -923,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);
@ -986,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);
@ -1058,11 +1060,9 @@ App::post('/v1/functions/:functionId/deployments')
}
if ($commands === null) {
$commands = $function->getAttribute('entrypoint', '');
$commands = $function->getAttribute('commands', '');
}
$commands = $function->getAttribute('commands', '');
if (empty($entrypoint)) {
throw new Exception(Exception::FUNCTION_ENTRYPOINT_MISSING);
}
@ -1432,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);
@ -1458,6 +1456,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
$deploymentId = ID::unique();
$deployment->removeAttribute('$internalId');
$deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([
'$id' => $deploymentId,
'buildId' => '',
@ -1521,7 +1520,8 @@ App::post('/v1/functions/:functionId/executions')
throw new Exception(Exception::FUNCTION_NOT_FOUND);
}
$runtimes = Config::getParam('runtimes', []);
$version = $function->getAttribute('version', 'v2');
$runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []);
$runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null;
@ -1658,16 +1658,25 @@ App::post('/v1/functions/:functionId/executions')
$vars = [];
// V2 vars
if ($version === 'v2') {
$vars = \array_merge($vars, [
'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '',
'APPWRITE_FUNCTION_DATA' => $body ?? '',
'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '',
'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? ''
]);
}
// 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, [
@ -1682,7 +1691,9 @@ App::post('/v1/functions/:functionId/executions')
/** Execute function */
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
try {
$version = $function->getAttribute('version', 'v2');
$command = $runtime['startCommand'];
$command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"';
$executionResponse = $executor->createExecution(
projectId: $project->getId(),
deploymentId: $deployment->getId(),
@ -1692,11 +1703,11 @@ App::post('/v1/functions/:functionId/executions')
image: $runtime['image'],
source: $build->getAttribute('path', ''),
entrypoint: $deployment->getAttribute('entrypoint', ''),
version: $function->getAttribute('version'),
version: $version,
path: $path,
method: $method,
headers: $headers,
runtimeEntrypoint: 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'
runtimeEntrypoint: $command
);
$headersFiltered = [];
@ -1900,11 +1911,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()) {
@ -1933,7 +1943,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));
@ -1945,8 +1954,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);
@ -1974,8 +1981,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);
});
@ -2035,11 +2042,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);
@ -2066,7 +2072,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));
@ -2078,8 +2083,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);
});
@ -2097,11 +2100,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()) {
@ -2129,7 +2131,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();
});

View file

@ -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();
});

View file

@ -1316,7 +1316,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$fileSecurity = $bucket->getAttributes('fileSecurity', false);
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_UPDATE);
$valid = $validator->isValid($bucket->getUpdate());
if (!$fileSecurity && !$valid) {
@ -1423,7 +1423,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
}
$fileSecurity = $bucket->getAttributes('fileSecurity', false);
$fileSecurity = $bucket->getAttribute('fileSecurity', false);
$validator = new Authorization(Database::PERMISSION_DELETE);
$valid = $validator->isValid($bucket->getDelete());
if (!$fileSecurity && !$valid) {

View file

@ -378,7 +378,7 @@ App::post('/v1/teams/:teamId/memberships')
->param('userId', '', new UID(), 'ID of the user to be added to a team.', true)
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.')
->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['clients']) // TODO add our own built-in confirm page
->param('url', '', fn($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page
->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true)
->param('from', '', new Text(128), 'Sender of the message. It can be alphanumeric (Ex: MyCompany20). Restrictions may apply depending of the destination.', true)
->inject('response')
@ -389,7 +389,15 @@ App::post('/v1/teams/:teamId/memberships')
->inject('mails')
->inject('messaging')
->inject('events')
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, string $from, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, Messaging $messaging, Event $events) {
->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, string $from, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $mails, EventPhone $messaging, Event $events) {
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
if (empty($url)) {
if (!$isAPIKey && !$isPrivilegedUser) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'URL is required');
}
}
if (empty($userId) && empty($email) && empty($phone)) {
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'At least one of userId, email, or phone is required');
@ -484,7 +492,6 @@ App::post('/v1/teams/:teamId/memberships')
'tokens' => null,
'memberships' => null,
'search' => implode(' ', [$userId, $email, $name]),
'accessedAt' => DateTime::now(),
])));
} catch (Duplicate $th) {
throw new Exception(Exception::USER_ALREADY_EXISTS);

View file

@ -97,7 +97,6 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e
'tokens' => null,
'memberships' => null,
'search' => implode(' ', [$userId, $email, $phone, $name]),
'accessedAt' => DateTime::now(),
]));
} catch (Duplicate $th) {
throw new Exception(Exception::USER_ALREADY_EXISTS);
@ -873,7 +872,7 @@ App::put('/v1/users/:userId/labels')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('userId', '', new UID(), 'User ID.')
->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), 5), 'Array of user labels. Replaces the previous labels. Maximum of 5 labels are allowed, each up to 36 alphanumeric characters long.')
->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.')
->inject('response')
->inject('dbForProject')
->inject('events')

View file

@ -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"
@ -783,14 +789,14 @@ App::post('/v1/vcs/github/events')
->inject('getProjectDB')
->action(
function (GitHub $github, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB) use ($createGitDeployments) {
$signature = $request->getHeader('x-hub-signature-256', '');
$payload = $request->getRawPayload();
$signatureRemote = $request->getHeader('x-hub-signature-256', '');
$signatureLocal = App::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', '');
$signatureKey = App::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', '');
$valid = empty($signatureRemote) ? true : $github->validateWebhookEvent($payload, $signatureRemote, $signatureLocal);
$valid = $github->validateWebhookEvent($payload, $signature, $signatureKey);
if (!$valid) {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, "Invalid webhook signature.");
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, "Invalid webhook payload signature. Please make sure the webhook secret has same value in your GitHub app and in the _APP_VCS_GITHUB_WEBHOOK_SECRET environment variable");
}
$event = $request->getHeader('x-github-event', '');

View file

@ -47,8 +47,6 @@ Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleRequest, Request $request, Response $response)
{
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
$host = $request->getHostname() ?? '';
$route = Authorization::skip(
@ -59,15 +57,12 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques
)[0] ?? null;
if ($route === null) {
$mainDomain = App::getEnv('_APP_DOMAIN', '');
if ($mainDomain === 'localhost') {
throw new AppwriteException(AppwriteException::ROUTER_DOMAIN_NOT_CONFIGURED);
} else {
throw new AppwriteException(AppwriteException::ROUTER_HOST_NOT_FOUND);
}
// Act as API - no Proxy logic
return false;
}
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
$projectId = $route->getAttribute('projectId');
$project = Authorization::skip(
fn () => $dbForConsole->getDocument('projects', $projectId)
@ -163,6 +158,7 @@ function router(App $utopia, Database $dbForConsole, SwooleRequest $swooleReques
return true;
} elseif ($type === 'api') {
$utopia->getRoute()?->label('error', '');
return false;
} else {
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type);
@ -193,7 +189,7 @@ App::init()
$host = $request->getHostname() ?? '';
$mainDomain = App::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain && $host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL) {
if ($host !== $mainDomain) {
if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) {
return;
}
@ -234,6 +230,61 @@ App::init()
Request::setFilter(null);
}
$domain = $request->getHostname();
$domains = Config::getParam('domains', []);
if (!array_key_exists($domain, $domains)) {
$domain = new Domain(!empty($domain) ? $domain : '');
if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) {
$domains[$domain->get()] = false;
Console::warning($domain->get() . ' is not a publicly accessible domain. Skipping SSL certificate generation.');
} elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) {
Console::warning('Skipping SSL certificates generation on ACME challenge.');
} else {
Authorization::disable();
$envDomain = App::getEnv('_APP_DOMAIN', '');
$mainDomain = null;
if (!empty($envDomain) && $envDomain !== 'localhost') {
$mainDomain = $envDomain;
} else {
$domainDocument = $dbForConsole->findOne('rules', [Query::orderAsc('$id')]);
$mainDomain = $domainDocument ? $domainDocument->getAttribute('domain') : $domain->get();
}
if ($mainDomain !== $domain->get()) {
Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.');
} else {
$domainDocument = $dbForConsole->findOne('rules', [
Query::equal('domain', [$domain->get()])
]);
if (!$domainDocument) {
$domainDocument = new Document([
'domain' => $domain->get(),
'resourceType' => 'api',
'status' => 'verifying',
'projectId' => 'console',
'projectInternalId' => 'console'
]);
$domainDocument = $dbForConsole->createDocument('rules', $domainDocument);
Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...');
(new Certificate())
->setDomain($domainDocument)
->setSkipRenewCheck(true)
->trigger();
}
}
$domains[$domain->get()] = true;
Authorization::reset(); // ensure authorization is re-enabled
}
Config::setParam('domains', $domains);
}
$localeParam = (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));
if (\in_array($localeParam, $localeCodes)) {
$locale->setDefault($localeParam);
@ -327,7 +378,7 @@ App::init()
* @see https://www.owasp.org/index.php/List_of_useful_HTTP_headers
*/
if (App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
if ($request->getProtocol() !== 'https' && ($swooleRequest->header['host'] ?? '') !== 'localhost' && ($swooleRequest->header['host'] ?? '') !== APP_HOSTNAME_INTERNAL) { // Localhost allowed for proxy, APP_HOSTNAME_INTERNAL allowed for migrations
if ($request->getProtocol() !== 'https' && ($swooleRequest->header['host'] ?? '') !== 'localhost' && ($swooleRequest->header['host'] ?? '') !== APP_HOSTNAME_INTERNAL) { // localhost allowed for proxy, APP_HOSTNAME_INTERNAL allowed for migrations
if ($request->getMethod() !== Request::METHOD_GET) {
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP.');
}
@ -497,7 +548,7 @@ App::options()
$host = $request->getHostname() ?? '';
$mainDomain = App::getEnv('_APP_DOMAIN', '');
// Only run Router when external domain
if ($host !== $mainDomain && $host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL) {
if ($host !== $mainDomain) {
if (router($utopia, $dbForConsole, $swooleRequest, $request, $response)) {
return;
}

View file

@ -8,12 +8,14 @@ use Utopia\Validator\Host;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Database\Database;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Integer;
use Utopia\Validator\Text;
use Utopia\Storage\Validator\File;
use Utopia\Validator\WhiteList;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Validator\UID;
use Utopia\Validator\Nullable;
App::get('/v1/mock/tests/foo')
@ -605,6 +607,32 @@ App::get('/v1/mock/tests/general/oauth2/failure')
]);
});
App::patch('/v1/mock/functions-v2')
->desc('Update Function Version to V2 (outdated code syntax)')
->groups(['mock', 'api', 'functions'])
->label('scope', 'functions.write')
->label('docs', false)
->param('functionId', '', new UID(), 'Function ID.')
->inject('response')
->inject('dbForProject')
->action(function (string $functionId, Response $response, Database $dbForProject) {
$isDevelopment = App::getEnv('_APP_ENV', 'development') === 'development';
if (!$isDevelopment) {
throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED);
}
$function = $dbForProject->getDocument('functions', $functionId);
if ($function->isEmpty()) {
throw new Exception(Exception::FUNCTION_NOT_FOUND);
}
$dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('version', 'v2'));
$response->noContent();
});
App::shutdown()
->groups(['mock'])
->inject('utopia')

View file

@ -254,8 +254,6 @@ App::init()
->setContentType($data['contentType'])
->send(base64_decode($data['payload']))
;
$route->setIsActive(false);
} else {
$response->addHeader('X-Appwrite-Cache', 'miss');
}

View file

@ -31,13 +31,6 @@ App::get('/console/*')
->inject('request')
->inject('response')
->action(function (Request $request, Response $response) {
// Serve static files (console) only for main domain
$host = $request->getHostname() ?? '';
$mainDomain = App::getEnv('_APP_DOMAIN', '');
if ($host !== $mainDomain && $host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL) {
throw new Exception(Exception::GENERAL_ROUTE_NOT_FOUND);
}
$fallback = file_get_contents(__DIR__ . '/../../../console/index.html');
// Card SSR

View file

@ -229,21 +229,16 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo
$request = new Request($swooleRequest);
$response = new Response($swooleResponse);
// Serve static files (console) only for main domain
$host = $request->getHostname() ?? '';
$mainDomain = App::getEnv('_APP_DOMAIN', '');
if ($host === $mainDomain || $host === 'localhost') {
if (Files::isFileLoaded($request->getURI())) {
$time = (60 * 60 * 24 * 365 * 2); // 45 days cache
if (Files::isFileLoaded($request->getURI())) {
$time = (60 * 60 * 24 * 365 * 2); // 45 days cache
$response
->setContentType(Files::getFileMimeType($request->getURI()))
->addHeader('Cache-Control', 'public, max-age=' . $time)
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache
->send(Files::getFileContents($request->getURI()));
$response
->setContentType(Files::getFileMimeType($request->getURI()))
->addHeader('Cache-Control', 'public, max-age=' . $time)
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time) . ' GMT') // 45 days cache
->send(Files::getFileContents($request->getURI()));
return;
}
return;
}
$app = new App('UTC');

View file

@ -108,8 +108,8 @@ const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return
const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours
const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 508;
const APP_VERSION_STABLE = '1.4.1';
const APP_CACHE_BUSTER = 509;
const APP_VERSION_STABLE = '1.4.2';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
@ -237,6 +237,7 @@ Config::load('authProviders', __DIR__ . '/config/authProviders.php');
Config::load('platforms', __DIR__ . '/config/platforms.php');
Config::load('collections', __DIR__ . '/config/collections.php');
Config::load('runtimes', __DIR__ . '/config/runtimes.php');
Config::load('runtimes-v2', __DIR__ . '/config/runtimes-v2.php');
Config::load('roles', __DIR__ . '/config/roles.php'); // User roles and scopes
Config::load('scopes', __DIR__ . '/config/scopes.php'); // User roles and scopes
Config::load('services', __DIR__ . '/config/services.php'); // List of services
@ -492,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) {

View file

@ -89,9 +89,9 @@ services:
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
@ -111,26 +111,26 @@ services:
- _APP_STORAGE_ANTIVIRUS
- _APP_STORAGE_ANTIVIRUS_HOST
- _APP_STORAGE_ANTIVIRUS_PORT
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_FUNCTIONS_SIZE_LIMIT
- _APP_FUNCTIONS_TIMEOUT
@ -156,14 +156,14 @@ services:
- _APP_GRAPHQL_MAX_BATCH_SIZE
- _APP_GRAPHQL_MAX_COMPLEXITY
- _APP_GRAPHQL_MAX_DEPTH
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_VCS_GITHUB_WEBHOOK_SECRET
- _APP_VCS_GITHUB_CLIENT_SECRET
- _APP_VCS_GITHUB_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_VCS_GITHUB_WEBHOOK_SECRET
- _APP_VCS_GITHUB_CLIENT_SECRET
- _APP_VCS_GITHUB_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
- _APP_ASSISTANT_OPENAI_API_KEY
appwrite-realtime:
@ -281,35 +281,35 @@ services:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
- _APP_STORAGE_DO_SPACES_BUCKET
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- _APP_STORAGE_BACKBLAZE_SECRET
- _APP_STORAGE_BACKBLAZE_REGION
- _APP_STORAGE_BACKBLAZE_BUCKET
- _APP_STORAGE_LINODE_ACCESS_KEY
- _APP_STORAGE_LINODE_SECRET
- _APP_STORAGE_LINODE_REGION
- _APP_STORAGE_LINODE_BUCKET
- _APP_STORAGE_WASABI_ACCESS_KEY
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
@ -354,6 +354,9 @@ services:
depends_on:
- redis
- mariadb
volumes:
- appwrite-functions:/storage/functions:rw
- appwrite-builds:/storage/builds:rw
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@ -371,14 +374,14 @@ services:
- _APP_DB_PASS
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_MEMORY
- _APP_OPTIONS_FORCE_HTTPS
- _APP_VCS_GITHUB_APP_NAME
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_MEMORY
- _APP_OPTIONS_FORCE_HTTPS
- _APP_DOMAIN
appwrite-worker-certificates:
@ -403,9 +406,9 @@ services:
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
@ -441,15 +444,15 @@ services:
- _APP_DB_USER
- _APP_DB_PASS
- _APP_FUNCTIONS_TIMEOUT
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_BUILD_TIMEOUT
- _APP_FUNCTIONS_CPUS
- _APP_FUNCTIONS_MEMORY
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_USAGE_STATS
- _APP_DOCKER_HUB_USERNAME
- _APP_DOCKER_HUB_PASSWORD
- _APP_LOGGING_CONFIG
- _APP_DOCKER_HUB_USERNAME
- _APP_DOCKER_HUB_PASSWORD
- _APP_LOGGING_CONFIG
- _APP_LOGGING_PROVIDER
appwrite-worker-mails:
@ -502,6 +505,37 @@ services:
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
appwrite-worker-migrations:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
entrypoint: worker-migrations
<<: *x-logging
container_name: appwrite-worker-migrations
restart: unless-stopped
networks:
- appwrite
depends_on:
- mariadb
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
appwrite-maintenance:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
entrypoint: maintenance
@ -515,10 +549,10 @@ services:
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- _APP_DOMAIN_TARGET
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
@ -563,6 +597,7 @@ services:
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
@ -575,26 +610,38 @@ services:
networks:
- appwrite
depends_on:
- mariadb
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
appwrite-assistant:
image: appwrite/assistant:0.2.1
container_name: appwrite-assistant
<<: *x-logging
restart: unless-stopped
networks:
- appwrite
environment:
- _APP_ASSISTANT_OPENAI_API_KEY
openruntimes-executor:
container_name: openruntimes-executor
hostname: executor
hostname: appwrite-executor
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/executor:0.3.5
image: openruntimes/executor:0.4.0
networks:
- appwrite
- runtimes
@ -602,6 +649,8 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-builds:/storage/builds:rw
- appwrite-functions:/storage/functions:rw
# Host mount nessessary to share files between executor and runtimes.
# It's not possible to share mount file between 2 containers without host mount (copying is too slow)
- /tmp:/tmp:rw
environment:
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD

View file

@ -90,7 +90,8 @@ class BuildsV1 extends Worker
throw new Exception('Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".', 500);
}
$runtimes = Config::getParam('runtimes', []);
$version = $function->getAttribute('version', 'v2');
$runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []);
$key = $function->getAttribute('runtime');
$runtime = isset($runtimes[$key]) ? $runtimes[$key] : null;
if (\is_null($runtime)) {
@ -320,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, [
@ -358,17 +353,20 @@ class BuildsV1 extends Worker
Co::join([
Co\go(function () use (&$response, $project, $deployment, $source, $function, $runtime, $vars, $command, &$err) {
try {
$version = $function->getAttribute('version', 'v2');
$command = $version === 'v2' ? 'tar -zxf /tmp/code.tar.gz -C /usr/code && cd /usr/local/src/ && ./build.sh' : 'tar -zxf /tmp/code.tar.gz -C /mnt/code && helpers/build.sh "' . $command . '"';
$response = $this->executor->createRuntime(
deploymentId: $deployment->getId(),
projectId: $project->getId(),
source: $source,
image: $runtime['image'],
version: $function->getAttribute('version'),
version: $version,
remove: true,
entrypoint: $deployment->getAttribute('entrypoint'),
destination: APP_STORAGE_BUILDS . "/app-{$project->getId()}",
variables: $vars,
command: 'tar -zxf /tmp/code.tar.gz -C /mnt/code && helpers/build.sh "' . $command . '"'
command: $command
);
} catch (Exception $error) {
$err = $error;

View file

@ -174,6 +174,7 @@ class CertificatesV1 extends Worker
$certificate = $this->dbForConsole->updateDocument('certificates', $certificate->getId(), $certificate);
} else {
$certificate->removeAttribute('$internalId');
$certificate = $this->dbForConsole->createDocument('certificates', $certificate);
}
@ -438,6 +439,12 @@ class CertificatesV1 extends Worker
$this->dbForConsole->updateDocument('rules', $rule->getId(), $rule);
$projectId = $rule->getAttribute('projectId');
// Skip events for console project (triggered by auto-ssl generation for 1 click setups)
if ($projectId === 'console') {
return;
}
$project = $this->dbForConsole->getDocument('projects', $projectId);
/** Trigger Webhook */

View file

@ -74,7 +74,8 @@ Server::setResource('execute', function () {
}
/** Check if runtime is supported */
$runtimes = Config::getParam('runtimes', []);
$version = $function->getAttribute('version', 'v2');
$runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []);
if (!\array_key_exists($function->getAttribute('runtime'), $runtimes)) {
throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported');
@ -105,7 +106,7 @@ Server::setResource('execute', function () {
'functionId' => $function->getId(),
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentId' => $deployment->getId(),
'trigger' => 'http',
'trigger' => $trigger,
'status' => 'processing',
'responseStatusCode' => 0,
'responseHeaders' => [],
@ -139,20 +140,34 @@ Server::setResource('execute', function () {
$durationStart = \microtime(true);
$body = $eventData ?? '';
if (empty($body)) {
$body = $data ?? '';
}
$vars = [];
// V2 vars
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_EVENT' => $headers['x-appwrite-event'] ?? '',
'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '',
'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? ''
]);
}
// 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, [
@ -164,15 +179,12 @@ Server::setResource('execute', function () {
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '',
]);
$body = $eventData ?? '';
if (empty($body)) {
$body = $data ?? '';
}
/** Execute function */
try {
$version = $function->getAttribute('version', 'v2');
$command = $runtime['startCommand'];
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
$command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"';
$executionResponse = $executor->createExecution(
projectId: $project->getId(),
deploymentId: $deploymentId,
@ -182,11 +194,11 @@ Server::setResource('execute', function () {
image: $runtime['image'],
source: $build->getAttribute('path', ''),
entrypoint: $deployment->getAttribute('entrypoint', ''),
version: $function->getAttribute('version'),
version: $version,
path: $path,
method: $method,
headers: $headers,
runtimeEntrypoint: 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'
runtimeEntrypoint: $command
);
$status = $executionResponse['statusCode'] >= 400 ? 'failed' : 'completed';
@ -335,6 +347,7 @@ $server->job()
}
Console::success('Iterating function: ' . $function->getAttribute('name'));
$execute(
log: $log,
statsd: $statsd,
dbForProject: $dbForProject,
project: $project,
@ -380,9 +393,9 @@ $server->job()
data: $data,
user: $user,
jwt: $jwt,
path: $payload['path'],
method: $payload['method'],
headers: $payload['headers'],
path: $payload['path'] ?? '',
method: $payload['method'] ?? 'POST',
headers: $payload['headers'] ?? [],
statsd: $statsd,
);
break;
@ -400,9 +413,9 @@ $server->job()
data: null,
user: null,
jwt: null,
path: $payload['path'],
method: $payload['method'],
headers: $payload['headers'],
path: $payload['path'] ?? '/',
method: $payload['method'] ?? 'POST',
headers: $payload['headers'] ?? [],
statsd: $statsd,
);
break;

View file

@ -86,7 +86,7 @@
}
],
"require-dev": {
"appwrite/sdk-generator": "0.34.*",
"appwrite/sdk-generator": "0.35.0",
"ext-fileinfo": "*",
"phpunit/phpunit": "9.5.20",
"squizlabs/php_codesniffer": "^3.7",

50
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1386218ddf332adf80889ab78be0a143",
"content-hash": "ce37f32b5c3c12e85d8d67bad35f57d7",
"packages": [
{
"name": "adhocore/jwt",
@ -2564,16 +2564,16 @@
},
{
"name": "utopia-php/migration",
"version": "0.3.4",
"version": "0.3.3",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a"
"reference": "45bd831ed9819994f05cb3b467c58f8155e27692"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/ade836d61b3e1547bc9f0dc300ee75b24ab49f7a",
"reference": "ade836d61b3e1547bc9f0dc300ee75b24ab49f7a",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/45bd831ed9819994f05cb3b467c58f8155e27692",
"reference": "45bd831ed9819994f05cb3b467c58f8155e27692",
"shasum": ""
},
"require": {
@ -2616,9 +2616,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/0.3.4"
"source": "https://github.com/utopia-php/migration/tree/0.3.3"
},
"time": "2023-09-14T17:17:55+00:00"
"time": "2023-09-06T03:54:54+00:00"
},
{
"name": "utopia-php/mongo",
@ -3391,16 +3391,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.34.2",
"version": "0.35.0",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "06ea25aace27790e42d57fdbc7ccf97e0b31a6ba"
"reference": "edd5da6763d7f8f28155b77200682c69d08c9954"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/06ea25aace27790e42d57fdbc7ccf97e0b31a6ba",
"reference": "06ea25aace27790e42d57fdbc7ccf97e0b31a6ba",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/edd5da6763d7f8f28155b77200682c69d08c9954",
"reference": "edd5da6763d7f8f28155b77200682c69d08c9954",
"shasum": ""
},
"require": {
@ -3436,9 +3436,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.34.2"
"source": "https://github.com/appwrite/sdk-generator/tree/0.35.0"
},
"time": "2023-08-31T14:10:33+00:00"
"time": "2023-09-07T17:13:18+00:00"
},
{
"name": "doctrine/deprecations",
@ -4145,16 +4145,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.24.1",
"version": "1.24.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01"
"reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01",
"reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/3510b0a6274cc42f7219367cb3abfc123ffa09d6",
"reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6",
"shasum": ""
},
"require": {
@ -4186,22 +4186,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.1"
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.0"
},
"time": "2023-09-18T12:18:02+00:00"
"time": "2023-09-07T20:46:32+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.29",
"version": "9.2.28",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76"
"reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76",
"reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef",
"reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef",
"shasum": ""
},
"require": {
@ -4258,7 +4258,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.28"
},
"funding": [
{
@ -4266,7 +4266,7 @@
"type": "github"
}
],
"time": "2023-09-19T04:57:46+00:00"
"time": "2023-09-12T14:36:20+00:00"
},
{
"name": "phpunit/php-file-iterator",

View file

@ -171,6 +171,7 @@ services:
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_SMS_PROVIDER
- _APP_SMS_FROM
- _APP_GRAPHQL_MAX_BATCH_SIZE
@ -673,6 +674,7 @@ services:
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
@ -685,7 +687,7 @@ services:
appwrite-assistant:
container_name: appwrite-assistant
image: appwrite/assistant:0.2.0
image: appwrite/assistant:0.2.1
networks:
- appwrite
environment:
@ -693,10 +695,10 @@ services:
openruntimes-executor:
container_name: openruntimes-executor
hostname: executor
hostname: appwrite-executor
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/executor:0.3.5
image: openruntimes/executor:0.4.0
networks:
- appwrite
- runtimes
@ -716,6 +718,7 @@ services:
- OPR_EXECUTOR_ENV=$_APP_ENV
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
- OPR_EXECUTOR_RUNTIME_VERSIONS=v2,v3
- OPR_EXECUTOR_LOGGING_PROVIDER=$_APP_LOGGING_PROVIDER
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
@ -745,7 +748,7 @@ services:
hostname: proxy
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/proxy:0.3.0
image: openruntimes/proxy:0.3.1
networks:
- appwrite
- runtimes
@ -757,7 +760,7 @@ services:
- OPR_PROXY_LOGGING_PROVIDER=$_APP_LOGGING_PROVIDER
- OPR_PROXY_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
- OPR_PROXY_ALGORITHM=random
- OPR_PROXY_EXECUTORS=executor
- OPR_PROXY_EXECUTORS=appwrite-executor
- OPR_PROXY_HEALTHCHECK_INTERVAL=10000
- OPR_PROXY_MAX_TIMEOUT=600
- OPR_PROXY_HEALTHCHECK=enabled

View file

@ -11,7 +11,6 @@ Teams teams = new Teams(client);
teams.createMembership(
"[TEAM_ID]",
listOf(),
"https://example.com",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();

View file

@ -10,5 +10,4 @@ val teams = Teams(client)
val response = teams.createMembership(
teamId = "[TEAM_ID]",
roles = listOf(),
url = "https://example.com",
)

View file

@ -8,7 +8,6 @@ let teams = Teams(client)
let membership = try await teams.createMembership(
teamId: "[TEAM_ID]",
roles: [],
url: "https://example.com"
roles: []
)

View file

@ -11,7 +11,6 @@ void main() { // Init SDK
Future result = teams.createMembership(
teamId: '[TEAM_ID]',
roles: [],
url: 'https://example.com',
);
result

View file

@ -1,8 +1,7 @@
mutation {
teamsCreateMembership(
teamId: "[TEAM_ID]",
roles: [],
url: "https://example.com"
roles: []
) {
_id
_createdAt

View file

@ -9,7 +9,7 @@ client
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = teams.createMembership('[TEAM_ID]', [], 'https://example.com');
const promise = teams.createMembership('[TEAM_ID]', []);
promise.then(function (response) {
console.log(response); // Success

View file

@ -1,7 +1,7 @@
appwrite functions create \
--functionId [FUNCTION_ID] \
--name [NAME] \
--runtime node-14.5 \
--runtime node-18.0 \

View file

@ -1,7 +1,7 @@
appwrite functions update \
--functionId [FUNCTION_ID] \
--name [NAME] \
--runtime node-14.5 \

View file

@ -1,7 +1,7 @@
appwrite teams createMembership \
--teamId [TEAM_ID] \
--roles one two three \
--url https://example.com \

View file

@ -0,0 +1,18 @@
import { Client, Account } from "@appwrite.io/console";
const client = new Client();
const account = new Account(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = account.createWithInviteCode('[USER_ID]', 'email@example.com', 'password');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -6,6 +6,7 @@ const assistant = new Assistant(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = assistant.chat('[PROMPT]');

View file

@ -9,7 +9,7 @@ client
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = functions.create('[FUNCTION_ID]', '[NAME]', 'node-14.5');
const promise = functions.create('[FUNCTION_ID]', '[NAME]', 'node-18.0');
promise.then(function (response) {
console.log(response); // Success

View file

@ -9,7 +9,7 @@ client
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = functions.update('[FUNCTION_ID]', '[NAME]', 'node-14.5');
const promise = functions.update('[FUNCTION_ID]', '[NAME]');
promise.then(function (response) {
console.log(response); // Success

View file

@ -6,6 +6,7 @@ const migrations = new Migrations(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = migrations.deleteFirebaseAuth();

View file

@ -6,6 +6,7 @@ const migrations = new Migrations(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = migrations.listFirebaseProjects();

View file

@ -0,0 +1,18 @@
import { Client, Projects } from "@appwrite.io/console";
const client = new Client();
const projects = new Projects(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = projects.createDomain('[PROJECT_ID]', '');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -0,0 +1,18 @@
import { Client, Projects } from "@appwrite.io/console";
const client = new Client();
const projects = new Projects(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = projects.deleteDomain('[PROJECT_ID]', '[DOMAIN_ID]');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -0,0 +1,18 @@
import { Client, Projects } from "@appwrite.io/console";
const client = new Client();
const projects = new Projects(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = projects.getDomain('[PROJECT_ID]', '[DOMAIN_ID]');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -0,0 +1,18 @@
import { Client, Projects } from "@appwrite.io/console";
const client = new Client();
const projects = new Projects(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = projects.listDomains('[PROJECT_ID]');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -0,0 +1,18 @@
import { Client, Projects } from "@appwrite.io/console";
const client = new Client();
const projects = new Projects(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = projects.updateDomainVerification('[PROJECT_ID]', '[DOMAIN_ID]');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -9,7 +9,7 @@ client
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = teams.createMembership('[TEAM_ID]', [], 'https://example.com');
const promise = teams.createMembership('[TEAM_ID]', []);
promise.then(function (response) {
console.log(response); // Success

View file

@ -0,0 +1,18 @@
import { Client, Teams } from "@appwrite.io/console";
const client = new Client();
const teams = new Teams(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = teams.updateMembershipRoles('[TEAM_ID]', '[MEMBERSHIP_ID]', []);
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.createRepositoryDetection('[INSTALLATION_ID]', '[PROVIDER_REPOSITORY_ID]');

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.createRepository('[INSTALLATION_ID]', '[NAME]', false);

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.deleteInstallation('[INSTALLATION_ID]');

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.getInstallation('[INSTALLATION_ID]');

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.getRepository('[INSTALLATION_ID]', '[PROVIDER_REPOSITORY_ID]');

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.listInstallations();

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.listRepositories('[INSTALLATION_ID]');

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.listRepositoryBranches('[INSTALLATION_ID]', '[PROVIDER_REPOSITORY_ID]');

View file

@ -6,6 +6,7 @@ const vcs = new Vcs(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = vcs.updateExternalDeployments('[INSTALLATION_ID]', '[REPOSITORY_ID]', '[PROVIDER_PULL_REQUEST_ID]');

View file

@ -13,7 +13,7 @@ void main() { // Init SDK
Future result = functions.create(
functionId: '[FUNCTION_ID]',
name: '[NAME]',
runtime: 'node-14.5',
runtime: 'node-18.0',
);
result

View file

@ -13,7 +13,6 @@ void main() { // Init SDK
Future result = functions.update(
functionId: '[FUNCTION_ID]',
name: '[NAME]',
runtime: 'node-14.5',
);
result

View file

@ -13,7 +13,6 @@ void main() { // Init SDK
Future result = teams.createMembership(
teamId: '[TEAM_ID]',
roles: [],
url: 'https://example.com',
);
result

View file

@ -12,7 +12,7 @@ client
;
let promise = functions.create('[FUNCTION_ID]', '[NAME]', 'node-14.5');
let promise = functions.create('[FUNCTION_ID]', '[NAME]', 'node-18.0');
promise.then(function (response) {
console.log(response);

View file

@ -12,7 +12,7 @@ client
;
let promise = functions.update('[FUNCTION_ID]', '[NAME]', 'node-14.5');
let promise = functions.update('[FUNCTION_ID]', '[NAME]');
promise.then(function (response) {
console.log(response);

View file

@ -12,7 +12,7 @@ client
;
let promise = teams.createMembership('[TEAM_ID]', [], 'https://example.com');
let promise = teams.createMembership('[TEAM_ID]', []);
promise.then(function (response) {
console.log(response);

View file

@ -12,4 +12,4 @@ var functions = new Functions(client);
Function result = await functions.Create(
functionId: "[FUNCTION_ID]",
name: "[NAME]",
runtime: "node-14.5");
runtime: "node-18.0");

View file

@ -11,5 +11,4 @@ var functions = new Functions(client);
Function result = await functions.Update(
functionId: "[FUNCTION_ID]",
name: "[NAME]",
runtime: "node-14.5");
name: "[NAME]");

View file

@ -11,5 +11,4 @@ var teams = new Teams(client);
Membership result = await teams.CreateMembership(
teamId: "[TEAM_ID]",
roles: new List<string> {},
url: "https://example.com");
roles: new List<string> {});

View file

@ -2,7 +2,7 @@ mutation {
functionsCreate(
functionId: "[FUNCTION_ID]",
name: "[NAME]",
runtime: "node-14.5"
runtime: "node-18.0"
) {
_id
_createdAt

View file

@ -1,8 +1,7 @@
mutation {
functionsUpdate(
functionId: "[FUNCTION_ID]",
name: "[NAME]",
runtime: "node-14.5"
name: "[NAME]"
) {
_id
_createdAt

View file

@ -1,8 +1,7 @@
mutation {
teamsCreateMembership(
teamId: "[TEAM_ID]",
roles: [],
url: "https://example.com"
roles: []
) {
_id
_createdAt

View file

@ -12,7 +12,7 @@ Functions functions = new Functions(client);
functions.create(
"[FUNCTION_ID]",
"[NAME]",
"node-14.5",
"node-18.0",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();

View file

@ -12,7 +12,6 @@ Functions functions = new Functions(client);
functions.update(
"[FUNCTION_ID]",
"[NAME]",
"node-14.5",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();

View file

@ -12,7 +12,6 @@ Teams teams = new Teams(client);
teams.createMembership(
"[TEAM_ID]",
listOf(),
"https://example.com",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();

View file

@ -11,5 +11,5 @@ val functions = Functions(client)
val response = functions.create(
functionId = "[FUNCTION_ID]",
name = "[NAME]",
runtime = "node-14.5",
runtime = "node-18.0",
)

View file

@ -11,5 +11,4 @@ val functions = Functions(client)
val response = functions.update(
functionId = "[FUNCTION_ID]",
name = "[NAME]",
runtime = "node-14.5",
)

View file

@ -11,5 +11,4 @@ val teams = Teams(client)
val response = teams.createMembership(
teamId = "[TEAM_ID]",
roles = listOf(),
url = "https://example.com",
)

View file

@ -11,7 +11,7 @@ client
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = functions.create('[FUNCTION_ID]', '[NAME]', 'node-14.5');
const promise = functions.create('[FUNCTION_ID]', '[NAME]', 'node-18.0');
promise.then(function (response) {
console.log(response);

View file

@ -11,7 +11,7 @@ client
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = functions.update('[FUNCTION_ID]', '[NAME]', 'node-14.5');
const promise = functions.update('[FUNCTION_ID]', '[NAME]');
promise.then(function (response) {
console.log(response);

View file

@ -11,7 +11,7 @@ client
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = teams.createMembership('[TEAM_ID]', [], 'https://example.com');
const promise = teams.createMembership('[TEAM_ID]', []);
promise.then(function (response) {
console.log(response);

View file

@ -13,4 +13,4 @@ $client
$functions = new Functions($client);
$result = $functions->create('[FUNCTION_ID]', '[NAME]', 'node-14.5');
$result = $functions->create('[FUNCTION_ID]', '[NAME]', 'node-18.0');

View file

@ -13,4 +13,4 @@ $client
$functions = new Functions($client);
$result = $functions->update('[FUNCTION_ID]', '[NAME]', 'node-14.5');
$result = $functions->update('[FUNCTION_ID]', '[NAME]');

Some files were not shown because too many files have changed in this diff Show more