fix: don't use unpublished org for credit usage (#22154)

* only return publichsed orgs

* fix twilioWebhook tests

* code clean up

* add missing import

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
This commit is contained in:
Carina WollendorferandCarinaWolli authored and GitHub committed 2025-07-01 16:04:13 +00:00
1 parent 9405bc9553
commit 4963d247dc
3 files changed
+65 -39

No files matched your search

+2 -2
View File
@@ -3,7 +3,7 @@ import { z } from "zod";
import * as twilio from "@calcom/features/ee/workflows/lib/reminders/providers/twilioProvider";
import { IS_SMS_CREDITS_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
import { getPublishedOrgIdFromMemberOrTeamId } from "@calcom/lib/getOrgIdFromMemberOrTeamId";
import { defaultHandler } from "@calcom/lib/server/defaultHandler";
import prisma from "@calcom/prisma";
@@ -120,7 +120,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
if (!orgId) {
orgId = await getOrgIdFromMemberOrTeamId({
orgId = await getPublishedOrgIdFromMemberOrTeamId({
...(!parsedTeamId ? { memberId: parsedUserId } : {}),
teamId: parsedTeamId,
});
@@ -34,6 +34,11 @@ vi.mock("@calcom/prisma", () => ({
},
}));
vi.mock("@calcom/lib/getOrgIdFromMemberOrTeamId", () => ({
default: vi.fn().mockResolvedValue(null),
getPublishedOrgIdFromMemberOrTeamId: vi.fn().mockResolvedValue(null),
}));
describe("Twilio Webhook Handler", () => {
beforeEach(() => {
vi.clearAllMocks();
@@ -117,10 +122,6 @@ describe("Twilio Webhook Handler", () => {
mockFindFirst.mockResolvedValue(null);
const webhookHandler = (await import("../../../../../../apps/web/pages/api/twilio/webhook")).default;
vi.mock("@calcom/lib/getOrgIdFromMemberOrTeamId", () => ({
default: vi.fn().mockResolvedValue(null),
}));
const mockRequest = {
method: "POST",
headers: {
+58 -33
View File
@@ -1,45 +1,70 @@
import prisma from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
const getOrgMemberOrTeamWhere = (memberId?: number | null, teamId?: number | null) => {
const conditions: Prisma.TeamWhereInput[] = [];
if (memberId) {
conditions.push({
AND: [
{
members: {
some: {
userId: memberId,
accepted: true,
},
},
},
{
isOrganization: true,
},
],
});
}
if (teamId) {
conditions.push({
AND: [
{
children: {
some: {
id: teamId,
},
},
},
{
isOrganization: true,
},
],
});
}
return {
OR: conditions,
};
};
export default async function getOrgIdFromMemberOrTeamId(args: {
memberId?: number | null;
teamId?: number | null;
}) {
const userId = args.memberId ?? 0;
const teamId = args.teamId ?? 0;
const orgId = await prisma.team.findFirst({
where: getOrgMemberOrTeamWhere(args.memberId, args.teamId),
select: {
id: true,
},
});
return orgId?.id;
}
export async function getPublishedOrgIdFromMemberOrTeamId(args: {
memberId?: number | null;
teamId?: number | null;
}) {
const orgId = await prisma.team.findFirst({
where: {
OR: [
{
AND: [
{
members: {
some: {
userId,
accepted: true,
},
},
},
{
isOrganization: true,
},
],
},
{
AND: [
{
children: {
some: {
id: teamId,
},
},
},
{
isOrganization: true,
},
],
},
],
...getOrgMemberOrTeamWhere(args.memberId, args.teamId),
slug: { not: null },
},
select: {
id: true,