-
Notifications
You must be signed in to change notification settings - Fork 19
fix[validation]: add profileById validation for user queries(BUG-3833) #827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -39,4 +39,60 @@ module.exports = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .isString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('preferred_language must be string') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| profileById: (req) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // id (numeric only) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkParams('id') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .optional() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches(/^[0-9]+$/) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('id is invalid. Must be numeric') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkQuery('email') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .optional() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .isEmail() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('email is invalid. Must be a valid email format') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // username | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkQuery('username') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .optional() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches(/^(?:[a-z0-9_-]{3,40}|[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})$/) //accept random string (min 3 max 40) of smaller case letters _ - and numbers OR email in lowercase as username | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('username is invalid') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // phone | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkQuery('phone') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .optional() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches(/^[0-9]{7,15}$/) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('phone is invalid. Must be digits only, length 7–15') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // phone_code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkQuery('phone_code') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .optional() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches(/^\+[0-9]{1,4}$/) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('phone_code is invalid. Must start with + and contain 1–4 digits') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // tenant_code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkQuery('tenant_code') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches(/^[A-Za-z0-9_-]+$/) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage('tenant_code is invalid. Only letters, numbers, underscore, and hyphen allowed') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!req.params.id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.checkQuery(['email', 'username', 'phone', 'phone_code']).custom(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { email, username, phone, phone_code } = req.query | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!email && !username && !phone) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error('At least one of id, email, username, or phone must be provided') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (phone && !phone_code) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error('phone_code is required when phone is provided') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+82
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Array-scoped custom validator will duplicate errors; anchor cross-field rules to single fields. Using checkQuery(['a','b','c']).custom(...) executes per field, yielding multiple identical errors. Replace with single-field custom checks to avoid duplication and clearer error attribution. Also refine message (id isn’t relevant inside the id-absent branch). - if (!req.params.id) {
- req.checkQuery(['email', 'username', 'phone', 'phone_code']).custom(() => {
- const { email, username, phone, phone_code } = req.query
-
- if (!email && !username && !phone) {
- throw new Error('At least one of id, email, username, or phone must be provided')
- }
-
- if (phone && !phone_code) {
- throw new Error('phone_code is required when phone is provided')
- }
-
- return true
- })
- }
+ // Cross-field: require one of email/username/phone when id is absent
+ req.checkQuery('email').custom((_val, { req }) => {
+ const { id } = req.params || {}
+ const { email, username, phone } = req.query || {}
+ if (!id && !email && !username && !phone) {
+ throw new Error('At least one of email, username, or phone must be provided')
+ }
+ return true
+ })
+
+ // Cross-field: require phone_code when phone is provided (and id is absent)
+ req.checkQuery('phone_code').custom((_val, { req }) => {
+ const { id } = req.params || {}
+ const { phone, phone_code } = req.query || {}
+ if (!id && phone && !phone_code) {
+ throw new Error('phone_code is required when phone is provided')
+ }
+ return true
+ })📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.