diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts index 772a243c83..23b8cda8e3 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts @@ -8,7 +8,6 @@ import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_ import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service"; import { SchedulesRepository_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.repository"; import { AppsRepository } from "@/modules/apps/apps.repository"; -import { ConferencingModule } from "@/modules/conferencing/conferencing.module"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; import { MembershipsModule } from "@/modules/memberships/memberships.module"; import { PrismaModule } from "@/modules/prisma/prisma.module"; @@ -19,7 +18,7 @@ import { UsersRepository } from "@/modules/users/users.repository"; import { Module } from "@nestjs/common"; @Module({ - imports: [PrismaModule, MembershipsModule, TokensModule, SelectedCalendarsModule, ConferencingModule], + imports: [PrismaModule, MembershipsModule, TokensModule, SelectedCalendarsModule], providers: [ EventTypesRepository_2024_06_14, EventTypesService_2024_06_14, diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts index a932f6b3eb..a234b145fe 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts @@ -5,6 +5,9 @@ import { ConferencingService } from "@/modules/conferencing/services/conferencin import { UserWithProfile } from "@/modules/users/users.repository"; import { Injectable, BadRequestException } from "@nestjs/common"; +import { CONFERENCING_APPS } from "@calcom/platform-constants"; +import { getUsersCredentials } from "@calcom/platform-libraries"; +import { getApps } from "@calcom/platform-libraries/app-store"; import { transformBookingFieldsApiToInternal, transformLocationsApiToInternal, @@ -50,8 +53,7 @@ interface ValidationContext { export class InputEventTypesService_2024_06_14 { constructor( private readonly eventTypesRepository: EventTypesRepository_2024_06_14, - private readonly calendarsService: CalendarsService, - private readonly conferencingService: ConferencingService + private readonly calendarsService: CalendarsService ) {} async transformAndValidateCreateEventTypeInput( @@ -457,10 +459,32 @@ export class InputEventTypesService_2024_06_14 { if (location.type === "integration") { // cal-video is global, so we can skip this check if (location.integration !== "cal-video") { - await this.conferencingService.checkAppIsValidAndConnected(user, location.integration); + await this.checkAppIsValidAndConnected(user, location.integration); } } }) ?? [] ); } + + async checkAppIsValidAndConnected(user: UserWithProfile, appSlug: string) { + const conferencingApps = ["google-meet", "office365-video", "zoom"]; + if (!conferencingApps.includes(appSlug)) { + throw new BadRequestException("Invalid app, available apps are: ", conferencingApps.join(", ")); + } + + if (appSlug === "office365-video") { + appSlug = "msteams"; + } + + const credentials = await getUsersCredentials(user); + + const foundApp = getApps(credentials, true).filter((app) => app.slug === appSlug)[0]; + + const appLocation = foundApp?.appData?.location; + + if (!foundApp || !appLocation) { + throw new BadRequestException(`${appSlug} not connected.`); + } + return foundApp.credential; + } } diff --git a/apps/api/v2/src/modules/organizations/event-types/services/input.service.ts b/apps/api/v2/src/modules/organizations/event-types/services/input.service.ts index 76de368874..974ff71828 100644 --- a/apps/api/v2/src/modules/organizations/event-types/services/input.service.ts +++ b/apps/api/v2/src/modules/organizations/event-types/services/input.service.ts @@ -1,4 +1,5 @@ import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/input-event-types.service"; +import { ConferencingRepository } from "@/modules/conferencing/repositories/conferencing.repository"; import { OrganizationsConferencingService } from "@/modules/organizations/conferencing/services/organizations-conferencing.service"; import { TeamsEventTypesRepository } from "@/modules/teams/event-types/teams-event-types.repository"; import { TeamsRepository } from "@/modules/teams/teams/teams.repository"; @@ -27,7 +28,8 @@ export class InputOrganizationsEventTypesService { private readonly teamsRepository: TeamsRepository, private readonly usersRepository: UsersRepository, private readonly teamsEventTypesRepository: TeamsEventTypesRepository, - private readonly conferencingService: OrganizationsConferencingService + private readonly conferencingService: OrganizationsConferencingService, + private readonly conferencingRepository: ConferencingRepository ) {} async transformAndValidateCreateTeamEventTypeInput( userId: number, @@ -306,6 +308,22 @@ export class InputOrganizationsEventTypesService { }) ?? [] ); } + + async checkAppIsValidAndConnected(teamId: number, app: string) { + const conferencingApps = ["google-meet", "office365-video", "zoom"]; + if (!conferencingApps.includes(app)) { + throw new BadRequestException("Invalid app, available apps are: ", conferencingApps.join(", ")); + } + if (app === "office365-video") { + app = "msteams"; + } + const credential = await this.conferencingRepository.findTeamConferencingApp(teamId, app); + + if (!credential) { + throw new BadRequestException(`${app} not connected.`); + } + return credential; + } } function getPriorityValue(priority: keyof typeof HostPriority): number { diff --git a/apps/api/v2/src/modules/teams/event-types/teams-event-types.module.ts b/apps/api/v2/src/modules/teams/event-types/teams-event-types.module.ts index ac7419ad5e..843dda9ff2 100644 --- a/apps/api/v2/src/modules/teams/event-types/teams-event-types.module.ts +++ b/apps/api/v2/src/modules/teams/event-types/teams-event-types.module.ts @@ -1,4 +1,5 @@ import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module"; +import { ConferencingRepository } from "@/modules/conferencing/repositories/conferencing.repository"; import { MembershipsModule } from "@/modules/memberships/memberships.module"; import { OrganizationsConferencingModule } from "@/modules/organizations/conferencing/organizations-conferencing.module"; import { OutputTeamEventTypesResponsePipe } from "@/modules/organizations/event-types/pipes/team-event-types-response.transformer"; @@ -31,6 +32,7 @@ import { Module } from "@nestjs/common"; OrganizationsTeamsRepository, OutputTeamEventTypesResponsePipe, OutputOrganizationsEventTypesService, + ConferencingRepository, ], exports: [TeamsEventTypesRepository, TeamsEventTypesService], controllers: [TeamsEventTypesController], diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json index ad281f3b00..9537893286 100644 --- a/apps/api/v2/swagger/documentation.json +++ b/apps/api/v2/swagger/documentation.json @@ -17104,154 +17104,6 @@ "data" ] }, - "ConferencingAppsOutputDto": { - "type": "object", - "properties": { - "id": { - "type": "number", - "description": "Id of the conferencing app credentials" - }, - "type": { - "type": "string", - "example": "google_video", - "description": "Type of conferencing app" - }, - "userId": { - "type": "number", - "description": "Id of the user associated to the conferencing app" - }, - "invalid": { - "type": "boolean", - "nullable": true, - "example": true, - "description": "Whether if the connection is working or not." - } - }, - "required": [ - "id", - "type", - "userId" - ] - }, - "ConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "data": { - "$ref": "#/components/schemas/ConferencingAppsOutputDto" - } - }, - "required": [ - "status", - "data" - ] - }, - "GetConferencingAppsOauthUrlResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": [ - "success", - "error" - ] - } - }, - "required": [ - "status" - ] - }, - "ConferencingAppsOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConferencingAppsOutputDto" - } - } - }, - "required": [ - "status", - "data" - ] - }, - "SetDefaultConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": [ - "success", - "error" - ] - } - }, - "required": [ - "status" - ] - }, - "DefaultConferencingAppsOutputDto": { - "type": "object", - "properties": { - "appSlug": { - "type": "string" - }, - "appLink": { - "type": "string" - } - } - }, - "GetDefaultConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": [ - "success", - "error" - ] - }, - "data": { - "$ref": "#/components/schemas/DefaultConferencingAppsOutputDto" - } - }, - "required": [ - "status" - ] - }, - "DisconnectConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": [ - "success", - "error" - ] - } - }, - "required": [ - "status" - ] - }, "OrgTeamOutputDto": { "type": "object", "properties": { @@ -21143,6 +20995,154 @@ "data" ] }, + "ConferencingAppsOutputDto": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "Id of the conferencing app credentials" + }, + "type": { + "type": "string", + "example": "google_video", + "description": "Type of conferencing app" + }, + "userId": { + "type": "number", + "description": "Id of the user associated to the conferencing app" + }, + "invalid": { + "type": "boolean", + "nullable": true, + "example": true, + "description": "Whether if the connection is working or not." + } + }, + "required": [ + "id", + "type", + "userId" + ] + }, + "ConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "data": { + "$ref": "#/components/schemas/ConferencingAppsOutputDto" + } + }, + "required": [ + "status", + "data" + ] + }, + "GetConferencingAppsOauthUrlResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": [ + "success", + "error" + ] + } + }, + "required": [ + "status" + ] + }, + "ConferencingAppsOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "success", + "error" + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConferencingAppsOutputDto" + } + } + }, + "required": [ + "status", + "data" + ] + }, + "SetDefaultConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": [ + "success", + "error" + ] + } + }, + "required": [ + "status" + ] + }, + "DefaultConferencingAppsOutputDto": { + "type": "object", + "properties": { + "appSlug": { + "type": "string" + }, + "appLink": { + "type": "string" + } + } + }, + "GetDefaultConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": [ + "success", + "error" + ] + }, + "data": { + "$ref": "#/components/schemas/DefaultConferencingAppsOutputDto" + } + }, + "required": [ + "status" + ] + }, + "DisconnectConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": [ + "success", + "error" + ] + } + }, + "required": [ + "status" + ] + }, "GoogleServiceAccountKeyInput": { "type": "object", "properties": { diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index 16892a1f6c..da00831bc4 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -15979,118 +15979,6 @@ }, "required": ["status", "data"] }, - "ConferencingAppsOutputDto": { - "type": "object", - "properties": { - "id": { - "type": "number", - "description": "Id of the conferencing app credentials" - }, - "type": { - "type": "string", - "example": "google_video", - "description": "Type of conferencing app" - }, - "userId": { - "type": "number", - "description": "Id of the user associated to the conferencing app" - }, - "invalid": { - "type": "boolean", - "nullable": true, - "example": true, - "description": "Whether if the connection is working or not." - } - }, - "required": ["id", "type", "userId"] - }, - "ConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": ["success", "error"] - }, - "data": { - "$ref": "#/components/schemas/ConferencingAppsOutputDto" - } - }, - "required": ["status", "data"] - }, - "GetConferencingAppsOauthUrlResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": ["success", "error"] - } - }, - "required": ["status"] - }, - "ConferencingAppsOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": ["success", "error"] - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConferencingAppsOutputDto" - } - } - }, - "required": ["status", "data"] - }, - "SetDefaultConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": ["success", "error"] - } - }, - "required": ["status"] - }, - "DefaultConferencingAppsOutputDto": { - "type": "object", - "properties": { - "appSlug": { - "type": "string" - }, - "appLink": { - "type": "string" - } - } - }, - "GetDefaultConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": ["success", "error"] - }, - "data": { - "$ref": "#/components/schemas/DefaultConferencingAppsOutputDto" - } - }, - "required": ["status"] - }, - "DisconnectConferencingAppOutputResponseDto": { - "type": "object", - "properties": { - "status": { - "type": "string", - "example": "success", - "enum": ["success", "error"] - } - }, - "required": ["status"] - }, "OrgTeamOutputDto": { "type": "object", "properties": { @@ -19417,6 +19305,118 @@ }, "required": ["status", "data"] }, + "ConferencingAppsOutputDto": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "Id of the conferencing app credentials" + }, + "type": { + "type": "string", + "example": "google_video", + "description": "Type of conferencing app" + }, + "userId": { + "type": "number", + "description": "Id of the user associated to the conferencing app" + }, + "invalid": { + "type": "boolean", + "nullable": true, + "example": true, + "description": "Whether if the connection is working or not." + } + }, + "required": ["id", "type", "userId"] + }, + "ConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["success", "error"] + }, + "data": { + "$ref": "#/components/schemas/ConferencingAppsOutputDto" + } + }, + "required": ["status", "data"] + }, + "GetConferencingAppsOauthUrlResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + } + }, + "required": ["status"] + }, + "ConferencingAppsOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["success", "error"] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConferencingAppsOutputDto" + } + } + }, + "required": ["status", "data"] + }, + "SetDefaultConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + } + }, + "required": ["status"] + }, + "DefaultConferencingAppsOutputDto": { + "type": "object", + "properties": { + "appSlug": { + "type": "string" + }, + "appLink": { + "type": "string" + } + } + }, + "GetDefaultConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + }, + "data": { + "$ref": "#/components/schemas/DefaultConferencingAppsOutputDto" + } + }, + "required": ["status"] + }, + "DisconnectConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + } + }, + "required": ["status"] + }, "GoogleServiceAccountKeyInput": { "type": "object", "properties": {