Files
milsim-site-v4/api/src/routes/calendar.ts
ajdj100 c7d79ae586
All checks were successful
Pull Request CI / Update Deployment (pull_request) Successful in 3m28s
integrated audit log into pretty everything hopefully
2026-02-12 22:04:14 -05:00

207 lines
6.8 KiB
TypeScript

import { Request, Response } from "express";
import { createEvent, getEventAttendance, getEventDetails, getShortEventsInRange, setAttendanceStatus, setEventCancelled, updateEvent } from "../services/db/calendarService";
import { CalendarAttendance, CalendarEvent } from "@app/shared/types/calendar";
import { requireLogin, requireMemberState, requireRole } from "../middleware/auth";
import { MemberState } from "@app/shared/types/member";
import { logger } from "../services/logging/logger";
import { audit } from "../services/logging/auditLog";
const express = require('express');
const r = express.Router();
function addMonths(date: Date, months: number): Date {
const d = new Date(date)
d.setMonth(d.getMonth() + months)
return d
}
//get calendar events paged, requires a query string with from= and to= as mariadb ISO strings
r.get('/', async (req, res) => {
try {
const fromDate: string = req.query.from;
const toDate: string = req.query.to;
if (fromDate === undefined || toDate === undefined) {
res.status(400).send("Missing required query parameters 'from' and 'to'");
return;
}
const events = await getShortEventsInRange(fromDate, toDate);
res.status(200).json(events);
} catch (error) {
logger.error(
'app',
'Failed to get calendar events',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send('Error fetching calendar events');
}
});
r.get('/upcoming', async (req, res) => {
res.sendStatus(501);
})
r.post('/:id/cancel', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
let member = req.user.id;
try {
const eventID = Number(req.params.id);
await setEventCancelled(eventID, true);
audit.calendar('cancelled', { actorId: member, targetId: eventID });
logger.info('app', 'Calendar event cancelled', {
event: eventID,
user: req.user.id
})
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to get cancel calendar event',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send('Error setting cancel status');
}
})
r.post('/:id/uncancel', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
let member = req.user.id;
try {
const eventID = Number(req.params.id);
setEventCancelled(eventID, false);
audit.calendar('un-cancelled', { actorId: member, targetId: eventID });
logger.info('app', 'Calendar event un-cancelled', {
event: eventID,
user: req.user.id
})
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to uncancel calendar event',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send('Error setting cancel status');
}
})
r.post('/:id/attendance', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
try {
let member = req.user.id;
let event = Number(req.params.id);
let state = req.query.state as CalendarAttendance;
await setAttendanceStatus(member, event, state);
audit.calendar('attendance_set', { actorId: member, targetId: event }, { attendanceState: state });
logger.info('app', 'Member set calendar event attendance', {
event: event,
user: req.user.id,
state: state
})
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to set attendance',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
//get event details
r.get('/:id', async (req: Request, res: Response) => {
try {
const eventID: number = Number(req.params.id);
let details: CalendarEvent = await getEventDetails(eventID);
details.eventSignups = await getEventAttendance(eventID);
res.status(200).json(details);
} catch (error) {
logger.error(
'app',
'Failed to get calendar event details',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500);
}
})
//post a new calendar event
r.post('/', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
try {
const member = req.user.id;
let event: CalendarEvent = req.body;
event.creator_id = member;
event.start = new Date(event.start);
event.end = new Date(event.end);
let eventID = await createEvent(event);
audit.calendar('event_created', { actorId: member, targetId: eventID });
logger.info('app', 'Calendar event posted', {
event: event.id,
user: req.user.id
})
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to create calendar event',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
r.put('/', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
let member = req.user.id;
try {
let event: CalendarEvent = req.body;
event.start = new Date(event.start);
event.end = new Date(event.end);
updateEvent(event);
audit.calendar('event_updated', { actorId: member, targetId: event.id });
logger.info('app', 'Calendar event updated', {
event: event.id,
user: req.user.id
})
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to update calendar event',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
export const calendarRouter = r;