diff --git a/apps/web/pages/signup.tsx b/apps/web/pages/signup.tsx index 9ff81360cc..08d117f6b7 100644 --- a/apps/web/pages/signup.tsx +++ b/apps/web/pages/signup.tsx @@ -6,7 +6,6 @@ import type { SubmitHandler } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form"; import { z } from "zod"; -import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired"; import { checkPremiumUsername } from "@calcom/features/ee/common/lib/checkPremiumUsername"; import { getOrgFullDomain } from "@calcom/features/ee/organizations/lib/orgDomains"; import { isSAMLLoginEnabled } from "@calcom/features/ee/sso/lib/saml"; @@ -83,7 +82,7 @@ export default function Signup({ prepopulateFormValues, token, orgSlug }: Signup }; return ( - + <>
-
+ ); } diff --git a/packages/lib/server/queries/teams/index.ts b/packages/lib/server/queries/teams/index.ts index d5385170e1..0ce3a231ae 100644 --- a/packages/lib/server/queries/teams/index.ts +++ b/packages/lib/server/queries/teams/index.ts @@ -79,11 +79,12 @@ export async function getTeamWithMembers(id?: number, slug?: string, userId?: nu ...baseEventTypeSelect, }, }, - inviteToken: { + inviteTokens: { select: { token: true, expires: true, expiresInDays: true, + identifier: true, }, }, }); @@ -114,7 +115,16 @@ export async function getTeamWithMembers(id?: number, slug?: string, userId?: nu ...eventType, metadata: EventTypeMetaDataSchema.parse(eventType.metadata), })); - return { ...team, metadata: teamMetadataSchema.parse(team.metadata), eventTypes, members }; + /** Don't leak invite tokens to the frontend */ + const { inviteTokens, ...teamWithoutInviteTokens } = team; + return { + ...teamWithoutInviteTokens, + /** To prevent breaking we only return non-email attached token here, if we have one */ + inviteToken: inviteTokens.find((token) => token.identifier === "invite-link-for-teamId-" + team.id), + metadata: teamMetadataSchema.parse(team.metadata), + eventTypes, + members, + }; } // also returns team diff --git a/packages/prisma/migrations/20230712192734_fixes_team_verification_tokens/migration.sql b/packages/prisma/migrations/20230712192734_fixes_team_verification_tokens/migration.sql new file mode 100644 index 0000000000..1c80622085 --- /dev/null +++ b/packages/prisma/migrations/20230712192734_fixes_team_verification_tokens/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "VerificationToken_teamId_key"; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index f78010425e..854d2b52fd 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -270,7 +270,7 @@ model Team { parent Team? @relation("organization", fields: [parentId], references: [id], onDelete: Cascade) children Team[] @relation("organization") orgUsers User[] @relation("scope") - inviteToken VerificationToken? + inviteTokens VerificationToken[] webhooks Webhook[] timeFormat Int? timeZone String @default("Europe/London") @@ -310,7 +310,7 @@ model VerificationToken { expiresInDays Int? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - teamId Int? @unique + teamId Int? team Team? @relation(fields: [teamId], references: [id]) @@unique([identifier, token]) diff --git a/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts b/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts index f760dbf257..18f391134f 100644 --- a/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts @@ -22,7 +22,7 @@ export const createInviteHandler = async ({ ctx, input }: CreateInviteOptions) = const token = randomBytes(32).toString("hex"); await prisma.verificationToken.create({ data: { - identifier: "", + identifier: "invite-link-for-teamId-" + teamId, token, expires: new Date(), teamId, diff --git a/packages/trpc/server/routers/viewer/teams/list.handler.ts b/packages/trpc/server/routers/viewer/teams/list.handler.ts index 1a2710f421..e5cfa15f27 100644 --- a/packages/trpc/server/routers/viewer/teams/list.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/list.handler.ts @@ -26,20 +26,22 @@ export const listHandler = async ({ ctx }: ListOptions) => { include: { team: { include: { - inviteToken: true, + inviteTokens: true, }, }, }, orderBy: { role: "desc" }, }); - const isOrgAdmin = !!(await isOrganisationAdmin(ctx.user.id, ctx.user?.organization?.id ?? -1)); // Org id exists here as we're inside a conditional TS complaining for some reason + const isOrgAdmin = !!(await isOrganisationAdmin(ctx.user.id, ctx.user.organization.id)); // Org id exists here as we're inside a conditional TS complaining for some reason - return membershipsWithoutParent.map(({ team, ...membership }) => ({ + return membershipsWithoutParent.map(({ team: { inviteTokens, ..._team }, ...membership }) => ({ role: membership.role, accepted: membership.accepted, isOrgAdmin, - ...team, + ..._team, + /** To prevent breaking we only return non-email attached token here, if we have one */ + inviteToken: inviteTokens.find((token) => token.identifier === "invite-link-for-teamId-" + _team.id), })); } @@ -50,7 +52,7 @@ export const listHandler = async ({ ctx }: ListOptions) => { include: { team: { include: { - inviteToken: true, + inviteTokens: true, }, }, }, @@ -62,9 +64,11 @@ export const listHandler = async ({ ctx }: ListOptions) => { const metadata = teamMetadataSchema.parse(mmship.team.metadata); return !metadata?.isOrganization; }) - .map(({ team, ...membership }) => ({ + .map(({ team: { inviteTokens, ..._team }, ...membership }) => ({ role: membership.role, accepted: membership.accepted, - ...team, + ..._team, + /** To prevent breaking we only return non-email attached token here, if we have one */ + inviteToken: inviteTokens.find((token) => token.identifier === "invite-link-for-teamId-" + _team.id), })); };