Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/api/v2/src/modules/teams/teams/teams.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { Injectable, NotFoundException } from "@nestjs/common";

import { teamMetadataSchema } from "@calcom/platform-libraries";
import { teamMetadataStrictSchema } from "@calcom/platform-libraries";
import { Prisma } from "@calcom/prisma/client";

@Injectable()
Expand Down Expand Up @@ -87,7 +87,7 @@ export class TeamsRepository {

async setDefaultConferencingApp(teamId: number, appSlug?: string, appLink?: string) {
const team = await this.getById(teamId);
const teamMetadata = teamMetadataSchema.parse(team?.metadata);
const teamMetadata = teamMetadataStrictSchema.parse(team?.metadata);

if (!team) {
throw new NotFoundException("user not found");
Expand Down
6 changes: 3 additions & 3 deletions apps/web/app/api/teams/[team]/upgrade/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import stripe from "@calcom/features/ee/payments/server/stripe";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { HttpError } from "@calcom/lib/http-error";
import prisma from "@calcom/prisma";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import { buildLegacyRequest } from "@lib/buildLegacyCtx";

Expand Down Expand Up @@ -50,7 +50,7 @@ async function getHandler(req: NextRequest, { params }: { params: Promise<Params
if (!team) {
const prevTeam = await prisma.team.findFirstOrThrow({ where: { id } });

metadata = teamMetadataSchema.safeParse(prevTeam.metadata);
metadata = teamMetadataStrictSchema.safeParse(prevTeam.metadata);
if (!metadata.success) {
throw new HttpError({ statusCode: 400, message: "Invalid team metadata" });
}
Expand Down Expand Up @@ -80,7 +80,7 @@ async function getHandler(req: NextRequest, { params }: { params: Promise<Params
}

if (!metadata) {
metadata = teamMetadataSchema.safeParse(team.metadata);
metadata = teamMetadataStrictSchema.safeParse(team.metadata);
if (!metadata.success) {
throw new HttpError({ statusCode: 400, message: "Invalid team metadata" });
}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/playwright/lib/orgMigration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { Team, User } from "@calcom/prisma/client";
import { RedirectType } from "@calcom/prisma/client";
import { Prisma } from "@calcom/prisma/client";
import type { MembershipRole } from "@calcom/prisma/enums";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataSchema, teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

const log = logger.getSubLogger({ prefix: ["orgMigration"] });

Expand Down Expand Up @@ -588,7 +588,7 @@ async function dbRemoveTeamFromOrg({ teamId }: { teamId: number }) {
});
}

const teamMetadata = teamMetadataSchema.parse(team?.metadata);
const teamMetadata = teamMetadataStrictSchema.parse(team?.metadata);
try {
return await prisma.team.update({
where: {
Expand Down
4 changes: 2 additions & 2 deletions packages/features/ee/billing/teams/internal-team-billing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import { Redirect } from "@calcom/lib/redirect";
import { safeStringify } from "@calcom/lib/safeStringify";
import { OrganizationOnboardingRepository } from "@calcom/lib/server/repository/organizationOnboarding";
import prisma from "@calcom/prisma";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import billing from "..";
import { TeamBillingPublishResponseStatus, type TeamBilling, type TeamBillingInput } from "./team-billing";

const log = logger.getSubLogger({ prefix: ["TeamBilling"] });

const teamPaymentMetadataSchema = teamMetadataSchema.unwrap();
const teamPaymentMetadataSchema = teamMetadataStrictSchema.unwrap();

export class InternalTeamBilling implements TeamBilling {
private _team!: Omit<TeamBillingInput, "metadata"> & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
orgOnboardingInvitedMembersSchema,
orgOnboardingTeamsSchema,
} from "@calcom/prisma/zod-utils";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";
import { createTeamsHandler } from "@calcom/trpc/server/routers/viewer/organizations/createTeams.handler";
import { inviteMembersWithNoInviterPermissionCheck } from "@calcom/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler";

Expand Down Expand Up @@ -344,7 +344,7 @@ async function backwardCompatibilityForSubscriptionDetails({
return organization;
}

const existingMetadata = teamMetadataSchema.parse(organization.metadata);
const existingMetadata = teamMetadataStrictSchema.parse(organization.metadata);
const updatedOrganization = await OrganizationRepository.updateStripeSubscriptionDetails({
id: organization.id,
stripeSubscriptionId: paymentSubscriptionId,
Expand Down
3 changes: 2 additions & 1 deletion packages/lib/server/repository/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { safeStringify } from "@calcom/lib/safeStringify";
import { prisma } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import type { CreationSource } from "@calcom/prisma/enums";
import type { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";

import { createAProfileForAnExistingUser } from "../../createAProfileForAnExistingUser";
Expand Down Expand Up @@ -448,7 +449,7 @@ export class OrganizationRepository {
id: number;
stripeSubscriptionId: string;
stripeSubscriptionItemId: string;
existingMetadata: z.infer<typeof teamMetadataSchema>;
existingMetadata: z.infer<typeof teamMetadataStrictSchema>;
}) {
return await prisma.team.update({
where: { id, isOrganization: true },
Expand Down
51 changes: 34 additions & 17 deletions packages/prisma/zod-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,24 +372,41 @@ export enum BillingPeriod {
ANNUALLY = "ANNUALLY",
}

export const teamMetadataSchema = z
.object({
defaultConferencingApp: schemaDefaultConferencingApp.optional(),
requestedSlug: z.string().or(z.null()),
paymentId: z.string(),
subscriptionId: z.string().nullable(),
subscriptionItemId: z.string().nullable(),
orgSeats: z.number().nullable(),
orgPricePerSeat: z.number().nullable(),
migratedToOrgFrom: z
.object({
teamSlug: z.string().or(z.null()).optional(),
lastMigrationTime: z.string().optional(),
reverted: z.boolean().optional(),
lastRevertTime: z.string().optional(),
const baseTeamMetadataSchema = z.object({
defaultConferencingApp: schemaDefaultConferencingApp.optional(),
requestedSlug: z.string().or(z.null()),
paymentId: z.string(),
subscriptionId: z.string().nullable(),
subscriptionItemId: z.string().nullable(),
orgSeats: z.number().nullable(),
orgPricePerSeat: z.number().nullable(),
migratedToOrgFrom: z
.object({
teamSlug: z.string().or(z.null()).optional(),
lastMigrationTime: z.string().optional(),
reverted: z.boolean().optional(),
lastRevertTime: z.string().optional(),
})
.optional(),
billingPeriod: z.nativeEnum(BillingPeriod).optional(),
});

export const teamMetadataSchema = baseTeamMetadataSchema.partial().nullable();

export const teamMetadataStrictSchema = baseTeamMetadataSchema
.extend({
subscriptionId: z
.string()
.refine((val) => val.startsWith("sub_"), {
message: "subscriptionId must start with 'sub_'",
})
.optional(),
billingPeriod: z.nativeEnum(BillingPeriod).optional(),
.nullable(),
subscriptionItemId: z
.string()
.refine((val) => val.startsWith("si_"), {
message: "subscriptionItemId must start with 'si_'",
})
.nullable(),
})
.partial()
.nullable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { renameDomain } from "@calcom/lib/domainManager/organization";
import { getMetadataHelpers } from "@calcom/lib/getMetadataHelpers";
import { HttpError } from "@calcom/lib/http-error";
import { prisma } from "@calcom/prisma";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import type { TrpcSessionUser } from "../../../types";
import type { TAdminUpdate } from "./adminUpdate.schema";
Expand Down Expand Up @@ -34,7 +34,7 @@ export const adminUpdateHandler = async ({ input }: AdminUpdateOptions) => {
});
}

const { mergeMetadata } = getMetadataHelpers(teamMetadataSchema.unwrap(), existingOrg.metadata || {});
const { mergeMetadata } = getMetadataHelpers(teamMetadataStrictSchema.unwrap(), existingOrg.metadata || {});

const data: Prisma.TeamUpdateArgs["data"] = restInput;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import slugify from "@calcom/lib/slugify";
import { prisma } from "@calcom/prisma";
import type { CreationSource } from "@calcom/prisma/enums";
import { MembershipRole, RedirectType } from "@calcom/prisma/enums";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataSchema, teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import { TRPCError } from "@trpc/server";

Expand Down Expand Up @@ -295,7 +295,7 @@ async function tryToCancelSubscription(subscriptionId: string) {
}

function getSubscriptionId(metadata: Prisma.JsonValue) {
const parsedMetadata = teamMetadataSchema.safeParse(metadata);
const parsedMetadata = teamMetadataStrictSchema.safeParse(metadata);
if (parsedMetadata.success) {
const subscriptionId = parsedMetadata.data?.subscriptionId;
if (!subscriptionId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { purchaseTeamOrOrgSubscription } from "@calcom/features/ee/teams/lib/pay
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
import { isOrganisationAdmin } from "@calcom/lib/server/queries/organisations";
import { prisma } from "@calcom/prisma";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import { TRPCError } from "@trpc/server";

Expand Down Expand Up @@ -31,7 +31,7 @@ export const publishHandler = async ({ ctx }: PublishOptions) => {

if (!prevTeam) throw new TRPCError({ code: "NOT_FOUND", message: "Organization not found." });

const metadata = teamMetadataSchema.safeParse(prevTeam.metadata);
const metadata = teamMetadataStrictSchema.safeParse(prevTeam.metadata);
if (!metadata.success) throw new TRPCError({ code: "BAD_REQUEST", message: "Invalid team metadata" });

// Since this is an ORG we need to make sure ORG members are scyned with the team. Every time a user is added to the TEAM, we need to add them to the ORG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image";
import type { PrismaClient } from "@calcom/prisma";
import { prisma } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import { TRPCError } from "@trpc/server";

Expand Down Expand Up @@ -165,7 +165,10 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {

if (!prevOrganisation) throw new TRPCError({ code: "NOT_FOUND", message: "Organisation not found." });

const { mergeMetadata } = getMetadataHelpers(teamMetadataSchema.unwrap(), prevOrganisation.metadata ?? {});
const { mergeMetadata } = getMetadataHelpers(
teamMetadataStrictSchema.unwrap(),
prevOrganisation.metadata ?? {}
);

const data: Prisma.TeamUpdateArgs["data"] = {
logoUrl: input.logoUrl,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from "zod";

import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

export const ZUpdateInputSchema = z.object({
name: z.string().optional(),
Expand All @@ -28,7 +28,7 @@ export const ZUpdateInputSchema = z.object({
timeZone: timeZoneSchema.optional(),
weekStart: z.string().optional(),
timeFormat: z.number().optional(),
metadata: teamMetadataSchema.unwrap().optional(),
metadata: teamMetadataStrictSchema.unwrap().optional(),
lockEventTypeCreation: z.boolean().optional(),
lockEventTypeCreationOptions: z.enum(["DELETE", "HIDE"]).optional(),
adminGetsNoSlotsNotification: z.boolean().optional(),
Expand Down
4 changes: 2 additions & 2 deletions packages/trpc/server/routers/viewer/teams/update.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { uploadLogo } from "@calcom/lib/server/avatar";
import { isTeamAdmin } from "@calcom/lib/server/queries/teams";
import { prisma } from "@calcom/prisma";
import { RedirectType, RRTimestampBasis } from "@calcom/prisma/enums";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { teamMetadataStrictSchema } from "@calcom/prisma/zod-utils";

import { TRPCError } from "@trpc/server";

Expand Down Expand Up @@ -95,7 +95,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
data.slug = input.slug;

// If we save slug, we don't need the requestedSlug anymore
const metadataParse = teamMetadataSchema.safeParse(prevTeam.metadata);
const metadataParse = teamMetadataStrictSchema.safeParse(prevTeam.metadata);
if (metadataParse.success) {
const { requestedSlug: _, ...cleanMetadata } = metadataParse.data || {};
data.metadata = {
Expand Down
Loading