fix: Update credentialId when null for a given selectedCalendar (#13735)
* fix: Update credentialId when null for a given selectedCalendar * Add returnTo return path * chore * chore: undo return --------- Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Udit Takkar <udit222001@gmail.com>
This commit is contained in:
co-authored by
Udit Takkar
Udit Takkar
parent
b38807cb0f
commit
3d1ac4523f
@@ -2,6 +2,7 @@ import type { Auth } from "googleapis";
|
||||
import { google } from "googleapis";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { renewSelectedCalendarCredentialId } from "@calcom/lib/connectedCalendar";
|
||||
import { WEBAPP_URL_FOR_OAUTH, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
@@ -105,23 +106,38 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
appId: "google-calendar",
|
||||
},
|
||||
});
|
||||
|
||||
const selectedCalendarWhereUnique = {
|
||||
userId: req.session.user.id,
|
||||
externalId: primaryCal.id,
|
||||
integration: "google_calendar",
|
||||
};
|
||||
|
||||
// Wrapping in a try/catch to reduce chance of race conditions-
|
||||
// also this improves performance for most of the happy-paths.
|
||||
try {
|
||||
await prisma.selectedCalendar.create({
|
||||
data: {
|
||||
userId: req.session.user.id,
|
||||
externalId: primaryCal.id,
|
||||
credentialId: credential.id,
|
||||
integration: "google_calendar",
|
||||
...selectedCalendarWhereUnique,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
await prisma.credential.delete({ where: { id: credential.id } });
|
||||
let errorMessage = "something_went_wrong";
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
|
||||
// it is possible a selectedCalendar was orphaned, in this situation-
|
||||
// we want to recover by connecting the existing selectedCalendar to the new Credential.
|
||||
if (await renewSelectedCalendarCredentialId(selectedCalendarWhereUnique, credential.id)) {
|
||||
res.redirect(
|
||||
getSafeRedirectUrl(state?.returnTo) ??
|
||||
getInstalledAppPath({ variant: "calendar", slug: "google-calendar" })
|
||||
);
|
||||
return;
|
||||
}
|
||||
// else
|
||||
errorMessage = "account_already_linked";
|
||||
}
|
||||
await prisma.credential.delete({ where: { id: credential.id } });
|
||||
res.redirect(
|
||||
`${
|
||||
getSafeRedirectUrl(state?.onErrorReturnTo) ??
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Calendar as OfficeCalendar } from "@microsoft/microsoft-graph-types-beta";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { renewSelectedCalendarCredentialId } from "@calcom/lib/connectedCalendar";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { handleErrorsJson } from "@calcom/lib/errors";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
@@ -119,23 +120,36 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
appId: "office365-calendar",
|
||||
},
|
||||
});
|
||||
const selectedCalendarWhereUnique = {
|
||||
userId: req.session?.user.id,
|
||||
integration: "office365_calendar",
|
||||
externalId: defaultCalendar.id,
|
||||
};
|
||||
// Wrapping in a try/catch to reduce chance of race conditions-
|
||||
// also this improves performance for most of the happy-paths.
|
||||
try {
|
||||
await prisma.selectedCalendar.create({
|
||||
data: {
|
||||
userId: req.session?.user.id,
|
||||
integration: "office365_calendar",
|
||||
externalId: defaultCalendar.id,
|
||||
...selectedCalendarWhereUnique,
|
||||
credentialId: credential.id,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
await prisma.credential.delete({ where: { id: credential.id } });
|
||||
let errorMessage = "something_went_wrong";
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
|
||||
// it is possible a selectedCalendar was orphaned, in this situation-
|
||||
// we want to recover by connecting the existing selectedCalendar to the new Credential.
|
||||
if (await renewSelectedCalendarCredentialId(selectedCalendarWhereUnique, credential.id)) {
|
||||
res.redirect(
|
||||
getSafeRedirectUrl(state?.returnTo) ??
|
||||
getInstalledAppPath({ variant: "calendar", slug: "office365-calendar" })
|
||||
);
|
||||
return;
|
||||
}
|
||||
// else
|
||||
errorMessage = "account_already_linked";
|
||||
}
|
||||
await prisma.credential.delete({ where: { id: credential.id } });
|
||||
res.redirect(
|
||||
`${
|
||||
getSafeRedirectUrl(state?.onErrorReturnTo) ??
|
||||
@@ -146,8 +160,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
}
|
||||
}
|
||||
|
||||
return res.redirect(
|
||||
res.redirect(
|
||||
getSafeRedirectUrl(state?.returnTo) ??
|
||||
getInstalledAppPath({ variant: "calendar", slug: "office365-calendar" })
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { stringify } from "querystring";
|
||||
|
||||
import { renewSelectedCalendarCredentialId } from "@calcom/lib/connectedCalendar";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import logger from "@calcom/lib/logger";
|
||||
@@ -86,23 +87,36 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
appId: config.slug,
|
||||
},
|
||||
});
|
||||
const selectedCalendarWhereUnique = {
|
||||
userId: req.session?.user.id,
|
||||
integration: config.type,
|
||||
externalId: primaryCalendar.uid,
|
||||
};
|
||||
// Wrapping in a try/catch to reduce chance of race conditions-
|
||||
// also this improves performance for most of the happy-paths.
|
||||
try {
|
||||
await prisma.selectedCalendar.create({
|
||||
data: {
|
||||
userId: req.session.user.id,
|
||||
integration: config.type,
|
||||
externalId: primaryCalendar.uid,
|
||||
...selectedCalendarWhereUnique,
|
||||
credentialId: credential.id,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
await prisma.credential.delete({ where: { id: credential.id } });
|
||||
let errorMessage = "something_went_wrong";
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
|
||||
// it is possible a selectedCalendar was orphaned, in this situation-
|
||||
// we want to recover by connecting the existing selectedCalendar to the new Credential.
|
||||
if (await renewSelectedCalendarCredentialId(selectedCalendarWhereUnique, credential.id)) {
|
||||
res.redirect(
|
||||
getSafeRedirectUrl(state?.returnTo) ??
|
||||
getInstalledAppPath({ variant: "calendar", slug: config.slug })
|
||||
);
|
||||
return;
|
||||
}
|
||||
// else
|
||||
errorMessage = "account_already_linked";
|
||||
}
|
||||
await prisma.credential.delete({ where: { id: credential.id } });
|
||||
res.redirect(
|
||||
`${
|
||||
getSafeRedirectUrl(state?.onErrorReturnTo) ??
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
export async function renewSelectedCalendarCredentialId(
|
||||
selectedCalendarWhereUnique: {
|
||||
userId: number;
|
||||
integration: string;
|
||||
externalId: string;
|
||||
},
|
||||
credentialId: number
|
||||
): Promise<boolean> /* True if renewed, false if not */ {
|
||||
const selectedCalendar = await prisma.selectedCalendar.findFirst({
|
||||
where: {
|
||||
...selectedCalendarWhereUnique,
|
||||
credentialId: null,
|
||||
},
|
||||
});
|
||||
if (selectedCalendar) {
|
||||
await prisma.selectedCalendar.update({
|
||||
where: {
|
||||
userId_integration_externalId: selectedCalendarWhereUnique,
|
||||
},
|
||||
data: {
|
||||
credentialId: credentialId,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user