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
This commit is contained in:
parent
3ff99f7877
commit
3587e1ac9c
8 changed files with 80 additions and 72 deletions
|
@ -1,48 +1,47 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { getSession } from "next-auth/client";
|
|
||||||
|
|
||||||
|
import { getSession } from "@lib/auth";
|
||||||
import { symmetricEncrypt } from "@lib/crypto";
|
import { symmetricEncrypt } from "@lib/crypto";
|
||||||
import { AppleCalendar } from "@lib/integrations/Apple/AppleCalendarAdapter";
|
import { AppleCalendar } from "@lib/integrations/Apple/AppleCalendarAdapter";
|
||||||
import logger from "@lib/logger";
|
import logger from "@lib/logger";
|
||||||
|
import prisma from "@lib/prisma";
|
||||||
import prisma from "../../../../lib/prisma";
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
if (req.method === "POST") {
|
if (req.method === "POST") {
|
||||||
// Check that user is authenticated
|
// 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" });
|
res.status(401).json({ message: "You must be logged in to do this" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
// Get user
|
// Get user
|
||||||
await prisma.user.findFirst({
|
const user = await prisma.user.findFirst({
|
||||||
|
rejectOnNotFound: true,
|
||||||
where: {
|
where: {
|
||||||
email: session.user.email,
|
id: session?.user?.id,
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
type: "apple_calendar",
|
||||||
|
key: symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY!),
|
||||||
|
userId: user.id,
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dav = new AppleCalendar({
|
const dav = new AppleCalendar({
|
||||||
id: 0,
|
id: 0,
|
||||||
type: "apple_calendar",
|
...data,
|
||||||
key: symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY),
|
|
||||||
userId: session.user.id,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await dav.listCalendars();
|
await dav.listCalendars();
|
||||||
await prisma.credential.create({
|
await prisma.credential.create({
|
||||||
data: {
|
data,
|
||||||
type: "apple_calendar",
|
|
||||||
key: symmetricEncrypt(JSON.stringify({ username, password }), process.env.CALENDSO_ENCRYPTION_KEY),
|
|
||||||
userId: session.user.id,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
logger.error("Could not add this caldav account", reason);
|
logger.error("Could not add this caldav account", reason);
|
||||||
|
|
|
@ -4,51 +4,47 @@ import { getSession } from "@lib/auth";
|
||||||
import { symmetricEncrypt } from "@lib/crypto";
|
import { symmetricEncrypt } from "@lib/crypto";
|
||||||
import { CalDavCalendar } from "@lib/integrations/CalDav/CalDavCalendarAdapter";
|
import { CalDavCalendar } from "@lib/integrations/CalDav/CalDavCalendarAdapter";
|
||||||
import logger from "@lib/logger";
|
import logger from "@lib/logger";
|
||||||
|
import prisma from "@lib/prisma";
|
||||||
import prisma from "../../../../lib/prisma";
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
if (req.method === "POST") {
|
if (req.method === "POST") {
|
||||||
// Check that user is authenticated
|
// 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" });
|
res.status(401).json({ message: "You must be logged in to do this" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { username, password, url } = req.body;
|
const { username, password, url } = req.body;
|
||||||
// Get user
|
// Get user
|
||||||
await prisma.user.findFirst({
|
const user = await prisma.user.findFirst({
|
||||||
|
rejectOnNotFound: true,
|
||||||
where: {
|
where: {
|
||||||
email: session.user.email,
|
id: session?.user?.id,
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
type: "caldav_calendar",
|
||||||
|
key: symmetricEncrypt(
|
||||||
|
JSON.stringify({ username, password, url }),
|
||||||
|
process.env.CALENDSO_ENCRYPTION_KEY!
|
||||||
|
),
|
||||||
|
userId: user.id,
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dav = new CalDavCalendar({
|
const dav = new CalDavCalendar({
|
||||||
id: 0,
|
id: 0,
|
||||||
type: "caldav_calendar",
|
...data,
|
||||||
key: symmetricEncrypt(
|
|
||||||
JSON.stringify({ username, password, url }),
|
|
||||||
process.env.CALENDSO_ENCRYPTION_KEY
|
|
||||||
),
|
|
||||||
userId: session.user.id,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await dav.listCalendars();
|
await dav.listCalendars();
|
||||||
await prisma.credential.create({
|
await prisma.credential.create({
|
||||||
data: {
|
data,
|
||||||
type: "caldav_calendar",
|
|
||||||
key: symmetricEncrypt(
|
|
||||||
JSON.stringify({ username, password, url }),
|
|
||||||
process.env.CALENDSO_ENCRYPTION_KEY
|
|
||||||
),
|
|
||||||
userId: session.user.id,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
logger.error("Could not add this caldav account", reason);
|
logger.error("Could not add this caldav account", reason);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { google } from "googleapis";
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
import { BASE_URL } from "@lib/config/constants";
|
||||||
|
|
||||||
import { encodeOAuthState } from "../utils";
|
import { encodeOAuthState } from "../utils";
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
|
|
||||||
// Get token from Google Calendar API
|
// Get token from Google Calendar API
|
||||||
const { client_secret, client_id } = JSON.parse(credentials).web;
|
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 oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri);
|
||||||
|
|
||||||
const authUrl = oAuth2Client.generateAuthUrl({
|
const authUrl = oAuth2Client.generateAuthUrl({
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { google } from "googleapis";
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
import { BASE_URL } from "@lib/config/constants";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
|
||||||
import { decodeOAuthState } from "../utils";
|
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 { 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 oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri);
|
||||||
const token = await oAuth2Client.getToken(code);
|
const token = await oAuth2Client.getToken(code);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
import { stringify } from "querystring";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
import { BASE_URL } from "@lib/config/constants";
|
||||||
|
|
||||||
import { encodeOAuthState } from "../utils";
|
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) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
if (req.method === "GET") {
|
if (req.method === "GET") {
|
||||||
// Check that user is authenticated
|
// Check that user is authenticated
|
||||||
const session = await getSession({ req: req });
|
const session = await getSession({ req });
|
||||||
|
|
||||||
if (!session?.user) {
|
if (!session?.user) {
|
||||||
res.status(401).json({ message: "You must be logged in to do this" });
|
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);
|
const state = encodeOAuthState(req);
|
||||||
let url =
|
const params = {
|
||||||
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=code&scope=" +
|
response_type: "code",
|
||||||
scopes.join(" ") +
|
scope: scopes.join(" "),
|
||||||
"&client_id=" +
|
client_id: process.env.MS_GRAPH_CLIENT_ID,
|
||||||
process.env.MS_GRAPH_CLIENT_ID +
|
redirect_uri: BASE_URL + "/api/integrations/office365calendar/callback",
|
||||||
"&redirect_uri=" +
|
state,
|
||||||
process.env.BASE_URL +
|
};
|
||||||
"/api/integrations/office365calendar/callback";
|
const query = stringify(params);
|
||||||
if (state) {
|
const url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?${query}`;
|
||||||
url += "&state=" + encodeURIComponent(state);
|
|
||||||
}
|
|
||||||
res.status(200).json({ url });
|
res.status(200).json({ url });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
import { BASE_URL } from "@lib/config/constants";
|
||||||
|
|
||||||
import prisma from "../../../../lib/prisma";
|
import prisma from "../../../../lib/prisma";
|
||||||
import { decodeOAuthState } from "../utils";
|
import { decodeOAuthState } from "../utils";
|
||||||
|
@ -31,7 +32,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
grant_type: "authorization_code",
|
grant_type: "authorization_code",
|
||||||
code,
|
code,
|
||||||
scope: scopes.join(" "),
|
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!,
|
client_secret: process.env.MS_GRAPH_CLIENT_SECRET!,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,40 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
import { stringify } from "querystring";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
import { BASE_URL } from "@lib/config/constants";
|
||||||
import prisma from "../../../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
|
||||||
const client_id = process.env.ZOOM_CLIENT_ID;
|
const client_id = process.env.ZOOM_CLIENT_ID;
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
if (req.method === "GET") {
|
if (req.method === "GET") {
|
||||||
// Check that user is authenticated
|
// 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" });
|
res.status(401).json({ message: "You must be logged in to do this" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user
|
// Get user
|
||||||
await prisma.user.findFirst({
|
await prisma.user.findFirst({
|
||||||
|
rejectOnNotFound: true,
|
||||||
where: {
|
where: {
|
||||||
email: session.user.email,
|
id: session?.user?.id,
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const redirectUri = encodeURI(process.env.BASE_URL + "/api/integrations/zoomvideo/callback");
|
const params = {
|
||||||
const authUrl =
|
response_type: "code",
|
||||||
"https://zoom.us/oauth/authorize?response_type=code&client_id=" +
|
client_id,
|
||||||
client_id +
|
redirect_uri: BASE_URL + "/api/integrations/zoomvideo/callback",
|
||||||
"&redirect_uri=" +
|
};
|
||||||
redirectUri;
|
const query = stringify(params);
|
||||||
|
const url = `https://zoom.us/oauth/authorize?${query}`;
|
||||||
res.status(200).json({ url: authUrl });
|
res.status(200).json({ url });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
import { BASE_URL } from "@lib/config/constants";
|
||||||
|
|
||||||
import prisma from "../../../../lib/prisma";
|
import prisma from "../../../../lib/prisma";
|
||||||
|
|
||||||
|
@ -11,14 +12,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
const { code } = req.query;
|
const { code } = req.query;
|
||||||
|
|
||||||
// Check that user is authenticated
|
// 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" });
|
res.status(401).json({ message: "You must be logged in to do this" });
|
||||||
return;
|
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 authHeader = "Basic " + Buffer.from(client_id + ":" + client_secret).toString("base64");
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
"https://zoom.us/oauth/token?grant_type=authorization_code&code=" + code + "&redirect_uri=" + redirectUri,
|
"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();
|
const json = await result.json();
|
||||||
|
|
||||||
await prisma.credential.create({
|
await prisma.user.update({
|
||||||
|
where: {
|
||||||
|
id: session.user.id,
|
||||||
|
},
|
||||||
data: {
|
data: {
|
||||||
type: "zoom_video",
|
credentials: {
|
||||||
key: json,
|
create: {
|
||||||
userId: session.user.id,
|
type: "zoom_video",
|
||||||
|
key: json,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
res.redirect("/integrations");
|
res.redirect("/integrations");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue