diff --git a/.env b/.env index b889ebb513..2283ceeb30 100644 --- a/.env +++ b/.env @@ -9,7 +9,8 @@ _APP_CONSOLE_COUNTRIES_DENYLIST=AQ _APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io _APP_SYSTEM_EMAIL_NAME=Appwrite _APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io -_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io +_APP_EMAIL_SECURITY=security@appwrite.io +_APP_EMAIL_CERTIFICATES=certificates@appwrite.io _APP_SYSTEM_RESPONSE_FORMAT= _APP_OPTIONS_ABUSE=disabled _APP_OPTIONS_ROUTER_PROTECTION=disabled diff --git a/app/cli.php b/app/cli.php index da7d23c18d..d132f25b1a 100644 --- a/app/cli.php +++ b/app/cli.php @@ -202,7 +202,7 @@ CLI::setResource('logError', function (Registry $register) { }, ['register']); $platform = new Appwrite(); -$platform->init(Service::TYPE_CLI); +$platform->init(Service::TYPE_TASK); $cli = $platform->getCli(); diff --git a/app/config/variables.php b/app/config/variables.php index b61a267785..f7cd34b1e1 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -162,13 +162,31 @@ return [ ], [ 'name' => '_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', - 'description' => 'This is the email address used to issue SSL certificates for custom domains or the user agent in your webhooks payload.', + 'description' => 'Deprecated since 1.5.1 use _APP_EMAIL_SECURITY and _APP_EMAIL_CERTIFICATES instead', 'introduction' => '0.7.0', 'default' => 'certs@appwrite.io', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_EMAIL_SECURITY', + 'description' => 'This is the email address used as the user agent in your webhooks payload.', + 'introduction' => '1.5.1', + 'default' => '', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_EMAIL_CERTIFICATES', + 'description' => 'This is the email address used to issue SSL certificates for custom domains', + 'introduction' => '1.5.1', + 'default' => '', + 'required' => true, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_USAGE_STATS', 'description' => 'This variable allows you to disable the collection and displaying of usage stats. This value is set to \'enabled\' by default, to disable the usage stats set the value to \'disabled\'. When disabled, it\'s recommended to turn off the Worker Usage container to reduce resource usage.', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index d005a6594c..8ffce17576 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -290,7 +290,9 @@ App::post('/v1/account') $existingTarget = $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ]); - $user->setAttribute('targets', [...$user->getAttribute('targets', []), $existingTarget]); + if($existingTarget) { + $user->setAttribute('targets', $existingTarget, Document::SET_TYPE_APPEND); + } } $dbForProject->purgeCachedDocument('users', $user->getId()); diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 337ba8fd9e..a3bd47595d 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -321,7 +321,7 @@ App::get('/v1/avatars/favicon') ->setUserAgent(\sprintf( APP_USERAGENT, System::getEnv('_APP_VERSION', 'UNKNOWN'), - System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) + System::getEnv('_APP_EMAIL_SECURITY', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)) )) ->fetch($url); } catch (\Throwable) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 9215d99345..1dd3bb597c 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -351,7 +351,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ->label('sdk.response.model', Response::MODEL_FILE) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new CustomId(), 'File 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('file', [], new File(), 'Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https://appwrite.io/docs/storage#file-input).', skipValidation: true) + ->param('file', [], new File(), 'Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https://appwrite.io/docs/products/storage/upload-download#input-file).', skipValidation: true) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->inject('request') ->inject('response') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index d003fcfd37..5891fb67f0 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -387,7 +387,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](https://appwrite.io/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.', true, ['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. This parameter is not required when an API key is supplied. 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) ->inject('response') ->inject('project') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index abfcb34a5a..193f3f095e 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -138,7 +138,9 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e $existingTarget = $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ]); - $user->setAttribute('targets', [...$user->getAttribute('targets', []), $existingTarget]); + if($existingTarget) { + $user->setAttribute('targets', $existingTarget, Document::SET_TYPE_APPEND); + } } } @@ -160,7 +162,9 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e $existingTarget = $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ]); - $user->setAttribute('targets', [...$user->getAttribute('targets', []), $existingTarget]); + if($existingTarget) { + $user->setAttribute('targets', $existingTarget, Document::SET_TYPE_APPEND); + } } } diff --git a/app/init.php b/app/init.php index 6df2c02908..7e788d0979 100644 --- a/app/init.php +++ b/app/init.php @@ -1011,7 +1011,7 @@ foreach ($locales as $locale) { 'user_agent' => \sprintf( APP_USERAGENT, System::getEnv('_APP_VERSION', 'UNKNOWN'), - System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) + System::getEnv('_APP_EMAIL_SECURITY', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)) ), 'timeout' => 2, ], diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 9547cfda00..374e20eb39 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -79,7 +79,7 @@ $image = $this->getParam('image', ''); - _APP_CONSOLE_HOSTNAMES - _APP_SYSTEM_EMAIL_NAME - _APP_SYSTEM_EMAIL_ADDRESS - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_SECURITY - _APP_SYSTEM_RESPONSE_FORMAT - _APP_OPTIONS_ABUSE - _APP_OPTIONS_ROUTER_PROTECTION @@ -249,6 +249,7 @@ $image = $this->getParam('image', ''); - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 + - _APP_EMAIL_SECURITY - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS - _APP_DB_HOST - _APP_DB_PORT @@ -430,7 +431,7 @@ $image = $this->getParam('image', ''); - _APP_DOMAIN - _APP_DOMAIN_TARGET - _APP_DOMAIN_FUNCTIONS - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_CERTIFICATES - _APP_REDIS_HOST - _APP_REDIS_PORT - _APP_REDIS_USER @@ -580,7 +581,7 @@ $image = $this->getParam('image', ''); - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - _APP_DOMAIN_TARGET - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_SECURITY - _APP_REDIS_HOST - _APP_REDIS_PORT - _APP_REDIS_USER diff --git a/app/worker.php b/app/worker.php index 60358ad6b2..7037614f8e 100644 --- a/app/worker.php +++ b/app/worker.php @@ -284,11 +284,6 @@ if (!isset($args[1])) { \array_shift($args); $workerName = $args[0]; -$workerIndex = $args[1] ?? ''; - -if (!empty($workerIndex)) { - $workerName .= '_' . $workerIndex; -} if (\str_starts_with($workerName, 'databases')) { $queueName = System::getEnv('_APP_QUEUE_NAME', 'database_db_main'); diff --git a/composer.json b/composer.json index 205fe308f0..82e3e15a05 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "utopia-php/messaging": "0.11.*", "utopia-php/migration": "0.4.*", "utopia-php/orchestration": "0.9.*", - "utopia-php/platform": "0.5.*", + "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.5.*", "utopia-php/preloader": "0.2.*", "utopia-php/queue": "0.7.*", diff --git a/composer.lock b/composer.lock index 5464005e37..3d6e112eda 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "53996479cd4ba0c73dbc72d46b240be0", + "content-hash": "18bab1e5f72cc82896aef9e64bf566e8", "packages": [ { "name": "adhocore/jwt", @@ -2327,16 +2327,16 @@ }, { "name": "utopia-php/platform", - "version": "0.5.2", + "version": "0.7.0", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "b9feabc79b92dc2b05683a986ad43bce5c1583e3" + "reference": "beeea0f2c9bce14a6869fc5c87a1047cdecb5c52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/b9feabc79b92dc2b05683a986ad43bce5c1583e3", - "reference": "b9feabc79b92dc2b05683a986ad43bce5c1583e3", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/beeea0f2c9bce14a6869fc5c87a1047cdecb5c52", + "reference": "beeea0f2c9bce14a6869fc5c87a1047cdecb5c52", "shasum": "" }, "require": { @@ -2344,7 +2344,8 @@ "ext-redis": "*", "php": ">=8.0", "utopia-php/cli": "0.15.*", - "utopia-php/framework": "0.33.*" + "utopia-php/framework": "0.33.*", + "utopia-php/queue": "0.7.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -2370,9 +2371,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.5.2" + "source": "https://github.com/utopia-php/platform/tree/0.7.0" }, - "time": "2024-05-22T12:50:35+00:00" + "time": "2024-05-08T17:00:55+00:00" }, { "name": "utopia-php/pools", diff --git a/docker-compose.yml b/docker-compose.yml index b1e30a1e07..2b13a98f41 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -101,7 +101,7 @@ services: - _APP_CONSOLE_HOSTNAMES - _APP_SYSTEM_EMAIL_NAME - _APP_SYSTEM_EMAIL_ADDRESS - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_SECURITY - _APP_SYSTEM_RESPONSE_FORMAT - _APP_OPTIONS_ABUSE - _APP_OPTIONS_ROUTER_PROTECTION @@ -286,7 +286,7 @@ services: - _APP_ENV - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_SECURITY - _APP_DB_HOST - _APP_DB_PORT - _APP_DB_SCHEMA @@ -475,7 +475,7 @@ services: - _APP_DOMAIN - _APP_DOMAIN_TARGET - _APP_DOMAIN_FUNCTIONS - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_CERTIFICATES - _APP_REDIS_HOST - _APP_REDIS_PORT - _APP_REDIS_USER @@ -635,7 +635,7 @@ services: - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - _APP_DOMAIN_TARGET - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_SECURITY - _APP_REDIS_HOST - _APP_REDIS_PORT - _APP_REDIS_USER diff --git a/src/Appwrite/Platform/Appwrite.php b/src/Appwrite/Platform/Appwrite.php index 05224799f3..6b3eb077fa 100644 --- a/src/Appwrite/Platform/Appwrite.php +++ b/src/Appwrite/Platform/Appwrite.php @@ -2,15 +2,13 @@ namespace Appwrite\Platform; -use Appwrite\Platform\Services\Tasks; -use Appwrite\Platform\Services\Workers; +use Appwrite\Platform\Modules\Core; use Utopia\Platform\Platform; class Appwrite extends Platform { public function __construct() { - $this->addService('tasks', new Tasks()); - $this->addService('workers', new Workers()); + parent::__construct(new Core()); } } diff --git a/src/Appwrite/Platform/Modules/Core.php b/src/Appwrite/Platform/Modules/Core.php new file mode 100644 index 0000000000..859ca3b529 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Core.php @@ -0,0 +1,17 @@ +addService('tasks', new Tasks()); + $this->addService('workers', new Workers()); + } + +} diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index ac1f99eec3..31465d2f26 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -22,7 +22,7 @@ class Tasks extends Service { public function __construct() { - $this->type = self::TYPE_CLI; + $this->type = Service::TYPE_TASK; $this ->addAction(Doctor::getName(), new Doctor()) ->addAction(Install::getName(), new Install()) diff --git a/src/Appwrite/Platform/Services/Workers.php b/src/Appwrite/Platform/Services/Workers.php index 62a7fcf3fb..0e79f4257c 100644 --- a/src/Appwrite/Platform/Services/Workers.php +++ b/src/Appwrite/Platform/Services/Workers.php @@ -20,7 +20,7 @@ class Workers extends Service { public function __construct() { - $this->type = self::TYPE_WORKER; + $this->type = Service::TYPE_WORKER; $this ->addAction(Audits::getName(), new Audits()) ->addAction(Builds::getName(), new Builds()) diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 1fbbd3b2ec..ad6cf09fa7 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -135,9 +135,9 @@ class Certificates extends Action try { // Email for alerts is required by LetsEncrypt - $email = System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS'); + $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); if (empty($email)) { - throw new Exception('You must set a valid security email address (_APP_SYSTEM_SECURITY_EMAIL_ADDRESS) to issue an SSL certificate.'); + throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue an SSL certificate.'); } // Validate domain and DNS records. Skip if job is forced @@ -474,7 +474,7 @@ class Certificates extends Action ->setBody($body) ->setName('Appwrite Administrator') ->setVariables($emailVariables) - ->setRecipient(System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')) + ->setRecipient(System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS'))) ->trigger(); } diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index d60946f709..88ca7871f2 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -104,7 +104,7 @@ class Webhooks extends Action \curl_setopt($ch, CURLOPT_USERAGENT, \sprintf( APP_USERAGENT, System::getEnv('_APP_VERSION', 'UNKNOWN'), - System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY) + System::getEnv('_APP_EMAIL_SECURITY', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)) )); \curl_setopt( $ch, diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 23771712e8..b1f7c85cd9 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -150,7 +150,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); $this->assertArrayHasKey('accessedAt', $response['body']); @@ -294,7 +294,7 @@ class AccountCustomClientTest extends Scope $this->assertIsNumeric($response['body']['total']); $this->assertEquals("user.create", $response['body']['logs'][2]['event']); $this->assertEquals(filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP), $response['body']['logs'][2]['ip']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); $this->assertEquals('Windows', $response['body']['logs'][1]['osName']); $this->assertEquals('WIN', $response['body']['logs'][1]['osCode']); @@ -327,7 +327,6 @@ class AccountCustomClientTest extends Scope $this->assertEquals('desktop', $response['body']['logs'][2]['deviceName']); $this->assertEquals('', $response['body']['logs'][2]['deviceBrand']); $this->assertEquals('', $response['body']['logs'][2]['deviceModel']); - $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); $this->assertEquals('--', $response['body']['logs'][2]['countryCode']); $this->assertEquals('Unknown', $response['body']['logs'][2]['countryName']); @@ -343,7 +342,7 @@ class AccountCustomClientTest extends Scope ] ]); - $this->assertEquals($responseLimit['headers']['status-code'], 200); + $this->assertEquals(200, $responseLimit['headers']['status-code']); $this->assertIsArray($responseLimit['body']['logs']); $this->assertNotEmpty($responseLimit['body']['logs']); $this->assertCount(1, $responseLimit['body']['logs']); @@ -382,7 +381,7 @@ class AccountCustomClientTest extends Scope ] ]); - $this->assertEquals($responseLimitOffset['headers']['status-code'], 200); + $this->assertEquals(200, $responseLimitOffset['headers']['status-code']); $this->assertIsArray($responseLimitOffset['body']['logs']); $this->assertNotEmpty($responseLimitOffset['body']['logs']); $this->assertCount(1, $responseLimitOffset['body']['logs']); @@ -430,7 +429,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $newName); @@ -497,7 +496,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ @@ -587,7 +586,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $newEmail); /** @@ -629,7 +628,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $data['email']); $this->assertEquals($response['body']['name'], $data['name']); @@ -771,7 +770,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); $lastEmail = $this->getLastEmail(); @@ -1073,7 +1072,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); $lastEmail = $this->getLastEmail(); @@ -1668,7 +1667,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ @@ -1756,13 +1755,11 @@ class AccountCustomClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($response['body']['$id'], $userId); - $this->assertEquals($response['body']['name'], 'User Name'); - $this->assertEquals($response['body']['email'], 'useroauth@localhost.test'); + $this->assertEquals('User Name', $response['body']['name']); + $this->assertEquals('useroauth@localhost.test', $response['body']['email']); // Since we only support one oauth user, let's also check updateSession here - $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/account/sessions/current', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', @@ -1808,7 +1805,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals($response['body']['provider'], 'anonymous'); + $this->assertEquals('anonymous', $response['body']['provider']); $sessionID = $response['body']['$id']; @@ -1821,7 +1818,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals($response['body']['provider'], 'anonymous'); + $this->assertEquals('anonymous', $response['body']['provider']); $response = $this->client->call(Client::METHOD_GET, '/account/sessions/97823askjdkasd80921371980', array_merge([ 'origin' => 'http://localhost', @@ -1934,7 +1931,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); $userId = $response['body']['userId']; @@ -2085,7 +2082,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ @@ -2127,7 +2124,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['phone'], $newPhone); /** @@ -2240,7 +2237,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); $smsRequest = $this->getLastRequest(); @@ -2327,7 +2324,7 @@ class AccountCustomClientTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); $this->assertEmpty($response['body']['phrase']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); $userId = $response['body']['userId']; @@ -2452,7 +2449,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertTrue($response['body']['emailVerification']); @@ -2512,7 +2509,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); + $this->assertTrue((new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 119c1a2223..0b8ea71aad 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -716,4 +716,94 @@ class FunctionsCustomClientTest extends Scope return []; } + + public function testNonOverrideOfHeaders(): array + { + /** + * Test for SUCCESS + */ + $projectId = $this->getProject()['$id']; + $apikey = $this->getProject()['apiKey']; + + $function = $this->client->call(Client::METHOD_POST, '/functions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'functionId' => ID::unique(), + 'name' => 'Test', + 'execute' => [Role::any()->toString()], + 'runtime' => 'node-18.0', + 'entrypoint' => 'index.js' + ]); + + $functionId = $function['body']['$id'] ?? ''; + + $this->assertEquals(201, $function['headers']['status-code']); + + $folder = 'node'; + $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; + $this->packageCode($folder); + + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', [ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'entrypoint' => 'index.js', + 'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional + 'activate' => true + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->assertEquals(202, $deployment['headers']['status-code']); + + // Poll until deployment is built + while (true) { + $deployment = $this->client->call(Client::METHOD_GET, '/functions/' . $function['body']['$id'] . '/deployments/' . $deploymentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + + if ( + $deployment['headers']['status-code'] >= 400 + || \in_array($deployment['body']['status'], ['ready', 'failed']) + ) { + break; + } + + \sleep(1); + } + + $this->assertEquals('ready', $deployment['body']['status']); + + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'x-appwrite-event' => "OVERRIDDEN", + 'x-appwrite-trigger' => "OVERRIDDEN", + 'x-appwrite-user-id' => "OVERRIDDEN", + 'x-appwrite-user-jwt' => "OVERRIDDEN", + ]); + + $output = json_decode($execution['body']['responseBody'], true); + $this->assertNotEquals('OVERRIDDEN', $output['APPWRITE_FUNCTION_JWT']); + $this->assertNotEquals('OVERRIDDEN', $output['APPWRITE_FUNCTION_EVENT']); + $this->assertNotEquals('OVERRIDDEN', $output['APPWRITE_FUNCTION_TRIGGER']); + $this->assertNotEquals('OVERRIDDEN', $output['APPWRITE_FUNCTION_USER_ID']); + + // Cleanup : Delete function + $response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], []); + + $this->assertEquals(204, $response['headers']['status-code']); + + return []; + } }