Fix possible 404 when obtaining calendar busy lists (#3345)

pull/3391/head^2
alannnc 2022-07-15 14:28:24 -06:00 committed by GitHub
parent 48916cf85e
commit 4c2f6df94d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 15 deletions

View File

@ -153,6 +153,7 @@ function ConnectedCalendarsList(props: Props) {
actions={ actions={
<DisconnectIntegration <DisconnectIntegration
id={item.credentialId} id={item.credentialId}
externalId={item.primary?.externalId}
render={(btnProps) => ( render={(btnProps) => (
<Button {...btnProps} color="warn" data-testid="integration-connection-button"> <Button {...btnProps} color="warn" data-testid="integration-connection-button">
{t("disconnect")} {t("disconnect")}

View File

@ -13,10 +13,11 @@ import ConfirmationDialogContent from "@components/dialog/ConfirmationDialogCont
export default function DisconnectIntegration(props: { export default function DisconnectIntegration(props: {
/** Integration credential id */ /** Integration credential id */
id: number; id: number;
externalId?: string;
render: (renderProps: ButtonBaseProps) => JSX.Element; render: (renderProps: ButtonBaseProps) => JSX.Element;
onOpenChange: (isOpen: boolean) => unknown | Promise<unknown>; onOpenChange: (isOpen: boolean) => unknown | Promise<unknown>;
}) { }) {
const { id } = props; const { id, externalId = "" } = props;
const { t } = useLocale(); const { t } = useLocale();
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
@ -42,7 +43,7 @@ export default function DisconnectIntegration(props: {
confirmBtnText={t("yes_remove_app")} confirmBtnText={t("yes_remove_app")}
cancelBtnText="Cancel" cancelBtnText="Cancel"
onConfirm={() => { onConfirm={() => {
mutation.mutate({ id }); mutation.mutate({ id, externalId });
}}> }}>
{t("are_you_sure_you_want_to_remove_this_app")} {t("are_you_sure_you_want_to_remove_this_app")}
</ConfirmationDialogContent> </ConfirmationDialogContent>

View File

@ -991,9 +991,10 @@ const loggedInViewerRouter = createProtectedRouter()
.mutation("deleteCredential", { .mutation("deleteCredential", {
input: z.object({ input: z.object({
id: z.number(), id: z.number(),
externalId: z.string().optional(),
}), }),
async resolve({ input, ctx }) { async resolve({ input, ctx }) {
const { id } = input; const { id, externalId } = input;
const credential = await prisma.credential.findFirst({ const credential = await prisma.credential.findFirst({
where: { where: {
@ -1060,14 +1061,41 @@ const loggedInViewerRouter = createProtectedRouter()
} }
} }
// If it's a calendar, remove the destination claendar from the event type // If it's a calendar, remove the destination calendar from the event type
if (credential.app?.categories.includes(AppCategories.calendar)) { if (credential.app?.categories.includes(AppCategories.calendar)) {
if (eventType.destinationCalendar?.integration === credential.type) { if (eventType.destinationCalendar?.integration === credential.type) {
await prisma.destinationCalendar.delete({ const destinationCalendar = await prisma.destinationCalendar.findFirst({
where: { where: {
id: eventType.destinationCalendar.id, id: eventType.destinationCalendar?.id,
}, },
}); });
if (destinationCalendar) {
await prisma.destinationCalendar.delete({
where: {
id: destinationCalendar.id,
},
});
}
}
if (externalId) {
const existingSelectedCalendar = await prisma.selectedCalendar.findFirst({
where: {
externalId: externalId,
},
});
// @TODO: SelectedCalendar doesn't have unique ID so we should only delete one item
if (existingSelectedCalendar) {
await prisma.selectedCalendar.delete({
where: {
userId_integration_externalId: {
userId: existingSelectedCalendar.userId,
externalId: existingSelectedCalendar.externalId,
integration: existingSelectedCalendar.integration,
},
},
});
}
} }
} }

View File

@ -140,16 +140,18 @@ export default class Office365CalendarService implements Calendar {
}); });
const responseBody = await handleErrorsJson(response); const responseBody = await handleErrorsJson(response);
return responseBody.responses.reduce( return responseBody.responses.reduce(
(acc: BufferedBusyTime[], subResponse: { body: { value: any[] } }) => (acc: BufferedBusyTime[], subResponse: { body: { value?: any[] } }) =>
acc.concat( acc.concat(
subResponse.body.value subResponse.body?.value
.filter((evt) => evt.showAs !== "free" && evt.showAs !== "workingElsewhere") ? subResponse.body.value
.map((evt) => { .filter((evt) => evt.showAs !== "free" && evt.showAs !== "workingElsewhere")
return { .map((evt) => {
start: evt.start.dateTime + "Z", return {
end: evt.end.dateTime + "Z", start: evt.start.dateTime + "Z",
}; end: evt.end.dateTime + "Z",
}) };
})
: []
), ),
[] []
); );