fix: delegation credential error webhooks + refactor repeated code (#25232)
* fix: delegation credential error webhooks * refactor: extract repeated delegation credential error webhook logic into helper methods - Added private triggerDelegationCredentialError method in Office365CalendarService class - Added triggerDelegationCredentialError helper function in TeamsVideoApiAdapter - Replaced all 4 instances in Office365CalendarService with helper method call - Replaced all 4 instances in TeamsVideoApiAdapter with helper function call - Keeps code DRY by eliminating repeated if statement and webhook trigger logic Co-Authored-By: morgan@cal.com <morgan@cal.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
morgan@cal.com
Devin AI
parent
7f1b94ad19
commit
b8530e2d78
@@ -140,7 +140,7 @@ export class CalendarAuth {
|
||||
delegationError = new CalendarAppDelegationCredentialError("Error authorizing delegation credential");
|
||||
}
|
||||
|
||||
if (user && user.email && this.credential.appId) {
|
||||
if (user && user.email && this.credential.appId && this.credential.delegatedToId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error: delegationError,
|
||||
credential: {
|
||||
@@ -152,7 +152,7 @@ export class CalendarAuth {
|
||||
id: this.credential.userId ?? 0,
|
||||
email: user.email,
|
||||
},
|
||||
orgId: this.credential.teamId,
|
||||
delegationCredentialId: this.credential.delegatedToId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,29 @@ export default class Office365CalendarService implements Calendar {
|
||||
this.log = logger.getSubLogger({ prefix: [`[[lib] ${this.integrationName}`] });
|
||||
}
|
||||
|
||||
private async triggerDelegationCredentialError(error: Error): Promise<void> {
|
||||
if (
|
||||
this.credential.userId &&
|
||||
this.credential.user &&
|
||||
this.credential.appId &&
|
||||
this.credential.delegatedToId
|
||||
) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: this.credential.id,
|
||||
type: this.credential.type,
|
||||
appId: this.credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: this.credential.userId,
|
||||
email: this.credential.user.email,
|
||||
},
|
||||
delegationCredentialId: this.credential.delegatedToId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async getAuthUrl(delegatedTo: boolean, tenantId?: string): Promise<string> {
|
||||
if (delegatedTo) {
|
||||
if (!tenantId) {
|
||||
@@ -131,21 +154,7 @@ export default class Office365CalendarService implements Calendar {
|
||||
"Invalid DelegationCredential Settings: tenantId is missing"
|
||||
);
|
||||
|
||||
if (this.credential.userId && this.credential.user && this.credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: this.credential.id,
|
||||
type: this.credential.type,
|
||||
appId: this.credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: this.credential.userId,
|
||||
email: this.credential.user.email,
|
||||
},
|
||||
orgId: this.credential.teamId,
|
||||
});
|
||||
}
|
||||
await this.triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -165,21 +174,7 @@ export default class Office365CalendarService implements Calendar {
|
||||
"Delegation credential without clientId or Secret"
|
||||
);
|
||||
|
||||
if (this.credential.userId && this.credential.user && this.credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: this.credential.id,
|
||||
type: this.credential.type,
|
||||
appId: this.credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: this.credential.userId,
|
||||
email: this.credential.user.email,
|
||||
},
|
||||
orgId: this.credential.teamId,
|
||||
});
|
||||
}
|
||||
await this.triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -207,21 +202,7 @@ export default class Office365CalendarService implements Calendar {
|
||||
"Delegation credential without clientId or Secret"
|
||||
);
|
||||
|
||||
if (this.credential.userId && this.credential.user && this.credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: this.credential.id,
|
||||
type: this.credential.type,
|
||||
appId: this.credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: this.credential.userId,
|
||||
email: this.credential.user.email,
|
||||
},
|
||||
orgId: this.credential.teamId,
|
||||
});
|
||||
}
|
||||
await this.triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -260,21 +241,7 @@ export default class Office365CalendarService implements Calendar {
|
||||
"User might not exist in Microsoft Azure Active Directory"
|
||||
);
|
||||
|
||||
if (this.credential.userId && this.credential.user && this.credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: this.credential.id,
|
||||
type: this.credential.type,
|
||||
appId: this.credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: this.credential.userId ?? 0,
|
||||
email: this.credential.user.email,
|
||||
},
|
||||
orgId: this.credential.teamId,
|
||||
});
|
||||
}
|
||||
await this.triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,24 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant
|
||||
let azureUserId: string | null;
|
||||
const tokenResponse = oAuthManagerHelper.getTokenObjectFromCredential(credential);
|
||||
|
||||
async function triggerDelegationCredentialError(error: Error): Promise<void> {
|
||||
if (credential.userId && credential.user && credential.appId && credential.delegatedToId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
appId: credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: credential.userId ?? 0,
|
||||
email: credential.user.email,
|
||||
},
|
||||
delegationCredentialId: credential.delegatedToId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const auth = new OAuthManager({
|
||||
credentialSyncVariables: oAuthManagerHelper.credentialSyncVariables,
|
||||
resourceOwner: {
|
||||
@@ -68,21 +86,7 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant
|
||||
"Delegation credential without clientId or Secret"
|
||||
);
|
||||
|
||||
if (credential.userId && credential.user && credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
appId: credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: credential.userId ?? 0,
|
||||
email: credential.user.email,
|
||||
},
|
||||
orgId: credential.teamId,
|
||||
});
|
||||
}
|
||||
await triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -130,21 +134,7 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant
|
||||
"Invalid DelegationCredential Settings: tenantId is missing"
|
||||
);
|
||||
|
||||
if (credential.userId && credential.user && credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
appId: credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: credential.userId ?? 0,
|
||||
email: credential.user.email,
|
||||
},
|
||||
orgId: credential.teamId,
|
||||
});
|
||||
}
|
||||
await triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -179,21 +169,7 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant
|
||||
"Delegation credential without clientId or Secret"
|
||||
);
|
||||
|
||||
if (credential.userId && credential.user && credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
appId: credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: credential.userId ?? 0,
|
||||
email: credential.user.email,
|
||||
},
|
||||
orgId: credential.teamId,
|
||||
});
|
||||
}
|
||||
await triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -231,21 +207,7 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant
|
||||
"User might not exist in Microsoft Azure Active Directory"
|
||||
);
|
||||
|
||||
if (credential.userId && credential.user && credential.appId) {
|
||||
await triggerDelegationCredentialErrorWebhook({
|
||||
error,
|
||||
credential: {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
appId: credential.appId,
|
||||
},
|
||||
user: {
|
||||
id: credential.userId ?? 0,
|
||||
email: credential.user.email,
|
||||
},
|
||||
orgId: credential.teamId,
|
||||
});
|
||||
}
|
||||
await triggerDelegationCredentialError(error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -498,10 +498,12 @@ export type DelegationCredentialErrorPayloadType = {
|
||||
id: number;
|
||||
type: string;
|
||||
appId: string;
|
||||
delegationCredentialId?: string;
|
||||
};
|
||||
user: {
|
||||
id: number;
|
||||
email: string;
|
||||
organizationId?: number;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -261,6 +261,36 @@ export class WebhookRepository implements IWebhookRepository {
|
||||
});
|
||||
}
|
||||
|
||||
async findByOrgIdAndTrigger({
|
||||
orgId,
|
||||
triggerEvent,
|
||||
}: {
|
||||
orgId: number;
|
||||
triggerEvent: WebhookTriggerEvents;
|
||||
}): Promise<WebhookSubscriber[]> {
|
||||
return await this.prisma.webhook.findMany({
|
||||
where: {
|
||||
teamId: orgId,
|
||||
platform: false,
|
||||
eventTriggers: { has: triggerEvent },
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
subscriberUrl: true,
|
||||
payloadTemplate: true,
|
||||
active: true,
|
||||
eventTriggers: true,
|
||||
secret: true,
|
||||
teamId: true,
|
||||
userId: true,
|
||||
platform: true,
|
||||
time: true,
|
||||
timeUnit: true,
|
||||
appId: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getFilteredWebhooksForUser({ userId, userRole }: { userId: number; userRole?: UserPermissionRole }) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository";
|
||||
import { DelegationCredentialErrorPayloadType } from "@calcom/features/webhooks/lib/dto/types";
|
||||
import type { CalendarAppDelegationCredentialError } from "@calcom/lib/CalendarAppError";
|
||||
import logger from "@calcom/lib/logger";
|
||||
@@ -15,24 +16,30 @@ export async function triggerDelegationCredentialErrorWebhook(params: {
|
||||
error: CalendarAppDelegationCredentialError;
|
||||
credential: DelegationCredentialErrorPayloadType["credential"];
|
||||
user: DelegationCredentialErrorPayloadType["user"];
|
||||
orgId?: number | null;
|
||||
delegationCredentialId: string;
|
||||
}): Promise<void> {
|
||||
try {
|
||||
const { error, credential, user, orgId } = params;
|
||||
const { error, credential, user, delegationCredentialId } = params;
|
||||
|
||||
if (!orgId) {
|
||||
log.debug("Skipping webhook emission - no organization context");
|
||||
const delegationCredential = await DelegationCredentialRepository.findById({
|
||||
id: delegationCredentialId,
|
||||
});
|
||||
|
||||
if (!delegationCredential) {
|
||||
log.debug("No delegation credential found", { delegationCredentialId });
|
||||
return;
|
||||
}
|
||||
|
||||
const webhookRepository = WebhookRepository.getInstance();
|
||||
const webhooks = await webhookRepository.getSubscribers({
|
||||
teamId: orgId,
|
||||
const webhooks = await webhookRepository.findByOrgIdAndTrigger({
|
||||
orgId: delegationCredential.organizationId,
|
||||
triggerEvent: WebhookTriggerEvents.DELEGATION_CREDENTIAL_ERROR,
|
||||
});
|
||||
|
||||
if (webhooks.length === 0) {
|
||||
log.debug("No webhooks subscribed to DELEGATION_CREDENTIAL_ERROR for organization", { orgId });
|
||||
log.debug("No webhooks subscribed to DELEGATION_CREDENTIAL_ERROR for organization", {
|
||||
orgId: delegationCredential.organizationId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,10 +52,12 @@ export async function triggerDelegationCredentialErrorWebhook(params: {
|
||||
id: credential.id,
|
||||
type: credential.type,
|
||||
appId: credential.appId || "unknown",
|
||||
delegationCredentialId: delegationCredential.id,
|
||||
},
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
organizationId: delegationCredential.organizationId,
|
||||
},
|
||||
} satisfies DelegationCredentialErrorPayloadType;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user