Enhance sign-up rules with derived country code and risk score handling#1232
Enhance sign-up rules with derived country code and risk score handling#1232mantrakp04 wants to merge 18 commits intofraud-protectionfrom
Conversation
…ng. Introduced new functions for calculating derived country codes and risk scores, updated API request handling to support optional risk scores, and improved validation for user input in the dashboard. Updated tests to cover new functionality and ensure proper handling of country codes and risk scores in user creation and updates.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
|
@greptile-ai review |
Greptile SummaryThis PR extends the sign-up rules system with derived country code support and improved risk score handling. A Key changes and observations:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Sign-up Request] --> B{signUpRuleOptions\ncountryCode !== null?}
B -- Yes: explicit override --> C[Use provided countryCode]
B -- No: derive --> D[getSpoofableEndUserLocation\nfrom request geo headers]
D --> E[getDerivedSignUpCountryCode]
E --> F{email matches\[email protected]?}
F -- Yes --> G[Use email-embedded CC\ntest stub priority]
F -- No --> H{requestLocation\ncountryCode valid?}
H -- Yes --> I[Use geo-derived CC]
H -- No --> J[countryCode = null]
C --> K[createSignUpRuleContext\nnull → empty string]
G --> K
I --> K
J --> K
K --> L[evaluateSignUpRules\nCEL evaluation with countryCode]
L --> M{Rule result}
M -- Rejected --> N[throw SignUpRejected]
M -- Allowed/Restricted --> O{currentUser is anonymous\nAND has country_code?}
O -- Yes --> P[Preserve anonymous user's\nexisting country_code]
O -- No --> Q[Use derived countryCode]
P --> R[Persist to DB via adminUpdate/adminCreate]
Q --> R
|
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx
Show resolved
Hide resolved
…entralized `countryCodeSchema` for validation and normalization, updated relevant components and APIs to utilize this schema, and replaced ad-hoc country code handling with a new `CountryCodeSelect` component. Enhanced tests to ensure proper validation of country codes in various contexts, including sign-up rules and user dialogs.
|
@greptile-ai review |
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx
Show resolved
Hide resolved
…o, removing email-based inference. Update related functions and tests to reflect this change, ensuring proper handling of null values. Preserve existing country codes during anonymous user upgrades when geo is unavailable.
|
@greptile-ai review |
apps/backend/src/app/api/latest/auth/otp/sign-in/verification-code-handler.tsx
Show resolved
Hide resolved
apps/backend/src/app/api/latest/auth/oauth/callback/[provider_id]/route.tsx
Show resolved
Hide resolved
…ountryCodeSet` for improved consistency across the application. Update relevant imports and functions to utilize the new set, ensuring proper handling of country codes in user sign-up and validation processes.
|
@greptile-ai review |
… country code inference. Update related API and tests to accommodate the new email parameter, ensuring accurate country code derivation from both request geo and email tags. Maintain existing functionality for handling null values.
…d country code handling. Introduced new validation logic for `restricted_by_admin` fields and updated risk score schema. Enhanced consistency and maintainability of user-related data structures.
…e user schema to include risk scores. Enhanced tests to validate new fields and ensure proper handling of country codes and risk scores across various endpoints.
…. Enhanced test coverage for user data structures to ensure proper handling of new attributes across various scenarios.
…res fields. Improved test coverage for user data structures, ensuring proper handling of new attributes across various scenarios.
|
@greptile-ai review |
|
@greptile-ai The risk-score stub in The Please re-review with this context in mind. |
…structures. Adjusted status codes and error messages for team membership actions, and removed unnecessary fields from user responses. Enhanced test coverage for user data structures, ensuring proper handling of new attributes across various scenarios.
…ded tests to verify behavior of 'in_list' and 'equals' operations for country codes. Updated user dialog and country code select components to handle null values and improve validation logic. Refactored condition builder to ensure proper handling of single values and arrays for country code conditions.
…ttributes and country code. Updated conditions for setting `restricted_by_admin` and added `country_code` to the user response structure. Enhanced test snapshots to reflect these changes, ensuring accurate representation of user data.
| return value.replace(/\\\\/g, '\\').replace(/\\"/g, '"'); | ||
| } | ||
|
|
||
| function normalizeConditionValue(condition: ConditionNode): ConditionNode['value'] { | ||
| if (condition.field !== 'countryCode') { | ||
| return condition.value; | ||
| } | ||
|
|
||
| if (Array.isArray(condition.value)) { | ||
| return condition.value.map(normalizeCountryCode); | ||
| } | ||
|
|
||
| if (typeof condition.value === 'number') { | ||
| return condition.value; |
There was a problem hiding this comment.
normalizeConditionValue silently passes numeric values for countryCode field
When condition.field === 'countryCode' and typeof condition.value === 'number', the function returns the number unchanged (falls through the array and string guards). conditionToCel then uses this number to build the CEL expression. Depending on the operator, it would generate:
countryCode == 42(number literal, not a quoted string)countryCode in [42](list of numbers, not strings)
Both would silently evaluate to false in the CEL runtime because the context variable countryCode is always a string — there's no type error, just a rule that never matches. The current UI never produces a numeric country-code value, but this is reachable through parseCelToVisualTree if it parses an existing expression and returns a ConditionNode with a numeric value, or after a future refactor.
// current — number passes through unchanged
if (typeof condition.value === 'number') {
return condition.value; // ← will produce countryCode == 42
}Consider throwing or coercing to an empty string so the condition renders as invalid rather than silently never-matching:
if (typeof condition.value === 'number') {
return ''; // treated as invalid by validateCountryCodeValue
}| const countryCodeToPersist = currentUser?.is_anonymous && currentUser.country_code != null | ||
| ? currentUser.country_code | ||
| : countryCode; |
There was a problem hiding this comment.
countryCodeToPersist preserves only anonymous users' existing country code, not non-anonymous users'
The guard on line 96 reads:
const countryCodeToPersist = currentUser?.is_anonymous && currentUser.country_code != null
? currentUser.country_code
: countryCode;This correctly preserves the stored code when upgrading an anonymous user that already has a country_code set. However, for non-anonymous currentUser instances (e.g. an OAuth sign-in where the account already exists in the oauth.tsx caller's params.currentUser), currentUser?.is_anonymous is false, so countryCodeToPersist becomes the freshly-derived countryCode from the current request. If this is non-null, line 135 (...(countryCodeToPersist !== null ? { country_code: countryCodeToPersist } : {})) will overwrite the user's previously-stored country code.
The field is documented as "captured at sign-up time" but could be updated on every sign-in if the user's geo changes. Apply the same preservation logic to all users that already have a non-null country_code:
const countryCodeToPersist = (currentUser?.country_code != null)
? currentUser.country_code
: countryCode;
Stacked on
fraud-protection.Made with Cursor