Files
calendar/packages/trpc/server/routers/viewer/delegationCredential/toggleEnabled.handler.ts
T

155 lines
4.9 KiB
TypeScript

import { assertSuccessfullyConfiguredInWorkspace } from "@calcom/app-store/delegationCredential";
import { sendDelegationCredentialDisabledEmail } from "@calcom/emails/integration-email-service";
import type { ServiceAccountKey } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository";
import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository";
import logger from "@calcom/lib/logger";
import { getTranslation } from "@calcom/i18n/server";
import type { z } from "zod";
import { getAffectedMembersForDisable } from "./getAffectedMembersForDisable.handler";
import type { DelegationCredentialToggleEnabledSchema } from "./schema";
import { ensureNoServiceAccountKey } from "./utils";
const log = logger.getSubLogger({ prefix: ["viewer", "delegationCredential", "toggleEnabled"] });
type LoggedInUser = {
id: number;
email: string;
locale: string;
emailVerified: Date | null;
organizationId: number | null;
};
export default async function toggleEnabledHandler({
ctx,
input,
}: {
ctx: {
user: LoggedInUser;
};
input: z.infer<typeof DelegationCredentialToggleEnabledSchema>;
}) {
const { user: loggedInUser } = ctx;
const t = await getTranslation(ctx.user.locale ?? "en", "common");
if (!loggedInUser.emailVerified) {
throw new Error(t("verify_your_email"));
}
return toggleDelegationCredentialEnabled(loggedInUser, input);
}
export async function toggleDelegationCredentialEnabled(
loggedInUser: Omit<LoggedInUser, "locale" | "emailVerified">,
input: z.infer<typeof DelegationCredentialToggleEnabledSchema>
) {
// Fetch the current credential to check the current enabled state
const currentDelegationCredential = await DelegationCredentialRepository.findById({
id: input.id,
});
if (!currentDelegationCredential) {
throw new Error("Delegation credential not found");
}
if (!loggedInUser.organizationId) {
throw new Error("You must be part of an organization to toggle a delegation credential");
}
if (currentDelegationCredential.organizationId !== loggedInUser.organizationId) {
throw new Error("Delegation credential not found");
}
const shouldBeEnabled = input.enabled;
if (shouldBeEnabled === currentDelegationCredential.enabled) {
// Already enabled or disabled, so no need to do anything
return currentDelegationCredential;
}
if (shouldBeEnabled) {
await assertWorkspaceConfigured({
delegationCredentialId: input.id,
user: loggedInUser,
});
}
if (!shouldBeEnabled) {
const affectedMemberships = await getAffectedMembersForDisable({ delegationCredentialId: input.id });
const slug = currentDelegationCredential.workspacePlatform?.slug;
if (!slug) {
log.error(`Delegation credential ${input.id} has no workspace platform slug`);
}
let calendarAppName: string;
let conferencingAppName: string;
if (slug === "google") {
calendarAppName = "Google Calendar";
conferencingAppName = "Google Meet";
} else if (slug === "office365") {
calendarAppName = "Microsoft 365";
conferencingAppName = "Microsoft Teams";
} else {
throw new Error(`Unsupported workspace platform slug: ${slug}`);
}
for (const membership of affectedMemberships) {
if (membership.email) {
await sendDelegationCredentialDisabledEmail({
recipientEmail: membership.email,
recipientName: membership.name || undefined,
calendarAppName,
conferencingAppName,
});
}
}
}
const updatedDelegationCredential = await DelegationCredentialRepository.updateById({
id: input.id,
data: {
enabled: shouldBeEnabled,
// Don't touch lastEnabledAt if we are disabling
lastEnabledAt: shouldBeEnabled ? new Date() : undefined,
// Don't touch lastDisabledAt if we are enabling
lastDisabledAt: shouldBeEnabled ? undefined : new Date(),
},
});
return ensureNoServiceAccountKey(updatedDelegationCredential);
}
const assertWorkspaceConfigured = async ({
delegationCredentialId,
user,
}: {
delegationCredentialId: string;
user: { id: number; email: string; organizationId: number | null };
}) => {
const delegationCredential = await DelegationCredentialRepository.findByIdIncludeSensitiveServiceAccountKey(
{
id: delegationCredentialId,
}
);
if (!delegationCredential) {
throw new Error("Domain wide delegation not found");
}
if (!hasServiceAccountKey(delegationCredential)) {
throw new Error("Domain wide delegation doesn't have service account key");
}
await assertSuccessfullyConfiguredInWorkspace({
delegationCredential,
user,
});
};
function hasServiceAccountKey<T extends { serviceAccountKey: ServiceAccountKey | null }>(
delegationCredential: T
): delegationCredential is T & { serviceAccountKey: ServiceAccountKey } {
return delegationCredential.serviceAccountKey !== null;
}