feat: org-wide webhooks (#15144)
* feat: include org in teams list * feat: org-wide webhooks * Move getOrgIdFromMemberOrTeamId to packages/lib
This commit is contained in:
@@ -7,6 +7,7 @@ import { getDownloadLinkOfCalVideoByRecordingId } from "@calcom/core/videoClient
|
||||
import { sendDailyVideoRecordingEmails } from "@calcom/emails";
|
||||
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
@@ -60,11 +61,16 @@ const triggerWebhook = async ({
|
||||
// Send Webhook call if hooked to BOOKING.RECORDING_READY
|
||||
const triggerForUser = !booking.teamId || (booking.teamId && booking.eventTypeParentId);
|
||||
|
||||
const organizerUserId = triggerForUser ? booking.userId : null;
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: organizerUserId, teamId: booking.teamId });
|
||||
|
||||
const subscriberOptions = {
|
||||
userId: triggerForUser ? booking.userId : null,
|
||||
userId: organizerUserId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: eventTrigger,
|
||||
teamId: booking.teamId,
|
||||
orgId,
|
||||
};
|
||||
const webhooks = await getWebhooks(subscriberOptions);
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import WeebhooksView from "@calcom/features/webhooks/pages/webhooks-view";
|
||||
import WebhooksView from "@calcom/features/webhooks/pages/webhooks-view";
|
||||
|
||||
import type { CalPageWrapper } from "@components/PageWrapper";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const Page = WeebhooksView as CalPageWrapper;
|
||||
const Page = WebhooksView as CalPageWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import WeebhookNewView from "@calcom/features/webhooks/pages/webhook-new-view";
|
||||
import WebhookNewView from "@calcom/features/webhooks/pages/webhook-new-view";
|
||||
|
||||
import type { CalPageWrapper } from "@components/PageWrapper";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const Page = WeebhookNewView as CalPageWrapper;
|
||||
const Page = WebhookNewView as CalPageWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { App_RoutingForms_Form, User } from "@prisma/client";
|
||||
|
||||
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { WebhookTriggerEvents } from "@calcom/prisma/client";
|
||||
import type { Ensure } from "@calcom/types/utils";
|
||||
@@ -33,9 +34,15 @@ export async function onFormSubmission(
|
||||
};
|
||||
}
|
||||
|
||||
const { userId, teamId } = getWebhookTargetEntity(form);
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
|
||||
|
||||
const subscriberOptions = {
|
||||
userId,
|
||||
teamId,
|
||||
orgId,
|
||||
triggerEvent: WebhookTriggerEvents.FORM_SUBMITTED,
|
||||
...getWebhookTargetEntity(form),
|
||||
};
|
||||
|
||||
const webhooks = await getWebhooks(subscriberOptions);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { sendAttendeeRequestEmail, sendOrganizerRequestEmail } from "@calcom/ema
|
||||
import { getWebhookPayloadForBooking } from "@calcom/features/bookings/lib/getWebhookPayloadForBooking";
|
||||
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
@@ -39,12 +40,18 @@ export async function handleBookingRequested(args: {
|
||||
await sendOrganizerRequestEmail({ ...evt });
|
||||
await sendAttendeeRequestEmail({ ...evt }, evt.attendees[0]);
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({
|
||||
memberId: booking.userId,
|
||||
teamId: booking.eventType?.teamId,
|
||||
});
|
||||
|
||||
try {
|
||||
const subscribersBookingRequested = await getWebhooks({
|
||||
userId: booking.userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_REQUESTED,
|
||||
teamId: booking.eventType?.teamId,
|
||||
orgId,
|
||||
});
|
||||
|
||||
const webhookPayload = getWebhookPayloadForBooking({
|
||||
|
||||
@@ -16,6 +16,7 @@ import { deleteWebhookScheduledTriggers } from "@calcom/features/webhooks/lib/sc
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import type { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import logger from "@calcom/lib/logger";
|
||||
@@ -183,12 +184,16 @@ async function handler(req: CustomRequest) {
|
||||
},
|
||||
});
|
||||
const triggerForUser = !teamId || (teamId && bookingToDelete.eventType?.parentId);
|
||||
const organizerUserId = triggerForUser ? bookingToDelete.userId : null;
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: organizerUserId, teamId });
|
||||
|
||||
const subscriberOptions = {
|
||||
userId: triggerForUser ? bookingToDelete.userId : null,
|
||||
userId: organizerUserId,
|
||||
eventTypeId: bookingToDelete.eventTypeId as number,
|
||||
triggerEvent: eventTrigger,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
const eventTypeInfo: EventTypeInfo = {
|
||||
eventTitle: bookingToDelete?.eventType?.title || null,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { scheduleTrigger } from "@calcom/features/webhooks/lib/scheduleTrigger";
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import type { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
@@ -302,23 +303,30 @@ export async function handleConfirmation(args: {
|
||||
|
||||
const triggerForUser = !teamId || (teamId && booking.eventType?.parentId);
|
||||
|
||||
const userId = triggerForUser ? booking.userId : null;
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
|
||||
|
||||
const subscribersBookingCreated = await getWebhooks({
|
||||
userId: triggerForUser ? booking.userId : null,
|
||||
userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_CREATED,
|
||||
teamId,
|
||||
orgId,
|
||||
});
|
||||
const subscribersMeetingStarted = await getWebhooks({
|
||||
userId: triggerForUser ? booking.userId : null,
|
||||
userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.MEETING_STARTED,
|
||||
teamId: booking.eventType?.teamId,
|
||||
orgId,
|
||||
});
|
||||
const subscribersMeetingEnded = await getWebhooks({
|
||||
userId: triggerForUser ? booking.userId : null,
|
||||
userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.MEETING_ENDED,
|
||||
teamId: booking.eventType?.teamId,
|
||||
orgId,
|
||||
});
|
||||
|
||||
const scheduleTriggerPromises: Promise<unknown>[] = [];
|
||||
@@ -381,10 +389,11 @@ export async function handleConfirmation(args: {
|
||||
if (paid) {
|
||||
let paymentExternalId: string | undefined;
|
||||
const subscriberMeetingPaid = await getWebhooks({
|
||||
userId: triggerForUser ? booking.userId : null,
|
||||
userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_PAID,
|
||||
teamId: booking.eventType?.teamId,
|
||||
orgId,
|
||||
});
|
||||
const bookingWithPayment = await prisma.booking.findFirst({
|
||||
where: {
|
||||
|
||||
@@ -70,6 +70,7 @@ import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { extractBaseEmail } from "@calcom/lib/extract-base-email";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import getPaymentAppData from "@calcom/lib/getPaymentAppData";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
@@ -1663,11 +1664,16 @@ async function handler(
|
||||
|
||||
const triggerForUser = !teamId || (teamId && eventType.parentId);
|
||||
|
||||
const organizerUserId = triggerForUser ? organizerUser.id : null;
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: organizerUserId, teamId });
|
||||
|
||||
const subscriberOptions: GetSubscriberOptions = {
|
||||
userId: triggerForUser ? organizerUser.id : null,
|
||||
userId: organizerUserId,
|
||||
eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_CREATED,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
|
||||
const eventTrigger: WebhookTriggerEvents = rescheduleUid
|
||||
@@ -1681,6 +1687,7 @@ async function handler(
|
||||
eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.MEETING_ENDED,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
|
||||
const subscriberOptionsMeetingStarted = {
|
||||
@@ -1688,6 +1695,7 @@ async function handler(
|
||||
eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.MEETING_STARTED,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
|
||||
// For seats, if the booking already exists then we want to add the new attendee to the existing booking
|
||||
@@ -2335,6 +2343,7 @@ async function handler(
|
||||
eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_PAYMENT_INITIATED,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
await handleWebhookTrigger({
|
||||
subscriberOptions: subscriberOptionsPaymentInitiated,
|
||||
|
||||
@@ -17,6 +17,7 @@ import { getFullName } from "@calcom/features/form-builder/utils";
|
||||
import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { isPrismaObjOrUndefined } from "@calcom/lib";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { getTranslation } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -25,18 +26,32 @@ import { BookingStatus, WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
const handleInstantMeetingWebhookTrigger = async (args: {
|
||||
eventTypeId: number;
|
||||
webhookData: Record<string, unknown>;
|
||||
teamId: number;
|
||||
}) => {
|
||||
const orgId = (await getOrgIdFromMemberOrTeamId({ teamId: args.teamId })) ?? 0;
|
||||
|
||||
try {
|
||||
const eventTrigger = WebhookTriggerEvents.INSTANT_MEETING;
|
||||
|
||||
const subscribers = await prisma.webhook.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
teamId: {
|
||||
in: [orgId, args.teamId],
|
||||
},
|
||||
},
|
||||
{
|
||||
eventTypeId: args.eventTypeId,
|
||||
},
|
||||
],
|
||||
AND: {
|
||||
eventTypeId: args.eventTypeId,
|
||||
eventTriggers: {
|
||||
has: eventTrigger,
|
||||
},
|
||||
active: true,
|
||||
active: {
|
||||
equals: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
@@ -213,6 +228,7 @@ async function handler(req: NextApiRequest) {
|
||||
await handleInstantMeetingWebhookTrigger({
|
||||
eventTypeId: eventType.id,
|
||||
webhookData,
|
||||
teamId: eventType.team?.id,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -7,12 +7,15 @@ export type GetSubscriberOptions = {
|
||||
eventTypeId?: number | null;
|
||||
triggerEvent: WebhookTriggerEvents;
|
||||
teamId?: number | null;
|
||||
orgId?: number | null;
|
||||
};
|
||||
|
||||
const getWebhooks = async (options: GetSubscriberOptions, prisma: PrismaClient = defaultPrisma) => {
|
||||
const userId = options.userId ?? 0;
|
||||
const eventTypeId = options.eventTypeId ?? 0;
|
||||
const teamId = options.teamId ?? 0;
|
||||
const orgId = options.orgId ?? 0;
|
||||
|
||||
// if we have userId and teamId it is a managed event type and should trigger for team and user
|
||||
const allWebhooks = await prisma.webhook.findMany({
|
||||
where: {
|
||||
@@ -27,7 +30,9 @@ const getWebhooks = async (options: GetSubscriberOptions, prisma: PrismaClient =
|
||||
eventTypeId,
|
||||
},
|
||||
{
|
||||
teamId,
|
||||
teamId: {
|
||||
in: [teamId, orgId],
|
||||
},
|
||||
},
|
||||
],
|
||||
AND: {
|
||||
|
||||
@@ -355,18 +355,72 @@ export async function updateTriggerForExistingBookings(
|
||||
|
||||
if (Array.isArray(where.AND)) {
|
||||
if (webhook.teamId) {
|
||||
const teamEvents = await prisma.eventType.findMany({
|
||||
const org = await prisma.team.findFirst({
|
||||
where: {
|
||||
teamId: webhook.teamId,
|
||||
id: webhook.teamId,
|
||||
isOrganization: true,
|
||||
},
|
||||
select: {
|
||||
bookings: {
|
||||
where,
|
||||
id: true,
|
||||
children: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
members: {
|
||||
select: {
|
||||
userId: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
// checking if teamId is an org id
|
||||
if (org) {
|
||||
const teamEvents = await prisma.eventType.findMany({
|
||||
where: {
|
||||
teamId: {
|
||||
in: org.children.map((team) => team.id),
|
||||
},
|
||||
},
|
||||
select: {
|
||||
bookings: {
|
||||
where,
|
||||
},
|
||||
},
|
||||
});
|
||||
const teamEventBookings = teamEvents.flatMap((event) => event.bookings);
|
||||
const teamBookingsId = teamEventBookings.map((booking) => booking.id);
|
||||
const orgMemberIds = org.members.map((member) => member.userId);
|
||||
where.AND.push({
|
||||
userId: {
|
||||
in: orgMemberIds,
|
||||
},
|
||||
});
|
||||
// don't want to get the team bookings again
|
||||
where.AND.push({
|
||||
id: {
|
||||
notIn: teamBookingsId,
|
||||
},
|
||||
});
|
||||
const userBookings = await prisma.booking.findMany({
|
||||
where,
|
||||
});
|
||||
// add teams bookings and users bookings to get total org bookings
|
||||
bookings = teamEventBookings.concat(userBookings);
|
||||
} else {
|
||||
const teamEvents = await prisma.eventType.findMany({
|
||||
where: {
|
||||
teamId: webhook.teamId,
|
||||
},
|
||||
select: {
|
||||
bookings: {
|
||||
where,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
bookings = teamEvents.flatMap((event) => event.bookings);
|
||||
bookings = teamEvents.flatMap((event) => event.bookings);
|
||||
}
|
||||
} else {
|
||||
if (webhook.eventTypeId) {
|
||||
where.AND.push({ eventTypeId: webhook.eventTypeId });
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
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: {
|
||||
OR: [
|
||||
{
|
||||
AND: [
|
||||
{
|
||||
members: {
|
||||
some: {
|
||||
userId,
|
||||
accepted: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
isOrganization: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
AND: [
|
||||
{
|
||||
children: {
|
||||
some: {
|
||||
id: teamId,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
isOrganization: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
return orgId?.id;
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import authedProcedure from "../../../procedures/authedProcedure";
|
||||
import { ZTeamsAndUserProfilesQueryInputSchema } from "../teamsAndUserProfilesQuery.schema";
|
||||
|
||||
export const teamsAndUserProfilesQuery = authedProcedure.query(async ({ ctx }) => {
|
||||
const handler = (await import("../teamsAndUserProfilesQuery.handler")).teamsAndUserProfilesQuery;
|
||||
export const teamsAndUserProfilesQuery = authedProcedure
|
||||
.input(ZTeamsAndUserProfilesQueryInputSchema)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const handler = (await import("../teamsAndUserProfilesQuery.handler")).teamsAndUserProfilesQuery;
|
||||
|
||||
return handler({ ctx });
|
||||
});
|
||||
return handler({ ctx, input });
|
||||
});
|
||||
|
||||
@@ -7,14 +7,17 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import type { TTeamsAndUserProfilesQueryInputSchema } from "./teamsAndUserProfilesQuery.schema";
|
||||
|
||||
type TeamsAndUserProfileOptions = {
|
||||
ctx: {
|
||||
user: NonNullable<TrpcSessionUser>;
|
||||
prisma: PrismaClient;
|
||||
};
|
||||
input: TTeamsAndUserProfilesQueryInputSchema;
|
||||
};
|
||||
|
||||
export const teamsAndUserProfilesQuery = async ({ ctx }: TeamsAndUserProfileOptions) => {
|
||||
export const teamsAndUserProfilesQuery = async ({ ctx, input }: TeamsAndUserProfileOptions) => {
|
||||
const { prisma } = ctx;
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
@@ -56,15 +59,27 @@ export const teamsAndUserProfilesQuery = async ({ ctx }: TeamsAndUserProfileOpti
|
||||
throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
|
||||
}
|
||||
|
||||
const nonOrgTeams = user.teams
|
||||
.filter((membership) => !membership.team.isOrganization)
|
||||
.map((membership) => ({
|
||||
let teamsData;
|
||||
|
||||
if (input?.includeOrg) {
|
||||
teamsData = user.teams.map((membership) => ({
|
||||
...membership,
|
||||
team: {
|
||||
...membership.team,
|
||||
metadata: teamMetadataSchema.parse(membership.team.metadata),
|
||||
},
|
||||
}));
|
||||
} else {
|
||||
teamsData = user.teams
|
||||
.filter((membership) => !membership.team.isOrganization)
|
||||
.map((membership) => ({
|
||||
...membership,
|
||||
team: {
|
||||
...membership.team,
|
||||
metadata: teamMetadataSchema.parse(membership.team.metadata),
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -76,7 +91,7 @@ export const teamsAndUserProfilesQuery = async ({ ctx }: TeamsAndUserProfileOpti
|
||||
}),
|
||||
readOnly: false,
|
||||
},
|
||||
...nonOrgTeams.map((membership) => ({
|
||||
...teamsData.map((membership) => ({
|
||||
teamId: membership.team.id,
|
||||
name: membership.team.name,
|
||||
slug: membership.team.slug ? `team/${membership.team.slug}` : null,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const ZTeamsAndUserProfilesQueryInputSchema = z
|
||||
.object({
|
||||
includeOrg: z.boolean().optional(),
|
||||
})
|
||||
.optional();
|
||||
|
||||
export type TTeamsAndUserProfilesQueryInputSchema = z.infer<typeof ZTeamsAndUserProfilesQueryInputSchema>;
|
||||
@@ -10,6 +10,7 @@ import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhoo
|
||||
import type { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import { getTranslation } from "@calcom/lib/server";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
@@ -370,12 +371,15 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => {
|
||||
},
|
||||
});
|
||||
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: booking.userId, teamId });
|
||||
|
||||
// send BOOKING_REJECTED webhooks
|
||||
const subscriberOptions = {
|
||||
userId: booking.userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_REJECTED,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
const eventTrigger: WebhookTriggerEvents = WebhookTriggerEvents.BOOKING_REJECTED;
|
||||
const eventTypeInfo: EventTypeInfo = {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { deleteWebhookScheduledTriggers } from "@calcom/features/webhooks/lib/sc
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import { isPrismaObjOrUndefined } from "@calcom/lib";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
@@ -290,13 +291,16 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
|
||||
});
|
||||
|
||||
const triggerForUser = !teamId || (teamId && bookingToReschedule.eventType?.parentId);
|
||||
const userId = triggerForUser ? bookingToReschedule.userId : null;
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
|
||||
|
||||
// Send Webhook call if hooked to BOOKING.CANCELLED
|
||||
const subscriberOptions = {
|
||||
userId: triggerForUser ? bookingToReschedule.userId : null,
|
||||
userId,
|
||||
eventTypeId: bookingToReschedule.eventTypeId as number,
|
||||
triggerEvent: eventTrigger,
|
||||
teamId,
|
||||
orgId,
|
||||
};
|
||||
const webhooks = await getWebhooks(subscriberOptions);
|
||||
const promises = webhooks.map((webhook) =>
|
||||
|
||||
@@ -4,6 +4,7 @@ import appStore from "@calcom/app-store";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { sendNoShowFeeChargedEmail } from "@calcom/emails";
|
||||
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import sendPayload from "@calcom/lib/server/webhooks/sendPayload";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
@@ -124,10 +125,14 @@ export const paymentsRouter = router({
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: `Could not generate payment data` });
|
||||
}
|
||||
|
||||
const userId = ctx.user.id || 0;
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: userId });
|
||||
|
||||
const subscriberOptions = {
|
||||
userId: ctx.user.id || 0,
|
||||
userId,
|
||||
eventTypeId: booking.eventTypeId || 0,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_PAID,
|
||||
orgId,
|
||||
};
|
||||
|
||||
const subscribers = await getWebhooks(subscriberOptions);
|
||||
|
||||
@@ -111,37 +111,29 @@ export const getByViewerHandler = async ({ ctx }: GetByViewerOptions) => {
|
||||
membershipRole: membership.role,
|
||||
}));
|
||||
|
||||
const teamWebhookGroups: WebhookGroup[] = user.teams
|
||||
.filter((mmship) => {
|
||||
return !mmship.team.isOrganization;
|
||||
})
|
||||
.map((membership) => {
|
||||
const orgMembership = teamMemberships.find(
|
||||
(teamM) => teamM.teamId === membership.team.parentId
|
||||
)?.membershipRole;
|
||||
return {
|
||||
teamId: membership.team.id,
|
||||
profile: {
|
||||
name: membership.team.name,
|
||||
slug: membership.team.slug
|
||||
? !membership.team.parentId
|
||||
? `/team`
|
||||
: `${membership.team.slug}`
|
||||
: null,
|
||||
image: `${bookerUrl}/team/${membership.team.slug}/avatar.png`,
|
||||
},
|
||||
metadata: {
|
||||
readOnly:
|
||||
membership.role ===
|
||||
(membership.team.parentId
|
||||
? orgMembership && compareMembership(orgMembership, membership.role)
|
||||
? orgMembership
|
||||
: MembershipRole.MEMBER
|
||||
: MembershipRole.MEMBER),
|
||||
},
|
||||
webhooks: membership.team.webhooks.filter(filterWebhooks),
|
||||
};
|
||||
});
|
||||
const teamWebhookGroups: WebhookGroup[] = user.teams.map((membership) => {
|
||||
const orgMembership = teamMemberships.find(
|
||||
(teamM) => teamM.teamId === membership.team.parentId
|
||||
)?.membershipRole;
|
||||
return {
|
||||
teamId: membership.team.id,
|
||||
profile: {
|
||||
name: membership.team.name,
|
||||
slug: membership.team.slug ? (!membership.team.parentId ? `/team` : `${membership.team.slug}`) : null,
|
||||
image: `${bookerUrl}/team/${membership.team.slug}/avatar.png`,
|
||||
},
|
||||
metadata: {
|
||||
readOnly:
|
||||
membership.role ===
|
||||
(membership.team.parentId
|
||||
? orgMembership && compareMembership(orgMembership, membership.role)
|
||||
? orgMembership
|
||||
: MembershipRole.MEMBER
|
||||
: MembershipRole.MEMBER),
|
||||
},
|
||||
webhooks: membership.team.webhooks.filter(filterWebhooks),
|
||||
};
|
||||
});
|
||||
|
||||
webhookGroups = webhookGroups.concat(teamWebhookGroups);
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ export function CreateButtonWithTeamsList(
|
||||
isAdmin?: boolean;
|
||||
}
|
||||
) {
|
||||
const query = trpc.viewer.teamsAndUserProfilesQuery.useQuery();
|
||||
const query = trpc.viewer.teamsAndUserProfilesQuery.useQuery({
|
||||
includeOrg: true,
|
||||
});
|
||||
if (!query.data) return null;
|
||||
|
||||
const teamsAndUserProfiles: Option[] = query.data
|
||||
|
||||
Reference in New Issue
Block a user