B2B-88: add starter kit structure and elements
This commit is contained in:
10
packages/features/auth/src/schemas/password-reset.schema.ts
Normal file
10
packages/features/auth/src/schemas/password-reset.schema.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RefinedPasswordSchema, refineRepeatPassword } from './password.schema';
|
||||
|
||||
export const PasswordResetSchema = z
|
||||
.object({
|
||||
password: RefinedPasswordSchema,
|
||||
repeatPassword: RefinedPasswordSchema,
|
||||
})
|
||||
.superRefine(refineRepeatPassword);
|
||||
@@ -0,0 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { PasswordSchema } from './password.schema';
|
||||
|
||||
export const PasswordSignInSchema = z.object({
|
||||
email: z.string().email(),
|
||||
password: PasswordSchema,
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RefinedPasswordSchema, refineRepeatPassword } from './password.schema';
|
||||
|
||||
export const PasswordSignUpSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
password: RefinedPasswordSchema,
|
||||
repeatPassword: RefinedPasswordSchema,
|
||||
})
|
||||
.superRefine(refineRepeatPassword);
|
||||
82
packages/features/auth/src/schemas/password.schema.ts
Normal file
82
packages/features/auth/src/schemas/password.schema.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Password requirements
|
||||
* These are the requirements for the password when signing up or changing the password
|
||||
*/
|
||||
const requirements = {
|
||||
minLength: 6,
|
||||
maxLength: 99,
|
||||
specialChars:
|
||||
process.env.NEXT_PUBLIC_PASSWORD_REQUIRE_SPECIAL_CHARS === 'true',
|
||||
numbers: process.env.NEXT_PUBLIC_PASSWORD_REQUIRE_NUMBERS === 'true',
|
||||
uppercase: process.env.NEXT_PUBLIC_PASSWORD_REQUIRE_UPPERCASE === 'true',
|
||||
};
|
||||
|
||||
/**
|
||||
* Password schema
|
||||
* This is used to validate the password on sign in (for existing users when requirements are not enforced)
|
||||
*/
|
||||
export const PasswordSchema = z
|
||||
.string()
|
||||
.min(requirements.minLength)
|
||||
.max(requirements.maxLength);
|
||||
|
||||
/**
|
||||
* Refined password schema with additional requirements
|
||||
* This is required to validate the password requirements on sign up and password change
|
||||
*/
|
||||
export const RefinedPasswordSchema = PasswordSchema.superRefine((val, ctx) =>
|
||||
validatePassword(val, ctx),
|
||||
);
|
||||
|
||||
export function refineRepeatPassword(
|
||||
data: { password: string; repeatPassword: string },
|
||||
ctx: z.RefinementCtx,
|
||||
) {
|
||||
if (data.password !== data.repeatPassword) {
|
||||
ctx.addIssue({
|
||||
message: 'auth:errors.passwordsDoNotMatch',
|
||||
path: ['repeatPassword'],
|
||||
code: 'custom',
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function validatePassword(password: string, ctx: z.RefinementCtx) {
|
||||
if (requirements.specialChars) {
|
||||
const specialCharsCount =
|
||||
password.match(/[!@#$%^&*(),.?":{}|<>]/g)?.length ?? 0;
|
||||
|
||||
if (specialCharsCount < 1) {
|
||||
ctx.addIssue({
|
||||
message: 'auth:errors.minPasswordSpecialChars',
|
||||
code: 'custom',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (requirements.numbers) {
|
||||
const numbersCount = password.match(/\d/g)?.length ?? 0;
|
||||
|
||||
if (numbersCount < 1) {
|
||||
ctx.addIssue({
|
||||
message: 'auth:errors.minPasswordNumbers',
|
||||
code: 'custom',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (requirements.uppercase) {
|
||||
if (!/[A-Z]/.test(password)) {
|
||||
ctx.addIssue({
|
||||
message: 'auth:errors.uppercasePassword',
|
||||
code: 'custom',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user