Skip to content

Feat: Audits upgrade#10953

Merged
lohanidamodar merged 30 commits into1.8.xfrom
feat-audits-upgrade
Dec 31, 2025
Merged

Feat: Audits upgrade#10953
lohanidamodar merged 30 commits into1.8.xfrom
feat-audits-upgrade

Conversation

@lohanidamodar
Copy link
Copy Markdown
Member

What does this PR do?

  • Upgrade audits to 2.0.0

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)

Related PRs and Issues

  • (Related PR or issue)

Checklist

  • Have you read the Contributing Guidelines on issues?
  • If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Dec 14, 2025

📝 Walkthrough

Walkthrough

Audit integration was refactored to use dependency injection and an adapter layer. Multiple controllers and platform modules now accept an injected Audit instance (replacing inline new Audit(...)). Audit is constructed with an AdapterDatabase (SQL adapter constant used for collection checks). Log endpoints compute pagination via Query::groupByType($queries) (defaults limit 25, offset 0), call getLogsByResource with named offset/limit, and call countLogsByResource without forwarding query filters. A getAudit server resource was added to resolve per-project or platform Audit instances. Worker and deletion flows were updated to use the new audit retrieval; composer dependencies were bumped.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.18% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat: Audits upgrade' directly corresponds to the main objective of the PR, which upgrades the audits dependency from version 1.* to 2.0.2-rc1 and refactors audit initialization and usage throughout the codebase.
Description check ✅ Passed The description states 'Upgrade audits to 2.0.0' which is directly related to the changeset, though it lacks detailed test instructions beyond the placeholder.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-audits-upgrade

📜 Recent 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 6943015 and d2cda97.

📒 Files selected for processing (1)
  • src/Appwrite/Platform/Workers/Deletes.php
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Platform/Workers/Deletes.php (2)
src/Appwrite/Event/Audit.php (1)
  • Audit (8-162)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (1)
  • cleanup (393-410)
⏰ 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: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (2)
src/Appwrite/Platform/Workers/Deletes.php (2)

523-523: SQL::COLLECTION usage aligns with audit 2.0.0 upgrade.

The change from Audit::COLLECTION to SQL::COLLECTION is part of the audit library upgrade to version 2.0.0. A previous review comment questioned whether this constant should be abstracted behind the delete method. While that architectural improvement remains valid, this change correctly reflects the new audit library's adapter pattern.

Based on learnings, the previous reviewer suggested abstracting the collection constant.


787-798: The implementation correctly uses the audit library's cleanup() method. The method signature accepts \DateTime as documented, and catching Throwable is appropriate since the underlying adapters may throw various exception types.


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.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 14, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
libpng 1.6.51-r0 CVE-2025-66293 HIGH
libpng-dev 1.6.51-r0 CVE-2025-66293 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

Copy link
Copy Markdown
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (2)

5-27: Fix Pint ordered_imports failure in this file before merge.
The linter is already failing on PSR-12 import ordering; please run Pint (or apply the repo’s import ordering rules) and commit the result.


89-90: Fix method calls to Audit::getLogsByResource() and Audit::countLogsByResource(): these v2.0.0 methods do not accept a $queries array.

Per utopia-php/audit v2.0.0, the correct signatures are:

  • getLogsByResource(resource: string, events: array|null = null, after: \DateTime|null = null, before: \DateTime|null = null, limit: int|null = null, offset: int|null = null, ascending: bool|null = null): array
  • countLogsByResource(resource: string, events: array|null = null, after: \DateTime|null = null, before: \DateTime|null = null): int

The calls at lines 89 and 136 pass $queries as a second positional argument, which these methods do not accept. Additionally, countLogsByResource does not support limit/offset parameters at all. Convert $queries to individual named parameters matching the method signatures.

app/controllers/api/messaging.php (1)

1148-1167: Query::groupByType() method does not exist — this will cause a fatal runtime error.

The code calls Query::groupByType($queries) at line 1162, but this method does not exist in either utopia-php/database or Appwrite's codebase. The method call will throw a fatal "Call to undefined method" error when executed.

Check the correct query parsing/extraction method in Appwrite's Query class or utopia-php/database to properly extract limit and offset values.

🧹 Nitpick comments (2)
app/init/resources.php (1)

657-660: Type-hint the injected DB (and consider a return type) for the new audit resource.
Right now $dbForProject is untyped, which makes DI errors harder to spot and static analysis weaker.

-App::setResource('audit', function ($dbForProject) {
+App::setResource('audit', function (Database $dbForProject): Audit {
     $adapter = new AdapterDatabase($dbForProject);
     return new Audit($adapter);
 }, ['dbForProject']);
app/controllers/api/messaging.php (1)

1162-1167: Extract filters-only for count or pass full queries consistently to both methods.

The provider logs endpoint extracts offset and limit from queries to pass to getLogsByResource(), but passes the full $queries array (containing offset/limit) to countLogsByResource(). This parameter misalignment can cause incorrect totals if countLogsByResource() ignores pagination parameters. Align by either: (1) extracting filters-only and passing to both methods, or (2) passing the full $queries to both (consistent with other endpoints like teams.php). Also verify Audit v2's countLogsByResource() behavior with limit/offset in the query array.

📜 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 7d2a95c and 9441295.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • app/controllers/api/messaging.php (5 hunks)
  • app/controllers/api/projects.php (1 hunks)
  • app/controllers/api/teams.php (1 hunks)
  • app/controllers/api/users.php (1 hunks)
  • app/http.php (3 hunks)
  • app/init/resources.php (4 hunks)
  • composer.json (2 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Workers/Audits.php (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.

Applied to files:

  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php
  • app/controllers/api/messaging.php
  • app/controllers/api/users.php
📚 Learning: 2025-10-02T10:16:48.075Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10023
File: src/Appwrite/Databases/TransactionState.php:174-219
Timestamp: 2025-10-02T10:16:48.075Z
Learning: In `src/Appwrite/Databases/TransactionState.php`, the `listDocuments` method intentionally applies queries only to the initial database fetch of committed documents. Transaction state changes (creates, updates, deletes) are then overlaid on top of the filtered committed set without re-evaluating the queries against the final merged result. This is the intended behavior for transaction-aware document listing.

Applied to files:

  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php
📚 Learning: 2025-08-22T06:23:32.026Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 10348
File: app/controllers/shared/api.php:546-546
Timestamp: 2025-08-22T06:23:32.026Z
Learning: The Utopia\Queue\Broker\Pool class (aliased as BrokerPool) implements both Publisher and Consumer interfaces, making it directly compatible with constructors expecting Publisher parameters like Func::__construct(protected Publisher $publisher). No wrapping is needed.

Applied to files:

  • app/init/resources.php
📚 Learning: 2025-08-22T06:23:32.026Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 10348
File: app/controllers/shared/api.php:546-546
Timestamp: 2025-08-22T06:23:32.026Z
Learning: In the Utopia Queue system, the Pool class implements both Publisher and Consumer interfaces, so BrokerPool (Pool) can be passed directly to constructors expecting Publisher parameters like Func::__construct(protected Publisher $publisher).

Applied to files:

  • app/init/resources.php
🧬 Code graph analysis (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)
  • action (69-134)
app/controllers/api/teams.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-152)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)
  • action (69-134)
app/controllers/api/users.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
🪛 GitHub Actions: Linter
src/Appwrite/Platform/Workers/Audits.php

[error] 1-1: PSR-12: Coding standard issue detected by Pint (ordered_imports).

src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php

[error] 1-1: PSR-12: Coding standard issue detected by Pint (ordered_imports).

⏰ 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: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (10)
app/controllers/api/users.php (1)

948-1005: Injected Audit usage is correctly scoped to dbForProject.

The audit resource definition (app/init/resources.php:657-659) explicitly declares dbForProject as its dependency, wrapping it in AdapterDatabase before passing to the Audit class. This ensures audit logs are fetched from the current project's database, not a platform-level store. The DI scoping correctly implements tenant isolation.

app/controllers/api/projects.php (1)

249-253: Avoid $adapter shadowing + verify adapter class namespace.

Variable shadowing is valid: $adapter is reused after being declared earlier at Line 226 for DatabasePool, making the code harder to follow. Rename to $auditAdapter for clarity.

However, the adapter namespace \Utopia\Audit\Adapters\Database requires verification. Official Utopia framework documentation shows that Audit typically accepts \Utopia\Database\Database instances directly, not a separate \Utopia\Audit\Adapters\Database class. Confirm that the namespace in the proposed fix matches what Audit v2 actually expects before applying the change.

-                $adapter = new \Utopia\Audit\Adapters\Database($dbForProject);
-                $audit = new Audit($adapter);
+                $auditAdapter = new \Utopia\Audit\Adapters\Database($dbForProject);
+                $audit = new Audit($auditAdapter);
                 $audit->setup();
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (1)

75-76: Verify audit DI wiring pattern consistency across document log endpoints.

Unable to verify the claim that the audit DI wiring mirrors the collection logs endpoint due to the file being new/uncommitted in this PR. Confirm that all document-level log endpoints (line 75-76 and line 79) use consistent DI injection patterns with the collection-level logs endpoint, following the standard ->inject('audit') pattern without local instantiation.

src/Appwrite/Platform/Workers/Audits.php (1)

8-8: Verify adapter namespace and import order against Audit v2 documentation.

The review raises concerns about ordered imports failing Pint linting and inconsistent adapter namespaces. Based on Audit v2 package structure, adapters should come from Utopia\Database\Adapter\* (not Utopia\Audit\Adapters\* or Utopia\Audit\Adapter\*). Confirm the correct import path and ensure all imports are sorted per Pint configuration.

app/http.php (1)

15-16: Verify namespace usage across changed files. The import statement uses Utopia\Audit\Adapter\Database but the review claims other files in this PR use Utopia\Audit\Adapters\Database (plural). Confirm which namespace is correct according to utopia-php/audit documentation and ensure all imports are aligned.

src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)

61-66: Audit DI update matches the other logs endpoints. Injected Audit $audit usage for getLogsByResource() and countLogsByResource() is consistent and removes duplicated instantiation across all log endpoint implementations.

composer.json (1)

50-56: No action needed—Audit v2 and database v3.5.0 are compatible.

The codebase already successfully uses Utopia\Audit\Adapters\Database with database v3.5.0 (aliased as 4.0.0), as shown in src/Appwrite/Platform/Workers/Audits.php. The recent "Audits upgrade" commit (Dec 14, 2025) confirms this combination is intentional. The "2." constraint for Audit is consistent with how other utopia-php packages are versioned in this project (e.g., "1.", "0.15.*"). Database v3.5.0 (released Nov 18, 2025) contains no breaking changes for Audit compatibility.

app/init/resources.php (1)

150-152: queueForAudits now returns AuditEvent — double-check downstream expectations.
If any consumers expected a Utopia\Audit\Audit instance from queueForAudits, this will be a runtime break; the naming (queueForAudits) also reads “audit service” vs “audit event publisher,” so consider a follow-up rename for clarity.

src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)

66-71: DI wiring for Audit looks consistent with the broader refactor.
Good move removing local instantiation and injecting audit into the handler.

Also applies to: 74-74

app/controllers/api/teams.php (1)

1467-1469: Audit DI for /v1/teams/:teamId/logs looks good.
This matches the pattern used in other updated log endpoints and removes per-request construction.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 14, 2025

✨ Benchmark results

  • Requests per second: 1,098
  • Requests with 200 status code: 197,605
  • P99 latency: 0.174625167

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,098 1,167
200 197,605 210,050
P99 0.174625167 0.176102235

Copy link
Copy Markdown
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 (1)
app/http.php (1)

395-399: Consider renaming the adapter variable for clarity.

The variable $adapter on line 396 shadows the $adapter variable defined on line 381. While functionally correct (the original adapter is no longer needed), using a more descriptive name like $auditAdapter would improve code clarity and prevent potential confusion during future maintenance.

Apply this diff to improve variable naming:

             if ($dbForProject->getCollection(AuditAdapterSQL::COLLECTION)->isEmpty()) {
-                $adapter = new AdapterDatabase($dbForProject);
-                $audit = new Audit($adapter);
+                $auditAdapter = new AdapterDatabase($dbForProject);
+                $audit = new Audit($auditAdapter);
                 $audit->setup();
             }
📜 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 c50db11 and 2dcb131.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • app/http.php (3 hunks)
  • composer.json (2 hunks)
⏰ 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: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (1)
app/http.php (1)

15-16: LGTM!

The import aliases are well-chosen to avoid naming conflicts with existing Database imports, and both are properly utilized in the adapter-based Audit construction below.

Copy link
Copy Markdown
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/controllers/api/messaging.php (1)

1148-1168: Fix undefined $filterQueries in provider logs and remove invalid parameters from countLogsByResource() calls

The provider logs endpoint on line ~1221 calls $audit->countLogsByResource($resource, $filterQueries) where $filterQueries is never defined, causing a fatal error. Additionally, the Audit::countLogsByResource() method signature only accepts resource, after, and before parameters—it does not accept filter or query parameters. Both provider logs and message logs endpoints are passing invalid parameters to this method.

Provider logs fix:

-            'total' => $includeTotal ? $audit->countLogsByResource($resource, $filterQueries) : 0,
+            'total' => $includeTotal ? $audit->countLogsByResource($resource) : 0,

Message logs fix (line ~1168):

-            'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0,
+            'total' => $includeTotal ? $audit->countLogsByResource($resource) : 0,

Also remove the unused $filterQueries = $grouped['filters'] ?? []; line from the message logs handler.

🧹 Nitpick comments (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (1)

106-109: LGTM! Pagination logic correctly implemented.

The query grouping and explicit offset/limit extraction follows the established pattern across all log endpoints. The default values (limit: 25, offset: 0) are consistent with other log handlers in the codebase.

Consider extracting the pagination defaults to class constants for easier maintenance:

private const DEFAULT_LIMIT = 25;
private const DEFAULT_OFFSET = 0;

Then use:

-$limit = $grouped['limit'] ?? 25;
-$offset = $grouped['offset'] ?? 0;
+$limit = $grouped['limit'] ?? self::DEFAULT_LIMIT;
+$offset = $grouped['offset'] ?? self::DEFAULT_OFFSET;

This would improve consistency if defaults need to change across multiple log endpoints in the future.

app/controllers/api/account.php (1)

2974-2977: Optional: drop dbForProject injection if it’s no longer used in this route.
The updated handler doesn’t reference $dbForProject; consider removing the injection/parameter to keep the route signature minimal (unless DI requires it for per-project Audit wiring).

app/controllers/api/messaging.php (1)

1170-1211: Avoid foreach (... as &$log) without unset($log)
Using a by-reference loop variable can leak a reference to the last element into later code paths. If you don’t need by-ref, drop &. If you do, unset($log) after the loop.

-        foreach ($logs as $i => &$log) {
+        foreach ($logs as $i => $log) {
             $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
@@
-        }
+        }

Also applies to: 2578-2619, 2998-3039, 3797-3838

📜 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 b83125a and f270e47.

📒 Files selected for processing (7)
  • app/controllers/api/account.php (1 hunks)
  • app/controllers/api/messaging.php (11 hunks)
  • app/controllers/api/teams.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.

Applied to files:

  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php
  • app/controllers/api/messaging.php
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php
🧬 Code graph analysis (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (1)
  • action (79-160)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-155)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-142)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-155)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)
  • action (69-137)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-142)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
app/controllers/api/account.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-142)
🪛 GitHub Actions: Linter
app/controllers/api/account.php

[error] 1-1: PSR-12: no_unused_imports. Remove unused imports in this file.


[error] 1-1: Pint lint failed. No_unused_imports issue detected by PSR-12 linter. Command: vendor/bin/pint --test --config pint.json

⏰ 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). (16)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V2)
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V1)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V2)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V1)
  • GitHub Check: Benchmark
  • GitHub Check: scan
🔇 Additional comments (10)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (4)

74-74: LGTM! Proper dependency injection.

The Audit service is correctly injected into the dependency chain, aligning with the upgrade to Audit v2.0.0 and the shift to dependency-injected services across the platform.


78-78: LGTM! Correct method signature update.

The Audit parameter correctly receives the injected dependency, replacing the previous pattern of local Audit instantiation.


101-104: LGTM! Correct adaptation to Audit v2 API.

The query handling properly:

  • Groups queries to extract pagination parameters
  • Applies sensible defaults (limit=25, offset=0)
  • Passes offset and limit as named parameters to getLogsByResource

This pattern is consistent with the updated Audit v2.0.0 API and matches the implementation in related files.


153-153: LGTM! Correct usage of updated count API.

The countLogsByResource call correctly passes only the resource parameter, aligning with the Audit v2.0.0 API where count operations no longer require query parameters.

src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (2)

75-75: LGTM! Audit service properly injected.

The dependency injection is correctly wired in both the constructor and the action method signature, aligning with the repository-wide audit v2.0.0 upgrade pattern.

Also applies to: 79-79


158-158: LGTM! Count method correctly updated.

The countLogsByResource call properly uses the new v2.0.0 API signature without the queries parameter, consistent with the audit upgrade across the codebase.

src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)

65-66: Audit DI injection and method calls are correct. The Audit::getLogsByResource($resource, offset: ..., limit: ...) and Audit::countLogsByResource($resource) signatures match the usage in lines 87 and 134. Pagination logic is sound—extracting offset/limit via Query::groupByType() and passing them as named parameters to getLogsByResource while calling countLogsByResource without pagination parameters avoids double-counting.

app/controllers/api/teams.php (1)

1467-1469: Audit DI and pagination implementation verified as correct.

The Audit dependency injection and API usage are properly implemented:

  • getLogsByResource($resource, offset: $offset, limit: $limit) uses named arguments compatible with the API signature
  • countLogsByResource($resource) correctly excludes queries (pagination only affects fetching, not counting)
  • Implementation is consistent across all team log endpoints

No action needed.

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

2991-2995: Same limit/offset typing concern (subscriber logs)
Same pattern as topic logs; please ensure $limit and $offset are ints derived from query values.

Also applies to: 3041-3043


2571-2575: No action needed. The code correctly uses Query::groupByType() to extract pagination parameters. The method returns an associative array where limit and offset are integers (or null), not Query objects. The null coalescing operators (?? 25 and ?? 0) properly convert null values to integer defaults, which are then correctly passed as integer parameters to getLogsByResource(). This implementation pattern is used consistently throughout the codebase and functions correctly.

Copy link
Copy Markdown
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: 1

📜 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 f270e47 and 2437d2b.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • app/controllers/api/account.php (3 hunks)
  • src/Appwrite/Platform/Workers/Audits.php (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/api/account.php
⏰ 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). (2)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (2)
src/Appwrite/Platform/Workers/Audits.php (2)

7-7: LGTM!

The import correctly uses the singular Utopia\Audit\Adapter namespace, consistent with v2.0.0 and other usages across the codebase.


140-142: LGTM!

The adapter-based Audit construction correctly follows the v2.0.0 pattern: wrapping the database connection with AdapterDatabase and passing it to the Audit constructor. This aligns with the dependency injection approach across the codebase.

Copy link
Copy Markdown
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/controllers/api/teams.php (1)

1463-1468: Team logs: adjust Audit calls to use limit/offset, not $queries

The injected Utopia\Audit\Audit instance expects scalar pagination (int limit/offset) and optional DateTime filters; passing $queries (array of Query objects) into getLogsByResource() and countLogsByResource() will cause a runtime TypeError.

Extract limit/offset from the parsed queries using the standard pattern already used in other endpoints:

        try {
            $queries = Query::parseQueries($queries);
        } catch (QueryException $e) {
            throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
        }

+       $grouped = Query::groupByType($queries);
+       $limit = $grouped['limit'] ?? 25;
+       $offset = $grouped['offset'] ?? 0;
+
        $resource = 'team/' . $team->getId();
-       $logs = $audit->getLogsByResource($resource, $queries);
+       $logs = $audit->getLogsByResource(
+           resource: $resource,
+           limit: $limit,
+           offset: $offset,
+       );

And update the count call:

-       'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0,
+       'total' => $includeTotal ? $audit->countLogsByResource($resource) : 0,
♻️ Duplicate comments (2)
app/controllers/api/messaging.php (2)

1148-1149: Providers logs: keep offset/limit, fix countLogsByResource signature

Injecting Audit and deriving $limit / $offset via Query::groupByType is the right direction, but:

$response->dynamic(new Document([
    'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0,

still passes $queries into countLogsByResource, which expects only the resource plus optional DateTime bounds, not a Query[] array. This will raise a type error. (github.com)

You can keep pagination behavior and fix the signature with:

-        $grouped = Query::groupByType($queries);
-        $limit = $grouped['limit'] ?? 25;
-        $offset = $grouped['offset'] ?? 0;
+        $grouped = Query::groupByType($queries);
+        $limit = $grouped['limit'] ?? 25;
+        $offset = $grouped['offset'] ?? 0;
@@
-        $logs = $audit->getLogsByResource($resource, offset: $offset, limit: $limit);
+        $logs = $audit->getLogsByResource(
+            resource: $resource,
+            limit: $limit,
+            offset: $offset,
+        );
@@
-        $response->dynamic(new Document([
-            'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0,
-            'logs' => $output,
-        ]), Response::MODEL_LOG_LIST);
+        $response->dynamic(new Document([
+            'total' => $includeTotal ? $audit->countLogsByResource($resource) : 0,
+            'logs' => $output,
+        ]), Response::MODEL_LOG_LIST);

Please confirm against your local Audit::countLogsByResource signature that only resource / DateTime parameters are accepted, and adjust if it has been extended.

Also applies to: 1162-1167, 1213-1216


2556-2557: Topic/subscriber/message logs: don’t pass $queries into getLogsByResource / countLogsByResource

Across the topic, subscriber, and message log endpoints the newly injected Audit is used like:

$logs = $audit->getLogsByResource($resource, $queries);
...
'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0,

However, Utopia\Audit\Audit expects getLogsByResource(string $resource, ?\DateTime $after = null, ?\DateTime $before = null, int $limit = 25, int $offset = 0, bool $ascending = false) and countLogsByResource(string $resource, ?\DateTime $after = null, ?\DateTime $before = null). Passing a Query[] array as the second argument will cause a TypeError. (github.com)

To preserve the existing API while using Audit correctly, follow the same pattern as in the providers logs endpoint:

@@ App::get('/v1/messaging/topics/:topicId/logs')
-        try {
-            $queries = Query::parseQueries($queries);
-        } catch (QueryException $e) {
-            throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
-        }
-
-        $resource = 'topic/' . $topicId;
-        $logs = $audit->getLogsByResource($resource, $queries);
+        try {
+            $queries = Query::parseQueries($queries);
+        } catch (QueryException $e) {
+            throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
+        }
+
+        $grouped = Query::groupByType($queries);
+        $limit = $grouped['limit'] ?? 25;
+        $offset = $grouped['offset'] ?? 0;
+
+        $resource = 'topic/' . $topicId;
+        $logs = $audit->getLogsByResource(
+            resource: $resource,
+            limit: $limit,
+            offset: $offset,
+        );
@@
-        $response->dynamic(new Document([
-            'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0,
-            'logs' => $output,
-        ]), Response::MODEL_LOG_LIST);
+        $response->dynamic(new Document([
+            'total' => $includeTotal ? $audit->countLogsByResource($resource) : 0,
+            'logs' => $output,
+        ]), Response::MODEL_LOG_LIST);

Apply the same pattern for:

  • Subscriber logs (/v1/messaging/subscribers/:subscriberId/logs)
  • Message logs (/v1/messaging/messages/:messageId/logs)

i.e., parse queries, extract limit / offset via Query::groupByType, pass them via named args to getLogsByResource, and remove $queries from countLogsByResource.

Verify your installed utopia-php/audit version’s method signatures (especially getLogsByResource and countLogsByResource) to ensure they match the README examples and that no additional query-array overload was introduced.

Also applies to: 2570-2572, 2618-2620, 2973-2974, 2987-2989, 3035-3037, 3768-3769, 3782-3784, 3830-3832

🧹 Nitpick comments (2)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (2)

59-66: Minor indentation inconsistency in method chaining.

The ->inject() calls (lines 61-65) have extra indentation compared to the ->param() calls above them. This is a stylistic nit that doesn't affect functionality but could be aligned for consistency.

             ->param('databaseId', '', new UID(), 'Database ID.')
             ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
-                ->inject('response')
-                ->inject('dbForProject')
-                ->inject('locale')
-                ->inject('geodb')
-                ->inject('audit')
+            ->inject('response')
+            ->inject('dbForProject')
+            ->inject('locale')
+            ->inject('geodb')
+            ->inject('audit')
             ->callback($this->action(...));

88-89: Unnecessary reference in foreach loop.

The &$log reference modifies $log['userAgent'] on line 89, but this modification isn't used since $output[$i] is populated independently. The reference can be removed for clarity.

-        foreach ($logs as $i => &$log) {
-            $log['userAgent'] = $log['userAgent'] ?: 'UNKNOWN';
+        foreach ($logs as $i => $log) {
+            $userAgent = $log['userAgent'] ?: 'UNKNOWN';
-            $detector = new Detector($log['userAgent']);
+            $detector = new Detector($userAgent);
📜 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 2437d2b and 0037305.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • app/controllers/api/messaging.php (5 hunks)
  • app/controllers/api/projects.php (1 hunks)
  • app/controllers/api/teams.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Workers/Audits.php (2 hunks)
  • tests/e2e/Services/Account/AccountCustomClientTest.php (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/e2e/Services/Account/AccountCustomClientTest.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/controllers/api/projects.php
  • src/Appwrite/Platform/Workers/Audits.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.

Applied to files:

  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php
  • app/controllers/api/messaging.php
🧬 Code graph analysis (5)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-152)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)
  • action (69-134)
app/controllers/api/teams.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-152)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-139)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (2)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
  • action (80-177)
🪛 GitHub Actions: Linter
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php

[error] 1-1: PSR-12 linting failed. Pint reported issues in 890 files total with 2 style issues; file shows a lint issue in this path.

⏰ 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). (20)
  • GitHub Check: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E General Test
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V2)
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V1)
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V1)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V2)
  • GitHub Check: Unit Test
  • GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (2)

69-69: LGTM!

The action method signature correctly receives the injected Audit $audit parameter, aligning with the new DI pattern for the audit upgrade.


83-84: LGTM!

The audit usage correctly follows the new DI pattern:

  • getLogsByResource for fetching logs with query support
  • countLogsByResource for total count with the same queries

This is consistent with the established pattern in other log endpoints. Based on learnings, the database layer internally handles filter separation for count operations, so passing queries directly is correct.

Also applies to: 130-131

src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)

70-74: LGTM: Audit dependency injection properly configured.

The addition of the audit injection follows the established DI pattern and is correctly positioned after other dependencies.

Copy link
Copy Markdown
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/teams.php (1)

1467-1469: Team logs: Audit usage and pagination are correct; consider small consistency/refactor tweaks

The team logs route cleanly injects Audit, derives limit/offset from grouped queries, and uses getLogsByResource() plus countLogsByResource() in line with the other audit-backed log endpoints—behavior looks correct. For readability and future maintenance, you might (a) match the other handlers by ordering the named arguments as limit then offset in the getLogsByResource() call, and (b) consider a shared helper for the repeated “audit log → Document + geodb country lookup” transformation used across the various log endpoints.

Also applies to: 1482-1488, 1534-1535

📜 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 dc3459e and cec5cd7.

📒 Files selected for processing (9)
  • app/controllers/api/messaging.php (12 hunks)
  • app/controllers/api/teams.php (3 hunks)
  • app/controllers/api/users.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (3 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.

Applied to files:

  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php
  • src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php
  • app/controllers/api/messaging.php
  • app/controllers/api/users.php
  • src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php
🧬 Code graph analysis (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
app/controllers/api/teams.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (1)
  • action (79-162)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-156)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
app/controllers/api/users.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-156)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
⏰ 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). (6)
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V2)
  • GitHub Check: Unit Test
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V2)
  • GitHub Check: Benchmark
  • GitHub Check: scan
🔇 Additional comments (13)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php (1)

54-55: Parent class signature verified. The Audit service injection is correctly positioned in the DI chain. The parent class DocumentLogXList::action() signature confirms the Audit $audit parameter is properly placed after Reader $geodb, matching the injection order in lines 50-54.

src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php (1)

53-54: LGTM! The Audit service injection is correctly positioned in the DI chain, and the parent class CollectionLogXList::action() method signature properly includes the Audit $audit parameter at the correct position (after Reader $geodb).

src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php (5)

75-75: LGTM! Audit service injection follows DI pattern.

The addition of the Audit service via dependency injection is consistent with the refactoring described in the PR summary and aligns with similar patterns in related endpoints.


79-79: LGTM! Method signature correctly accepts injected Audit service.

The Audit parameter is properly aligned with the injection declaration and follows the established parameter ordering convention.


106-111: LGTM! Pagination logic correctly implemented.

The code properly extracts limit and offset from grouped queries and passes them as named parameters to getLogsByResource. This correctly addresses the method signature requirements and avoids the TypeError that would result from passing the $queries array directly.

Based on learnings from past review, this fix was previously identified and has been correctly applied here.


160-160: LGTM! Count method call is correct.

The countLogsByResource method is correctly called with only the $resource parameter, matching its signature and avoiding the invalid $queries argument.

Based on learnings from past review, this fix was previously identified and has been correctly applied here.


75-79: The audit library dependency in composer.json is specified as "utopia-php/audit": "dev-feat-db-3.x", not version 2.0.0 as referenced in the PR description. Verify that this development branch version is intentional and aligns with the actual audit API changes implemented in this PR.

Likely an incorrect or invalid review comment.

src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (2)

69-78: Audit DI injection and action signature alignment look good

Injecting 'audit' and appending Audit $audit at the end of the action parameters matches the inject chain order (response, dbForProject, locale, geodb, audit) and is consistent with the broader DI pattern in this PR. I don't see wiring or type-hint issues here.


93-106: Audit 2.x pagination + counting usage looks correct; just confirm API and total semantics

Parsing queries, grouping with Query::groupByType(), and defaulting limit/offset is appropriate given the validator only allows Limit and Offset. Passing them as named args to getLogsByResource($resource, limit: $limit, offset: $offset) matches the new Audit API style (see README examples using named limit/offset/after/before/ascending parameters for getters), and avoids the earlier incompatibility of passing raw Query[]. (github.com)

Using countLogsByResource($resource) for 'total' delegates counting to the Audit adapter, which is a good consolidation, but it intentionally ignores pagination/time filters — the total returned here is for all logs on that resource, not just the current page.

Please double‑check that:

  • The utopia-php/audit version wired into this branch exposes getLogsByResource(string $resource, ?DateTime $after = null, ?DateTime $before = null, int $limit = 25, int $offset = 0, bool $ascending = false) (or equivalent) so the limit/offset named arguments resolve correctly, and
  • The client/SDK for this endpoint indeed expects total to be the overall resource log count, not a page-scoped count.

Also applies to: 152-155

src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)

70-71: Audit DI and pagination for database logs look correct

Audit is cleanly injected, the action signature matches the param/inject order, and limit/offset are correctly derived via Query::groupByType() before calling getLogsByResource(). Using countLogsByResource($resource) for total aligns with the other audit log handlers; no issues spotted here.

Also applies to: 74-75, 89-95, 140-142

src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Logs/XList.php (1)

65-66: TablesDB database logs endpoint correctly migrated to injected Audit

The TablesDB logs route mirrors the database logs handler: Audit is injected, queries are parsed and grouped to get limit/offset, and both retrieval and total counting use the injected Audit instance without leaking the raw $queries. Implementation looks consistent and sound.

Also applies to: 69-70, 83-89, 135-136

app/controllers/api/users.php (1)

948-949: User logs endpoint: Audit injection and total handling look good

Audit is properly injected, queries are parsed and grouped to derive limit/offset, and getLogsByUser() is called with those pagination values. The total field correctly honours the total flag while returning the overall user-log count rather than just the current page. No issues from a correctness perspective.

Also applies to: 962-967, 1005-1007

app/controllers/api/messaging.php (1)

1148-1149: Audit DI and pagination for messaging log endpoints look good

Injecting Audit and switching the provider/topic/subscriber/message log endpoints to use Query::groupByType for limit/offset, getLogsByResource($resource, ...) for retrieval, and countLogsByResource($resource) for totals is consistent and aligns with the documented "limit + offset only" query support on these routes. This also resolves the earlier incorrect extra-argument usage on countLogsByResource. I don't see any functional or correctness issues in these changes.

Also applies to: 1162-1164, 1167-1167, 1214-1214, 2556-2557, 2570-2572, 2575-2575, 2623-2623, 2977-2978, 2991-2993, 2996-2996, 3044-3044, 3776-3777, 3790-3792, 3795-3795, 3843-3843

Copy link
Copy Markdown
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/teams.php (1)

30-30: Team logs Audit integration and pagination are correctly wired.

  • Importing Audit, injecting audit, and type-hinting Audit $audit in /v1/teams/:teamId/logs are consistent with the new DI pattern.
  • Parsing queries, using Query::groupByType to compute limit/offset, then calling $audit->getLogsByResource($resource, offset: $offset, limit: $limit) and $audit->countLogsByResource($resource) matches the expected usage and keeps total independent of pagination.

As a minor future clean-up, the user-agent + geo-IP → log DTO transformation here is nearly identical to other log endpoints (databases, collections, account); extracting a shared helper could reduce duplication later on.

Also applies to: 1467-1468, 1482-1485, 1487-1487, 1534-1535

📜 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 cec5cd7 and 8baa5cb.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • app/controllers/api/account.php (3 hunks)
  • app/controllers/api/messaging.php (12 hunks)
  • app/controllers/api/teams.php (3 hunks)
  • app/controllers/api/users.php (3 hunks)
  • app/init/resources.php (4 hunks)
  • src/Appwrite/Platform/Workers/Deletes.php (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/api/messaging.php
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.

Applied to files:

  • app/controllers/api/users.php
  • src/Appwrite/Platform/Workers/Deletes.php
📚 Learning: 2025-10-23T08:06:38.889Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10546
File: src/Appwrite/Platform/Workers/Migrations.php:144-148
Timestamp: 2025-10-23T08:06:38.889Z
Learning: In the Appwrite codebase, migration workers receive already-validated data from queued jobs. Query validation using Query::parseQueries() happens at the API endpoint level (with try-catch for QueryException) before jobs are queued, so workers in src/Appwrite/Platform/Workers/Migrations.php don't need redundant validation.

Applied to files:

  • src/Appwrite/Platform/Workers/Deletes.php
📚 Learning: 2025-08-22T06:23:32.026Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 10348
File: app/controllers/shared/api.php:546-546
Timestamp: 2025-08-22T06:23:32.026Z
Learning: The Utopia\Queue\Broker\Pool class (aliased as BrokerPool) implements both Publisher and Consumer interfaces, making it directly compatible with constructors expecting Publisher parameters like Func::__construct(protected Publisher $publisher). No wrapping is needed.

Applied to files:

  • app/init/resources.php
📚 Learning: 2025-08-22T06:23:32.026Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 10348
File: app/controllers/shared/api.php:546-546
Timestamp: 2025-08-22T06:23:32.026Z
Learning: In the Utopia Queue system, the Pool class implements both Publisher and Consumer interfaces, so BrokerPool (Pool) can be passed directly to constructors expecting Publisher parameters like Func::__construct(protected Publisher $publisher).

Applied to files:

  • app/init/resources.php
🧬 Code graph analysis (3)
app/controllers/api/users.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
app/controllers/api/teams.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-156)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
app/controllers/api/account.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
⏰ 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: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (9)
src/Appwrite/Platform/Workers/Deletes.php (2)

12-12: LGTM! Audit adapter import updated.

The import change from Utopia\Audit\Audit to Utopia\Audit\Adapter\SQL aligns with the audit system upgrade to version 2.0.0.


520-520: Verify that SQL::COLLECTION constant is correctly defined.

The code references SQL::COLLECTION instead of Audit::COLLECTION. Ensure this constant is properly defined in the Utopia\Audit\Adapter\SQL class and matches the expected audit collection name in the database schema.

Applies to: Lines 520 and 789-794

app/init/resources.php (3)

7-7: LGTM! Audit-related imports added.

The new imports support the audit system upgrade:

  • AuditEvent for the audit event queue
  • AdapterDatabase and Audit for the new dependency-injected audit resource

Also applies to: 33-34


150-152: Verify AuditEvent constructor signature.

The queueForAudits resource now returns new AuditEvent($publisher) instead of new Audit($publisher). Based on the learnings, BrokerPool (aliased as Publisher) should be compatible with event queue constructors. However, verify that the AuditEvent class constructor accepts a Publisher parameter.

#!/bin/bash
# Description: Verify AuditEvent constructor accepts Publisher parameter

# Find AuditEvent class constructor
ast-grep --pattern $'class AuditEvent {
  $$$
  public function __construct($$$) {
    $$$
  }
  $$$
}'

# Also check parent class if it extends Event
rg -nP 'class\s+AuditEvent\s+extends' --type=php

645-648: The audit resource initialization properly wraps the dbForProject database in an AdapterDatabase adapter before passing it to the Audit constructor. Constructor signatures are compatible:

  • AdapterDatabase::__construct(DatabaseClient $db) accepts a Utopia\Database\Database instance
  • Audit::__construct(Adapter $adapter) accepts adapter instances, and AdapterDatabase properly extends the Adapter base class

This adapter pattern implementation is correct and aligns with the utopia-php/audit library design.

app/controllers/api/users.php (3)

948-949: LGTM! Audit dependency injection implemented.

The route now injects the audit resource (registered in app/init/resources.php) instead of instantiating Audit locally. This follows a cleaner dependency injection pattern and aligns with similar changes across other controllers in this PR.


962-964: LGTM! Pagination logic follows established pattern.

The pagination parameters are now extracted using Query::groupByType($queries) with sensible defaults (limit: 25, offset: 0). This pattern is consistent with other log listing endpoints in the codebase (e.g., src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php).


966-966: Verify that $user->getSequence() (integer) is the correct parameter type for getLogsByUser() and countLogsByUser().

The Audit library's public documentation shows countLogsByUser and similar retrieval methods accept a user identifier as the first parameter, with pagination and filtering as named parameters. However, the code uses $user->getSequence() (an integer) where documentation examples show string userId values. Confirm whether the Audit library v2.0.0 accepts integer sequence IDs or expects string user IDs for these methods.

app/controllers/api/account.php (1)

40-40: Audit DI and account logs pagination look correct and consistent.

  • Importing Utopia\Audit\Audit and injecting audit into /v1/account/logs aligns the handler with the new DI-based audit setup.
  • Using Query::groupByType($queries) to derive limit/offset, and then passing them via named args to $audit->getLogsByUser(...), with countLogsByUser called without pagination params, matches the intended API and avoids the previous incorrect $queries argument.

No functional issues spotted here.

Also applies to: 2984-2986, 2993-2997, 3025-3025

Copy link
Copy Markdown
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

♻️ Duplicate comments (1)
app/http.php (1)

265-269: Verify complete migration of Audit::COLLECTION references across the codebase.

The adapter-based initialization pattern here is correct. However, as flagged in a previous review, there may be remaining references to Audit::COLLECTION in other files (e.g., src/Appwrite/Platform/Workers/Deletes.php) that need to be updated to AuditAdapterSQL::COLLECTION for consistency.

#!/bin/bash
# Verify all Audit::COLLECTION and AuditAdapterSQL::COLLECTION references
echo "=== Searching for Audit::COLLECTION references ==="
rg 'Audit::COLLECTION' --type=php -n

echo -e "\n=== Searching for AuditAdapterSQL::COLLECTION references ==="
rg 'AuditAdapterSQL::COLLECTION' --type=php -n
🧹 Nitpick comments (2)
app/controllers/api/account.php (1)

40-40: Audit injection and pagination look good; consider normalizing log shape before merging

The /v1/account/logs changes are aligned with the new audit API:

  • Importing Utopia\Audit\Audit and injecting audit matches the new App::setResource('audit', ...).
  • Using Query::groupByType($queries) to derive $limit/$offset, and passing them as named arguments into getLogsByUser(...), follows the v2.0.0 README patterns.
  • Total is now computed via countLogsByUser($user->getSequence()), which matches the count API (time filters optional, queries not accepted).

One robustness concern:

  • Inside the loop, $log is treated both as an array ($log['userAgent'], $log['data'], $log['ip']) and as an object ($log->getArrayCopy()). Other handlers in this PR (e.g. database/collection log XList endpoints) only use array-style access and don’t call getArrayCopy(), which suggests adapters may legitimately return plain arrays.

To make this endpoint resilient regardless of whether the adapter returns Log objects or plain arrays, you can normalize to an array once and merge from there:

Proposed safer handling for log normalization
-        foreach ($logs as $i => &$log) {
-            $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
-
-            $detector = new Detector($log['userAgent']);
-
-            $output[$i] = new Document(array_merge(
-                $log->getArrayCopy(),
-                $log['data'],
-                $detector->getOS(),
-                $detector->getClient(),
-                $detector->getDevice()
-            ));
+        foreach ($logs as $i => &$log) {
+            // Normalize to array for both Log objects and plain arrays
+            if (\is_object($log) && \method_exists($log, 'getArrayCopy')) {
+                $logArray = $log->getArrayCopy();
+            } else {
+                $logArray = (array) $log;
+            }
+
+            $logArray['userAgent'] = !empty($logArray['userAgent']) ? $logArray['userAgent'] : 'UNKNOWN';
+
+            $detector = new Detector($logArray['userAgent']);
+
+            $output[$i] = new Document(array_merge(
+                $logArray,
+                $logArray['data'] ?? [],
+                $detector->getOS(),
+                $detector->getClient(),
+                $detector->getDevice()
+            ));
 
-            $record = $geodb->get($log['ip']);
+            $record = $geodb->get($logArray['ip'] ?? null);

This keeps the response model the same while avoiding a potential fatal error if the adapter returns arrays instead of objects.

Please confirm against the concrete return type from your configured Utopia\Audit\Adapter (Database/ClickHouse) that $logs is always an object with getArrayCopy(). If there is any chance of plain arrays, adopting the normalization above (or an equivalent check) will prevent runtime errors. You can verify quickly by dumping get_class($logs[0]) in a test environment or by asserting the type in a unit test for /v1/account/logs.

Also applies to: 3043-3056, 3084-3084

app/controllers/api/messaging.php (1)

1169-1169: Consider consistent parameter order for maintainability.

Provider and topic log endpoints use offset: $offset, limit: $limit, while subscriber and message log endpoints use limit: $limit, offset: $offset. Although named parameters make this functionally equivalent, aligning all calls to use limit: $limit, offset: $offset (matching the pattern in the database logs modules) would improve code consistency.

🔎 Suggested alignment
-        $logs = $audit->getLogsByResource($resource, offset: $offset, limit: $limit);
+        $logs = $audit->getLogsByResource($resource, limit: $limit, offset: $offset);

Apply the same change at line 2578 for topic logs.

Also applies to: 2578-2578

📜 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 8baa5cb and a943e8e.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • app/controllers/api/account.php (3 hunks)
  • app/controllers/api/messaging.php (12 hunks)
  • app/controllers/api/projects.php (1 hunks)
  • app/controllers/api/teams.php (3 hunks)
  • app/controllers/api/users.php (3 hunks)
  • app/http.php (3 hunks)
  • app/init/resources.php (4 hunks)
  • composer.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • composer.json
  • app/controllers/api/projects.php
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-22T06:23:32.026Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 10348
File: app/controllers/shared/api.php:546-546
Timestamp: 2025-08-22T06:23:32.026Z
Learning: The Utopia\Queue\Broker\Pool class (aliased as BrokerPool) implements both Publisher and Consumer interfaces, making it directly compatible with constructors expecting Publisher parameters like Func::__construct(protected Publisher $publisher). No wrapping is needed.

Applied to files:

  • app/init/resources.php
📚 Learning: 2025-08-22T06:23:32.026Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 10348
File: app/controllers/shared/api.php:546-546
Timestamp: 2025-08-22T06:23:32.026Z
Learning: In the Utopia Queue system, the Pool class implements both Publisher and Consumer interfaces, so BrokerPool (Pool) can be passed directly to constructors expecting Publisher parameters like Func::__construct(protected Publisher $publisher).

Applied to files:

  • app/init/resources.php
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
Repo: appwrite/appwrite PR: 10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.

Applied to files:

  • app/controllers/api/users.php
  • app/controllers/api/messaging.php
🧬 Code graph analysis (5)
app/controllers/api/users.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
app/controllers/api/account.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (79-157)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
app/controllers/api/teams.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (79-157)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
app/controllers/api/messaging.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (79-157)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
src/Appwrite/Platform/Workers/Audits.php (1)
  • action (64-154)
app/http.php (2)
src/Appwrite/Event/Database.php (1)
  • getCollection (137-140)
src/Appwrite/Vcs/Comment.php (1)
  • isEmpty (58-61)
⏰ 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: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (9)
app/init/resources.php (1)

7-7: Audit DI wiring and aliasing look correct

Alias for Appwrite\Event\Audit and the new audit resource using AdapterDatabase + Audit are consistent with the updated utopia-php/audit adapter-based API and avoid class name collisions. No issues from a wiring/correctness perspective.

Please run the audit-related tests (account logs, database/collection logs, and workers) against a project with existing audit data to confirm that logs are written and read correctly after the adapter upgrade.

Also applies to: 33-35, 150-152, 656-659

app/controllers/api/account.php (1)

1277-1277: Authorization injection is now explicit and consistent across flows

The added ->inject('authorization') calls for the token-based session, email update, phone update, recovery confirmation, and phone verification endpoints make existing $authorization usage (e.g. skip() and role changes) explicit and DI-driven. This improves clarity without changing behavior.

If you have API tests around these flows, rerun them to confirm there are no regressions in auth scoping (especially around skip() blocks and role additions) after the injection change.

Also applies to: 3250-3250, 3360-3360, 3738-3738, 4160-4160

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

948-966: LGTM - Audit DI and pagination pattern correctly applied.

The changes properly inject Audit via dependency injection, extract pagination parameters using Query::groupByType($queries), and use the new API methods with named parameters. The default limit of 25 and offset of 0 are consistent with other log endpoints in the codebase.


1006-1006: Count method usage is correct.

The countLogsByUser method is called without forwarding queries, which aligns with the new Audit API where count methods take only the resource/user identifier. Based on learnings, the database layer internally handles filter separation for count operations.

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

1474-1494: LGTM - Teams logs endpoint correctly updated for Audit upgrade.

The dependency injection, pagination extraction, and method calls follow the same pattern applied across other log endpoints. The implementation is consistent with the relevant code snippets from XList.php handlers.


1541-1541: Count method usage is consistent with the new Audit API.

The countLogsByResource call correctly omits the queries parameter, matching the pattern used in other log endpoints.

app/http.php (2)

15-16: LGTM - Adapter imports correctly added.

The imports for AdapterDatabase and AuditAdapterSQL properly support the new adapter-based Audit initialization pattern required by utopia-php/audit 2.0.0.


395-399: LGTM - Project database audit setup follows the same pattern.

The adapter-based Audit initialization for shared project tables correctly mirrors the platform database setup, ensuring consistency across both initialization paths.

app/controllers/api/messaging.php (1)

1150-1151: LGTM – Audit DI and pagination correctly implemented.

The dependency injection of Audit, extraction of pagination parameters via Query::groupByType($queries), and method calls to getLogsByResource and countLogsByResource are all correctly implemented and match the expected pattern for the Audit 2.0.0 upgrade.

Also applies to: 1164-1169, 1216-1216

Copy link
Copy Markdown
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Appwrite/Platform/Workers/Audits.php (1)

52-63: PHPDoc parameter is out of sync with the method signature.

Line 54 still references @param callable $getProjectDB but this parameter no longer exists in the method signature on line 63. The PHPDoc should be updated to reflect the current parameters.

🔎 Proposed fix
     /**
      * @param Message $message
-     * @param callable $getProjectDB
      * @param Document $project
      * @param callable $getAudit
      * @return Commit|NoCommit
📜 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 a943e8e and d48a330.

📒 Files selected for processing (2)
  • app/worker.php (2 hunks)
  • src/Appwrite/Platform/Workers/Audits.php (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
app/worker.php (1)
app/realtime.php (1)
  • getProjectDB (79-131)
src/Appwrite/Platform/Workers/Audits.php (1)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
⏰ 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). (20)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: Unit Test
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E General Test
  • GitHub Check: scan
🔇 Additional comments (4)
src/Appwrite/Platform/Workers/Audits.php (2)

105-105: Field rename from 'timestamp' to 'time' is correct.

Per the past discussion, this aligns with the audit collection's actual attribute name. The audit library was previously mapping 'timestamp' to 'time' internally, so this change eliminates the inconsistency.


138-139: DI-based Audit instantiation looks good.

The change from direct instantiation to using the $getAudit callable aligns with the broader refactoring pattern across the codebase, ensuring consistent adapter-based Audit creation.

app/worker.php (2)

24-25: Import namespaces are correct for utopia-php/audit v2.0.0.

The imports use the correct singular Adapter namespace (Utopia\Audit\Adapter\Database) which aligns with the v2.0.0 API.


471-482: Well-structured getAudit resource factory.

The implementation correctly:

  • Returns a factory closure for project-aware Audit instantiation
  • Handles console/empty projects using dbForPlatform
  • Uses getProjectDB for project-specific databases
  • Follows the same DI pattern as other resources in this file

Copy link
Copy Markdown
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: 1

♻️ Duplicate comments (3)
composer.json (2)

50-50: Dev branch dependency already flagged in previous review.

The use of dev-feat-db-3x instead of a stable release was already identified. Ensure this is resolved before merging to a stable branch.


112-112: Missing trailing newline already flagged.

src/Appwrite/Platform/Workers/Audits.php (1)

105-105: Field rename from 'timestamp' to 'time' already discussed and confirmed.

Per the author's comments, this aligns the field name with the audit collection attribute.

🧹 Nitpick comments (1)
app/worker.php (1)

455-466: New getAudit resource follows established patterns and is correctly implemented.

The resource correctly handles platform vs. per-project Audit instance creation using dependency injection. Consider a minor simplification to reduce duplication:

🔎 Optional: Reduce duplication
 Server::setResource('getAudit', function (Database $dbForPlatform, callable $getProjectDB) {
     return function (Document $project) use ($dbForPlatform, $getProjectDB) {
-        if ($project->isEmpty() || $project->getId() === 'console') {
-            $adapter = new AdapterDatabase($dbForPlatform);
-            return new UtopiaAudit($adapter);
-        }
-
-        $dbForProject = $getProjectDB($project);
-        $adapter = new AdapterDatabase($dbForProject);
-        return new UtopiaAudit($adapter);
+        $db = ($project->isEmpty() || $project->getId() === 'console')
+            ? $dbForPlatform
+            : $getProjectDB($project);
+        return new UtopiaAudit(new AdapterDatabase($db));
     };
 }, ['dbForPlatform', 'getProjectDB']);
📜 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 33b9f33 and 5519086.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • app/controllers/api/projects.php
  • app/worker.php
  • composer.json
  • src/Appwrite/Platform/Workers/Audits.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/api/projects.php
🧰 Additional context used
🧬 Code graph analysis (2)
src/Appwrite/Platform/Workers/Audits.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php (1)
  • action (78-156)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Logs/XList.php (1)
  • action (74-144)
app/worker.php (3)
src/Appwrite/Event/Audit.php (1)
  • Audit (8-162)
app/realtime.php (1)
  • getProjectDB (80-132)
src/Appwrite/Utopia/Response/Model/Document.php (1)
  • Document (8-115)
⏰ 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). (19)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V2)
  • GitHub Check: E2E Shared Mode Service Test (Dev Keys) (Shared V1)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V1)
  • GitHub Check: E2E Shared Mode Service Test (Site Screenshots) (Shared V2)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E General Test
  • GitHub Check: Benchmark
🔇 Additional comments (5)
composer.json (1)

55-55: Version constraint change is acceptable.

The change from "3.*" to "3.*.*" is functionally equivalent for Composer's semver resolution and has no practical impact.

app/worker.php (1)

24-25: Imports are correctly namespaced for the audit v2 adapter pattern.

The singular Adapter namespace aligns with the utopia-php/audit v2 API and matches usage across other files in this PR.

src/Appwrite/Platform/Workers/Audits.php (3)

45-46: Injection updated correctly to use the new getAudit resource.

The change from getProjectDB to getAudit aligns with the new resource pattern introduced in app/worker.php.


63-63: Action method signature correctly updated.

The parameter order matches the injection order in the constructor, and the $getAudit callable is properly typed.


133-147: Batch processing correctly uses the injected Audit factory.

The loop properly retrieves the Audit instance per project using $getAudit($projectDocument) and handles errors with appropriate try/catch/finally cleanup.

Comment on lines 54 to +56
* @param callable $getProjectDB
* @param Document $project
* @param callable $getAudit
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Stale docblock parameter reference.

Line 54 still references $getProjectDB which no longer exists in the method signature. This appears to be a leftover from the refactor.

🔎 Proposed fix
     /**
      * @param Message $message
-     * @param callable $getProjectDB
      * @param Document $project
      * @param callable $getAudit
      * @return Commit|NoCommit
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* @param callable $getProjectDB
* @param Document $project
* @param callable $getAudit
/**
* @param Message $message
* @param Document $project
* @param callable $getAudit
* @return Commit|NoCommit
🤖 Prompt for AI Agents
In src/Appwrite/Platform/Workers/Audits.php around lines 54 to 56, the docblock
still references a parameter named $getProjectDB that no longer exists in the
method signature; update the docblock to match the current signature by removing
the stale @param entry for $getProjectDB (or renaming it if the parameter was
renamed) and ensure the remaining @param tags and types correspond exactly to
the actual method parameters and types.


try {
$this->deleteByGroup(Audit::COLLECTION, [
$this->deleteByGroup(SQL::COLLECTION, [
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we need this constant? can we abstract it behind the delete method? we already Iintialize the adapter so we should be able to know this internally.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

updated.

}

if ($create || $projectTables) {
$audit = new Audit($dbForProject);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we remove all audit related stuff from the project creation once we complete the switch?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, we can.


Server::setResource('executor', fn () => new Executor());

Server::setResource('getAudit', function (Database $dbForPlatform, callable $getProjectDB) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For future we need to avoid using DI to return callbacks, this can be done by standardizing the way we pass project / user to message jobs which will allow us to auto create needed dependencies without needing to pass params to every dependency.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes thi will need a proper refactor.

Copy link
Copy Markdown
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Appwrite/Platform/Workers/Deletes.php (1)

190-190: Fix incorrect parameters in deleteAuditLogs call.

The call to deleteAuditLogs passes incorrect parameters. The method signature at line 787 expects (Document $project, string $auditRetention, callable $getAudit), but this call provides ($project, $getProjectDB, $auditRetention). This will cause a type error at runtime when DELETE_TYPE_MAINTENANCE is triggered.

🔎 Proposed fix
-                $this->deleteAuditLogs($project, $getProjectDB, $auditRetention);
+                $this->deleteAuditLogs($project, $auditRetention, $getAudit);
📜 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 6943015 and d2cda97.

📒 Files selected for processing (1)
  • src/Appwrite/Platform/Workers/Deletes.php
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Platform/Workers/Deletes.php (2)
src/Appwrite/Event/Audit.php (1)
  • Audit (8-162)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php (1)
  • cleanup (393-410)
⏰ 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: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (2)
src/Appwrite/Platform/Workers/Deletes.php (2)

523-523: SQL::COLLECTION usage aligns with audit 2.0.0 upgrade.

The change from Audit::COLLECTION to SQL::COLLECTION is part of the audit library upgrade to version 2.0.0. A previous review comment questioned whether this constant should be abstracted behind the delete method. While that architectural improvement remains valid, this change correctly reflects the new audit library's adapter pattern.

Based on learnings, the previous reviewer suggested abstracting the collection constant.


787-798: The implementation correctly uses the audit library's cleanup() method. The method signature accepts \DateTime as documented, and catching Throwable is appropriate since the underlying adapters may throw various exception types.

@lohanidamodar lohanidamodar merged commit aad7d6d into 1.8.x Dec 31, 2025
231 of 237 checks passed
@lohanidamodar lohanidamodar deleted the feat-audits-upgrade branch December 31, 2025 01: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