Files
calendar/apps/api/lib/validations/user.ts
T
MorganandGitHub 367c8a96d8 feat: Add user's avatar to POST and PATCH requests in users endpoints (#11187) (#12256)
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>

## What does this PR do?

<!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. -->

Fix wrong import introduced in this pr: #11187

<!-- Please provide a loom video for visual changes to speed up reviews
 Loom Video: https://www.loom.com/
-->

## Requirement/Documentation

<!-- Please provide all documents that are important to understand the reason of that PR. -->

- If there is a requirement document, please, share it here.
- If there is ab UI/UX design document, please, share it here.

## Type of change

<!-- Please delete bullets that are not relevant. -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Chore (refactoring code, technical debt, workflow improvements)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## How should this be tested?

<!-- Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. Write details that help to start the tests -->

- Are there environment variables that should be set?
- What are the minimal test data to have?
- What is expected (happy path) to have (input and output)?
- Any other important info that could help to test that PR

## Mandatory Tasks

- [ ] Make sure you have self-reviewed the code. A decent size PR without self-review might be rejected.

## Checklist

<!-- Remove bullet points below that don't apply to you -->

- I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code doesn't follow the style guidelines of this project
- I haven't commented my code, particularly in hard-to-understand areas
- I haven't checked if my PR needs changes to the documentation
- I haven't checked if my changes generate no new warnings
- I haven't added tests that prove my fix is effective or that my feature works
- I haven't checked if new and existing unit tests pass locally with my changes
2023-11-07 10:21:20 +00:00

178 lines
5.1 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 { isValidBase64Image } from "~/lib/utils/isValidBase64Image";
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", // Disabled until Crowdin reaches at least 80% completion
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,
hideBranding: 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(),
hideBranding: z.boolean().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(),
avatar: z.string().refine(isValidBase64Image).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.
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(),
hideBranding: z.boolean().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(),
avatar: z.string().refine(isValidBase64Image).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,
hideBranding: true,
brandColor: true,
darkBrandColor: true,
allowDynamicBooking: true,
away: true,
createdDate: true,
verified: true,
invitedTo: true,
role: true,
});
export const schemaUsersReadPublic = z.array(schemaUserReadPublic);