chore: improve invitation form validation (#12594)

* chore: improve invitation form validation

* fixup! chore: improve invitation form validation

* fixup! fixup! chore: improve invitation form validation
This commit is contained in:
Morgan
2023-11-29 12:44:48 -07:00
committed by GitHub
parent d0f7085cb8
commit a65e18d92d
4 changed files with 26 additions and 6 deletions
@@ -1552,6 +1552,9 @@
"member_already_invited": "Member has already been invited",
"already_in_use_error": "Username already in use",
"enter_email_or_username": "Enter an email or username",
"enter_email": "Enter an email",
"enter_emails": "Enter emails",
"too_many_invites": "You are limited to inviting a maximum of {{nbUsers}} users at once.",
"team_name_taken": "This name is already taken",
"must_enter_team_name": "Must enter a team name",
"team_url_required": "Must enter a team URL",
@@ -6,11 +6,12 @@ import { Controller, useForm } from "react-hook-form";
import TeamInviteFromOrg from "@calcom/ee/organizations/components/TeamInviteFromOrg";
import { classNames } from "@calcom/lib";
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
import { IS_TEAM_BILLING_ENABLED, MAX_NB_INVITES } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
import type { RouterOutputs } from "@calcom/trpc";
import { trpc } from "@calcom/trpc";
import { isEmail } from "@calcom/trpc/server/routers/viewer/teams/util";
import {
Button,
Dialog,
@@ -199,7 +200,10 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
</Label>
<ToggleGroup
isFullWidth={true}
onValueChange={(val) => setModalInputMode(val as ModalMode)}
onValueChange={(val) => {
setModalInputMode(val as ModalMode);
newMemberFormMethods.clearErrors();
}}
defaultValue={modalImportMode}
options={toggleGroupOptions}
/>
@@ -213,8 +217,10 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
name="emailOrUsername"
control={newMemberFormMethods.control}
rules={{
required: t("enter_email_or_username"),
required: isOrg ? t("enter_email") : t("enter_email_or_username"),
validate: (value) => {
// orgs can only invite members by email
if (typeof value === "string" && isOrg && !isEmail(value)) return t("enter_email");
if (typeof value === "string")
return validateUniqueInvite(value) || t("member_already_invited");
},
@@ -241,7 +247,14 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
name="emailOrUsername"
control={newMemberFormMethods.control}
rules={{
required: t("enter_email_or_username"),
required: t("enter_email"),
validate: (value) => {
if (Array.isArray(value) && value.some((email) => !isEmail(email)))
return t("enter_emails");
if (Array.isArray(value) && value.length > MAX_NB_INVITES)
return t("too_many_invites", { nbUsers: MAX_NB_INVITES });
if (typeof value === "string" && !isEmail(value)) return t("enter_email");
},
}}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<>
+3
View File
@@ -119,3 +119,6 @@ export const AB_TEST_BUCKET_PROBABILITY = defaultOnNaN(
export const IS_PREMIUM_USERNAME_ENABLED =
(IS_CALCOM || (process.env.NEXT_PUBLIC_IS_E2E && IS_STRIPE_ENABLED)) &&
process.env.NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY;
// Max number of invites to join a team/org that can be sent at once
export const MAX_NB_INVITES = 100;
@@ -1,5 +1,6 @@
import { z } from "zod";
import { MAX_NB_INVITES } from "@calcom/lib/constants";
import { MembershipRole } from "@calcom/prisma/enums";
export const ZInviteMemberInputSchema = z.object({
@@ -15,13 +16,13 @@ export const ZInviteMemberInputSchema = z.object({
.refine(
(value) => {
if (Array.isArray(value)) {
if (value.length > 100) {
if (value.length > MAX_NB_INVITES) {
return false;
}
}
return true;
},
{ message: "You are limited to inviting a maximum of 100 users at once." }
{ message: `You are limited to inviting a maximum of ${MAX_NB_INVITES} users at once.` }
)
.refine(
(value) => {