chore: ensure default calendars for delegated users (#20300)
* chore: ensure default calendars for delegated users * fixup! chore: ensure default calendars for delegated users
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { CalendarsService } from "@/ee/calendars/services/calendars.service";
|
||||
import { Process, Processor } from "@nestjs/bull";
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { Job } from "bull";
|
||||
|
||||
export const DEFAULT_CALENDARS_JOB = "default_calendars_job";
|
||||
export const CALENDARS_QUEUE = "calendars";
|
||||
export type DefaultCalendarsJobDataType = {
|
||||
userId: number;
|
||||
};
|
||||
|
||||
@Processor(CALENDARS_QUEUE)
|
||||
export class CalendarsProcessor {
|
||||
private readonly logger = new Logger(CalendarsProcessor.name);
|
||||
|
||||
constructor(public readonly calendarsService: CalendarsService) {}
|
||||
|
||||
@Process(DEFAULT_CALENDARS_JOB)
|
||||
async handleEnsureDefaultCalendars(job: Job<DefaultCalendarsJobDataType>) {
|
||||
const { userId } = job.data;
|
||||
try {
|
||||
// getCalendars calls getConnectedDestinationCalendarsAndEnsureDefaultsInDb from platform libraries
|
||||
// which gets the calendars from third party providers and ensure default calendars are set in DB
|
||||
await this.calendarsService.getCalendars(userId);
|
||||
} catch (err) {
|
||||
this.logger.error(`Failed to load default calendars of user with id: ${userId}`, {
|
||||
userId,
|
||||
err,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
+18
-1
@@ -1,3 +1,5 @@
|
||||
import { CalendarsModule } from "@/ee/calendars/calendars.module";
|
||||
import { CALENDARS_QUEUE, CalendarsProcessor } from "@/ee/calendars/processors/calendars.processor";
|
||||
import { MembershipsModule } from "@/modules/memberships/memberships.module";
|
||||
import { OrganizationsDelegationCredentialController } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.controller";
|
||||
import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository";
|
||||
@@ -5,16 +7,31 @@ import { OrganizationsRepository } from "@/modules/organizations/index/organizat
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { RedisModule } from "@/modules/redis/redis.module";
|
||||
import { StripeModule } from "@/modules/stripe/stripe.module";
|
||||
import { BullModule } from "@nestjs/bull";
|
||||
import { Module } from "@nestjs/common";
|
||||
|
||||
import { OrganizationsDelegationCredentialService } from "./services/organizations-delegation-credential.service";
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, StripeModule, RedisModule, MembershipsModule],
|
||||
imports: [
|
||||
PrismaModule,
|
||||
StripeModule,
|
||||
RedisModule,
|
||||
CalendarsModule,
|
||||
MembershipsModule,
|
||||
BullModule.registerQueue({
|
||||
name: CALENDARS_QUEUE,
|
||||
limiter: {
|
||||
max: 1,
|
||||
duration: 1000,
|
||||
},
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
OrganizationsDelegationCredentialService,
|
||||
OrganizationsDelegationCredentialRepository,
|
||||
OrganizationsRepository,
|
||||
CalendarsProcessor,
|
||||
],
|
||||
controllers: [OrganizationsDelegationCredentialController],
|
||||
})
|
||||
|
||||
+12
@@ -28,4 +28,16 @@ export class OrganizationsDelegationCredentialRepository {
|
||||
include: { workspacePlatform: true },
|
||||
});
|
||||
}
|
||||
|
||||
async findDelegatedUserProfiles(orgId: number, domain: string) {
|
||||
return this.dbRead.prisma.profile.findMany({
|
||||
select: {
|
||||
userId: true,
|
||||
},
|
||||
where: {
|
||||
organizationId: orgId,
|
||||
user: { email: { endsWith: domain } },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+47
-3
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
CALENDARS_QUEUE,
|
||||
DEFAULT_CALENDARS_JOB,
|
||||
DefaultCalendarsJobDataType,
|
||||
} from "@/ee/calendars/processors/calendars.processor";
|
||||
import { CreateDelegationCredentialInput } from "@/modules/organizations/delegation-credentials/inputs/create-delegation-credential.input";
|
||||
import {
|
||||
GoogleServiceAccountKeyInput,
|
||||
@@ -5,9 +10,10 @@ import {
|
||||
} from "@/modules/organizations/delegation-credentials/inputs/service-account-key.input";
|
||||
import { UpdateDelegationCredentialInput } from "@/modules/organizations/delegation-credentials/inputs/update-delegation-credential.input";
|
||||
import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository";
|
||||
import { DelegationCredentialOutput } from "@/modules/organizations/delegation-credentials/outputs/delegation-credential.output";
|
||||
import { Injectable, NotFoundException } from "@nestjs/common";
|
||||
import { InjectQueue } from "@nestjs/bull";
|
||||
import { Injectable, NotFoundException, Logger } from "@nestjs/common";
|
||||
import { User } from "@prisma/client";
|
||||
import { Queue } from "bull";
|
||||
|
||||
import { encryptServiceAccountKey } from "@calcom/platform-libraries";
|
||||
import {
|
||||
@@ -17,8 +23,11 @@ import {
|
||||
|
||||
@Injectable()
|
||||
export class OrganizationsDelegationCredentialService {
|
||||
private logger = new Logger("OrganizationsDelegationCredentialService");
|
||||
|
||||
constructor(
|
||||
private readonly organizationsDelegationCredentialRepository: OrganizationsDelegationCredentialRepository
|
||||
private readonly organizationsDelegationCredentialRepository: OrganizationsDelegationCredentialRepository,
|
||||
@InjectQueue(CALENDARS_QUEUE) private readonly calendarsQueue: Queue
|
||||
) {}
|
||||
async createDelegationCredential(
|
||||
orgId: number,
|
||||
@@ -59,9 +68,44 @@ export class OrganizationsDelegationCredentialService {
|
||||
await this.updateDelegationCredentialServiceAccountKey(delegationCredentialId, body.serviceAccountKey);
|
||||
}
|
||||
|
||||
// once delegation credentials are enabled, slowly set all the destination calendars of delegated users
|
||||
if (body.enabled === true && delegationCredential.enabled === false) {
|
||||
await this.ensureDefaultCalendars(orgId, delegationCredential.domain);
|
||||
}
|
||||
|
||||
return { ...delegationCredential, enabled: body?.enabled ?? delegationCredential?.enabled };
|
||||
}
|
||||
|
||||
async ensureDefaultCalendars(orgId: number, domain: string) {
|
||||
try {
|
||||
const delegatedUserProfiles =
|
||||
await this.organizationsDelegationCredentialRepository.findDelegatedUserProfiles(orgId, domain);
|
||||
|
||||
delegatedUserProfiles.forEach(async (profile) => {
|
||||
if (profile.userId) {
|
||||
const job = await this.calendarsQueue.getJob(`${DEFAULT_CALENDARS_JOB}_${profile.userId}`);
|
||||
if (job) {
|
||||
await job.remove();
|
||||
this.logger.log(`Removed default calendar job for user with id: ${profile.userId}`);
|
||||
}
|
||||
this.logger.log(`Adding default calendar job for user with id: ${profile.userId}`);
|
||||
await this.calendarsQueue.add(
|
||||
DEFAULT_CALENDARS_JOB,
|
||||
{
|
||||
userId: profile.userId,
|
||||
} satisfies DefaultCalendarsJobDataType,
|
||||
{ jobId: `${DEFAULT_CALENDARS_JOB}_${profile.userId}`, removeOnComplete: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.error(
|
||||
err,
|
||||
`Could not ensure default calendars for delegated users in org with id:${orgId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async updateDelegationCredentialEnabled(
|
||||
orgId: number,
|
||||
delegationCredentialId: string,
|
||||
|
||||
Reference in New Issue
Block a user