diff --git a/app/config/sdks.php b/app/config/sdks.php index 78209cc5dd..9b5d17176f 100644 --- a/app/config/sdks.php +++ b/app/config/sdks.php @@ -116,6 +116,7 @@ return [ [ 'key' => 'android', 'name' => 'Android', + 'namespace' => 'io.appwrite', 'version' => '11.4.0', 'url' => 'https://github.com/appwrite/sdk-for-android', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', @@ -395,6 +396,7 @@ return [ [ 'key' => 'kotlin', 'name' => 'Kotlin', + 'namespace' => 'io.appwrite', 'version' => '13.1.0', 'url' => 'https://github.com/appwrite/sdk-for-kotlin', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin', diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index e6f4394e25..ec4cc25ea3 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -461,7 +461,7 @@ App::post('/v1/storage/buckets/:bucketId/files') // Add permissions for current the user if none were provided. if (\is_null($permissions)) { $permissions = []; - if (!empty($user->getId())) { + if (!empty($user->getId()) && !$isPrivilegedUser) { foreach ($allowedPermissions as $permission) { $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); } @@ -470,7 +470,7 @@ App::post('/v1/storage/buckets/:bucketId/files') // Users can only manage their own roles, API keys and Admin users can manage any $roles = Authorization::getRoles(); - if (!User::isApp($roles) && !User::isPrivileged($roles)) { + if (!$isAPIKey && !$isPrivilegedUser) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php index 3db0c74d45..356209ef6f 100644 --- a/src/Appwrite/Platform/Action.php +++ b/src/Appwrite/Platform/Action.php @@ -22,9 +22,9 @@ class Action extends UtopiaAction protected mixed $logError; protected array $filters = [ - 'subQueryKeys', 'subQueryWebhooks', 'subQueryPlatforms', 'subQueryProjectVariables', 'subQueryBlocks', 'subQueryDevKeys', // Project + 'subQueryKeys', 'subQueryWebhooks', 'subQueryPlatforms', 'subQueryBlocks', 'subQueryDevKeys', // Project 'subQueryAuthenticators', 'subQuerySessions', 'subQueryTokens', 'subQueryChallenges', 'subQueryMemberships', 'subQueryTargets', 'subQueryTopicTargets',// Users - 'subQueryVariables', // Sites + 'subQueryVariables', 'subQueryProjectVariables' // Sites / Functions ]; /** diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index 7c3a06ab30..6ec06f5c8a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -227,7 +227,7 @@ class Create extends Action // Add permissions for current the user if none were provided. if (\is_null($permissions)) { $permissions = []; - if (!empty($user->getId())) { + if (!empty($user->getId()) && !$isPrivilegedUser) { foreach ($allowedPermissions as $permission) { $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); } diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index e2ea93fdff..859e259b7c 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -193,8 +193,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND break; case 'php': $config = new PHP(); - $config->setComposerVendor('appwrite'); - $config->setComposerPackage('appwrite'); + $config->setComposerVendor($language['composerVendor'] ?? 'appwrite'); + $config->setComposerPackage($language['composerPackage'] ?? 'appwrite'); break; case 'nodejs': $config = new Node(); @@ -379,9 +379,9 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND $sdk ->setName($language['name']) - ->setNamespace('io appwrite') - ->setDescription("Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the {$language['name']} SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)") - ->setShortDescription('Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API') + ->setNamespace($language['namespace'] ?? 'appwrite') + ->setDescription($language['description'] ?? "Appwrite is an open-source backend as a service server that abstracts and simplifies complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the {$language['name']} SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)") + ->setShortDescription('Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API') ->setLicense($license) ->setLicenseContent($licenseContent) ->setVersion($language['version']) diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index 1ef348091a..e465f9cca2 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -192,13 +192,13 @@ class StatsResources extends Action } try { - $this->countForDatabase($dbForProject, $region); + $dbForProject->skipFilters(fn () => $this->countForDatabase($dbForProject, $region), ['subQueryAttributes', 'subQueryIndexes']); } catch (Throwable $th) { call_user_func_array($this->logError, [$th, "StatsResources", "count_for_database_{$project->getId()}"]); } try { - $this->countForSitesAndFunctions($dbForProject, $region); + $dbForProject->skipFilters(fn () => $this->countForSitesAndFunctions($dbForProject, $region), ['subQueryVariables', 'subQueryProjectVariables']); } catch (Throwable $th) { call_user_func_array($this->logError, [$th, "StatsResources", "count_for_functions_{$project->getId()}"]); } diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index 5c618d6357..2c39a12f09 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -160,4 +160,40 @@ class StorageConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(204, $response['headers']['status-code']); } + + public function testFilePermissionNotAutoSetInConsole(): void + { + // Create a bucket + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket Permissions', + 'fileSecurity' => true, + ]); + $this->assertEquals(201, $bucket['headers']['status-code']); + $bucketId = $bucket['body']['$id']; + + // Create a file without providing permissions (console client should not auto-set permissions) + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'test.png'), + ]); + $this->assertEquals(201, $file['headers']['status-code']); + + // Verify file permissions are empty (not auto-set for privileged console user) + $this->assertIsArray($file['body']['$permissions']); + $this->assertEmpty($file['body']['$permissions']); + + // Clean up: delete the bucket + $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(204, $response['headers']['status-code']); + } }