8000 refactor(account): move MFA endpoints to module actions by HarshMN2345 · Pull Request #10793 · appwrite/appwrite · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@HarshMN2345
Copy link
Member
@HarshMN2345 HarshMN2345 commented Nov 10, 2025

What does this PR do?

(Provide a description of what this PR does and why it's needed.)

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
Contributor
coderabbitai bot commented Nov 10, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (22)
  • docs/examples/1.5.x/client-rest/examples/account/create-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/client-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/client-rest/examples/account/create2f-a-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/client-rest/examples/account/update-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/client-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/server-rest/examples/account/create-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/server-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/server-rest/examples/account/create2f-a-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/server-rest/examples/account/update-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.5.x/server-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/client-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/client-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.6.x/server-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/client-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/server-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.7.x/server-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/client-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-rest/examples/account/create-mfa-challenge.md is excluded by !docs/examples/**
  • docs/examples/1.8.x/server-rest/examples/account/update-mfa-challenge.md is excluded by !docs/examples/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This change removes MFA-related API endpoints from the legacy account controller architecture and introduces a new modular Account service structure. The old public routes under /v1/account/mfa/* are removed, while new action classes are created in src/Appwrite/Platform/Modules/Account/Http/ to provide equivalent functionality through a plugin-based service pattern. The Account module is registered in the platform, and individual HTTP action handlers are introduced for MFA authenticators, challenges, recovery codes, factors listing, and general MFA settings.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Complex logic paths requiring careful verification: The Challenges/Create class handles dual factor flows (PHONE and EMAIL) with templating, validation, queuing, and metrics logic; Challenges/Update implements multi-type verification with recovery code support; authenticator operations interact with database documents, caching, and session state.
  • Broad structural changes across multiple files: ~12 new action classes introduced, each with constructor wiring, dependency injection, and action methods that require individual reasoning despite consistent patterns.
  • Critical areas requiring extra attention:
    • Challenges/Create.php - Complex branching for phone vs. email factors, SMS/email queueing, abuse tracking, and metrics logic
    • Challenges/Update.php - Multi-type verification flows and session/factor synchronization logic
    • Authenticators/Update.php - OTP verification and session factor management
    • Update.php (MFA settings) - Factor aggregation and session synchronization during enable/disable transitions
    • Verify proper error handling and exception types across all action classes
    • Validate dependency injection and parameter passing through the service registration chain

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Ch 8000 eck name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The description contains only a template with placeholder sections and minimal actual content, lacking any meaningful information about the changes, test plan, or related issues. Complete the PR description by filling in 'What does this PR do?' and 'Test Plan' sections with specific details about the MFA endpoint refactoring and how changes were verified.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: moving MFA endpoints from the controller to module-based actions, which aligns with the significant refactoring shown in the changeset.

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
github-actions bot commented Nov 10, 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: 2

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/Modules/Account/Http/Mfa/Challenge/Update.php (1)

170-201: Trigger the messaging queue for SMS challenges

After configuring $queueForMessaging, we never call ->trigger(), so the SMS job is never enqueued and phone challenges silently fail. Please trigger the queue once the payload is ready.

Apply this diff:

         $queueForMessaging
             ->setType(MESSAGE_SEND_TYPE_INTERNAL)
             ->setMessage(new Document([
                 '$id' => $challenge->getId(),
                 'data' => [
                     'content' => $code,
                 ],
             ]))
             ->setRecipients([$phone])
-            ->setProviderType(MESSAGE_TYPE_SMS);
+            ->setProviderType(MESSAGE_TYPE_SMS)
+            ->trigger();
🧹 Nitpick comments (2)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php (1)

64-72: Consider removing unused parameter.

The $requestTimestamp parameter is injected but never used in the action method. If it's not needed for future auditing or other purposes, consider removing it to clean up the method signature.

Apply this diff if the parameter is not needed:

     public function action(
         bool $mfa,
-        ?\DateTime $requestTimestamp,
         Response $response,
         Document $user,
         Document $session,
         Database $dbForProject,
         Event $queueForEvents
     ): void {

And remove the injection in the constructor:

             ->param('mfa', null, new Boolean(), 'Enable or disable MFA.')
-            ->inject('requestTimestamp')
             ->inject('response')
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (1)

89-97: Consider removing unused parameter.

The $requestTimestamp parameter is injected but never used in the action method. If it's not needed for future auditing or other purposes, consider removing it to clean up the method signature.

Apply this diff if the parameter is not needed:

     public function action(
         string $type,
-        ?\DateTime $requestTimestamp,
         Response $response,
         Document $project,
         Document $user,
         Database $dbForProject,
         Event $queueForEvents
     ): void {

And remove the injection in the constructor:

             ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator. Must be `' . Type::TOTP . '`')
-            ->inject('requestTimestamp')
             ->inject('response')
📜 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 0bf8cea and 64b4ea9.

📒 Files selected for processing (14)
  • app/controllers/api/account.php (0 hunks)
  • src/Appwrite/Platform/Appwrite.php (2 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Delete.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Factors/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Module.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Services/Http.php (1 hunks)
💤 Files with no reviewable changes (1)
  • app/controllers/api/account.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.

Applied to files:

  • src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php
🧬 Code graph analysis (13)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (5)
src/Appwrite/Platform/Modules/Account/Services/Http.php (1)
  • Http (17-34)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (2)
  • getName (23-26)
  • action (81-104)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (2)
  • getName (23-26)
  • action (81-103)
src/Appwrite/Platform/Modules/Account/Module.php (2)
src/Appwrite/Platform/Appwrite.php (2)
  • Appwrite (16-30)
  • __construct (18-29)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Create.php (7)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/Auth.php (3)
  • Auth (18-515)
  • codeGenerator (352-361)
  • tokenGenerator (331-341)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Event/Mail.php (13)
  • Mail (7-442)
  • setSmtpHost (171-175)
  • setSmtpPort (183-187)
  • setSmtpUsername (195-199)
  • setSmtpPassword (207-211)
  • setSmtpSecure (219-223)
  • setSmtpReplyTo (255-259)
  • setSmtpSenderEmail (231-235)
  • setSmtpSenderName (243-247)
  • setPreview (102-107)
  • setBodyTemplate (148-153)
  • setVariables (357-361)
  • setRecipient (57-62)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Template/Template.php (4)
  • Template (8-178)
  • fromFile (25-33)
  • fromString (45-54)
  • render (66-85)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (6)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (5)
  • Type (8-61)
  • setLabel (17-22)
  • setIssuer (29-34)
  • getSecret (41-44)
  • getProvisioningUri (46-49)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Delete.php (3)
  • getName (25-28)
  • __construct (30-82)
  • action (84-106)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (3)
  • getName (27-30)
  • __construct (32-86)
  • action (88-134)
src/Appwrite/Platform/Modules/Account/Services/Http.php (11)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (3)
  • Create (24-143)
  • __construct (33-87)
  • getName (28-31)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Create.php (3)
  • Create (34-329)
  • __construct (43-105)
  • getName (38-41)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (3)
  • Create (19-105)
  • __construct (28-79)
  • getName (23-26)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Delete.php (3)
  • Delete (21-107)
  • __construct (30-82)
  • getName (25-28)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (3)
  • Update (23-135)
  • __construct (32-86)
  • getName (27-30)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Update.php (3)
  • Update (22-160)
  • __construct (31-88)
  • getName (26-29)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (3)
  • Update (19-104)
  • __construct (28-79)
  • getName (23-26)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php (3)
  • Update (19-99)
  • __construct (28-62)
  • getName (23-26)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Factors/XList.php (3)
  • XList (17-89)
  • __construct (26-71)
  • getName (21-24)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (3)
  • Get (16-86)
  • __construct (25-70)
  • getName (20-23)
src/Appwrite/Platform/Modules/Account/Module.php (1)
  • __construct (10-13)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Delete.php (6)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (3)
  • getName (28-31)
  • __construct (33-87)
  • action (89-142)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (3)
  • getName (27-30)
  • __construct (32-86)
  • action (88-134)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (6)
src/Appwrite/Auth/MFA/Type.php (2)
  • Type (8-61)
  • generateBackupCodes (51-60)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (1)
  • action (81-104)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (1)
  • action (72-85)
src/Appwrite/Platform/Appwrite.php (1)
src/Appwrite/Platform/Modules/Account/Module.php (1)
  • Module (8-14)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Factors/XList.php (3)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Utopia/Response.php (1)
  • Response (158-980)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (10)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Update.php (2)
  • Update (22-160)
  • action (90-159)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (2)
  • Update (19-104)
  • action (81-103)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php (2)
  • Update (19-99)
  • action (64-98)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (1)
  • action (89-142)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Delete.php (1)
  • action (84-106)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (1)
  • action (81-104)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (1)
  • action (72-85)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Update.php (9)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (2)
  • Update (23-135)
  • action (88-134)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (2)
  • Update (19-104)
  • action (81-103)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Create.php (1)
  • action (107-328)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (1)
  • action (81-104)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (1)
  • action (72-85)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Create.php (7)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (2)
  • Type (8-61)
  • generateBackupCodes (51-60)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (3)
  • getName (20-23)
  • __construct (25-70)
  • action (72-85)
src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Update.php (3)
  • getName (23-26)
  • __construct (28-79)
  • action (81-103)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php (3)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Update.php (2)
  • Update (23-135)
  • action (88-134)
🪛 PHPMD (2.15.0)
src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php

91-91: Avoid unused parameters such as '$requestTimestamp'. (undefined)

(UnusedFormalParameter)

src/Appwrite/Platform/Modules/Account/Http/Mfa/Challenge/Update.php

93-93: Avoid unused parameters such as '$project'. (undefined)

(UnusedFormalParameter)

src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php

66-66: Avoid unused parameters such as '$requestTimestamp'. (undefined)

(UnusedFormalParameter)

⏰ 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 (8)
src/Appwrite/Platform/Appwrite.php (1)

5-5: LGTM! Clean module registration.

The Account module is properly imported and registered following the established pattern used by other modules in the platform.

Also applies to: 21-21

src/Appwrite/Platform/Modules/Account/Module.php (1)

8-13: LGTM! Module structure is correct.

The Account module is properly configured with the HTTP service registration following the framework's module pattern.

src/Appwrite/Platform/Modules/Account/Http/Mfa/RecoveryCodes/Get.php (1)

72-85: LGTM! Recovery codes retrieval logic is correct.

The action properly validates that recovery codes exist before returning them, with appropriate error handling and response modeling.

src/Appwrite/Platform/Modules/Account/Services/Http.php (1)

17-33: LGTM! MFA actions are properly registered.

The HTTP service correctly registers all MFA-related actions with proper naming and instantiation. The fluent interface pattern is applied consistently.

src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Delete.php (1)

84-106: LGTM! Authenticator deletion is correctly implemented.

The action properly validates the authenticator exists, deletes it, purges the user cache, and queues events. The 204 No Content response is appropriate for a DELETE operation.

src/Appwrite/Platform/Modules/Account/Http/Mfa/Factors/XList.php (1)

73-88: LGTM! Factor availability logic is sound.

The action correctly determines which MFA factors are available for the user by checking verification status for TOTP, email, phone, and the presence of recovery codes.

src/Appwrite/Platform/Modules/Account/Http/Mfa/Update.php (1)

73-98: LGTM! MFA update logic is correct.

The action properly toggles MFA status, and when enabling MFA, it correctly derives available factors based on user verification status and updates the session accordingly.

src/Appwrite/Platform/Modules/Account/Http/Mfa/Authenticators/Create.php (1)

98-142: LGTM! Authenticator creation logic is well-implemented.

The action correctly handles creating a new TOTP authenticator with proper error handling for unknown types and existing verified authenticators. The cleanup of unverified authenticators before creating a new one is appropriate, and permissions are properly configured.

@github-actions
Copy link
github-actions bot commented Nov 10, 2025

✨ Benchmark results

  • Requests per second: 1,163
  • Requests with 200 status code: 209,446
  • P99 latency: 0.167648259

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,163 1,210
200 209,446 217,784
P99 0.167648259 0.169028966

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: 8

♻️ Duplicate comments (3)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Update.php (1)

109-135: Restore recovery-code branch

Line 112 compares against \strtolower(Type::RECOVERY_CODE) and Line 134 uses the same lowercase key in the match. Because the stored type stays 'recoveryCode', this branch never runs and every recovery-code challenge fails. Please compare directly against Type::RECOVERY_CODE.

-                $challenge->getAttribute('type') === \strtolower(Type::RECOVERY_CODE)
+                $challenge->getAttribute('type') === Type::RECOVERY_CODE
...
-            \strtolower(Type::RECOVERY_CODE) => $recoveryCodeChallenge($challenge, $user, $otp),
+            Type::RECOVERY_CODE => $recoveryCodeChallenge($challenge, $user, $otp),
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Update.php (1)

109-135: Restore recovery-code branch

Line 112 still checks \strtolower(Type::RECOVERY_CODE) and Line 134 uses the lowercased key in the match, so the recovery-code path never executes and valid codes are rejected. Please compare directly against the constant.

-                $challenge->getAttribute('type') === \strtolower(Type::RECOVERY_CODE)
+                $challenge->getAttribute('type') === Type::RECOVERY_CODE
...
-            \strtolower(Type::RECOVERY_CODE) => $recoveryCodeChallenge($challenge, $user, $otp),
+            Type::RECOVERY_CODE => $recoveryCodeChallenge($challenge, $user, $otp),
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Create.php (1)

171-181: Still missing the SMS trigger call
We configure the messaging queue for phone MFA but never fire it, so no SMS leaves the system. This is the same breakage noted earlier and remains a blocker. Please trigger the queue right after setting the provider type.

         $queueForMessaging
             ->setType(MESSAGE_SEND_TYPE_INTERNAL)
             ->setMessage(new Document([
                 '$id' => $challenge->getId(),
                 'data' => [
                     'content' => $code,
                 ],
             ]))
             ->setRecipients([$phone])
-            ->setProviderType(MESSAGE_TYPE_SMS);
+            ->setProviderType(MESSAGE_TYPE_SMS)
+            ->trigger();
🧹 Nitpick comments (3)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Update.php (1)

55-66: Drop unused requestTimestamp injection

requestTimestamp is injected and threaded through the signature but never read. Trimming it avoids dead parameters and keeps the action signature minimal.

-            ->inject('requestTimestamp')
             ->inject('response')
             ->inject('user')
             ->inject('session')
             ->inject('dbForProject')
             ->inject('queueForEvents')
             ->callback($this->action(...));
     }
 
     public function action(
         bool $mfa,
-        ?\DateTime $requestTimestamp,
         Response $response,
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (2)

141-141: Consider using a more robust path construction.

The dirname(__DIR__, 7) approach is fragile and tightly couples this code to the current directory structure. If the file location changes, this path will break.

Consider using a constant or configuration value for the templates path:

-        $templatesPath = \dirname(__DIR__, 7) . '/app/config/locale/templates';
+        $templatesPath = APP_CONFIG_PATH . '/locale/templates';

Or define a method that retrieves the templates path from a centralized location.


269-282: Validate custom template content for security.

Custom templates allow overriding the email body and sender details without validating the content. While this provides flexibility, it could potentially be exploited if custom templates are populated from untrusted sources or contain malicious content.

Consider adding validation or sanitization for custom template content, especially if templates can be user-provided or modified through an API.

📜 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 64b4ea9 and b20c493.

📒 Files selected for processing (13)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Delete.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Factors/XList.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Get.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Update.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Services/Http.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Appwrite/Platform/Modules/Account/Services/Http.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-10T04:12:13.037Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php:85-86
Timestamp: 2025-05-10T04:12:13.037Z
Learning: The class `Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Action` defines a method `getGrantParentNotFoundException()` which is used to handle cases where a parent resource (like a database collection) is not found.

Applied to files:

  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Get.php
🧬 Code graph analysis (12)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Get.php (3)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (1)
  • Response (158-980)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Factors/XList.php (3)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Utopia/Response.php (1)
  • Response (158-980)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Update.php (4)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Utopia/Response.php (1)
  • Response (158-980)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Create.php (6)
src/Appwrite/Auth/Auth.php (3)
  • Auth (18-515)
  • codeGenerator (352-361)
  • tokenGenerator (331-341)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Event/Mail.php (14)
  • Mail (7-442)
  • setSmtpHost (171-175)
  • setSmtpPort (183-187)
  • setSmtpUsername (195-199)
  • setSmtpPassword (207-211)
  • setSmtpSecure (219-223)
  • setSmtpReplyTo (255-259)
  • setSmtpSenderEmail (231-235)
  • setSmtpSenderName (243-247)
  • setSubject (34-39)
  • setPreview (102-107)
  • setBodyTemplate (148-153)
  • setVariables (357-361)
  • setRecipient (57-62)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Template/Template.php (4)
  • Template (8-178)
  • fromFile (25-33)
  • fromString (45-54)
  • render (66-85)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Update.php (3)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (5)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (5)
  • Type (8-61)
  • setLabel (17-22)
  • setIssuer (29-34)
  • getSecret (41-44)
  • getProvisioningUri (46-49)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Delete.php (3)
  • getName (25-28)
  • __construct (30-82)
  • action (84-106)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Update.php (3)
  • getName (27-30)
  • __construct (32-86)
  • action (88-134)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (7)
src/Appwrite/Auth/Auth.php (3)
  • Auth (18-515)
  • codeGenerator (352-361)
  • tokenGenerator (331-341)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Event/Mail.php (14)
  • Mail (7-442)
  • setSmtpHost (171-175)
  • setSmtpPort (183-187)
  • setSmtpUsername (195-199)
  • setSmtpPassword (207-211)
  • setSmtpSecure (219-223)
  • setSmtpReplyTo (255-259)
  • setSmtpSenderEmail (231-235)
  • setSmtpSenderName (243-247)
  • setSubject (34-39)
  • setPreview (102-107)
  • setBodyTemplate (148-153)
  • setVariables (357-361)
  • setRecipient (57-62)
src/Appwrite/Platform/Workers/Messaging.php (1)
  • Messaging (49-816)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (1)
  • Response (158-980)
src/Appwrite/Template/Template.php (4)
  • Template (8-178)
  • fromFile (25-33)
  • fromString (45-54)
  • render (66-85)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Create.php (6)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (2)
  • Type (8-61)
  • generateBackupCodes (51-60)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Get.php (3)
  • getName (20-23)
  • __construct (25-70)
  • action (72-85)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Update.php (3)
  • getName (23-26)
  • __construct (28-79)
  • action (81-103)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Update.php (4)
src/Appwrite/Auth/MFA/Type.php (1)
  • Type (8-61)
src/Appwrite/Event/Event.php (1)
  • Event (10-654)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (1)
  • Response (158-980)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Update.php (5)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Utopia/Response.php (2)
  • Response (158-980)
  • dynamic (700-733)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Update.php (3)
  • Update (22-161)
  • __construct (31-89)
  • action (91-160)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (2)
  • __construct (33-87)
  • action (89-142)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Delete.php (2)
  • __construct (30-82)
  • action (84-106)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Delete.php (3)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (2)
  • getName (28-31)
  • __construct (33-87)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Update.php (2)
  • getName (27-30)
  • __construct (32-86)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Update.php (5)
src/Appwrite/Platform/Modules/Account/Services/Http.php (2)
  • Http (17-34)
  • __construct (19-33)
src/Appwrite/Auth/MFA/Type.php (2)
  • Type (8-61)
  • generateBackupCodes (51-60)
src/Appwrite/Extend/Exception.php (1)
  • Exception (7-464)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Create.php (3)
  • getName (23-26)
  • __construct (28-79)
  • action (81-104)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/RecoveryCodes/Get.php (3)
  • getName (20-23)
  • __construct (25-70)
  • action (72-85)
🪛 PHPMD (2.15.0)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Update.php

66-66: Avoid unused parameters such as '$requestTimestamp'. (undefined)

(UnusedFormalParameter)

src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenge/Update.php

94-94: Avoid unused parameters such as '$project'. (undefined)

(UnusedFormalParameter)

src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php

91-91: Avoid unused parameters such as '$requestTimestamp'. (undefined)

(UnusedFormalParameter)

src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Update.php

94-94: Avoid unused parameters such as '$project'. (undefined)

(UnusedFormalParameter)

⏰ 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 (Projects)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (3)

1-42: LGTM: Class structure is well-organized.

The namespace, imports, and class definition follow standard patterns for the new modular action architecture.


108-140: LGTM: Challenge document creation is correct.

The challenge document structure, permissions, and persistence logic are properly implemented. Token and code generation use the appropriate Auth utility methods.


324-329: LGTM: Event queuing and response handling are correct.

The events are properly queued with the necessary parameters, and the response uses the appropriate model type.

@HarshMN2345 HarshMN2345 requested a review from abnegate November 24, 2025 09:32
HarshMN2345 and others added 2 commits November 24, 2025 17:44
…ges/Create.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…icators/Create.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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

♻️ Duplicate comments (3)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (3)

92-92: Align accepted factor values with implemented handling and add a safe default.

factor validation allows Type::EMAIL, Type::PHONE 6D38 , Type::TOTP, and Type::RECOVERY_CODE, but the switch only handles EMAIL and PHONE, and there is no default branch. For TOTP, RECOVERY_CODE, or any unexpected value that slips past validation, you’ll create a challenge document but perform no associated action, which is hard to reason about and risks unusable/orphaned challenges.

Consider:

  • Either restricting the whitelist to only the factors this action actually handles, or
  • Implementing explicit branches for Type::TOTP and Type::RECOVERY_CODE if they are meant to be supported here, and
  • Adding a default case that throws a clear Exception for unsupported factors to avoid silent no‑ops.

Also applies to: 143-322


155-181: Fix SMS template handling and send the rendered message, not the raw code.

Two issues in the SMS path:

  1. When a project custom SMS template is configured, $message is overwritten with $customTemplate['message'] (a string), and then $message->setParam(...) is called. That will fail at runtime because $message is no longer a Template instance.
  2. You fully render $message (including localized content) into $message but then queue only the raw $code as 'content', effectively discarding the formatted SMS text. The earlier template rendering is dead code and users see just the bare OTP.

Suggested fix sketch:

-        $message = Template::fromFile($templatesPath . '/sms-base.tpl');
-
-        $customTemplate = $project->getAttribute('templates', [])['sms.mfaChallenge-' . $locale->default] ?? [];
-        if (!empty($customTemplate)) {
-            $message = $customTemplate['message'] ?? $message;
-        }
+        $message = Template::fromFile($templatesPath . '/sms-base.tpl');
+
+        $customTemplate = $project->getAttribute('templates', [])['sms.mfaChallenge-' . $locale->default] ?? [];
+        if (!empty($customTemplate) && !empty($customTemplate['message'])) {
+            $message = Template::fromString($customTemplate['message']);
+        }
@@
-        $messageContent = \strip_tags($messageContent->render());
-        $message = $message->setParam('{{token}}', $messageContent);
-
-        $message = $message->render();
+        $messageContent = \strip_tags($messageContent->render());
+        $message = $message
+            ->setParam('{{token}}', $messageContent)
+            ->render();
@@
-                ->setMessage(new Document([
-                    '$id' => $challenge->getId(),
-                    'data' => [
-                        'content' => $code,
-                    ],
-                ]))
+                ->setMessage(new Document([
+                    '$id' => $challenge->getId(),
+                    'data' => [
+                        'content' => $message,
+                    ],
+                ]))

This keeps the type of $message consistent and actually delivers the localized, templated SMS.


183-202: Revisit rate limiting behavior for SMS when authPhone is absent from the plan.

The timelimit/abuse logic only runs when $plan['authPhone'] is set. If a plan doesn’t define authPhone, SMS challenges are still sent but bypass rate limiting and abuse checks, which can be problematic from both cost and abuse perspectives.

Consider either:

  • Enforcing the timelimit/Abuse check regardless of whether authPhone is present, using a sensible default, or
  • Explicitly disallowing / gating SMS MFA for plans without authPhone, instead of silently sending without limits.

At minimum, this behavior should be intentional and documented, since it affects abuse protection for phone-based MFA.

🧹 Nitpick comments (3)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (2)

33-86: Endpoint wiring and SDK metadata look good; double‑check audits labels targeting response.$id

The HTTP method/path, scope, event label, and SDK Method definitions for both createMfaAuthenticator (deprecated) and createMFAAuthenticator are consistent and match the new module‑action style.

One thing to verify: both audits.resource (user/{response.$id}) and audits.userId ({response.$id}) reference the response payload, but this action ultimately returns Response::MODEL_MFA_TYPE built from a $model that only contains secret and uri. If MODEL_MFA_TYPE does not define an $id field, these placeholders may resolve to null and produce incomplete audit records.

It might be safer to align these labels with whatever pattern other Account/MFA actions use (for example, basing them on the authenticated user or the authenticator document), e.g. something along the lines of user/{user.$id} or a dedicated userId param, depending on existing conventions.


88-140: MFA authenticator creation logic is sound; remove unused $authenticator reassignment

The main flow—validating type, configuring TOTP, replacing an existing unverified authenticator, persisting the new one, purging the user cache, and queueing an event—looks consistent and preserves the “one TOTP authenticator per user” invariant.

The only cleanup worth doing here is the final reassignment of $authenticator:

$authenticator = $dbForProject->createDocument('authenticators', $authenticator);

$authenticator is not read after this line, so the reassignment is effectively unused. Dropping the assignment keeps things clearer and avoids potential static‑analysis warnings:

-        $authenticator = $dbForProject->createDocument('authenticators', $authenticator);
+        $dbForProject->createDocument('authenticators', $authenticator);

Everything else in this method looks good to me.

src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (1)

324-327: Confirm whether an explicit trigger()/project binding is required for events.

You populate $queueForEvents with userId and challengeId but never call something like ->setProject($project)->trigger(). In other actions, events are often explicitly triggered; if that convention still applies in the new HTTP module layer, this code will never emit the configured users.[userId].challenges.[challengeId].create event.

Please confirm the expected pattern for Event in this module. If explicit triggering is still required, add the appropriate setProject(...) and trigger() calls.

📜 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 cceb108 and b1f5b69.

📒 Files selected for processing (2)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (1 hunks)
  • src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Authenticators/Create.php (1)
src/Appwrite/Auth/MFA/Type.php (5)
  • Type (8-61)
  • setLabel (17-22)
  • setIssuer (29-34)
  • getSecret (41-44)
  • getProvisioningUri (46-49)
⏰ 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: Benchmark
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: Unit Test
🔇 Additional comments (1)
src/Appwrite/Platform/Modules/Account/Http/Account/MFA/Challenges/Create.php (1)

108-140: Overall flow and validations look solid, aside from the specific issues noted.

The general structure—challenge document creation, per-factor validation (env + user attributes), localized templates, SMTP configuration handling, and usage metrics—is consistent and readable. Once the SMS/template and factor-handling issues are resolved, this action should integrate cleanly with the new modular account HTTP layer.

Also applies to: 204-321

@Meldiron Meldiron merged commit 7efbae4 into 1.8.x Nov 25, 2025
40 checks passed
@HarshMN2345 HarshMN2345 deleted the feat-SER-448-improve-MFA-docs-endpoint-order branch November 25, 2025 08:48
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