diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 1dfbc0ba0f..29f39c55af 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -49,6 +49,12 @@ App::post('/v1/proxy/rules') if ($domain === $mainDomain) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your main domain to specific resource. Please use subdomain or a different domain.'); } + + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + if (str_ends_with($domain, $functionsDomain)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.'); + } + if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index d70f1c48b0..37c5c032e1 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -63,7 +63,7 @@ App::post('/v1/storage/buckets') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) - ->param('maximumFileSize', (int) System::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) System::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true) + ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) App::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) App::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) diff --git a/app/init.php b/app/init.php index 847c67bebc..7003b5c0fa 100644 --- a/app/init.php +++ b/app/init.php @@ -1688,3 +1688,6 @@ App::setResource('requestTimestamp', function ($request) { } return $requestTimestamp; }, ['request']); +App::setResource('plan', function (array $plan = []) { + return []; +}); diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index 012d09d92f..bae0d8bda9 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -2,12 +2,43 @@ namespace Tests\E2E\Services\Projects; +use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Utopia\System\System; class ProjectsCustomServerTest extends Scope { use ProjectCustom; use SideServer; + + // Domains + + public function testCreateProjectRule() + { + $headers = array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-mode' => 'admin', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]); + + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [ + 'resourceType' => 'api', + 'domain' => 'api.appwrite.test', + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // prevent functions domain + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [ + 'resourceType' => 'api', + 'domain' => $functionsDomain, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } }