Agenda refactor
This commit is contained in:
parent
95a56d8828
commit
a4c4baa491
@ -2,6 +2,8 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/app/api/auth/options";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { deleteMicrosoftEvent } from "@/lib/services/microsoft-calendar-sync";
|
||||
import { logger } from "@/lib/logger";
|
||||
|
||||
// Helper function to check if user can manage events in a mission calendar
|
||||
async function canManageMissionCalendar(userId: string, calendarId: string): Promise<boolean> {
|
||||
@ -45,10 +47,20 @@ export async function DELETE(req: NextRequest, props: { params: Promise<{ id: st
|
||||
}
|
||||
|
||||
try {
|
||||
// First, find the event and its associated calendar
|
||||
// First, find the event and its associated calendar with sync config
|
||||
const event = await prisma.event.findUnique({
|
||||
where: { id: params.id },
|
||||
include: { calendar: true },
|
||||
include: {
|
||||
calendar: {
|
||||
include: {
|
||||
syncConfig: {
|
||||
include: {
|
||||
mailCredential: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (!event) {
|
||||
@ -77,7 +89,41 @@ export async function DELETE(req: NextRequest, props: { params: Promise<{ id: st
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the event
|
||||
// If event has externalEventId and calendar has Microsoft sync, delete from Microsoft too
|
||||
if (event.externalEventId && event.calendar.syncConfig && event.calendar.syncConfig.provider === 'microsoft' && event.calendar.syncConfig.syncEnabled) {
|
||||
const syncConfig = event.calendar.syncConfig;
|
||||
const mailCredential = syncConfig.mailCredential;
|
||||
|
||||
if (mailCredential && mailCredential.use_oauth && mailCredential.refresh_token) {
|
||||
try {
|
||||
await deleteMicrosoftEvent(
|
||||
session.user.id,
|
||||
mailCredential.email,
|
||||
syncConfig.externalCalendarId || '',
|
||||
event.externalEventId
|
||||
);
|
||||
|
||||
logger.info('Successfully synced event deletion to Microsoft', {
|
||||
eventId: params.id,
|
||||
externalEventId: event.externalEventId,
|
||||
email: mailCredential.email,
|
||||
});
|
||||
} catch (syncError: any) {
|
||||
// Log error but don't fail the request - local deletion will proceed
|
||||
// Don't disable syncConfig for permission errors (403) - user just needs to re-authenticate
|
||||
const isPermissionError = syncError.response?.status === 403;
|
||||
logger.error('Failed to sync event deletion to Microsoft', {
|
||||
eventId: params.id,
|
||||
externalEventId: event.externalEventId,
|
||||
error: syncError instanceof Error ? syncError.message : String(syncError),
|
||||
isPermissionError,
|
||||
suggestion: isPermissionError ? 'User needs to re-authenticate with Calendars.ReadWrite scope' : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the event from local database
|
||||
await prisma.event.delete({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/app/api/auth/options";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { updateMicrosoftEvent } from "@/lib/services/microsoft-calendar-sync";
|
||||
import { updateMicrosoftEvent, deleteMicrosoftEvent } from "@/lib/services/microsoft-calendar-sync";
|
||||
import { logger } from "@/lib/logger";
|
||||
|
||||
// Helper function to check if user can manage events in a mission calendar
|
||||
@ -263,10 +263,14 @@ export async function PUT(req: NextRequest) {
|
||||
});
|
||||
} catch (syncError: any) {
|
||||
// Log error but don't fail the request - local update succeeded
|
||||
// Don't disable syncConfig for permission errors (403) - user just needs to re-authenticate
|
||||
const isPermissionError = syncError.response?.status === 403;
|
||||
logger.error('Failed to sync event update to Microsoft', {
|
||||
eventId: id,
|
||||
externalEventId: existingEvent.externalEventId,
|
||||
error: syncError instanceof Error ? syncError.message : String(syncError),
|
||||
isPermissionError,
|
||||
suggestion: isPermissionError ? 'User needs to re-authenticate with Calendars.ReadWrite scope' : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,6 +448,54 @@ export async function updateMicrosoftEvent(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Microsoft calendar event via Graph API
|
||||
*/
|
||||
export async function deleteMicrosoftEvent(
|
||||
userId: string,
|
||||
email: string,
|
||||
calendarId: string,
|
||||
eventId: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
const accessToken = await getMicrosoftGraphClient(userId, email);
|
||||
|
||||
const url = `https://graph.microsoft.com/v1.0/me/calendars/${calendarId}/events/${eventId}`;
|
||||
|
||||
logger.info('Deleting Microsoft event', {
|
||||
userId,
|
||||
email,
|
||||
calendarId,
|
||||
eventId,
|
||||
url,
|
||||
});
|
||||
|
||||
await axios.delete(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
logger.info('Successfully deleted Microsoft event', {
|
||||
userId,
|
||||
email,
|
||||
eventId,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error('Error deleting Microsoft event', {
|
||||
userId,
|
||||
email,
|
||||
calendarId,
|
||||
eventId,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
responseStatus: error.response?.status,
|
||||
responseData: error.response?.data,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync events from Microsoft calendar to local Prisma calendar
|
||||
*/
|
||||
|
||||
@ -21,6 +21,7 @@ const REQUIRED_SCOPES = [
|
||||
'https://graph.microsoft.com/Mail.Read', // Read mail via Graph API
|
||||
'https://graph.microsoft.com/Mail.Send', // Send mail via Graph API
|
||||
'https://graph.microsoft.com/Calendars.Read', // Read calendars via Graph API
|
||||
'https://graph.microsoft.com/Calendars.ReadWrite', // Read and write calendars via Graph API (for updates/deletes)
|
||||
].join(' ');
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user