8000 feat: per bucket image transformations flag by ChiragAgg5k · Pull Request #10722 · appwrite/appwrite · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@ChiragAgg5k
Copy link
Member

No description provided.

@coderabbitai
Copy link
Contributor
coderabbitai bot commented Oct 28, 2025

Warning

Rate limit exceeded

@ChiragAgg5k has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 24 minutes and 28 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between decad9f and 39c5b6c.

⛔ Files ignored due to path filters (86)
  • app/config/specs/open-api3-1.8.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.8.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/console-cli/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/console-cli/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/console-web/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/console-web/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/console-web/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/console-web/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-image.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dotnet/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dotnet/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-go/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-go/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-go/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-go/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-graphql/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-graphql/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-graphql/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-graphql/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/java/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/exam 8000 ples/1.8.x/server-kotlin/java/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/kotlin/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/kotlin/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-nodejs/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-nodejs/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-php/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-php/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-php/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-php/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-python/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-python/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-python/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-python/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-rest/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-rest/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-rest/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-rest/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-ruby/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-ruby/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-swift/examples/functions/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-swift/examples/sites/create-template-deployment.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-swift/examples/storage/create-bucket.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-swift/examples/storage/update-bucket.md is excluded by !docs/examples/**
📒 Files selected for processing (4)
  • app/config/collections/common.php (1 hunks)
  • app/controllers/api/storage.php (6 hunks)
  • app/controllers/shared/api.php (1 hunks)
  • src/Appwrite/Migration/Version/V23.php (1 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a new boolean bucket-level attribute transformations (default true) to the Buckets collection and threads it through storage APIs (create/update). Enforces the flag in preview/cache and bucket authorization flows so non-app/privileged users are denied when transformations are disabled. Adds error constant and mapping for this case, updates the Bucket response model and query validator, includes migration steps to create the attribute on platform and project databases, and adds end-to-end tests covering the enable/disable preview behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • app/controllers/api/storage.php — verify parameter additions, defaulting, persistence to bucket documents, and enforcement integration points.
  • app/controllers/shared/api.php — confirm preview/cache path properly checks transformations and distinguishes app/privileged users.
  • src/Appwrite/Migration/Version/V23.php — ensure migration calls create the attribute on both platform and project DBs and handle errors/logging appropriately.
  • src/Appwrite/Extend/Exception.php & app/config/errors.php — check new constant and error mapping are consistent and correctly used.
  • src/Appwrite/Utopia/Response/Model/Bucket.php & src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php — validate model and validator additions align with schema and defaults.
  • tests/e2e/Services/Storage/* — ensure tests are correct and remove any duplicated test blocks.

Suggested reviewers

  • abnegate

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to verify relevance to the changeset. Add a description explaining the purpose, implementation approach, and any relevant context for the per-bucket transformations feature.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a per-bucket image transformations flag throughout the codebase.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ChiragAgg5k ChiragAgg5k requested a review from Copilot October 28, 2025 08:45
Copy link
Contributor
Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a per-bucket flag to enable or disable image transformations. When transformations are disabled for a bucket, requests for image previews return a 403 error, except for console and API key requests which bypass this restriction.

  • Adds a transformations boolean attribute to bucket configuration (defaults to true)
  • Enforces transformation restrictions in the file preview/transformation endpoints
  • Includes migration logic to add the new attribute to existing buckets

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/e2e/Services/Storage/StorageCustomClientTest.php Adds test verifying transformations can be disabled and preview requests return 403
tests/e2e/Services/Storage/StorageConsoleClientTest.php Adds test verifying console requests bypass transformation restrictions
src/Appwrite/Utopia/Response/Model/Bucket.php Adds transformations field to bucket response model
src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php Adds transformations to queryable bucket attributes
src/Appwrite/Migration/Version/V23.php Adds migration to create transformations attribute on existing buckets
src/Appwrite/Extend/Exception.php Defines new exception constant for disabled transformations
app/controllers/shared/api.php Enforces transformation restriction check in shared controller
app/controllers/api/storage.php Adds transformation parameter to bucket create/update and enforces restriction in preview endpoint
app/config/errors.php Adds error configuration for transformation disabled exception
app/config/collections/common.php Adds transformations boolean attribute definition to buckets collection

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
github-actions bot commented Oct 28, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
imagemagick 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-c++ 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-dev 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-heic 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-jpeg 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-jxl 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-libs 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-openexr 7.1.2.3-r0 CVE-2025-62171 HIGH
imagemagick-webp 7.1.2.3-r0 CVE-2025-62171 HIGH
libecpg 17.6-r0 CVE-2025-12818 HIGH
libecpg-dev 17.6-r0 CVE-2025-12818 HIGH
libpq 17.6-r0 CVE-2025-12818 HIGH
libpq-dev 17.6-r0 CVE-2025-12818 HIGH
libxml2 2.13.8-r0 CVE-2025-49794 CRITICAL
libxml2 2.13.8-r0 CVE-2025-49796 CRITICAL
libxml2 2.13.8-r0 CVE-2025-49795 HIGH
libxml2 2.13.8-r0 CVE-2025-6021 HIGH
postgresql17-dev 17.6-r0 CVE-2025-12818 HIGH
github.com/containerd/containerd/v2 v2.0.2 CVE-2024-25621 HIGH
golang.org/x/crypto v0.31.0 CVE-2025-22869 HIGH
golang.org/x/oauth2 v0.24.0 CVE-2025-22868 HIGH
stdlib 1.22.10 CVE-2025-47907 HIGH
stdlib 1.22.10 CVE-2025-58183 HIGH
stdlib 1.22.10 CVE-2025-58186 HIGH
stdlib 1.22.10 CVE-2025-58187 HIGH
stdlib 1.22.10 CVE-2025-58188 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
tests/e2e/Services/Storage/StorageCustomClientTest.php (1)

1439-1441: Prefer asserting error type over full message text.

Matching the full error message is brittle. Assert the error type (storage_bucket_transformations_disabled) and 403 instead.

Example:

-        $this->assertEquals(403, $preview['headers']['status-code']);
-        $this->assertStringContainsString('Image transformations are disabled for the requested bucket.', $preview['body']['message']);
+        $this->assertEquals(403, $preview['headers']['status-code']);
+        $this->assertEquals('storage_bucket_transformations_disabled', $preview['body']['type']);
tests/e2e/Services/Storage/StorageConsoleClientTest.php (1)

149-155: Comment tweak (optional).

The 200 after disabling is because privileged/console requests bypass the transformations gate, not because “image transformations are not counted.” Consider rewording for clarity.

app/controllers/api/storage.php (2)

302-303: Update flow: make transformations nullable to preserve existing when omitted.

You coalesce $transformations to the current bucket value, but the parameter is typed bool and defaults to true, so omission won’t be distinguishable and will reset to true.

Apply:

-    ->param('transformations', true, new Boolean(true), 'Are image transformations enabled?', true)
+    ->param('transformations', null, new Boolean(true), 'Are image transformations enabled?', true)
...
-    ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, bool $transformations, Response $response, Database $dbForProject, Event $queueForEvents) {
+    ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, ?bool $transformations, Response $response, Database $dbForProject, Event $queueForEvents) {
...
-        $transformations ??= $bucket->getAttribute('transformations', true);
+        $transformations ??= $bucket->getAttribute('transformations', true);

If other update params use “replace” semantics intentionally, keep consistency and ignore; otherwise consider the nullable pattern above.

Also applies to: 306-321, 334-335


982-987: Name consistency: $isAPIKey vs $isAppUser.

Other handlers use $isAPIKey = Auth::isAppUser(...). Use one name across the file for readability.

-        $isAppUser = Auth::isAppUser(Authorization::getRoles());
+        $isAPIKey = Auth::isAppUser(Authorization::getRoles());
...
-        if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) {
+        if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
...
-        if (!$bucket->getAttribute('transformations', true) && !$isAppUser && !$isPrivilegedUser) {
+        if (!$bucket->getAttribute('transformations', true) && !$isAPIKey && !$isPrivilegedUser) {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e6d327 and 4aaaa46.

📒 Files selected for processing (10)
  • app/config/collections/common.php (1 hunks)
  • app/config/errors.php (1 hunks)
  • app/controllers/api/storage.php (6 hunks)
  • app/controllers/shared/api.php (1 hunks)
  • src/Appwrite/Extend/Exception.php (1 hunks)
  • src/Appwrite/Migration/Version/V23.php (1 hunks)
  • src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Bucket.php (1 hunks)
  • tests/e2e/Services/Storage/StorageConsoleClientTest.php (2 hunks)
  • tests/e2e/Services/Storage/StorageCustomClientTest.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
src/Appwrite/Migration/Version/V23.php (1)
src/Appwrite/Migration/Migration.php (1)
  • createAttributeFromCollection (323-371)
app/controllers/shared/api.php (2)
src/Appwrite/Auth/Auth.php (2)
  • isAppUser (441-448)
  • isPrivilegedUser (421-432)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-465)
app/config/errors.php (1)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-465)
src/Appwrite/Utopia/Response/Model/Bucket.php (1)
src/Appwrite/Utopia/Response/Model.php (1)
  • addRule (90-102)
tests/e2e/Services/Storage/StorageCustomClientTest.php (1)
tests/e2e/Client.php (1)
  • Client (8-342)
tests/e2e/Services/Storage/StorageConsoleClientTest.php (2)
tests/e2e/Client.php (1)
  • Client (8-342)
tests/e2e/Scopes/Scope.php (1)
  • getHeaders (145-145)
app/controllers/api/storage.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • param (255-356)
src/Appwrite/Auth/Auth.php (4)
  • isAppUser (441-448)
  • Auth (18-515)
  • getRoles (456-502)
  • isPrivilegedUser (421-432)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-465)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Linter
  • GitHub Check: Check if utopia-php/database changed
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (9)
app/controllers/shared/api.php (1)

597-599: LGTM! Authorization check is correctly implemented.

The transformations check properly:

  • Uses a safe default of true when the attribute doesn't exist
  • Validates user privileges (App users and privileged users can bypass)
  • Follows the same pattern as the enabled attribute check above
src/Appwrite/Extend/Exception.php (1)

153-153: LGTM! Exception constant follows naming conventions.

The new constant is correctly placed in the Storage section and follows the established naming pattern.

src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php (1)

13-14: LGTM! Validator correctly extended.

The transformations attribute is properly added to the allowed attributes list for bucket queries.

app/config/errors.php (1)

525-529: LGTM! Error mapping is properly configured.

The error entry provides a clear description and uses an appropriate HTTP 403 status code for this authorization scenario.

src/Appwrite/Utopia/Response/Model/Bucket.php (1)

89-94: LGTM! Response model correctly extended.

The transformations rule is properly configured with appropriate type, default value, and description. The default of true is consistent with the collection schema.

app/config/collections/common.php (1)

1530-1540: LGTM! Collection schema properly extended.

The transformations attribute is correctly defined with:

  • Appropriate default value of true for backward compatibility
  • required: false to avoid breaking existing buckets
  • Consistent structure with other boolean attributes
app/controllers/api/storage.php (3)

88-93: Create flow: new bucket.transformations wired correctly.

Param, action signature, and persistence look good. No functional concerns.

Also applies to: 145-147


989-991: Preview gate aligns with requirements.

403 for non-app/non-privileged when bucket.transformations=false is correctly enforced before file IO.


302-303: All public schema/model/migration requirements for transformations are properly implemented.

  • Error constant STORAGE_BUCKET_TRANSFORMATIONS_DISABLED is defined and mapped in error config
  • Response::MODEL_BUCKET exposes transformations as a Boolean field with default true
  • Validator includes transformations in the Buckets query attributes
  • Migration V23 creates the transformations attribute via createAttributeFromCollection
  • Endpoint parameter correctly uses Boolean validator with consistent defaults

@github-actions
Copy link
github-actions bot commented Oct 28, 2025

✨ Benchmark results

  • Requests per second: 1,162
  • Requests with 200 status code: 209,160
  • P99 latency: 0.165436463

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,162 1,167
200 209,160 210,071
P99 0.165436463 0.178864811

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
app/controllers/api/storage.php (1)

984-984: Consider consistent variable naming across endpoints.

The variable is renamed from $isAPIKey to $isAppUser, which is more semantically accurate. However, other file endpoints (lines 439, 801, 902, 1180, 1341, 1511, 1668, 1782) still use $isAPIKey for the same purpose, creating inconsistency.

Consider either:

  • Reverting to $isAPIKey here for consistency, or
  • Renaming $isAPIKey to $isAppUser across all endpoints in a separate refactoring effort

Apply this diff to maintain consistency with existing code:

-        $isAppUser = Auth::isAppUser(Authorization::getRoles());
+        $isAPIKey = Auth::isAppUser(Authorization::getRoles());
         $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
 
-        if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) {
+        if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) {
             throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
         }
 
-        if (!$bucket->getAttribute('transformations', true) && !$isAppUser && !$isPrivilegedUser) {
+        if (!$bucket->getAttribute('transformations', true) && !$isAPIKey && !$isPrivilegedUser) {
             throw new Exception(Exception::STORAGE_BUCKET_TRANSFORMATIONS_DISABLED);
         }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1546add and decad9f.

📒 Files selected for processing (2)
  • app/controllers/api/storage.php (6 hunks)
  • app/controllers/shared/api.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/shared/api.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-04-17T08:07:54.565Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9661
File: app/controllers/api/migrations.php:332-337
Timestamp: 2025-04-17T08:07:54.565Z
Learning: In the Appwrite codebase, error handling intentionally uses the same error codes for different failure conditions (like STORAGE_BUCKET_NOT_FOUND for both non-existent buckets and authorization failures) as a security measure to prevent information disclosure about what specifically went wrong.

Applied to files:

  • app/controllers/api/storage.php
🧬 Code graph analysis (1)
app/controllers/api/storage.php (2)
src/Appwrite/Auth/Auth.php (2)
  • isAppUser (441-448)
  • Auth (18-515)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-465)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: Benchmark
  • GitHub Check: scan
🔇 Additional comments (3)
app/controllers/api/storage.php (3)

88-88: LGTM! Bucket creation properly extended with transformations flag.

The new transformations parameter follows the same pattern as other bucket configuration flags (antivirus, encryption, compression). Default value of true ensures backward compatibility.

Also applies to: 92-92, 145-145


303-303: LGTM! Bucket update correctly implements transformations flag.

The update logic properly handles the null coalescing pattern to preserve existing values when not provided, consistent with other bucket attributes.

Also applies to: 307-307, 321-321, 335-336


991-993: LGTM! Transformation enforcement logic is correct.

The authorization check properly denies transformations when disabled for non-app/non-privileged users while allowing app users and privileged users to bypass the restriction. The placement in the preview endpoint is correct since download and view operations don't perform transformations.

@ChiragAgg5k ChiragAgg5k requested a review from Copilot November 18, 2025 04:24
Copy link
Contributor
Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 96 out of 96 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@pkg-pr-new
Copy link
pkg-pr-new bot commented Nov 18, 2025

Open in StackBlitz

npm i https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@10722

commit: 39c5b6c

@abnegate abnegate merged commit 275ff3d into 1.8.x Nov 18, 2025
50 checks passed
@abnegate abnegate deleted the feat-per-bucket-image-transformations branch November 18, 2025 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

0