171 lines
4.7 KiB
TypeScript
171 lines
4.7 KiB
TypeScript
|
import { z } from "zod";
|
||
|
|
||
|
import { checkUsername } from "@calcom/lib/server/checkUsername";
|
||
|
import { _UserModel as User } from "@calcom/prisma/zod";
|
||
|
import { iso8601 } from "@calcom/prisma/zod-utils";
|
||
|
|
||
|
import { timeZone } from "~/lib/validations/shared/timeZone";
|
||
|
|
||
|
// @note: These are the ONLY values allowed as weekStart. So user don't introduce bad data.
|
||
|
enum weekdays {
|
||
|
MONDAY = "Monday",
|
||
|
TUESDAY = "Tuesday",
|
||
|
WEDNESDAY = "Wednesday",
|
||
|
THURSDAY = "Thursday",
|
||
|
FRIDAY = "Friday",
|
||
|
SATURDAY = "Saturday",
|
||
|
SUNDAY = "Sunday",
|
||
|
}
|
||
|
|
||
|
// @note: extracted from apps/web/next-i18next.config.js, update if new locales.
|
||
|
enum locales {
|
||
|
EN = "en",
|
||
|
FR = "fr",
|
||
|
IT = "it",
|
||
|
RU = "ru",
|
||
|
ES = "es",
|
||
|
DE = "de",
|
||
|
PT = "pt",
|
||
|
RO = "ro",
|
||
|
NL = "nl",
|
||
|
PT_BR = "pt-BR",
|
||
|
ES_419 = "es-419",
|
||
|
KO = "ko",
|
||
|
JA = "ja",
|
||
|
PL = "pl",
|
||
|
AR = "ar",
|
||
|
IW = "iw",
|
||
|
ZH_CN = "zh-CN",
|
||
|
ZH_TW = "zh-TW",
|
||
|
CS = "cs",
|
||
|
SR = "sr",
|
||
|
SV = "sv",
|
||
|
VI = "vi",
|
||
|
}
|
||
|
enum theme {
|
||
|
DARK = "dark",
|
||
|
LIGHT = "light",
|
||
|
}
|
||
|
|
||
|
enum timeFormat {
|
||
|
TWELVE = 12,
|
||
|
TWENTY_FOUR = 24,
|
||
|
}
|
||
|
|
||
|
const usernameSchema = z
|
||
|
.string()
|
||
|
.transform((v) => v.toLowerCase())
|
||
|
// .refine(() => {})
|
||
|
.superRefine(async (val, ctx) => {
|
||
|
if (val) {
|
||
|
const result = await checkUsername(val);
|
||
|
if (!result.available) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "already_in_use_error" });
|
||
|
if (result.premium) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "premium_username" });
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// @note: These are the values that are editable via PATCH method on the user Model
|
||
|
export const schemaUserBaseBodyParams = User.pick({
|
||
|
name: true,
|
||
|
email: true,
|
||
|
username: true,
|
||
|
bio: true,
|
||
|
timeZone: true,
|
||
|
weekStart: true,
|
||
|
theme: true,
|
||
|
defaultScheduleId: true,
|
||
|
locale: true,
|
||
|
timeFormat: true,
|
||
|
brandColor: true,
|
||
|
darkBrandColor: true,
|
||
|
allowDynamicBooking: true,
|
||
|
away: true,
|
||
|
role: true,
|
||
|
// @note: disallowing avatar changes via API for now. We can add it later if needed. User should upload image via UI.
|
||
|
// avatar: true,
|
||
|
}).partial();
|
||
|
// @note: partial() is used to allow for the user to edit only the fields they want to edit making all optional,
|
||
|
// if want to make any required do it in the schemaRequiredParams
|
||
|
|
||
|
// Here we can both require or not (adding optional or nullish) and also rewrite validations for any value
|
||
|
// for example making weekStart only accept weekdays as input
|
||
|
const schemaUserEditParams = z.object({
|
||
|
email: z.string().email(),
|
||
|
username: usernameSchema,
|
||
|
weekStart: z.nativeEnum(weekdays).optional(),
|
||
|
brandColor: z.string().min(4).max(9).regex(/^#/).optional(),
|
||
|
darkBrandColor: z.string().min(4).max(9).regex(/^#/).optional(),
|
||
|
timeZone: timeZone.optional(),
|
||
|
theme: z.nativeEnum(theme).optional().nullable(),
|
||
|
timeFormat: z.nativeEnum(timeFormat).optional(),
|
||
|
defaultScheduleId: z
|
||
|
.number()
|
||
|
.refine((id: number) => id > 0)
|
||
|
.optional()
|
||
|
.nullable(),
|
||
|
locale: z.nativeEnum(locales).optional().nullable(),
|
||
|
});
|
||
|
|
||
|
// @note: These are the values that are editable via PATCH method on the user Model,
|
||
|
// merging both BaseBodyParams with RequiredParams, and omiting whatever we want at the end.
|
||
|
|
||
|
const schemaUserCreateParams = z.object({
|
||
|
email: z.string().email(),
|
||
|
username: usernameSchema,
|
||
|
weekStart: z.nativeEnum(weekdays).optional(),
|
||
|
brandColor: z.string().min(4).max(9).regex(/^#/).optional(),
|
||
|
darkBrandColor: z.string().min(4).max(9).regex(/^#/).optional(),
|
||
|
timeZone: timeZone.optional(),
|
||
|
theme: z.nativeEnum(theme).optional().nullable(),
|
||
|
timeFormat: z.nativeEnum(timeFormat).optional(),
|
||
|
defaultScheduleId: z
|
||
|
.number()
|
||
|
.refine((id: number) => id > 0)
|
||
|
.optional()
|
||
|
.nullable(),
|
||
|
locale: z.nativeEnum(locales).optional(),
|
||
|
createdDate: iso8601.optional(),
|
||
|
});
|
||
|
|
||
|
// @note: These are the values that are editable via PATCH method on the user Model,
|
||
|
// merging both BaseBodyParams with RequiredParams, and omiting whatever we want at the end.
|
||
|
export const schemaUserEditBodyParams = schemaUserBaseBodyParams
|
||
|
.merge(schemaUserEditParams)
|
||
|
.omit({})
|
||
|
.partial()
|
||
|
.strict();
|
||
|
|
||
|
export const schemaUserCreateBodyParams = schemaUserBaseBodyParams
|
||
|
.merge(schemaUserCreateParams)
|
||
|
.omit({})
|
||
|
.strict();
|
||
|
|
||
|
// @note: These are the values that are always returned when reading a user
|
||
|
export const schemaUserReadPublic = User.pick({
|
||
|
id: true,
|
||
|
username: true,
|
||
|
name: true,
|
||
|
email: true,
|
||
|
emailVerified: true,
|
||
|
bio: true,
|
||
|
avatar: true,
|
||
|
timeZone: true,
|
||
|
weekStart: true,
|
||
|
endTime: true,
|
||
|
bufferTime: true,
|
||
|
theme: true,
|
||
|
defaultScheduleId: true,
|
||
|
locale: true,
|
||
|
timeFormat: true,
|
||
|
brandColor: true,
|
||
|
darkBrandColor: true,
|
||
|
allowDynamicBooking: true,
|
||
|
away: true,
|
||
|
createdDate: true,
|
||
|
verified: true,
|
||
|
invitedTo: true,
|
||
|
role: true,
|
||
|
});
|
||
|
|
||
|
export const schemaUsersReadPublic = z.array(schemaUserReadPublic);
|