diff --git a/apps/web/server/routers/viewer/eventTypes.tsx b/apps/web/server/routers/viewer/eventTypes.tsx index dd165ced..bbc2822a 100644 --- a/apps/web/server/routers/viewer/eventTypes.tsx +++ b/apps/web/server/routers/viewer/eventTypes.tsx @@ -3,12 +3,8 @@ import short from "short-uuid"; import { v5 as uuidv5 } from "uuid"; import { z } from "zod"; -import { - _AvailabilityModel, - _DestinationCalendarModel, - _EventTypeCustomInputModel, - _EventTypeModel, -} from "@calcom/prisma/zod"; +import getAppKeysFromSlug from "@calcom/app-store/_utils/getAppKeysFromSlug"; +import { _DestinationCalendarModel, _EventTypeCustomInputModel, _EventTypeModel } from "@calcom/prisma/zod"; import { stringOrNumber } from "@calcom/prisma/zod-utils"; import { createEventTypeInput } from "@calcom/prisma/zod/custom/eventtype"; @@ -128,7 +124,8 @@ export const eventTypesRouter = createProtectedRouter() }, }; - if (process.env.DAILY_API_KEY) { + const appKeys = await getAppKeysFromSlug("dailyvideo"); + if (typeof appKeys.api_key === "string") { data.locations = [{ type: "integrations:daily" }]; } diff --git a/packages/app-store/tandemvideo/_metadata.ts b/packages/app-store/tandemvideo/_metadata.ts index 6cb4d6d2..9e1239cf 100644 --- a/packages/app-store/tandemvideo/_metadata.ts +++ b/packages/app-store/tandemvideo/_metadata.ts @@ -6,7 +6,6 @@ import _package from "./package.json"; export const metadata = { name: "Tandem Video", description: _package.description, - installed: !!(process.env.TANDEM_CLIENT_ID && process.env.TANDEM_CLIENT_SECRET), type: "tandem_video", title: "Tandem Video", imageSrc: "/api/app-store/tandemvideo/icon.svg", diff --git a/packages/app-store/tandemvideo/api/add.ts b/packages/app-store/tandemvideo/api/add.ts index 9db60951..bd73bdb2 100644 --- a/packages/app-store/tandemvideo/api/add.ts +++ b/packages/app-store/tandemvideo/api/add.ts @@ -1,11 +1,13 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { stringify } from "querystring"; -import { BASE_URL } from "@calcom/lib/constants"; +import { WEBAPP_URL } from "@calcom/lib/constants"; import prisma from "@calcom/prisma"; -const client_id = process.env.TANDEM_CLIENT_ID; -const TANDEM_BASE_URL = process.env.TANDEM_BASE_URL; +import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; + +let client_id = ""; +let base_url = ""; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "GET") { @@ -20,14 +22,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }, }); - const redirect_uri = encodeURI(BASE_URL + "/api/integrations/tandemvideo/callback"); + const appKeys = await getAppKeysFromSlug("tandem"); + if (typeof appKeys.client_id === "string") client_id = appKeys.client_id; + if (typeof appKeys.base_url === "string") base_url = appKeys.base_url; + if (!client_id) return res.status(400).json({ message: "Tandem client_id missing." }); + if (!base_url) return res.status(400).json({ message: "Tandem base_url missing." }); + + const redirect_uri = encodeURI(WEBAPP_URL + "/api/integrations/tandemvideo/callback"); const params = { client_id, redirect_uri, }; const query = stringify(params); - const url = `${TANDEM_BASE_URL}/oauth/approval?${query}`; + const url = `${base_url}/oauth/approval?${query}`; res.status(200).json({ url }); } } diff --git a/packages/app-store/tandemvideo/api/callback.ts b/packages/app-store/tandemvideo/api/callback.ts index 9df4dabe..66c2a701 100644 --- a/packages/app-store/tandemvideo/api/callback.ts +++ b/packages/app-store/tandemvideo/api/callback.ts @@ -2,9 +2,11 @@ import type { NextApiRequest, NextApiResponse } from "next"; import prisma from "@calcom/prisma"; -const client_id = process.env.TANDEM_CLIENT_ID as string; -const client_secret = process.env.TANDEM_CLIENT_SECRET as string; -const TANDEM_BASE_URL = (process.env.TANDEM_BASE_URL as string) || "https://tandem.chat"; +import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; + +let client_id = ""; +let client_secret = ""; +let base_url = "https://tandem.chat"; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (!req.query.code) { @@ -14,7 +16,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const code = req.query.code as string; - const result = await fetch(`${TANDEM_BASE_URL}/api/v1/oauth/v2/token`, { + const appKeys = await getAppKeysFromSlug("tandem"); + if (typeof appKeys.client_id === "string") client_id = appKeys.client_id; + if (typeof appKeys.client_secret === "string") client_secret = appKeys.client_secret; + if (typeof appKeys.base_url === "string") base_url = appKeys.base_url; + if (!client_id) return res.status(400).json({ message: "Tandem client_id missing." }); + if (!client_secret) return res.status(400).json({ message: "Tandem client_secret missing." }); + if (!base_url) return res.status(400).json({ message: "Tandem base_url missing." }); + + const result = await fetch(`${base_url}/api/v1/oauth/v2/token`, { method: "POST", headers: { "Content-Type": "application/json", @@ -37,6 +47,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) create: { type: "tandem_video", key: responseBody, + appId: "tandem", }, }, }, diff --git a/packages/app-store/tandemvideo/lib/VideoApiAdapter.ts b/packages/app-store/tandemvideo/lib/VideoApiAdapter.ts index 47e6f7d8..3b489f4e 100644 --- a/packages/app-store/tandemvideo/lib/VideoApiAdapter.ts +++ b/packages/app-store/tandemvideo/lib/VideoApiAdapter.ts @@ -1,11 +1,14 @@ import { Credential } from "@prisma/client"; import { handleErrorsJson, handleErrorsRaw } from "@calcom/lib/errors"; +import { HttpError } from "@calcom/lib/http-error"; import prisma from "@calcom/prisma"; import type { CalendarEvent } from "@calcom/types/Calendar"; import type { PartialReference } from "@calcom/types/EventManager"; import type { VideoApiAdapter, VideoCallData } from "@calcom/types/VideoApiAdapter"; +import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; + interface TandemToken { expires_in?: number; expiry_date: number; @@ -14,16 +17,24 @@ interface TandemToken { access_token: string; } -const client_id = process.env.TANDEM_CLIENT_ID as string; -const client_secret = process.env.TANDEM_CLIENT_SECRET as string; -const TANDEM_BASE_URL = process.env.TANDEM_BASE_URL as string; +let client_id = ""; +let client_secret = ""; +let base_url = ""; + +const tandemAuth = async (credential: Credential) => { + const appKeys = await getAppKeysFromSlug("tandem"); + if (typeof appKeys.client_id === "string") client_id = appKeys.client_id; + if (typeof appKeys.client_secret === "string") client_secret = appKeys.client_secret; + if (typeof appKeys.base_url === "string") base_url = appKeys.base_url; + if (!client_id) throw new HttpError({ statusCode: 400, message: "Tandem client_id missing." }); + if (!client_secret) throw new HttpError({ statusCode: 400, message: "Tandem client_secret missing." }); + if (!base_url) throw new HttpError({ statusCode: 400, message: "Tandem base_url missing." }); -const tandemAuth = (credential: Credential) => { const credentialKey = credential.key as unknown as TandemToken; const isTokenValid = (token: TandemToken) => token && token.access_token && token.expiry_date < Date.now(); const refreshAccessToken = (refreshToken: string) => { - fetch(`${TANDEM_BASE_URL}/api/v1/oauth/v2/token`, { + fetch(`${base_url}/api/v1/oauth/v2/token`, { method: "POST", body: new URLSearchParams({ client_id, @@ -95,9 +106,9 @@ const TandemVideoApiAdapter = (credential: Credential): VideoApiAdapter => { return Promise.resolve([]); }, createMeeting: async (event: CalendarEvent): Promise => { - const accessToken = await auth.getToken(); + const accessToken = await (await auth).getToken(); - const result = await fetch(`${TANDEM_BASE_URL}/api/v1/meetings`, { + const result = await fetch(`${base_url}/api/v1/meetings`, { method: "POST", headers: { Authorization: "Bearer " + accessToken, @@ -110,9 +121,9 @@ const TandemVideoApiAdapter = (credential: Credential): VideoApiAdapter => { }, deleteMeeting: async (uid: string): Promise => { - const accessToken = await auth.getToken(); + const accessToken = await (await auth).getToken(); - await fetch(`${TANDEM_BASE_URL}/api/v1/meetings/${uid}`, { + await fetch(`${base_url}/api/v1/meetings/${uid}`, { method: "DELETE", headers: { Authorization: "Bearer " + accessToken, @@ -123,9 +134,9 @@ const TandemVideoApiAdapter = (credential: Credential): VideoApiAdapter => { }, updateMeeting: async (bookingRef: PartialReference, event: CalendarEvent): Promise => { - const accessToken = await auth.getToken(); + const accessToken = await (await auth).getToken(); - const result = await fetch(`${TANDEM_BASE_URL}/api/v1/meetings/${bookingRef.meetingId}`, { + const result = await fetch(`${base_url}/api/v1/meetings/${bookingRef.meetingId}`, { method: "PUT", headers: { Authorization: "Bearer " + accessToken,