Merge remote-tracking branch 'origin/1.6.x' into feat-runtime-controls-1.5.x

# Conflicts:
#	app/config/specs/open-api3-latest-client.json
#	app/config/specs/open-api3-latest-console.json
#	app/config/specs/open-api3-latest-server.json
#	app/config/specs/swagger2-1.6.x-client.json
#	app/config/specs/swagger2-1.6.x-console.json
#	app/config/specs/swagger2-latest-client.json
#	app/config/specs/swagger2-latest-console.json
#	app/config/specs/swagger2-latest-server.json
This commit is contained in:
Bradley Schofield
2024-08-19 14:05:56 +09:00
27 changed files with 129 additions and 64 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \
--no-plugins --no-scripts --prefer-dist \
`if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi`
FROM appwrite/base:0.9.1 as final
FROM appwrite/base:0.9.2 as final
LABEL maintainer="team@appwrite.io"
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
+3 -2
View File
@@ -1700,15 +1700,16 @@ App::post('/v1/functions/:functionId/executions')
->label('sdk.method', 'createExecution')
->label('sdk.description', '/docs/references/functions/create-execution.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.type', Response::CONTENT_TYPE_MULTIPART)
->label('sdk.response.model', Response::MODEL_EXECUTION)
->label('sdk.request.type', Response::CONTENT_TYPE_MULTIPART)
->param('functionId', '', new UID(), 'Function ID.')
->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true)
->param('async', false, new Boolean(), 'Execute code in the background. Default value is false.', true)
->param('path', '/', new Text(2048), 'HTTP path of execution. Path can include query params. Default value is /', true)
->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true), 'HTTP method of execution. Default value is GET.', true)
->param('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', true)
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
->param('scheduledAt', null, new DatetimeValidator(true, DateTimeValidator::PRECISION_MINUTES, 60), 'Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.', true)
->inject('response')
->inject('request')
->inject('project')
+2 -2
View File
@@ -16,7 +16,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use PHPMailer\PHPMailer\PHPMailer;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Cache\Cache;
@@ -209,7 +209,7 @@ App::post('/v1/projects')
$audit = new Audit($dbForProject);
$audit->setup();
$abuse = new TimeLimit('', 0, 1, $dbForProject);
$abuse = new AbuseDatabase('', 0, 1, $dbForProject);
$abuse->setup();
/** @var array $collections */
+2 -2
View File
@@ -18,7 +18,7 @@ use Appwrite\Messaging\Adapter\Realtime;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
use Utopia\App;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
@@ -380,7 +380,7 @@ App::init()
foreach ($abuseKeyLabel as $abuseKey) {
$start = $request->getContentRangeStart();
$end = $request->getContentRangeEnd();
$timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
$timeLimit = new AbuseDatabase($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
$timeLimit
->setParam('{projectId}', $project->getId())
->setParam('{userId}', $user->getId())
+3 -3
View File
@@ -9,7 +9,7 @@ use Swoole\Http\Request as SwooleRequest;
use Swoole\Http\Response as SwooleResponse;
use Swoole\Http\Server;
use Swoole\Process;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\CLI\Console;
@@ -101,8 +101,8 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$audit->setup();
}
if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $dbForConsole);
if ($dbForConsole->getCollection(AbuseDatabase::COLLECTION)->isEmpty()) {
$adapter = new AbuseDatabase("", 0, 1, $dbForConsole);
$adapter->setup();
}
+1 -1
View File
@@ -118,7 +118,7 @@ const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours
const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours
const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours
const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours
const APP_CACHE_BUSTER = 4314;
const APP_CACHE_BUSTER = 4315;
const APP_VERSION_STABLE = '1.6.0';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
+3 -3
View File
@@ -13,7 +13,7 @@ use Swoole\Runtime;
use Swoole\Table;
use Swoole\Timer;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
use Utopia\App;
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
@@ -463,7 +463,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
*
* Abuse limits are connecting 128 times per minute and ip address.
*/
$timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject);
$timeLimit = new AbuseDatabase('url:{url},ip:{ip}', 128, 60, $dbForProject);
$timeLimit
->setParam('{ip}', $request->getIP())
->setParam('{url}', $request->getURI());
@@ -563,7 +563,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
*
* Abuse limits are sending 32 times per minute and connection.
*/
$timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database);
$timeLimit = new AbuseDatabase('url:{url},connection:{connection}', 32, 60, $database);
$timeLimit
->setParam('{connection}', $connection)
+1 -1
View File
@@ -166,7 +166,7 @@ $image = $this->getParam('image', '');
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: <?php echo $organization; ?>/console:appwrite/console:5.0.0-rc14
image: <?php echo $organization; ?>/console:appwrite/console:5.0.0-rc16
restart: unless-stopped
networks:
- appwrite
+3 -3
View File
@@ -44,13 +44,13 @@
"ext-sockets": "*",
"appwrite/php-runtimes": "0.14.*",
"appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "0.38.*",
"utopia-php/abuse": "0.40.*",
"utopia-php/analytics": "0.10.*",
"utopia-php/audit": "0.40.*",
"utopia-php/audit": "0.41.*",
"utopia-php/cache": "0.10.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.50.*",
"utopia-php/database": "0.51.*",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
Generated
+23 -21
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": "340aae0879435fc71eac688d47033eb4",
"content-hash": "cd0323e7303780f34b2f775a526de516",
"packages": [
{
"name": "adhocore/jwt",
@@ -1429,26 +1429,28 @@
},
{
"name": "utopia-php/abuse",
"version": "0.38.0",
"version": "0.40.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "b7be9086c9d9b4561d810cbd42fdda798742f56c"
"reference": "69748a6741a9e44f0c9e430f3c2bd2b8a677c048"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/b7be9086c9d9b4561d810cbd42fdda798742f56c",
"reference": "b7be9086c9d9b4561d810cbd42fdda798742f56c",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/69748a6741a9e44f0c9e430f3c2bd2b8a677c048",
"reference": "69748a6741a9e44f0c9e430f3c2bd2b8a677c048",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-pdo": "*",
"ext-redis": "*",
"php": ">=8.0",
"utopia-php/database": "0.50.*"
"utopia-php/database": "0.51.*"
},
"require-dev": {
"laravel/pint": "1.5.*",
"phpbench/phpbench": "^1.2",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.4"
},
@@ -1472,9 +1474,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.38.0"
"source": "https://github.com/utopia-php/abuse/tree/0.40.0"
},
"time": "2024-06-24T00:52:02+00:00"
"time": "2024-08-16T06:08:24+00:00"
},
{
"name": "utopia-php/analytics",
@@ -1524,21 +1526,21 @@
},
{
"name": "utopia-php/audit",
"version": "0.40.0",
"version": "0.41.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "735ae211ce5fee5b52b736731571b4030b1d7cdc"
"reference": "77f1d0a95ea791e38a38a8bc1b7728ffcedcd2d1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/735ae211ce5fee5b52b736731571b4030b1d7cdc",
"reference": "735ae211ce5fee5b52b736731571b4030b1d7cdc",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/77f1d0a95ea791e38a38a8bc1b7728ffcedcd2d1",
"reference": "77f1d0a95ea791e38a38a8bc1b7728ffcedcd2d1",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "0.50.*"
"utopia-php/database": "0.51.*"
},
"require-dev": {
"laravel/pint": "1.5.*",
@@ -1565,9 +1567,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.40.0"
"source": "https://github.com/utopia-php/audit/tree/0.41.0"
},
"time": "2024-06-24T00:52:17+00:00"
"time": "2024-08-16T06:08:00+00:00"
},
{
"name": "utopia-php/cache",
@@ -1721,16 +1723,16 @@
},
{
"name": "utopia-php/database",
"version": "0.50.4",
"version": "0.51.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "fd3b856be77bd643bc8a9e3572ee11e4185b9230"
"reference": "845783a54cced784e00db084a29486fdb96d3d58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/fd3b856be77bd643bc8a9e3572ee11e4185b9230",
"reference": "fd3b856be77bd643bc8a9e3572ee11e4185b9230",
"url": "https://api.github.com/repos/utopia-php/database/zipball/845783a54cced784e00db084a29486fdb96d3d58",
"reference": "845783a54cced784e00db084a29486fdb96d3d58",
"shasum": ""
},
"require": {
@@ -1771,9 +1773,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.50.4"
"source": "https://github.com/utopia-php/database/tree/0.51.1"
},
"time": "2024-08-13T03:18:26+00:00"
"time": "2024-08-16T10:54:25+00:00"
},
{
"name": "utopia-php/domains",
+1 -1
View File
@@ -195,7 +195,7 @@ services:
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: appwrite/console:5.0.0-rc15
image: appwrite/console:5.0.0-rc16
restart: unless-stopped
networks:
- appwrite
+3 -3
View File
@@ -7,7 +7,7 @@ use Appwrite\Extend\Exception;
use Executor\Executor;
use Throwable;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
use Utopia\Audit\Audit;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
@@ -493,7 +493,7 @@ class Deletes extends Action
$projectCollectionIds = [
...\array_keys(Config::getParam('collections', [])['projects']),
Audit::COLLECTION,
TimeLimit::COLLECTION,
AbuseDatabase::COLLECTION,
];
$limit = \count($projectCollectionIds) + 25;
@@ -686,7 +686,7 @@ class Deletes extends Action
{
$projectId = $project->getId();
$dbForProject = $getProjectDB($project);
$timeLimit = new TimeLimit("", 0, 1, $dbForProject);
$timeLimit = new AbuseDatabase("", 0, 1, $dbForProject);
$abuse = new Abuse($timeLimit);
try {
+1 -1
View File
@@ -14,7 +14,7 @@ class V18 extends Filter
unset($content['otp']);
break;
case 'functions.create':
$content['templateVersion'] = $content['templateBranch'];
$content['templateVersion'] = $content['templateBranch'] ?? "";
unset($content['templateBranch']);
break;
}
@@ -219,7 +219,8 @@ class FunctionsCustomClientTest extends Scope
// Schedule execution for the future
\date_default_timezone_set('UTC');
$futureTime = (new \DateTime())->add(new \DateInterval('PT10S'));
$futureTime = (new \DateTime())->add(new \DateInterval('PT2M'));
$futureTime->setTime($futureTime->format('H'), $futureTime->format('i'), 0, 0);
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
'content-type' => 'application/json',
@@ -236,7 +237,7 @@ class FunctionsCustomClientTest extends Scope
$executionId = $execution['body']['$id'];
sleep(10);
sleep(60 + 60 + 15); // up to 1 minute round up, 1 minute schedule postpone, 15s cold start safety
$start = \microtime(true);
while (true) {
@@ -251,7 +252,7 @@ class FunctionsCustomClientTest extends Scope
}
if (\microtime(true) - $start > 10) {
$this->fail('Execution did not complete within 10 seconds of schedule in status ' . $execution['body']['status'] . ': ' . \json_encode($execution));
$this->fail('Scheduled execution did not complete with status ' . $execution['body']['status'] . ': ' . \json_encode($execution));
}
usleep(500000); // 0.5 seconds
@@ -267,7 +268,6 @@ class FunctionsCustomClientTest extends Scope
/* Test for FAILURE */
// Schedule synchronous execution
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@@ -278,6 +278,41 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(400, $execution['headers']['status-code']);
// Execution with seconds precision
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'async' => true,
'scheduledAt' => (new \DateTime("2100-12-08 16:12:02"))->format(\DateTime::ATOM)
]);
$this->assertEquals(400, $execution['headers']['status-code']);
// Execution with milliseconds precision
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'async' => true,
'scheduledAt' => (new \DateTime("2100-12-08 16:12:02.255"))->format(\DateTime::ATOM)
]);
$this->assertEquals(400, $execution['headers']['status-code']);
// Execution too soon
$futureTime = (new \DateTime())->add(new \DateInterval('PT1M'));
$futureTime->setTime($futureTime->format('H'), $futureTime->format('i'), 0, 0);
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'async' => true,
'scheduledAt' => $futureTime->format(\DateTime::ATOM),
]);
$this->assertEquals(400, $execution['headers']['status-code']);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $function['body']['$id'], [
'content-type' => 'application/json',
@@ -455,8 +455,8 @@ class FunctionsCustomServerTest extends Scope
$entrypoint = null;
$rootDirectory = null;
$commands = null;
foreach($template['body']['runtimes'] as $runtime) {
if($runtime["name"] !== $runtimeName) {
foreach ($template['body']['runtimes'] as $runtime) {
if ($runtime["name"] !== $runtimeName) {
continue;
}
@@ -1287,14 +1287,15 @@ class FunctionsCustomServerTest extends Scope
*/
public function testDeleteScheduledExecution($data): array
{
$futureTime = (new \DateTime())->add(new \DateInterval('PT10H'))->format('Y-m-d H:i:s');
$futureTime = (new \DateTime())->add(new \DateInterval('PT10H'));
$futureTime->setTime($futureTime->format('H'), $futureTime->format('i'), 0, 0);
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'async' => true,
'scheduledAt' => $futureTime,
'scheduledAt' => $futureTime->format('Y-m-d H:i:s'),
]);
$executionId = $execution['body']['$id'] ?? '';
@@ -2512,4 +2513,30 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(204, $response['headers']['status-code']);
}
public function testCreateFunctionWithResponseFormatHeader()
{
$response = $this->client->call(Client::METHOD_POST, '/functions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-response-format' => '1.5.0', // add response format header
], $this->getHeaders()), [
'functionId' => ID::unique(),
'name' => 'Test',
'runtime' => 'php-8.0',
'entrypoint' => 'index.php',
'timeout' => 15,
]);
$this->assertEquals(201, $response['headers']['status-code']);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $response['body']['$id'], [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(204, $response['headers']['status-code']);
}
}