fix: DelegationCredential - Duplicate GoogleMeet and unnecessary serviceAccount key access (#21269)
* Remove unused return statement * Fix return from fn instead of continuing the loop * Ensure userId is set for existing records on update * ensure that serviceAccountKey is only retrieved whenb assked
This commit is contained in:
@@ -125,7 +125,10 @@ export async function getLocationGroupedOptions(
|
||||
: {}),
|
||||
};
|
||||
if (apps[groupByCategory]) {
|
||||
apps[groupByCategory] = [...apps[groupByCategory], option];
|
||||
const existingOption = apps[groupByCategory].find((o) => o.value === option.value);
|
||||
if (!existingOption) {
|
||||
apps[groupByCategory] = [...apps[groupByCategory], option];
|
||||
}
|
||||
} else {
|
||||
apps[groupByCategory] = [option];
|
||||
}
|
||||
|
||||
+28
-19
@@ -15,13 +15,14 @@ import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
// }
|
||||
// })
|
||||
|
||||
describe("getAllCredentials", () => {
|
||||
describe("getAllCredentialsIncludeServiceAccountKey", () => {
|
||||
test("Get an individual's credentials", async () => {
|
||||
vi.spyOn(UserRepository, "enrichUserWithItsProfile").mockReturnValue({
|
||||
profile: null,
|
||||
});
|
||||
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const userCredential = {
|
||||
id: 1,
|
||||
@@ -38,7 +39,7 @@ describe("getAllCredentials", () => {
|
||||
{ type: "team-credential", teamId: 1, key: {} },
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -65,7 +66,8 @@ describe("getAllCredentials", () => {
|
||||
profile: null,
|
||||
});
|
||||
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const crmCredential = {
|
||||
id: 1,
|
||||
@@ -101,7 +103,7 @@ describe("getAllCredentials", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -138,7 +140,8 @@ describe("getAllCredentials", () => {
|
||||
profile: null,
|
||||
});
|
||||
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const crmCredential = {
|
||||
id: 1,
|
||||
@@ -170,7 +173,7 @@ describe("getAllCredentials", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -204,7 +207,8 @@ describe("getAllCredentials", () => {
|
||||
profile: null,
|
||||
});
|
||||
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const teamId = 1;
|
||||
const crmCredential = {
|
||||
@@ -261,7 +265,7 @@ describe("getAllCredentials", () => {
|
||||
|
||||
console.log(testEventType);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -291,7 +295,8 @@ describe("getAllCredentials", () => {
|
||||
expect(credentials).toContainEqual(expect.objectContaining({ teamId, type: "salesforce_crm" }));
|
||||
});
|
||||
test("For an org user", async () => {
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
const orgId = 3;
|
||||
vi.spyOn(UserRepository, "enrichUserWithItsProfile").mockReturnValue({
|
||||
profile: { organizationId: orgId },
|
||||
@@ -357,7 +362,7 @@ describe("getAllCredentials", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -394,7 +399,8 @@ describe("getAllCredentials", () => {
|
||||
});
|
||||
describe("Default with _other_calendar credentials", () => {
|
||||
test("For users", async () => {
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const crmCredential = {
|
||||
id: 1,
|
||||
@@ -430,7 +436,7 @@ describe("getAllCredentials", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -459,7 +465,8 @@ describe("getAllCredentials", () => {
|
||||
);
|
||||
});
|
||||
test("For teams", async () => {
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const crmCredential = {
|
||||
id: 1,
|
||||
@@ -491,7 +498,7 @@ describe("getAllCredentials", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -517,7 +524,8 @@ describe("getAllCredentials", () => {
|
||||
);
|
||||
});
|
||||
test("For child of managed event type", async () => {
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
|
||||
const teamId = 1;
|
||||
const crmCredential = {
|
||||
@@ -574,7 +582,7 @@ describe("getAllCredentials", () => {
|
||||
|
||||
console.log(testEventType);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
@@ -600,7 +608,8 @@ describe("getAllCredentials", () => {
|
||||
);
|
||||
});
|
||||
test("For an org user", async () => {
|
||||
const getAllCredentials = (await import("./getAllCredentials")).getAllCredentials;
|
||||
const getAllCredentialsIncludeServiceAccountKey = (await import("./getAllCredentials"))
|
||||
.getAllCredentialsIncludeServiceAccountKey;
|
||||
const orgId = 3;
|
||||
vi.spyOn(UserRepository, "enrichUserWithItsProfile").mockReturnValue({
|
||||
profile: { organizationId: orgId },
|
||||
@@ -666,7 +675,7 @@ describe("getAllCredentials", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const credentials = await getAllCredentials(
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
{
|
||||
id: 1,
|
||||
username: "test",
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import type z from "zod";
|
||||
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
@@ -19,7 +19,7 @@ export type EventType = {
|
||||
* Gets credentials from the user, team, and org if applicable
|
||||
*
|
||||
*/
|
||||
export const getAllCredentials = async (
|
||||
export const getAllCredentialsIncludeServiceAccountKey = async (
|
||||
user: { id: number; username: string | null; email: string; credentials: CredentialPayload[] },
|
||||
eventType: EventType
|
||||
) => {
|
||||
@@ -120,7 +120,7 @@ export const getAllCredentials = async (
|
||||
}
|
||||
});
|
||||
|
||||
const userWithDelegationCredentials = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const userWithDelegationCredentials = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: { ...user, credentials: allCredentials },
|
||||
});
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
|
||||
import { getAllWorkflowsFromEventType } from "@calcom/trpc/server/routers/viewer/workflows/util";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { getAllCredentials } from "./getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "./getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getBookingToDelete } from "./getBookingToDelete";
|
||||
import { handleInternalNote } from "./handleInternalNote";
|
||||
import cancelAttendeeSeat from "./handleSeats/cancel/cancelAttendeeSeat";
|
||||
@@ -467,7 +467,7 @@ async function handler(input: CancelBookingInput) {
|
||||
|
||||
const bookingToDeleteEventTypeMetadata = bookingToDeleteEventTypeMetadataParsed.data;
|
||||
|
||||
const credentials = await getAllCredentials(bookingToDelete.user, {
|
||||
const credentials = await getAllCredentialsIncludeServiceAccountKey(bookingToDelete.user, {
|
||||
...bookingToDelete.eventType,
|
||||
metadata: bookingToDeleteEventTypeMetadata,
|
||||
});
|
||||
|
||||
@@ -81,7 +81,7 @@ import type { CredentialForCalendarService } from "@calcom/types/Credential";
|
||||
import type { EventResult, PartialReference } from "@calcom/types/EventManager";
|
||||
|
||||
import type { EventPayloadType, EventTypeInfo } from "../../webhooks/lib/sendPayload";
|
||||
import { getAllCredentials } from "./getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "./getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { refreshCredentials } from "./getAllCredentialsForUsersOnEvent/refreshCredentials";
|
||||
import getBookingDataSchema from "./getBookingDataSchema";
|
||||
import { addVideoCallDataToEvent } from "./handleNewBooking/addVideoCallDataToEvent";
|
||||
@@ -820,7 +820,7 @@ async function handler(
|
||||
: users[0];
|
||||
|
||||
const tOrganizer = await getTranslation(organizerUser?.locale ?? "en", "common");
|
||||
const allCredentials = await getAllCredentials(organizerUser, eventType);
|
||||
const allCredentials = await getAllCredentialsIncludeServiceAccountKey(organizerUser, eventType);
|
||||
|
||||
// If the Organizer himself is rescheduling, the booker should be sent the communication in his timezone and locale.
|
||||
const attendeeInfoOnReschedule =
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getCalendar } from "@calcom/app-store/_utils/getCalendar";
|
||||
import { sendCancelledSeatEmailsAndSMS } from "@calcom/emails";
|
||||
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import type { EventPayloadType, EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { getAllDelegationCredentialsForUser } from "@calcom/lib/delegationCredential/server";
|
||||
import { getAllDelegationCredentialsForUserIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { getDelegationCredentialOrFindRegularCredential } from "@calcom/lib/delegationCredential/server";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import logger from "@calcom/lib/logger";
|
||||
@@ -71,7 +71,8 @@ async function cancelAttendeeSeat(
|
||||
const attendee = bookingToDelete?.attendees.find((attendee) => attendee.id === seatReference.attendeeId);
|
||||
const bookingToDeleteUser = bookingToDelete.user ?? null;
|
||||
const delegationCredentials = bookingToDeleteUser
|
||||
? await getAllDelegationCredentialsForUser({
|
||||
? // We fetch delegation credentials with ServiceAccount key as CalendarService instance created later in the flow needs it
|
||||
await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user: { email: bookingToDeleteUser.email, id: bookingToDeleteUser.id },
|
||||
})
|
||||
: [];
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Attendee } from "@prisma/client";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { getCalendar } from "@calcom/app-store/_utils/getCalendar";
|
||||
import { getAllDelegationCredentialsForUser } from "@calcom/lib/delegationCredential/server";
|
||||
import { getAllDelegationCredentialsForUserIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { getDelegationCredentialOrFindRegularCredential } from "@calcom/lib/delegationCredential/server";
|
||||
import { deleteMeeting } from "@calcom/lib/videoClient";
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -21,7 +21,8 @@ const lastAttendeeDeleteBooking = async (
|
||||
let deletedReferences = false;
|
||||
const bookingUser = originalRescheduledBooking?.user;
|
||||
const delegationCredentials = bookingUser
|
||||
? await getAllDelegationCredentialsForUser({
|
||||
? // We fetch delegation credentials with ServiceAccount key as CalendarService instance created later in the flow needs it
|
||||
await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user: { email: bookingUser.email, id: bookingUser.id },
|
||||
})
|
||||
: [];
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ export type NewSeatedBookingObject = {
|
||||
bookerUrl: string;
|
||||
};
|
||||
invitee: Invitee;
|
||||
allCredentials: Awaited<ReturnType<typeof getAllCredentials>>;
|
||||
allCredentials: Awaited<ReturnType<typeof getAllCredentialsIncludeServiceAccountKey>>;
|
||||
organizerUser: OrganizerUser;
|
||||
originalRescheduledBooking: OriginalRescheduledBooking;
|
||||
bookerEmail: string;
|
||||
|
||||
+20
-15
@@ -95,8 +95,7 @@ Step 6: Enable Delegation Credential(To Be taken By Cal.com organization Owner/A
|
||||
### Terminology
|
||||
|
||||
- Delegation Credential: A Delegation Credential service account key along with user's email becomes the Delegation Credential which is an alternative to regular Credential in DB.
|
||||
- DWD: Domain Wide Delegation
|
||||
- non-dwd credential: Regular credentials that are stored in Credentials table
|
||||
- Delegation User Credential: A Delegation User Credential is a Credential record in DB that uses DelegationCredential record to actually access the user's calendar. A Credential record with delegationCredentialId set is a Delegation User Credential.
|
||||
|
||||
### How Delegation Credential works
|
||||
|
||||
@@ -108,6 +107,13 @@ Step 6: Enable Delegation Credential(To Be taken By Cal.com organization Owner/A
|
||||
- A Delegation Credential service account key along with user's email becomes the Delegation Credential which is an alternative to regular Credential in DB.
|
||||
- Delegation Credential doesn't completely replace the regular credentials. Delegation Credential gives access to the cal.com user's email in Google Calendar. So, if the user needs to connect to some other email's calendar, we need to use the regular credentials.
|
||||
|
||||
### Cron Jobs
|
||||
|
||||
Cron jobs ensure that for each and every member of the organization that has Delegation Credential enabled, corresponding SelectedCalendar records are there. These crons currently run every 5 minutes, look at vercel.json for the up-to-date schedule.
|
||||
|
||||
- `credentials` cron job creates Delegation User Credential records for all the members of the organization who don't have Delegation User Credentials yet. It also ensures that on disabling Delegation Credential, the Delegation User Credentials are deleted which automatically deletes the SelectedCalendars through DB cascade.
|
||||
- `selected-calendars` cron job creates SelectedCalendar records for all the Delegation User Credentials of the organization who don't have Selected Calendars yet.
|
||||
|
||||
### Important Points
|
||||
|
||||
- No Credential table entry is created when enabling Delegation Credential. The workspace platform's related apps will be considered as "installed" for the users with email matching dwd domain. An in-memory credential like object is created for this purpose. It allows avoiding creation of thousands of records for all the members of the organization when Delegation Credential is enabled.
|
||||
@@ -122,23 +128,16 @@ Step 6: Enable Delegation Credential(To Be taken By Cal.com organization Owner/A
|
||||
1. Identify the logged in user's email
|
||||
2. Identify the domainWideDelegations for that email's domain
|
||||
3. Build in-memory credentials for the domainWideDelegations and use them along with the actual credentials(that user might have connected) of the user
|
||||
4. We don't show the non-dwd connected calendar(if there is a corresponding dwd connected calendar). Though we use the non-dwd credentials to identify the selected calendars, for the dwd connected calendar.
|
||||
4. We don't show the non DelegationCredential connected calendar(if there is a corresponding DelegationCredential connected calendar). Though we use the non DelegationCredential credentials to identify the selected calendars, for the DelegationCredential connected calendar.
|
||||
|
||||
### Impact of disabling Delegation Credential
|
||||
|
||||
Disabling effectively stops generating in-memory delegation user credentials. So, any members who haven't manually connected their Calendar and thus their calendar connections were working only because of Delegation Credential, would have their connections broken.
|
||||
Disabling effectively stops generating in-memory delegation user credentials. So, any members who haven't manually connected their Calendar and thus their calendar connections were working only because of Delegation Credential, would have their calendar connections broken.
|
||||
|
||||
#### What would not work correctly ?
|
||||
|
||||
- Calendar won't be checked for conflicts. So, they could get booked at a time when they are marked busy in their calendar.
|
||||
- Cal.com bookings would still be checked for conflicts.
|
||||
- Bookings might not appear in the attendee and host's Google Calendar. Because we would be unable to use the API to create the events in calendar and Google doesn't always add events to calendar automatically based on .ics file alone.
|
||||
- Cal Video would be used as the booking location instead of Google Meet.
|
||||
|
||||
#### What would work correctly ?
|
||||
|
||||
- Bookings would still go through. People relying on Salesforce for booking details, would face no issues.
|
||||
- Cal.com bookings would still be checked for conflicts.
|
||||
### Impact of enabling Delegation Credential
|
||||
- Existing calendar-cache records are re-used as we identify the relevant record by userId and key of CalendarCache record.
|
||||
- Any updates to those calendar-cache records keep on working by using the non-delegation credential attached with the SelectedCalendar record.
|
||||
- For any new members, we create Credential records and SelectedCalendar records through cron jobs and thus their calendar-cache records will also be created.
|
||||
|
||||
### Notes when testing locally
|
||||
|
||||
@@ -146,3 +145,9 @@ Disabling effectively stops generating in-memory delegation user credentials. So
|
||||
- You could use Acme org and login as <owner1-acme@example.com>
|
||||
- Make sure to change the email of the user above to your workspace owner's email(other member's email might also work). This is necessary otherwise you won't be able to enable Delegation Credential for the organization.
|
||||
- Note: After changing the email, you would have to logout and login again
|
||||
|
||||
|
||||
|
||||
## TODO
|
||||
- Test what happens when credential expires that was used in CalendarCache/SelectedCalendar
|
||||
- It seems that if refresh token is valid then it would still be refreshed but if it becomes invalid then it ends up causing the calendar-cache updates to break because it isn't able to renew the access token. How do you fix it?
|
||||
@@ -5,7 +5,7 @@ import type Stripe from "stripe";
|
||||
|
||||
import { sendAttendeeRequestEmailAndSMS, sendOrganizerRequestEmail } from "@calcom/emails";
|
||||
import { doesBookingRequireConfirmation } from "@calcom/features/bookings/lib/doesBookingRequireConfirmation";
|
||||
import { getAllCredentials } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
@@ -75,7 +75,7 @@ const handleSetupSuccess = async (event: Stripe.Event) => {
|
||||
});
|
||||
|
||||
const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(eventType?.metadata);
|
||||
const allCredentials = await getAllCredentials(user, {
|
||||
const allCredentials = await getAllCredentialsIncludeServiceAccountKey(user, {
|
||||
...booking.eventType,
|
||||
metadata,
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Prisma } from "@prisma/client";
|
||||
|
||||
import { metadata as GoogleMeetMetadata } from "@calcom/app-store/googlevideo/_metadata";
|
||||
import { MeetLocationType } from "@calcom/app-store/locations";
|
||||
import { getAllCredentials } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import type { EventType } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getVideoCallDetails } from "@calcom/features/bookings/lib/handleNewBooking/getVideoCallDetails";
|
||||
import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
@@ -53,7 +53,10 @@ export const handleRescheduleEventManager = async ({
|
||||
prefix: ["handleRescheduleEventManager", `${bookingId}`],
|
||||
});
|
||||
|
||||
const allCredentials = await getAllCredentials(initParams.user, initParams?.eventType);
|
||||
const allCredentials = await getAllCredentialsIncludeServiceAccountKey(
|
||||
initParams.user,
|
||||
initParams?.eventType
|
||||
);
|
||||
|
||||
const eventManager = new EventManager(
|
||||
{ ...initParams.user, credentials: allCredentials },
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
import { scheduleWorkflowReminders } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler";
|
||||
import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
import { SENDER_NAME } from "@calcom/lib/constants";
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { getEventName } from "@calcom/lib/event";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj";
|
||||
@@ -282,7 +282,7 @@ export const roundRobinManualReassignment = async ({
|
||||
include: { user: { select: { email: true } } },
|
||||
});
|
||||
|
||||
const newUserWithCredentials = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const newUserWithCredentials = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: { ...newUser, credentials },
|
||||
});
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
import { SENDER_NAME } from "@calcom/lib/constants";
|
||||
import {
|
||||
enrichHostsWithDelegationCredentials,
|
||||
enrichUserWithDelegationCredentialsWithoutOrgId,
|
||||
enrichUserWithDelegationCredentialsIncludeServiceAccountKey,
|
||||
} from "@calcom/lib/delegationCredential/server";
|
||||
import { getEventName } from "@calcom/lib/event";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
@@ -337,7 +337,7 @@ export const roundRobinReassignment = async ({
|
||||
},
|
||||
});
|
||||
|
||||
const organizerWithCredentials = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const organizerWithCredentials = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: { ...organizer, credentials },
|
||||
});
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@ import { SMSLockState } from "@calcom/prisma/enums";
|
||||
import type { CredentialForCalendarService, CredentialPayload } from "@calcom/types/Credential";
|
||||
|
||||
import {
|
||||
getAllDelegationCredentialsForUser,
|
||||
buildAllCredentials,
|
||||
getDelegationCredentialOrRegularCredential,
|
||||
enrichUsersWithDelegationCredentials,
|
||||
enrichHostsWithDelegationCredentials,
|
||||
enrichUserWithDelegationCredentialsWithoutOrgId,
|
||||
enrichUserWithDelegationCredentialsIncludeServiceAccountKey,
|
||||
enrichUserWithDelegationConferencingCredentialsWithoutOrgId,
|
||||
getAllDelegationCredentialsForUserIncludeServiceAccountKey,
|
||||
} from "./server";
|
||||
|
||||
// Mock OrganizationRepository
|
||||
@@ -177,7 +177,7 @@ const buildMockDelegationCredential = (overrides: Partial<typeof mockDelegationC
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe("getAllDelegationCredentialsForUser", () => {
|
||||
describe("getAllDelegationCredentialsForUserIncludeServiceAccountKey", () => {
|
||||
setupAndTeardown();
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -189,7 +189,7 @@ describe("getAllDelegationCredentialsForUser", () => {
|
||||
vi.mocked(
|
||||
DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey
|
||||
).mockResolvedValue(null);
|
||||
const result = await getAllDelegationCredentialsForUser({ user: mockUser });
|
||||
const result = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({ user: mockUser });
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -197,7 +197,7 @@ describe("getAllDelegationCredentialsForUser", () => {
|
||||
vi.mocked(
|
||||
DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey
|
||||
).mockResolvedValue(buildMockDelegationCredential({ enabled: false }));
|
||||
const result = await getAllDelegationCredentialsForUser({ user: mockUser });
|
||||
const result = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({ user: mockUser });
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -205,7 +205,7 @@ describe("getAllDelegationCredentialsForUser", () => {
|
||||
vi.mocked(
|
||||
DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey
|
||||
).mockResolvedValue(buildMockDelegationCredential());
|
||||
const result = await getAllDelegationCredentialsForUser({ user: mockUser });
|
||||
const result = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({ user: mockUser });
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toEqual([
|
||||
@@ -225,7 +225,7 @@ describe("getAllDelegationCredentialsForUser", () => {
|
||||
},
|
||||
})
|
||||
);
|
||||
const result = await getAllDelegationCredentialsForUser({ user: mockUser });
|
||||
const result = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({ user: mockUser });
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -520,7 +520,7 @@ describe("enrichHostsWithDelegationCredentials", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("enrichUserWithDelegationCredentialsWithoutOrgId", () => {
|
||||
describe("enrichUserWithDelegationCredentialsIncludeServiceAccountKey", () => {
|
||||
const mockUserWithCredentials = {
|
||||
...mockUser,
|
||||
credentials: [buildRegularGoogleCalendarCredential()],
|
||||
@@ -535,7 +535,7 @@ describe("enrichUserWithDelegationCredentialsWithoutOrgId", () => {
|
||||
DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey
|
||||
).mockResolvedValue(buildMockDelegationCredential());
|
||||
|
||||
const result = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const result = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: mockUserWithCredentials,
|
||||
});
|
||||
|
||||
@@ -559,7 +559,7 @@ describe("enrichUserWithDelegationCredentialsWithoutOrgId", () => {
|
||||
DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey
|
||||
).mockResolvedValue(null);
|
||||
|
||||
const result = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const result = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: mockUserWithCredentials,
|
||||
});
|
||||
|
||||
@@ -578,7 +578,7 @@ describe("enrichUserWithDelegationCredentialsWithoutOrgId", () => {
|
||||
DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey
|
||||
).mockResolvedValue(buildMockDelegationCredential({ enabled: false }));
|
||||
|
||||
const result = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const result = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: mockUserWithCredentials,
|
||||
});
|
||||
|
||||
|
||||
@@ -188,7 +188,11 @@ const _buildDelegatedConferencingCredential = ({
|
||||
/**
|
||||
* Gets calendar as well as conferencing credentials(stored in-memory) for the user from the corresponding enabled DelegationCredential.
|
||||
*/
|
||||
export async function getAllDelegationCredentialsForUser({ user }: { user: { email: string; id: number } }) {
|
||||
export async function getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user,
|
||||
}: {
|
||||
user: { email: string; id: number };
|
||||
}) {
|
||||
log.debug("called with", safeStringify({ user }));
|
||||
// We access the repository without checking for feature flag here.
|
||||
// In case we need to disable the effects of DelegationCredential on credential we need to toggle DelegationCredential off from organization settings.
|
||||
@@ -211,13 +215,32 @@ export async function getAllDelegationCredentialsForUser({ user }: { user: { ema
|
||||
return delegationCredentials;
|
||||
}
|
||||
|
||||
export async function getAllDelegationCredentialsForUser({ user }: { user: { email: string; id: number } }) {
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user,
|
||||
});
|
||||
return delegationCredentials.map(({ delegatedTo: _1, ...rest }) => {
|
||||
return {
|
||||
...rest,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function getAllDelegatedCalendarCredentialsForUser({
|
||||
user,
|
||||
}: {
|
||||
user: { email: string; id: number };
|
||||
}) {
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUser({ user });
|
||||
return delegationCredentials.filter((credential) => credential.type.endsWith("_calendar"));
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user,
|
||||
});
|
||||
const delegationCalendarCredentials = delegationCredentials.filter((credential) =>
|
||||
credential.type.endsWith("_calendar")
|
||||
);
|
||||
return buildAllCredentials({
|
||||
delegationCredentials: delegationCalendarCredentials,
|
||||
existingCredentials: [],
|
||||
});
|
||||
}
|
||||
|
||||
async function _getDelegationCredentialsMapPerUser({
|
||||
@@ -325,8 +348,14 @@ export async function getAllDelegationCredentialsForUserByAppSlug({
|
||||
user: User;
|
||||
appSlug: string;
|
||||
}) {
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUser({ user });
|
||||
return delegationCredentials.filter((credential) => credential.appId === appSlug);
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user,
|
||||
});
|
||||
const appDelegationCredentials = delegationCredentials.filter((credential) => credential.appId === appSlug);
|
||||
return buildAllCredentials({
|
||||
delegationCredentials: appDelegationCredentials,
|
||||
existingCredentials: [],
|
||||
});
|
||||
}
|
||||
|
||||
type Host<TUser extends { id: number; email: string; credentials: CredentialPayload[] }> = {
|
||||
@@ -425,14 +454,16 @@ export const enrichHostsWithDelegationCredentials = async <
|
||||
return enrichedHosts;
|
||||
};
|
||||
|
||||
export const enrichUserWithDelegationCredentialsWithoutOrgId = async <
|
||||
export const enrichUserWithDelegationCredentialsIncludeServiceAccountKey = async <
|
||||
TUser extends { id: number; email: string; credentials: CredentialPayload[] }
|
||||
>({
|
||||
user,
|
||||
}: {
|
||||
user: TUser;
|
||||
}) => {
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUser({ user });
|
||||
const delegationCredentials = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
|
||||
user,
|
||||
});
|
||||
const { credentials, ...restUser } = user;
|
||||
return {
|
||||
...restUser,
|
||||
@@ -443,10 +474,28 @@ export const enrichUserWithDelegationCredentialsWithoutOrgId = async <
|
||||
};
|
||||
};
|
||||
|
||||
export const enrichUserWithDelegationCredentials = async <
|
||||
TUser extends { id: number; email: string; credentials: CredentialPayload[] }
|
||||
>({
|
||||
user,
|
||||
}: {
|
||||
user: TUser;
|
||||
}) => {
|
||||
const { credentials, ...restUser } = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user,
|
||||
});
|
||||
return {
|
||||
...restUser,
|
||||
credentials: credentials.filter(_isConferencingCredential).map(({ delegatedTo: _1, ...rest }) => rest),
|
||||
};
|
||||
};
|
||||
|
||||
export async function enrichUserWithDelegationConferencingCredentialsWithoutOrgId<
|
||||
TUser extends { id: number; email: string; credentials: CredentialPayload[] }
|
||||
>({ user }: { user: TUser }) {
|
||||
const { credentials, ...restUser } = await enrichUserWithDelegationCredentialsWithoutOrgId({ user });
|
||||
const { credentials, ...restUser } = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user,
|
||||
});
|
||||
return {
|
||||
...restUser,
|
||||
credentials: credentials.filter(_isConferencingCredential),
|
||||
@@ -456,7 +505,9 @@ export async function enrichUserWithDelegationConferencingCredentialsWithoutOrgI
|
||||
/**
|
||||
* Either get Delegation credential from delegationCredentials or find regular credential from Credential table
|
||||
*/
|
||||
export async function getDelegationCredentialOrFindRegularCredential({
|
||||
export async function getDelegationCredentialOrFindRegularCredential<
|
||||
TDelegationCredential extends { delegatedToId?: string | null }
|
||||
>({
|
||||
id,
|
||||
delegationCredentials,
|
||||
}: {
|
||||
@@ -464,7 +515,7 @@ export async function getDelegationCredentialOrFindRegularCredential({
|
||||
credentialId: number | null | undefined;
|
||||
delegationCredentialId: string | null | undefined;
|
||||
};
|
||||
delegationCredentials: CredentialForCalendarService[];
|
||||
delegationCredentials: TDelegationCredential[];
|
||||
}) {
|
||||
return id.delegationCredentialId
|
||||
? delegationCredentials.find((cred) => cred.delegatedToId === id.delegationCredentialId)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getAppFromSlug } from "@calcom/app-store/utils";
|
||||
import { checkAdminOrOwner } from "@calcom/features/auth/lib/checkAdminOrOwner";
|
||||
import getEnabledAppsFromCredentials from "@calcom/lib/apps/getEnabledAppsFromCredentials";
|
||||
import getInstallCountPerApp from "@calcom/lib/apps/getInstallCountPerApp";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
import type { AppCategories } from "@calcom/prisma/enums";
|
||||
@@ -66,7 +66,7 @@ export async function getConnectedApps({
|
||||
sortByInstalledFirst,
|
||||
appId,
|
||||
} = input;
|
||||
let credentials = await getUsersCredentials(user);
|
||||
let credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
let userTeams: TeamQuery[] = [];
|
||||
|
||||
if (includeTeamInstalledApps || teamId) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getCalendarCredentials, getConnectedCalendars } from "@calcom/lib/CalendarManager";
|
||||
import { isDelegationCredential } from "@calcom/lib/delegationCredential/clientAndServer";
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -285,7 +285,7 @@ export async function getConnectedDestinationCalendarsAndEnsureDefaultsInDb({
|
||||
select: credentialForCalendarServiceSelect,
|
||||
});
|
||||
|
||||
const { credentials: allCredentials } = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const { credentials: allCredentials } = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: { id: user.id, email: user.email, credentials: userCredentials },
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/crede
|
||||
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "../delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentials } from "../delegationCredential/server";
|
||||
import { getBookerBaseUrl } from "../getBookerUrl/server";
|
||||
|
||||
async function getEventType(id: number) {
|
||||
@@ -109,7 +109,7 @@ export async function getBooking(bookingId: number) {
|
||||
const { user: userWithoutDelegationCredentials } = booking;
|
||||
|
||||
if (!userWithoutDelegationCredentials) throw new HttpCode({ statusCode: 204, message: "No user found" });
|
||||
const user = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const user = await enrichUserWithDelegationCredentials({
|
||||
user: userWithoutDelegationCredentials,
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
|
||||
import { sendScheduledEmailsAndSMS } from "@calcom/emails";
|
||||
import { doesBookingRequireConfirmation } from "@calcom/features/bookings/lib/doesBookingRequireConfirmation";
|
||||
import { getAllCredentials } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { handleBookingRequested } from "@calcom/features/bookings/lib/handleBookingRequested";
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
@@ -27,7 +27,7 @@ export async function handlePaymentSuccess(paymentId: number, bookingId: number)
|
||||
status: BookingStatus.ACCEPTED,
|
||||
};
|
||||
|
||||
const allCredentials = await getAllCredentials(userWithCredentials, {
|
||||
const allCredentials = await getAllCredentialsIncludeServiceAccountKey(userWithCredentials, {
|
||||
...booking.eventType,
|
||||
metadata: booking.eventType?.metadata as EventTypeMetadata,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { availabilityUserSelect } from "@calcom/prisma";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
@@ -23,7 +23,7 @@ export async function findUsersForAvailabilityCheck({ where }: { where: Prisma.U
|
||||
return null;
|
||||
}
|
||||
|
||||
return await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
return await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: withSelectedCalendars(user),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import getAppKeysFromSlug from "@calcom/app-store/_utils/getAppKeysFromSlug";
|
||||
import { DailyLocationType } from "@calcom/app-store/locations";
|
||||
import getApps from "@calcom/app-store/utils";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { userMetadata as userMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeLocation } from "@calcom/prisma/zod/custom/eventtype";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
||||
@@ -17,7 +17,8 @@ export async function getDefaultLocations(user: User): Promise<EventTypeLocation
|
||||
const defaultConferencingData = userMetadataSchema.parse(user.metadata)?.defaultConferencingApp;
|
||||
|
||||
if (defaultConferencingData && defaultConferencingData.appSlug !== "daily-video") {
|
||||
const credentials = await getUsersCredentials(user);
|
||||
// We are not returning the credential, so we are fine with the service account key
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
|
||||
const foundApp = getApps(credentials, true).filter(
|
||||
(app) => app.slug === defaultConferencingData.appSlug
|
||||
|
||||
@@ -2,7 +2,7 @@ import { prisma } from "@calcom/prisma";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
||||
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "../delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "../delegationCredential/server";
|
||||
|
||||
type SessionUser = NonNullable<TrpcSessionUser>;
|
||||
type User = { id: SessionUser["id"]; email: SessionUser["email"] };
|
||||
@@ -10,7 +10,7 @@ type User = { id: SessionUser["id"]; email: SessionUser["email"] };
|
||||
/**
|
||||
* It includes in-memory DelegationCredential credentials as well.
|
||||
*/
|
||||
export async function getUsersCredentials(user: User) {
|
||||
export async function getUsersCredentialsIncludeServiceAccountKey(user: User) {
|
||||
const credentials = await prisma.credential.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
@@ -21,7 +21,7 @@ export async function getUsersCredentials(user: User) {
|
||||
},
|
||||
});
|
||||
|
||||
const { credentials: allCredentials } = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const { credentials: allCredentials } = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: {
|
||||
email: user.email,
|
||||
id: user.id,
|
||||
@@ -31,3 +31,8 @@ export async function getUsersCredentials(user: User) {
|
||||
|
||||
return allCredentials;
|
||||
}
|
||||
|
||||
export async function getUsersCredentials(user: User) {
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
return credentials.map(({ delegatedTo: _1, ...rest }) => rest);
|
||||
}
|
||||
|
||||
@@ -1955,6 +1955,7 @@ model DelegationCredential {
|
||||
// Should be fair to assume that one domain can be only on one workspace platform at a time. So, one can't have two different workspace platforms for the same domain
|
||||
// Because we don't know which domain the organization might have, we couldn't make "domain" unique here as that would prevent an actual owner of the domain to be unable to use that domain if it is used by someone else.
|
||||
@@unique([organizationId, domain])
|
||||
@@index([enabled])
|
||||
}
|
||||
|
||||
// Deprecated and probably unused - Use DelegationCredential instead
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import getApps from "@calcom/app-store/utils";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
@@ -16,7 +16,8 @@ type AppByIdOptions = {
|
||||
export const appByIdHandler = async ({ ctx, input }: AppByIdOptions) => {
|
||||
const { user } = ctx;
|
||||
const appId = input.appId;
|
||||
const credentials = await getUsersCredentials(user);
|
||||
// getApps need credentials with service account key, but we are filtering credentials out already before returning from this fn
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
const apps = getApps(credentials);
|
||||
const appFromDb = apps.find((app) => app.slug === appId);
|
||||
if (!appFromDb) {
|
||||
|
||||
+4
-2
@@ -1,7 +1,7 @@
|
||||
import z from "zod";
|
||||
|
||||
import getApps from "@calcom/app-store/utils";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { userMetadata } from "@calcom/prisma/zod-utils";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
||||
@@ -22,7 +22,9 @@ export const updateUserDefaultConferencingAppHandler = async ({
|
||||
input,
|
||||
}: UpdateUserDefaultConferencingAppOptions) => {
|
||||
const currentMetadata = userMetadata.parse(ctx.user.metadata);
|
||||
const credentials = await getUsersCredentials(ctx.user);
|
||||
// getApps need credentials with service account key
|
||||
// We aren't returning the credential, so we are fine with the service account key
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(ctx.user);
|
||||
const foundApp = getApps(credentials, true).filter((app) => app.slug === input.appSlug)[0];
|
||||
const appLocation = foundApp?.appData?.location;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getBusyCalendarTimes } from "@calcom/lib/CalendarManager";
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { EventBusyDate } from "@calcom/types/Calendar";
|
||||
|
||||
@@ -54,7 +54,7 @@ export const calendarOverlayHandler = async ({ ctx, input }: ListOptions) => {
|
||||
},
|
||||
});
|
||||
|
||||
const { credentials } = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const { credentials } = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: {
|
||||
...user,
|
||||
credentials: nonDelegationCredentials,
|
||||
|
||||
@@ -2,7 +2,7 @@ import dayjs from "@calcom/dayjs";
|
||||
import { sendAddGuestsEmails } from "@calcom/emails";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { isTeamAdmin, isTeamOwner } from "@calcom/lib/server/queries/teams";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
@@ -157,7 +157,7 @@ export const addGuestsHandler = async ({ ctx, input }: AddGuestsOptions) => {
|
||||
};
|
||||
}
|
||||
|
||||
const credentials = await getUsersCredentials(ctx.user);
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(ctx.user);
|
||||
|
||||
const eventManager = new EventManager({
|
||||
...user,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Prisma } from "@prisma/client";
|
||||
import type { LocationObject } from "@calcom/app-store/locations";
|
||||
import { getLocationValueForDB } from "@calcom/app-store/locations";
|
||||
import { sendDeclinedEmailsAndSMS } from "@calcom/emails";
|
||||
import { getAllCredentials } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses";
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhookTrigger";
|
||||
@@ -16,7 +16,7 @@ import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj";
|
||||
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
|
||||
import { processPaymentRefund } from "@calcom/lib/payment/processPaymentRefund";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
@@ -277,12 +277,12 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => {
|
||||
}
|
||||
|
||||
if (confirmed) {
|
||||
const credentials = await getUsersCredentials(user);
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
const userWithCredentials = {
|
||||
...user,
|
||||
credentials,
|
||||
};
|
||||
const allCredentials = await getAllCredentials(userWithCredentials, {
|
||||
const allCredentials = await getAllCredentialsIncludeServiceAccountKey(userWithCredentials, {
|
||||
...booking.eventType,
|
||||
metadata: booking.eventType?.metadata as EventTypeMetadata,
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import EventManager from "@calcom/lib/EventManager";
|
||||
import { buildCalEventFromBooking } from "@calcom/lib/buildCalEventFromBooking";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
|
||||
import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
@@ -121,14 +121,14 @@ async function updateBookingLocationInDb({
|
||||
});
|
||||
}
|
||||
|
||||
async function getAllCredentials({
|
||||
async function getAllCredentialsIncludeServiceAccountKey({
|
||||
user,
|
||||
conferenceCredentialId,
|
||||
}: {
|
||||
user: { id: number; email: string };
|
||||
conferenceCredentialId: number | null;
|
||||
}) {
|
||||
const credentials = await getUsersCredentials(user);
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
|
||||
let conferenceCredential;
|
||||
|
||||
@@ -265,7 +265,7 @@ export async function editLocationHandler({ ctx, input }: EditLocationOptions) {
|
||||
|
||||
const eventManager = new EventManager({
|
||||
...ctx.user,
|
||||
credentials: await getAllCredentials({ user: ctx.user, conferenceCredentialId }),
|
||||
credentials: await getAllCredentialsIncludeServiceAccountKey({ user: ctx.user, conferenceCredentialId }),
|
||||
});
|
||||
|
||||
const updatedResult = await updateLocationInConnectedAppForBooking({
|
||||
|
||||
@@ -17,7 +17,7 @@ import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { WorkflowRepository } from "@calcom/lib/server/repository/workflow";
|
||||
import { deleteMeeting } from "@calcom/lib/videoClient";
|
||||
@@ -226,7 +226,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
|
||||
|
||||
// Handling calendar and videos cancellation
|
||||
// This can set previous time as available, until virtual calendar is done
|
||||
const credentials = await getUsersCredentials(user);
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
const credentialsMap = new Map();
|
||||
credentials.forEach((credential) => {
|
||||
credentialsMap.set(credential.type, credential);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getCalendarCredentials, getConnectedCalendars } from "@calcom/lib/CalendarManager";
|
||||
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { getUsersCredentialsIncludeServiceAccountKey } from "@calcom/lib/server/getUsersCredentials";
|
||||
import { DestinationCalendarRepository } from "@calcom/lib/server/repository/destinationCalendar";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
||||
@@ -54,7 +54,7 @@ export const getFirstConnectedCalendar = ({
|
||||
export const setDestinationCalendarHandler = async ({ ctx, input }: SetDestinationCalendarOptions) => {
|
||||
const { user } = ctx;
|
||||
const { integration, externalId, eventTypeId } = input;
|
||||
const credentials = await getUsersCredentials(user);
|
||||
const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
|
||||
const calendarCredentials = getCalendarCredentials(credentials);
|
||||
const { connectedCalendars } = await getConnectedCalendars(
|
||||
calendarCredentials,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { enrichUserWithDelegationCredentialsWithoutOrgId } from "@calcom/lib/delegationCredential/server";
|
||||
import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server";
|
||||
import { getUserAvailability } from "@calcom/lib/getUserAvailability";
|
||||
import { isTeamMember } from "@calcom/lib/server/queries/teams";
|
||||
import { MembershipRepository } from "@calcom/lib/server/repository/membership";
|
||||
@@ -27,7 +27,7 @@ export const getMemberAvailabilityHandler = async ({ ctx, input }: GetMemberAvai
|
||||
if (!member.user.username)
|
||||
throw new TRPCError({ code: "BAD_REQUEST", message: "Member doesn't have a username" });
|
||||
const username = member.user.username;
|
||||
const user = await enrichUserWithDelegationCredentialsWithoutOrgId({
|
||||
const user = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
|
||||
user: member.user,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user