feat: implement identity and security features
- Added account types and privileged account types constants. - Created admin user controller for updating user security fields. - Developed role assignment controller for managing user roles. - Implemented validation middleware for request schemas. - Defined user role and auth session models for database interactions. - Created services for authentication, email notifications, and OTP handling. - Developed OAuth service for Google and Apple authentication. - Added JWT utility functions for token generation and verification. - Implemented comprehensive tests for authentication, session management, and password policies. - Created migration for updating user schema and adding new tables for auth sessions and user identities.
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
const { z } = require("zod");
|
||||
|
||||
const email = z.string().trim().toLowerCase().email();
|
||||
const password = z.string().min(12).superRefine((value, context) => {
|
||||
const failures = [!/[A-Z]/.test(value), !/[a-z]/.test(value), !/[^A-Za-z0-9]/.test(value), (value.match(/\d/g) || []).length < 4];
|
||||
if (failures.some(Boolean)) context.addIssue({ code: "custom", message: "Password must include uppercase, lowercase, a symbol, and at least four numbers" });
|
||||
});
|
||||
const body = (shape) => z.object({ body: z.object(shape).strict(), params: z.object({}).passthrough(), query: z.object({}).passthrough() });
|
||||
|
||||
module.exports = {
|
||||
passwordSchema: password,
|
||||
register: body({ firstName: z.string().trim().min(1).max(100), lastName: z.string().trim().min(1).max(100), email, password, phoneNumber: z.string().trim().min(1), address: z.string().trim().min(1), clientType: z.enum(["WEB", "MOBILE"]).default("WEB") }),
|
||||
login: body({ email, password: z.string().min(1), rememberMe: z.boolean().default(false), clientType: z.enum(["WEB", "MOBILE"]).default("WEB"), deviceName: z.string().max(100).optional() }),
|
||||
verifyOtp: body({ challengeId: z.string().uuid(), otp: z.string().regex(/^\d{6}$/), clientType: z.enum(["WEB", "MOBILE"]).default("WEB") }),
|
||||
refresh: body({ refreshToken: z.string().min(20).optional(), clientType: z.enum(["WEB", "MOBILE"]).default("WEB") }),
|
||||
forgot: body({ email }),
|
||||
reset: body({ token: z.string().min(20), newPassword: password, confirmPassword: z.string() }).superRefine(({ body }, context) => { if (body.newPassword !== body.confirmPassword) context.addIssue({ code: "custom", path: ["body", "confirmPassword"], message: "Passwords do not match" }); }),
|
||||
change: body({ currentPassword: z.string().min(1), newPassword: password, confirmPassword: z.string() }).superRefine(({ body }, context) => { if (body.newPassword !== body.confirmPassword) context.addIssue({ code: "custom", path: ["body", "confirmPassword"], message: "Passwords do not match" }); }),
|
||||
verifyEmail: body({ token: z.string().min(20) }),
|
||||
resend: body({ email }),
|
||||
oauth: body({ idToken: z.string().min(20), rememberMe: z.boolean().default(false), clientType: z.enum(["WEB", "MOBILE"]).default("WEB"), deviceName: z.string().max(100).optional(), firstName: z.string().max(100).optional(), lastName: z.string().max(100).optional() }),
|
||||
};
|
||||
Reference in New Issue
Block a user