fix: use zod in getting started and settings (#7698)

* fix: use zod in getting started and settings

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore: change name of variable

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
This commit is contained in:
Udit Takkar 2023-03-21 16:13:07 +05:30 committed by GitHub
parent db947591ad
commit 7af23305eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 6 deletions

View File

@ -1,8 +1,11 @@
import { ArrowRightIcon } from "@heroicons/react/outline";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import dayjs from "@calcom/dayjs";
import { FULL_NAME_LENGTH_MAX_LIMIT } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { trpc } from "@calcom/trpc/react";
@ -22,23 +25,30 @@ const UserSettings = (props: IUserSettingsProps) => {
const { t } = useLocale();
const [selectedTimeZone, setSelectedTimeZone] = useState(dayjs.tz.guess());
const telemetry = useTelemetry();
const userSettingsSchema = z.object({
name: z
.string()
.min(1)
.max(FULL_NAME_LENGTH_MAX_LIMIT, {
message: t("max_limit_allowed_hint", { limit: FULL_NAME_LENGTH_MAX_LIMIT }),
}),
});
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
} = useForm<z.infer<typeof userSettingsSchema>>({
defaultValues: {
name: user?.name || "",
},
reValidateMode: "onChange",
resolver: zodResolver(userSettingsSchema),
});
useEffect(() => {
telemetry.event(telemetryEventTypes.onboardingStarted);
}, [telemetry]);
const defaultOptions = { required: true, maxLength: 255 };
const utils = trpc.useContext();
const onSuccess = async () => {
await utils.viewer.me.invalidate();
@ -67,7 +77,9 @@ const UserSettings = (props: IUserSettingsProps) => {
{t("full_name")}
</label>
<input
{...register("name", defaultOptions)}
{...register("name", {
required: true,
})}
id="name"
name="name"
type="text"
@ -77,7 +89,7 @@ const UserSettings = (props: IUserSettingsProps) => {
/>
{errors.name && (
<p data-testid="required" className="py-2 text-xs text-red-500">
{t("required")}
{errors.name.message}
</p>
)}
</div>

View File

@ -1,12 +1,15 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { IdentityProvider } from "@prisma/client";
import crypto from "crypto";
import { signOut } from "next-auth/react";
import type { BaseSyntheticEvent } from "react";
import { useRef, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout";
import { FULL_NAME_LENGTH_MAX_LIMIT } from "@calcom/lib/constants";
import { APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { md } from "@calcom/lib/markdownIt";
@ -315,6 +318,20 @@ const ProfileForm = ({
extraField?: React.ReactNode;
}) => {
const { t } = useLocale();
const profileFormSchema = z.object({
username: z.string(),
avatar: z.string(),
name: z
.string()
.min(1)
.max(FULL_NAME_LENGTH_MAX_LIMIT, {
message: t("max_limit_allowed_hint", { limit: FULL_NAME_LENGTH_MAX_LIMIT }),
}),
email: z.string().email(),
bio: z.string(),
});
const emailMd5 = crypto
.createHash("md5")
.update(defaultValues.email || "example@example.com")
@ -322,6 +339,7 @@ const ProfileForm = ({
const formMethods = useForm<FormValues>({
defaultValues,
resolver: zodResolver(profileFormSchema),
});
const {

View File

@ -432,6 +432,7 @@
"password_hint_min": "Minimum 7 characters long",
"password_hint_admin_min": "Minimum 15 characters long",
"password_hint_num": "Contain at least 1 number",
"max_limit_allowed_hint":"Must be {{limit}} or fewer characters long",
"invalid_password_hint": "The password must be a minimum of {{passwordLength}} characters long containing at least one number and have a mixture of uppercase and lowercase letters",
"incorrect_password": "Password is incorrect.",
"incorrect_username_password": "Username or password is incorrect.",

View File

@ -62,3 +62,4 @@ export const IS_STRIPE_ENABLED = !!(
);
/** Self hosted shouldn't checkout when creating teams unless required */
export const IS_TEAM_BILLING_ENABLED = IS_STRIPE_ENABLED && (!IS_SELF_HOSTED || HOSTED_CAL_FEATURES);
export const FULL_NAME_LENGTH_MAX_LIMIT = 50;

View File

@ -26,6 +26,7 @@ import { samlTenantProduct } from "@calcom/features/ee/sso/lib/saml";
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
import getEnabledApps from "@calcom/lib/apps/getEnabledApps";
import { IS_SELF_HOSTED, WEBAPP_URL } from "@calcom/lib/constants";
import { FULL_NAME_LENGTH_MAX_LIMIT } from "@calcom/lib/constants";
import { symmetricDecrypt } from "@calcom/lib/crypto";
import getPaymentAppData from "@calcom/lib/getPaymentAppData";
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
@ -595,7 +596,7 @@ const loggedInViewerRouter = router({
.input(
z.object({
username: z.string().optional(),
name: z.string().optional(),
name: z.string().max(FULL_NAME_LENGTH_MAX_LIMIT).optional(),
email: z.string().optional(),
bio: z.string().optional(),
avatar: z.string().optional(),