mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.6.x' into feat-renaming-attributes
# Conflicts: # 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-console.json # app/config/specs/swagger2-latest-server.json # app/controllers/shared/api.php # app/realtime.php # composer.lock # src/Appwrite/Platform/Workers/Deletes.php
This commit is contained in:
+1
-1
@@ -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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1635,15 +1635,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 Text(65535), new Assoc()], 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('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', 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')
|
||||
|
||||
@@ -373,15 +373,15 @@ App::init()
|
||||
* Abuse Check
|
||||
*/
|
||||
$abuseKeyLabel = $route->getLabel('abuse-key', 'url:{url},ip:{ip}');
|
||||
$abuseAdapterArray = [];
|
||||
$timeLimitArray = [];
|
||||
|
||||
$abuseKeyLabel = (!is_array($abuseKeyLabel)) ? [$abuseKeyLabel] : $abuseKeyLabel;
|
||||
|
||||
foreach ($abuseKeyLabel as $abuseKey) {
|
||||
$start = $request->getContentRangeStart();
|
||||
$end = $request->getContentRangeEnd();
|
||||
$abuseAdapter = new AbuseDatabase($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
|
||||
$abuseAdapter
|
||||
$timeLimit = new AbuseDatabase($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
|
||||
$timeLimit
|
||||
->setParam('{projectId}', $project->getId())
|
||||
->setParam('{userId}', $user->getId())
|
||||
->setParam('{userAgent}', $request->getUserAgent(''))
|
||||
@@ -389,7 +389,7 @@ App::init()
|
||||
->setParam('{url}', $request->getHostname() . $route->getPath())
|
||||
->setParam('{method}', $request->getMethod())
|
||||
->setParam('{chunkId}', (int) ($start / ($end + 1 - $start)));
|
||||
$abuseAdapterArray[] = $abuseAdapter;
|
||||
$timeLimitArray[] = $timeLimit;
|
||||
}
|
||||
|
||||
$closestLimit = null;
|
||||
@@ -398,17 +398,17 @@ App::init()
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
|
||||
$isAppUser = Auth::isAppUser($roles);
|
||||
|
||||
foreach ($abuseAdapterArray as $abuseAdapter) {
|
||||
foreach ($timeLimitArray as $timeLimit) {
|
||||
foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
|
||||
if (!empty($value)) {
|
||||
$abuseAdapter->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value);
|
||||
$timeLimit->setParam('{param-' . $key . '}', (\is_array($value)) ? \json_encode($value) : $value);
|
||||
}
|
||||
}
|
||||
|
||||
$abuse = new Abuse($abuseAdapter);
|
||||
$remaining = $abuseAdapter->remaining();
|
||||
$limit = $abuseAdapter->limit();
|
||||
$time = (new \DateTime($abuseAdapter->time()))->getTimestamp() + $route->getLabel('abuse-time', 3600);
|
||||
$abuse = new Abuse($timeLimit);
|
||||
$remaining = $timeLimit->remaining();
|
||||
$limit = $timeLimit->limit();
|
||||
$time = (new \DateTime($timeLimit->time()))->getTimestamp() + $route->getLabel('abuse-time', 3600);
|
||||
|
||||
if ($limit && ($remaining < $closestLimit || is_null($closestLimit))) {
|
||||
$closestLimit = $remaining;
|
||||
|
||||
+1
-1
@@ -117,7 +117,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';
|
||||
|
||||
+6
-6
@@ -463,12 +463,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
||||
*
|
||||
* Abuse limits are connecting 128 times per minute and ip address.
|
||||
*/
|
||||
$abuseAdapter = new AbuseDatabase('url:{url},ip:{ip}', 128, 60, $dbForProject);
|
||||
$abuseAdapter
|
||||
$timeLimit = new AbuseDatabase('url:{url},ip:{ip}', 128, 60, $dbForProject);
|
||||
$timeLimit
|
||||
->setParam('{ip}', $request->getIP())
|
||||
->setParam('{url}', $request->getURI());
|
||||
|
||||
$abuse = new Abuse($abuseAdapter);
|
||||
$abuse = new Abuse($timeLimit);
|
||||
|
||||
if (System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) {
|
||||
throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests');
|
||||
@@ -563,13 +563,13 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
||||
*
|
||||
* Abuse limits are sending 32 times per minute and connection.
|
||||
*/
|
||||
$abuseDatabase = new AbuseDatabase('url:{url},connection:{connection}', 32, 60, $database);
|
||||
$timeLimit = new AbuseDatabase('url:{url},connection:{connection}', 32, 60, $database);
|
||||
|
||||
$abuseDatabase
|
||||
$timeLimit
|
||||
->setParam('{connection}', $connection)
|
||||
->setParam('{container}', $containerId);
|
||||
|
||||
$abuse = new Abuse($abuseDatabase);
|
||||
$abuse = new Abuse($timeLimit);
|
||||
|
||||
if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') {
|
||||
throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many messages.');
|
||||
|
||||
@@ -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
|
||||
@@ -475,6 +475,8 @@ $image = $this->getParam('image', '');
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
|
||||
Generated
+12
-12
@@ -1723,16 +1723,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.51.0",
|
||||
"version": "0.51.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "cf723c720e5aa938709e74f1ccfc3b46ecdc6de3"
|
||||
"reference": "845783a54cced784e00db084a29486fdb96d3d58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/cf723c720e5aa938709e74f1ccfc3b46ecdc6de3",
|
||||
"reference": "cf723c720e5aa938709e74f1ccfc3b46ecdc6de3",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/845783a54cced784e00db084a29486fdb96d3d58",
|
||||
"reference": "845783a54cced784e00db084a29486fdb96d3d58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1773,9 +1773,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.51.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.51.1"
|
||||
},
|
||||
"time": "2024-08-16T03:28:04+00:00"
|
||||
"time": "2024-08-16T10:54:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -2993,16 +2993,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.39.6",
|
||||
"version": "0.39.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "00e6f9e77ea380d8ab3138a36548b353077e4061"
|
||||
"reference": "a3998d8971c43ff2247542c128f98a94fa4833e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/00e6f9e77ea380d8ab3138a36548b353077e4061",
|
||||
"reference": "00e6f9e77ea380d8ab3138a36548b353077e4061",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a3998d8971c43ff2247542c128f98a94fa4833e7",
|
||||
"reference": "a3998d8971c43ff2247542c128f98a94fa4833e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3038,9 +3038,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.39.6"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.39.7"
|
||||
},
|
||||
"time": "2024-08-08T12:44:28+00:00"
|
||||
"time": "2024-08-19T09:33:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -686,8 +686,8 @@ class Deletes extends Action
|
||||
{
|
||||
$projectId = $project->getId();
|
||||
$dbForProject = $getProjectDB($project);
|
||||
$abuseAdapter = new AbuseDatabase("", 0, 1, $dbForProject);
|
||||
$abuse = new Abuse($abuseAdapter);
|
||||
$timeLimit = new AbuseDatabase("", 0, 1, $dbForProject);
|
||||
$abuse = new Abuse($timeLimit);
|
||||
|
||||
try {
|
||||
$abuse->cleanup($abuseRetention);
|
||||
|
||||
@@ -286,7 +286,13 @@ class Swagger2 extends Format
|
||||
$validator = $validator->getValidator();
|
||||
}
|
||||
|
||||
switch ((!empty($validator)) ? \get_class($validator) : '') {
|
||||
$validatorClass = (!empty($validator)) ? \get_class($validator) : '';
|
||||
if($validatorClass === 'Utopia\Validator\AnyOf') {
|
||||
$validator = $param['validator']->getValidators()[0];
|
||||
$validatorClass = \get_class($validator);
|
||||
}
|
||||
|
||||
switch ($validatorClass) {
|
||||
case 'Utopia\Validator\Text':
|
||||
case 'Utopia\Database\Validator\UID':
|
||||
$node['type'] = $validator->getType();
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -454,8 +454,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;
|
||||
}
|
||||
|
||||
@@ -1286,14 +1286,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'] ?? '';
|
||||
@@ -2063,8 +2064,33 @@ class FunctionsCustomServerTest extends Scope
|
||||
$this->assertEquals(201, $execution['headers']['status-code']);
|
||||
$this->assertEquals('completed', $execution['body']['status']);
|
||||
$this->assertEquals(200, $execution['body']['responseStatusCode']);
|
||||
$this->assertNotEmpty($execution['body']['responseBody']);
|
||||
$this->assertGreaterThan(0, $execution['body']['duration']);
|
||||
$this->assertNotEmpty($execution['body']['responseBody']);
|
||||
$this->assertStringContainsString("total", $execution['body']['responseBody']);
|
||||
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'async' => true
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $execution['headers']['status-code']);
|
||||
$this->assertNotEmpty($execution['body']['$id']);
|
||||
|
||||
\sleep(10);
|
||||
|
||||
$execution = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $execution['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), []);
|
||||
|
||||
$this->assertEquals(200, $execution['headers']['status-code']);
|
||||
$this->assertEquals('completed', $execution['body']['status']);
|
||||
$this->assertEquals(200, $execution['body']['responseStatusCode']);
|
||||
$this->assertGreaterThan(0, $execution['body']['duration']);
|
||||
$this->assertNotEmpty($execution['body']['logs']);
|
||||
$this->assertStringContainsString("total", $execution['body']['logs']);
|
||||
|
||||
// Cleanup : Delete function
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [
|
||||
@@ -2418,4 +2444,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']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,7 @@ return function ($context) {
|
||||
->setProject(getenv('APPWRITE_FUNCTION_PROJECT_ID'))
|
||||
->setKey($context->req->headers['x-appwrite-key']);
|
||||
$users = new Users($client);
|
||||
return $context->res->json($users->list());
|
||||
$response = $users->list();
|
||||
$context->log($response);
|
||||
return $context->res->json($response);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user