Files
milsim-site-v4/api/src/routes/loa.ts

262 lines
8.0 KiB
TypeScript

const express = require('express');
const router = express.Router();
import { Request, Response } from 'express';
import pool from '../db';
import { closeLOA, createNewLOA, getAllLOA, getLOAbyID, getLoaTypes, getUserLOA, setLOAExtension } from '../services/db/loaService';
import { LOARequest } from '@app/shared/types/loa';
import { requireLogin, requireRole } from '../middleware/auth';
import { logger } from '../services/logging/logger';
router.use(requireLogin);
//member posts LOA
router.post("/", async (req: Request, res: Response) => {
let LOARequest = req.body as LOARequest;
LOARequest.member_id = req.user.id;
LOARequest.created_by = req.user.id;
LOARequest.filed_date = new Date();
try {
await createNewLOA(LOARequest);
logger.info('app', 'LOA Posted', { poster: req.user.id, user: LOARequest.member_id })
res.sendStatus(201);
} catch (error) {
logger.error(
'app',
'Failed to post LOA',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send(error);
}
});
//admin posts LOA
router.post("/admin", [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
let LOARequest = req.body as LOARequest;
LOARequest.created_by = req.user.id;
LOARequest.filed_date = new Date();
try {
await createNewLOA(LOARequest);
logger.info('app', 'LOA Posted', { poster: req.user.id, user: LOARequest.member_id })
res.sendStatus(201);
} catch (error) {
logger.error(
'app',
'Failed to post LOA',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
); res.status(500).send(error);
}
});
//get my current LOA
router.get("/me", async (req: Request, res: Response) => {
const user = req.user.id;
try {
const result = await getUserLOA(user);
res.status(200).json(result)
} catch (error) {
logger.error(
'app',
'Failed to get user current LOA',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send(error);
}
})
//get my LOA history
router.get("/history", async (req: Request, res: Response) => {
try {
const user = req.user.id;
const page = Number(req.query.page) || undefined;
const pageSize = Number(req.query.pageSize) || undefined;
const result = await getUserLOA(user, page, pageSize);
res.status(200).json(result)
} catch (error) {
logger.error(
'app',
'Failed to get user LOA history',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send(error);
}
})
router.get('/all', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
try {
const page = Number(req.query.page) || undefined;
const pageSize = Number(req.query.pageSize) || undefined;
const result = await getAllLOA(page, pageSize);
res.status(200).json(result)
} catch (error) {
logger.error(
'app',
'Failed to get full LOA history',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).send(error);
}
})
router.get('/types', async (req: Request, res: Response) => {
try {
let out = await getLoaTypes();
res.status(200).json(out);
} catch (error) {
logger.error(
'app',
'Failed to get LOA types',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
router.post('/cancel/:id', async (req: Request, res: Response) => {
let closer = req.user.id;
let id = Number(req.params.id);
try {
let loa = await getLOAbyID(id);
if (loa.member_id != closer) {
return res.sendStatus(403);
}
await closeLOA(Number(req.params.id), closer);
logger.info('app', 'LOA Closed', { closed_by: closer, LOA: id })
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to cancel LOA',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
//TODO: enforce admin only
router.post('/adminCancel/:id', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
let closer = req.user.id;
try {
await closeLOA(Number(req.params.id), closer);
logger.info('app', 'LOA Closed', { closed_by: closer, LOA: req.params.id })
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to cancel LOA',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
// extend LOA
router.post('/extend/:id', [requireRole(['17th Administrator', '17th HQ', '17th Command'])], async (req: Request, res: Response) => {
const to: Date = req.body.to;
if (!to) {
res.status(400).send("Extension length is required");
}
try {
await setLOAExtension(Number(req.params.id), to);
logger.info('app', 'LOA Extended', { extended_by: req.user.id, LOA: req.params.id })
res.sendStatus(200);
} catch (error) {
logger.error(
'app',
'Failed to extend LOA',
{
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
}
);
res.status(500).json(error);
}
})
// GET /policy
router.get('/policy', async (req: Request, res: Response) => {
const t0 = performance.now();
try {
const response = await fetch(`${process.env.DOC_HOST}/api/pages/42`, {
headers: {
Authorization: `Token ${process.env.DOC_TOKEN_ID}:${process.env.DOC_TOKEN_SECRET}`,
},
});
if (!response.ok) {
const text = await response.text();
logger.error('app', 'Failed to fetch policy page from Bookstack', {
pageId: 42,
status: response.status,
statusText: response.statusText,
body: text,
userId: req.user?.id,
});
return res.sendStatus(500);
}
const out = await response.json();
res.status(200).json(out.html);
logger.info(
'profiling',
'GET /policy completed',
{
pageId: 42,
total_ms: performance.now() - t0,
},
'profiling'
);
} catch (error) {
logger.error('app', 'Error fetching policy page from Bookstack', {
pageId: 42,
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
userId: req.user?.id,
});
res.sendStatus(500);
}
});
export const loaRouter = router;