Add support for new CAPTCHA modal to issue updates
What does this MR do?
Switch to new modern captcha modal which uses Pajamas modal and handles all CAPTCHA rendering on the client. This introduces new, more decoupled approach of using axios interceptors to handle captcha modal hooks.
The backend now returns a 409 CONFLICT with a spam_log_id and
captcha_site_key. On the frontend side we, the aforementioned
interceptor detects this error, opens a modal asking the user to solve
the captcha. If the captcha is solved successfully, it re-issues the
request, attaching the captchaResponse. If it isn't solved, it will
throw an UnresolvedCaptchaError
instead. The application can choose to
gracefully handle this error, or treat it as any other axios request
error.
For now the interceptors only support PATCH, POST and PUT. Future iterations might want to switch to using HTTP headers instead, which would mean we could extend the approach to the other HTTP methods as well.
In this commit we are converting the issue update captcha to use this methodology. Before using an axios interceptor we needed to track the state of the captcha in the application and the logic looked something like this:
sequenceDiagram
participant U as User
participant V as Vue Application
participant G as GitLab API
U->>V: Save issue
V->>G: Request
G--xV: Response with Error and Captcha Data
V->>U: Please solve Captcha
U->>V: Captcha Solution
V->>G: Resend Request with solved Captcha Data
G-->>V: Response with Success
Now we are doing this:
sequenceDiagram
participant U as User
participant V as Vue Application
participant A as Axios Interceptor
participant G as GitLab API
U->>V: Save issue
V->>G: Request
G--xA: Response with Error and Captcha Data
A->>U: Please solve Captcha
U->>A: Captcha Solution
A->>G: Resend Request with solved Captcha Data
G-->>A: Response with Success
A-->>V: Response with Success
This way we have decoupled the Captcha handling from our Vue Application. For all the Vue Application knows, it is just a request that takes a bit longer than usual. This has the benefit that adding captcha support to new Vue endpoints is as easy as:
registerCaptchaModalInterceptor(axios);
Current Status
Tasks
-
Convert to new modal -
Convert to axios interceptor -
Closing Captcha modal without solving should still work
Screenshots (strongly suggested)
Screencast before | Screencast after (with solving the captcha ) | Screencast after (without solving the captcha) |
---|---|---|
captcha-before | captcha-success | captcha-fail |
Does this MR meet the acceptance criteria?
Conformity
-
Changelog entry -
Documentation (if required) -
Code review guidelines -
Merge request performance guidelines -
Style guides -
Database guides -
Separation of EE specific content
Availability and Testing
NOTE: See this section for details on how to test CAPTCHAs in local dev/GDK and review apps: https://gitlab.com/groups/gitlab-org/-/epics/5527#testing-notes
-
Review and add/update tests for this feature/bug. Consider all test levels. See the Test Planning Process. -
Tested in all supported browsers -
Informed Infrastructure department of a default or new setting change, if applicable per definition of done
Security
If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:
-
Label as security and @ mention @gitlab-com/gl-security/appsec
-
The MR includes necessary changes to maintain consistency between UI, API, email, or other methods -
Security reports checked/validated by a reviewer from the AppSec team