2024-10-07 21:13:38 +02:00
|
|
|
import type { DayOfWeek } from "@mantine/dates";
|
2023-12-10 17:12:20 +01:00
|
|
|
import { z } from "zod";
|
|
|
|
|
|
2024-09-01 20:37:52 +02:00
|
|
|
import { colorSchemes } from "@homarr/definitions";
|
2024-08-19 21:11:36 +02:00
|
|
|
import type { TranslationObject } from "@homarr/translation";
|
|
|
|
|
|
2024-09-01 20:37:52 +02:00
|
|
|
import { zodEnumFromArray } from "./enums";
|
2024-05-18 16:55:08 +02:00
|
|
|
import { createCustomErrorParams } from "./form/i18n";
|
|
|
|
|
|
2023-12-10 17:12:20 +01:00
|
|
|
const usernameSchema = z.string().min(3).max(255);
|
2024-08-19 21:11:36 +02:00
|
|
|
|
|
|
|
|
const regexCheck = (regex: RegExp) => (value: string) => regex.test(value);
|
|
|
|
|
export const passwordRequirements = [
|
|
|
|
|
{ check: (value) => value.length >= 8, value: "length" },
|
|
|
|
|
{ check: regexCheck(/[a-z]/), value: "lowercase" },
|
|
|
|
|
{ check: regexCheck(/[A-Z]/), value: "uppercase" },
|
|
|
|
|
{ check: regexCheck(/\d/), value: "number" },
|
|
|
|
|
{ check: regexCheck(/[$&+,:;=?@#|'<>.^*()%!-]/), value: "special" },
|
|
|
|
|
] satisfies {
|
|
|
|
|
check: (value: string) => boolean;
|
|
|
|
|
value: keyof TranslationObject["user"]["field"]["password"]["requirement"];
|
|
|
|
|
}[];
|
|
|
|
|
|
|
|
|
|
const passwordSchema = z
|
|
|
|
|
.string()
|
|
|
|
|
.min(8)
|
|
|
|
|
.max(255)
|
|
|
|
|
.refine(
|
|
|
|
|
(value) => {
|
|
|
|
|
return passwordRequirements.every((requirement) => requirement.check(value));
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-10-26 22:46:14 +02:00
|
|
|
params: createCustomErrorParams({
|
|
|
|
|
key: "passwordRequirements",
|
|
|
|
|
params: {},
|
|
|
|
|
}),
|
2024-08-19 21:11:36 +02:00
|
|
|
},
|
|
|
|
|
);
|
2023-12-10 17:12:20 +01:00
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const addConfirmPasswordRefinement = <TObj extends { password: string; confirmPassword: string }>(
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
|
schema: z.ZodObject<any, "strip", z.ZodTypeAny, TObj>,
|
|
|
|
|
) => {
|
|
|
|
|
return schema.refine((data) => data.password === data.confirmPassword, {
|
2024-05-18 16:55:08 +02:00
|
|
|
path: ["confirmPassword"],
|
2024-10-26 22:46:14 +02:00
|
|
|
params: createCustomErrorParams({
|
|
|
|
|
key: "passwordsDoNotMatch",
|
|
|
|
|
params: {},
|
|
|
|
|
}),
|
2024-11-28 20:21:29 +01:00
|
|
|
});
|
|
|
|
|
};
|
2024-05-18 16:55:08 +02:00
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const baseCreateUserSchema = z.object({
|
|
|
|
|
username: usernameSchema,
|
|
|
|
|
password: passwordSchema,
|
|
|
|
|
confirmPassword: z.string(),
|
|
|
|
|
email: z.string().email().or(z.string().length(0).optional()),
|
|
|
|
|
groupIds: z.array(z.string()),
|
|
|
|
|
});
|
2023-12-10 17:12:20 +01:00
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const createUserSchema = addConfirmPasswordRefinement(baseCreateUserSchema);
|
2024-11-23 17:18:29 +01:00
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const initUserSchema = addConfirmPasswordRefinement(baseCreateUserSchema.omit({ groupIds: true }));
|
2024-03-02 17:46:03 +01:00
|
|
|
|
2024-01-02 14:18:37 +01:00
|
|
|
const signInSchema = z.object({
|
2024-05-18 16:55:08 +02:00
|
|
|
name: z.string().min(1),
|
|
|
|
|
password: z.string().min(1),
|
2023-12-10 17:12:20 +01:00
|
|
|
});
|
2024-01-02 14:18:37 +01:00
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const registrationSchema = addConfirmPasswordRefinement(
|
|
|
|
|
z.object({
|
2024-05-12 10:04:20 +02:00
|
|
|
username: usernameSchema,
|
|
|
|
|
password: passwordSchema,
|
|
|
|
|
confirmPassword: z.string(),
|
2024-11-28 20:21:29 +01:00
|
|
|
}),
|
|
|
|
|
);
|
2024-05-12 10:04:20 +02:00
|
|
|
|
|
|
|
|
const registrationSchemaApi = registrationSchema.and(
|
|
|
|
|
z.object({
|
|
|
|
|
inviteId: z.string(),
|
|
|
|
|
token: z.string(),
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
2024-03-05 21:10:19 +01:00
|
|
|
const editProfileSchema = z.object({
|
2024-05-12 16:27:56 +02:00
|
|
|
id: z.string(),
|
2024-03-05 21:10:19 +01:00
|
|
|
name: usernameSchema,
|
|
|
|
|
email: z
|
|
|
|
|
.string()
|
|
|
|
|
.email()
|
|
|
|
|
.or(z.literal(""))
|
|
|
|
|
.transform((value) => (value === "" ? null : value))
|
|
|
|
|
.optional()
|
|
|
|
|
.nullable(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const baseChangePasswordSchema = z.object({
|
|
|
|
|
previousPassword: z.string().min(1),
|
|
|
|
|
password: passwordSchema,
|
|
|
|
|
confirmPassword: z.string(),
|
|
|
|
|
userId: z.string(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const changePasswordSchema = addConfirmPasswordRefinement(baseChangePasswordSchema.omit({ userId: true }));
|
2024-05-12 16:27:56 +02:00
|
|
|
|
2024-11-28 20:21:29 +01:00
|
|
|
const changePasswordApiSchema = addConfirmPasswordRefinement(baseChangePasswordSchema);
|
2024-03-06 21:20:41 +01:00
|
|
|
|
2024-08-09 19:24:50 +02:00
|
|
|
const changeHomeBoardSchema = z.object({
|
|
|
|
|
homeBoardId: z.string().min(1),
|
|
|
|
|
});
|
|
|
|
|
|
2024-09-01 20:37:52 +02:00
|
|
|
const changeColorSchemeSchema = z.object({
|
|
|
|
|
colorScheme: zodEnumFromArray(colorSchemes),
|
|
|
|
|
});
|
|
|
|
|
|
2024-10-07 21:13:38 +02:00
|
|
|
const firstDayOfWeekSchema = z.object({
|
|
|
|
|
firstDayOfWeek: z.custom<DayOfWeek>((value) => z.number().min(0).max(6).safeParse(value).success),
|
|
|
|
|
});
|
|
|
|
|
|
2024-10-12 00:20:47 +02:00
|
|
|
const pingIconsEnabledSchema = z.object({
|
|
|
|
|
pingIconsEnabled: z.boolean(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-01-02 14:18:37 +01:00
|
|
|
export const userSchemas = {
|
|
|
|
|
signIn: signInSchema,
|
2024-05-12 10:04:20 +02:00
|
|
|
registration: registrationSchema,
|
|
|
|
|
registrationApi: registrationSchemaApi,
|
2024-01-02 14:18:37 +01:00
|
|
|
init: initUserSchema,
|
2024-03-02 17:46:03 +01:00
|
|
|
create: createUserSchema,
|
2024-11-23 17:18:29 +01:00
|
|
|
baseCreate: baseCreateUserSchema,
|
2024-02-27 21:53:53 +01:00
|
|
|
password: passwordSchema,
|
2024-03-05 21:10:19 +01:00
|
|
|
editProfile: editProfileSchema,
|
2024-03-06 21:20:41 +01:00
|
|
|
changePassword: changePasswordSchema,
|
2024-08-09 19:24:50 +02:00
|
|
|
changeHomeBoard: changeHomeBoardSchema,
|
2024-05-12 16:27:56 +02:00
|
|
|
changePasswordApi: changePasswordApiSchema,
|
2024-09-01 20:37:52 +02:00
|
|
|
changeColorScheme: changeColorSchemeSchema,
|
2024-10-07 21:13:38 +02:00
|
|
|
firstDayOfWeek: firstDayOfWeekSchema,
|
2024-10-12 00:20:47 +02:00
|
|
|
pingIconsEnabled: pingIconsEnabledSchema,
|
2024-01-02 14:18:37 +01:00
|
|
|
};
|