Conversation
…Email rule and status polling
…e strict trial app db validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes in this release:
550687c chore: bump deps
64f14b5 chore: country list
46bd5e6 chore: fix email blocker disposable domains json url
e01c3a9 sec(forms): harden security, resolve config caching issue, and enforce strict trial app db validation
5a1e06a feat(forms): implement secure, public hosted iframe forms with BannedEmail rule and status polling
6876a15 chore: prevent spam users
6265442 chore: tweak sorting, add guard to db seeders
6dd3852 chore: update deps
9e95d89 chore: improve update metadata calls
1d18086 chore: bump up timeouts
Greptile Summary
This release PR ships three related features: a public iframe-hosted trial-signup form (
/f/{formSlug}), a layered email-ban system (BanEmailsCommand,EmailBlockerService,BannedEmailrule,polydock_banned_patternsmigration), and a hardenedRegisterControllerthat applies bothBannedEmailvalidation andSensitiveDataRedactorto every log call. The PR also guards theDatabaseSeederbehind an environment check and fixes the deploy-key loading to be safe in CI.FormController,BaseHostedForm,DrupalAIDemoDrupalOrgForm, blade views): renders an iframe-safe form with strict CSPframe-ancestors, validates thetrial_appUUID against a public-store subquery, calls the reCAPTCHA API, creates aUserRemoteRegistration, and returns a UUID for the client to poll.BanEmailsCommand,EmailBlockerService,BannedEmailrule): domain/wildcard patterns stored inpolydock_banned_patternsare matched via SQLLIKEwith a safe escaping chain; a secondary disposable-domain file check is layered on top and cached as a singleton.RegisterController,AuthenticatedApiController): credential fields in log output are now redacted viaSensitiveDataRedactor; theBannedEmailrule is applied to all three registration entry points.Confidence Score: 5/5
The PR is safe to merge; all new entry points validate input thoroughly and the credential-logging issue from the previous review has been addressed.
The three new entry points (FormController, RegisterController, AuthenticatedApiController) all apply the BannedEmail rule and run through the full validation pipeline before touching the database. The credential-logging concern raised in the last review round is now resolved via SensitiveDataRedactor. Remaining notes are forward-looking (the trial_app null-coalescing guard in BaseHostedForm for hypothetical future forms, the hardcoded poll URL, and the in-memory cache staleness for queue workers) and none block current functionality.
No files require special attention for merge. The BaseHostedForm::transformPayload null-coalescing gap is worth addressing before adding a second HostedForm implementation that omits trial_app.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant User participant IframeForm as /f/{formSlug} participant FormController participant Validator participant EmailBlockerService participant PolydockBannedPattern as DB: polydock_banned_patterns participant UserRemoteRegistration as DB: user_remote_registrations participant RegisterController as /api/register/{uuid} User->>IframeForm: GET /f/drupal-ai-demo IframeForm->>FormController: show() FormController->>FormController: Query public stores + trial apps FormController-->>User: Render form (CSP frame-ancestors set) User->>IframeForm: POST submit IframeForm->>FormController: submit() FormController->>Validator: Validate fields + BannedEmail rule Validator->>EmailBlockerService: checkEmail(email) EmailBlockerService->>PolydockBannedPattern: SQL LIKE match EmailBlockerService->>EmailBlockerService: Check disposable domains file EmailBlockerService-->>Validator: EmailBlockerResult alt Email blocked Validator-->>User: 422 Unprocessable end FormController->>FormController: reCAPTCHA verification FormController->>UserRemoteRegistration: create(email, request_data) FormController-->>User: "202 Accepted {status: pending, id: uuid}" loop Poll every 5s (up to 7 min) User->>RegisterController: "GET /api/register/{uuid}" RegisterController->>UserRemoteRegistration: find by uuid RegisterController-->>User: "{status, result_data}" end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant User participant IframeForm as /f/{formSlug} participant FormController participant Validator participant EmailBlockerService participant PolydockBannedPattern as DB: polydock_banned_patterns participant UserRemoteRegistration as DB: user_remote_registrations participant RegisterController as /api/register/{uuid} User->>IframeForm: GET /f/drupal-ai-demo IframeForm->>FormController: show() FormController->>FormController: Query public stores + trial apps FormController-->>User: Render form (CSP frame-ancestors set) User->>IframeForm: POST submit IframeForm->>FormController: submit() FormController->>Validator: Validate fields + BannedEmail rule Validator->>EmailBlockerService: checkEmail(email) EmailBlockerService->>PolydockBannedPattern: SQL LIKE match EmailBlockerService->>EmailBlockerService: Check disposable domains file EmailBlockerService-->>Validator: EmailBlockerResult alt Email blocked Validator-->>User: 422 Unprocessable end FormController->>FormController: reCAPTCHA verification FormController->>UserRemoteRegistration: create(email, request_data) FormController-->>User: "202 Accepted {status: pending, id: uuid}" loop Poll every 5s (up to 7 min) User->>RegisterController: "GET /api/register/{uuid}" RegisterController->>UserRemoteRegistration: find by uuid RegisterController-->>User: "{status, result_data}" endComments Outside Diff (1)
app/Http/Controllers/Api/RegisterController.php, line 107-112 (link)showRegisterlogs full registration record including credentials on every pollLine 111 calls
Log::info('Showing user remote registration', ['registration' => $registration->toArray()]). After a successful trial provision,result_datacontainsapp_admin_passwordandapp_admin_username. Since the new form polls this endpoint every 5 seconds until success (up to 7 minutes), credentials will be written to application logs repeatedly. This is a pre-existing call, but the new public polling flow dramatically increases the frequency of credential exposure in logs.Reviews (5): Last reviewed commit: "chore: singleton" | Re-trigger Greptile