From 3587e1ac9c89a3bdc5ed3343185940cdd6c69a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20L=C3=B3pez?= Date: Fri, 10 Dec 2021 14:14:54 -0700 Subject: [PATCH] Uses vercel url on integration endpoints for staging (#1293) * Legibility and base url fixes * Uses vercel url on integration endpoints for staging * We validate the user before creating credentials --- pages/api/integrations/apple/add.ts | 31 ++++++++------- pages/api/integrations/caldav/add.ts | 38 +++++++++---------- pages/api/integrations/googlecalendar/add.ts | 3 +- .../integrations/googlecalendar/callback.ts | 3 +- .../api/integrations/office365calendar/add.ts | 24 ++++++------ .../office365calendar/callback.ts | 3 +- pages/api/integrations/zoomvideo/add.ts | 28 +++++++------- pages/api/integrations/zoomvideo/callback.ts | 22 +++++++---- 8 files changed, 80 insertions(+), 72 deletions(-) diff --git a/pages/api/integrations/apple/add.ts b/pages/api/integrations/apple/add.ts index cb0ff1bd..23ebd7ba 100644 --- a/pages/api/integrations/apple/add.ts +++ b/pages/api/integrations/apple/add.ts @@ -1,48 +1,47 @@ import type { NextApiRequest, NextApiResponse } from "next"; -import { getSession } from "next-auth/client"; +import { getSession } from "@lib/auth"; import { symmetricEncrypt } from "@lib/crypto"; import { AppleCalendar } from "@lib/integrations/Apple/AppleCalendarAdapter"; import logger from "@lib/logger"; - -import prisma from "../../../../lib/prisma"; +import prisma from "@lib/prisma"; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") { // Check that user is authenticated - const session = await getSession({ req: req }); + const session = await getSession({ req }); - if (!session) { + if (!session?.user?.id) { res.status(401).json({ message: "You must be logged in to do this" }); return; } const { username, password } = req.body; // Get user - await prisma.user.findFirst({ + const user = await prisma.user.findFirst({ + rejectOnNotFound: true, where: { - email: session.user.email, + id: session?.user?.id, }, select: { id: true, }, }); + const data = { + type: "apple_calendar", + key: symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY!), + userId: user.id, + }; + try { const dav = new AppleCalendar({ id: 0, - type: "apple_calendar", - key: symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY), - userId: session.user.id, + ...data, }); - await dav.listCalendars(); await prisma.credential.create({ - data: { - type: "apple_calendar", - key: symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY), - userId: session.user.id, - }, + data, }); } catch (reason) { logger.error("Could not add this caldav account", reason); diff --git a/pages/api/integrations/caldav/add.ts b/pages/api/integrations/caldav/add.ts index 7ba4318a..e00740ab 100644 --- a/pages/api/integrations/caldav/add.ts +++ b/pages/api/integrations/caldav/add.ts @@ -4,51 +4,47 @@ import { getSession } from "@lib/auth"; import { symmetricEncrypt } from "@lib/crypto"; import { CalDavCalendar } from "@lib/integrations/CalDav/CalDavCalendarAdapter"; import logger from "@lib/logger"; - -import prisma from "../../../../lib/prisma"; +import prisma from "@lib/prisma"; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") { // Check that user is authenticated - const session = await getSession({ req: req }); + const session = await getSession({ req }); - if (!session) { + if (!session?.user?.id) { res.status(401).json({ message: "You must be logged in to do this" }); return; } const { username, password, url } = req.body; // Get user - await prisma.user.findFirst({ + const user = await prisma.user.findFirst({ + rejectOnNotFound: true, where: { - email: session.user.email, + id: session?.user?.id, }, select: { id: true, }, }); + const data = { + type: "caldav_calendar", + key: symmetricEncrypt( + JSON.stringify({ username, password, url }), + process.env.CALENDSO_ENCRYPTION_KEY! + ), + userId: user.id, + }; + try { const dav = new CalDavCalendar({ id: 0, - type: "caldav_calendar", - key: symmetricEncrypt( - JSON.stringify({ username, password, url }), - process.env.CALENDSO_ENCRYPTION_KEY - ), - userId: session.user.id, + ...data, }); - await dav.listCalendars(); await prisma.credential.create({ - data: { - type: "caldav_calendar", - key: symmetricEncrypt( - JSON.stringify({ username, password, url }), - process.env.CALENDSO_ENCRYPTION_KEY - ), - userId: session.user.id, - }, + data, }); } catch (reason) { logger.error("Could not add this caldav account", reason); diff --git a/pages/api/integrations/googlecalendar/add.ts b/pages/api/integrations/googlecalendar/add.ts index 30ada67e..15fdf782 100644 --- a/pages/api/integrations/googlecalendar/add.ts +++ b/pages/api/integrations/googlecalendar/add.ts @@ -2,6 +2,7 @@ import { google } from "googleapis"; import type { NextApiRequest, NextApiResponse } from "next"; import { getSession } from "@lib/auth"; +import { BASE_URL } from "@lib/config/constants"; import { encodeOAuthState } from "../utils"; @@ -23,7 +24,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) // Get token from Google Calendar API const { client_secret, client_id } = JSON.parse(credentials).web; - const redirect_uri = process.env.BASE_URL + "/api/integrations/googlecalendar/callback"; + const redirect_uri = BASE_URL + "/api/integrations/googlecalendar/callback"; const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri); const authUrl = oAuth2Client.generateAuthUrl({ diff --git a/pages/api/integrations/googlecalendar/callback.ts b/pages/api/integrations/googlecalendar/callback.ts index 778ae47a..61dbc601 100644 --- a/pages/api/integrations/googlecalendar/callback.ts +++ b/pages/api/integrations/googlecalendar/callback.ts @@ -2,6 +2,7 @@ import { google } from "googleapis"; import type { NextApiRequest, NextApiResponse } from "next"; import { getSession } from "@lib/auth"; +import { BASE_URL } from "@lib/config/constants"; import prisma from "@lib/prisma"; import { decodeOAuthState } from "../utils"; @@ -28,7 +29,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } const { client_secret, client_id } = JSON.parse(credentials).web; - const redirect_uri = process.env.BASE_URL + "/api/integrations/googlecalendar/callback"; + const redirect_uri = BASE_URL + "/api/integrations/googlecalendar/callback"; const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri); const token = await oAuth2Client.getToken(code); diff --git a/pages/api/integrations/office365calendar/add.ts b/pages/api/integrations/office365calendar/add.ts index e0d7501f..7ab61569 100644 --- a/pages/api/integrations/office365calendar/add.ts +++ b/pages/api/integrations/office365calendar/add.ts @@ -1,6 +1,8 @@ import type { NextApiRequest, NextApiResponse } from "next"; +import { stringify } from "querystring"; import { getSession } from "@lib/auth"; +import { BASE_URL } from "@lib/config/constants"; import { encodeOAuthState } from "../utils"; @@ -9,7 +11,7 @@ const scopes = ["User.Read", "Calendars.Read", "Calendars.ReadWrite", "offline_a export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "GET") { // Check that user is authenticated - const session = await getSession({ req: req }); + const session = await getSession({ req }); if (!session?.user) { res.status(401).json({ message: "You must be logged in to do this" }); @@ -17,17 +19,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } const state = encodeOAuthState(req); - let url = - "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=code&scope=" + - scopes.join(" ") + - "&client_id=" + - process.env.MS_GRAPH_CLIENT_ID + - "&redirect_uri=" + - process.env.BASE_URL + - "/api/integrations/office365calendar/callback"; - if (state) { - url += "&state=" + encodeURIComponent(state); - } + const params = { + response_type: "code", + scope: scopes.join(" "), + client_id: process.env.MS_GRAPH_CLIENT_ID, + redirect_uri: BASE_URL + "/api/integrations/office365calendar/callback", + state, + }; + const query = stringify(params); + const url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?${query}`; res.status(200).json({ url }); } } diff --git a/pages/api/integrations/office365calendar/callback.ts b/pages/api/integrations/office365calendar/callback.ts index d0cdb2ef..35814fba 100644 --- a/pages/api/integrations/office365calendar/callback.ts +++ b/pages/api/integrations/office365calendar/callback.ts @@ -1,6 +1,7 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { getSession } from "@lib/auth"; +import { BASE_URL } from "@lib/config/constants"; import prisma from "../../../../lib/prisma"; import { decodeOAuthState } from "../utils"; @@ -31,7 +32,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) grant_type: "authorization_code", code, scope: scopes.join(" "), - redirect_uri: process.env.BASE_URL + "/api/integrations/office365calendar/callback", + redirect_uri: BASE_URL + "/api/integrations/office365calendar/callback", client_secret: process.env.MS_GRAPH_CLIENT_SECRET!, }); diff --git a/pages/api/integrations/zoomvideo/add.ts b/pages/api/integrations/zoomvideo/add.ts index c271ce0a..013069c2 100644 --- a/pages/api/integrations/zoomvideo/add.ts +++ b/pages/api/integrations/zoomvideo/add.ts @@ -1,38 +1,40 @@ import type { NextApiRequest, NextApiResponse } from "next"; +import { stringify } from "querystring"; import { getSession } from "@lib/auth"; - -import prisma from "../../../../lib/prisma"; +import { BASE_URL } from "@lib/config/constants"; +import prisma from "@lib/prisma"; const client_id = process.env.ZOOM_CLIENT_ID; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "GET") { // Check that user is authenticated - const session = await getSession({ req: req }); + const session = await getSession({ req }); - if (!session) { + if (!session?.user?.id) { res.status(401).json({ message: "You must be logged in to do this" }); return; } // Get user await prisma.user.findFirst({ + rejectOnNotFound: true, where: { - email: session.user.email, + id: session?.user?.id, }, select: { id: true, }, }); - const redirectUri = encodeURI(process.env.BASE_URL + "/api/integrations/zoomvideo/callback"); - const authUrl = - "https://zoom.us/oauth/authorize?response_type=code&client_id=" + - client_id + - "&redirect_uri=" + - redirectUri; - - res.status(200).json({ url: authUrl }); + const params = { + response_type: "code", + client_id, + redirect_uri: BASE_URL + "/api/integrations/zoomvideo/callback", + }; + const query = stringify(params); + const url = `https://zoom.us/oauth/authorize?${query}`; + res.status(200).json({ url }); } } diff --git a/pages/api/integrations/zoomvideo/callback.ts b/pages/api/integrations/zoomvideo/callback.ts index 13a16145..458decec 100644 --- a/pages/api/integrations/zoomvideo/callback.ts +++ b/pages/api/integrations/zoomvideo/callback.ts @@ -1,6 +1,7 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { getSession } from "@lib/auth"; +import { BASE_URL } from "@lib/config/constants"; import prisma from "../../../../lib/prisma"; @@ -11,14 +12,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const { code } = req.query; // Check that user is authenticated - const session = await getSession({ req: req }); + const session = await getSession({ req }); - if (!session) { + if (!session?.user?.id) { res.status(401).json({ message: "You must be logged in to do this" }); return; } - const redirectUri = encodeURI(process.env.BASE_URL + "/api/integrations/zoomvideo/callback"); + const redirectUri = encodeURI(BASE_URL + "/api/integrations/zoomvideo/callback"); const authHeader = "Basic " + Buffer.from(client_id + ":" + client_secret).toString("base64"); const result = await fetch( "https://zoom.us/oauth/token?grant_type=authorization_code&code=" + code + "&redirect_uri=" + redirectUri, @@ -31,12 +32,19 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ); const json = await result.json(); - await prisma.credential.create({ + await prisma.user.update({ + where: { + id: session.user.id, + }, data: { - type: "zoom_video", - key: json, - userId: session.user.id, + credentials: { + create: { + type: "zoom_video", + key: json, + }, + }, }, }); + res.redirect("/integrations"); }