216 lines
6.8 KiB
TypeScript
216 lines
6.8 KiB
TypeScript
const express = require('express');
|
|
const router = express.Router();
|
|
|
|
import { Request, Response } from 'express';
|
|
import pool from '../db';
|
|
import { requireLogin, requireMemberState, requireRole } from '../middleware/auth';
|
|
import { getUserActiveLOA } from '../services/db/loaService';
|
|
import { getAllMembersLite, getMemberSettings, getMembersFull, getMembersLite, getUserData, getUserState, setUserSettings } from '../services/db/memberService';
|
|
import { getUserRoles } from '../services/db/rolesService';
|
|
import { memberSettings, MemberState, myData } from '@app/shared/types/member';
|
|
|
|
import { Performance } from 'perf_hooks';
|
|
import { logger } from '../services/logging/logger';
|
|
|
|
//get all users
|
|
router.get('/', [requireLogin, requireMemberState(MemberState.Member)], async (req, res) => {
|
|
try {
|
|
const result = await pool.query(
|
|
`SELECT
|
|
v.*,
|
|
CASE
|
|
WHEN EXISTS (
|
|
SELECT 1
|
|
FROM leave_of_absences l
|
|
WHERE l.member_id = v.member_id
|
|
AND l.deleted = 0
|
|
AND UTC_TIMESTAMP() BETWEEN l.start_date AND l.end_date
|
|
) THEN 1 ELSE 0
|
|
END AS on_loa
|
|
FROM view_member_rank_unit_status_latest v;`);
|
|
return res.status(200).json(result);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to get all users',
|
|
{
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
);
|
|
return res.status(500).json({ error: 'Failed to fetch users' });
|
|
}
|
|
});
|
|
|
|
router.get('/me', [requireLogin], async (req: Request, res) => {
|
|
if (!req.user) return res.sendStatus(401);
|
|
|
|
const routeStart = performance.now();
|
|
const timings: Record<string, number> = {};
|
|
|
|
try {
|
|
let t;
|
|
|
|
t = performance.now();
|
|
const memData = await getUserData(req.user.id);
|
|
timings.member = performance.now() - t;
|
|
|
|
t = performance.now();
|
|
const LOAData = await getUserActiveLOA(req.user.id);
|
|
timings.loa = performance.now() - t;
|
|
|
|
t = performance.now();
|
|
const memState = await getUserState(req.user.id);
|
|
timings.state = performance.now() - t;
|
|
|
|
t = performance.now();
|
|
const roleData = await getUserRoles(req.user.id);
|
|
timings.roles = performance.now() - t;
|
|
|
|
const userDataFull: myData = {
|
|
member: memData,
|
|
LOAs: LOAData,
|
|
roles: roleData,
|
|
state: memState,
|
|
};
|
|
|
|
res.status(200).json(userDataFull);
|
|
|
|
logger.info('profiling', 'GET /members/me completed', {
|
|
userId: req.user.id,
|
|
total_ms: performance.now() - routeStart,
|
|
breakdown_ms: timings,
|
|
}, 'profiling');
|
|
|
|
} catch (error) {
|
|
logger.error('profiling', 'GET /members/me failed', {
|
|
userId: req.user?.id,
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
|
|
return res.status(500).json({ error: 'Failed to fetch user data' });
|
|
}
|
|
});
|
|
|
|
|
|
router.get('/settings', [requireLogin], async (req: Request, res: Response) => {
|
|
try {
|
|
let user = req.user.id;
|
|
let output = await getMemberSettings(user);
|
|
res.status(200).json(output);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to get member settings',
|
|
{
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
);
|
|
res.status(500).json(error);
|
|
}
|
|
})
|
|
|
|
router.put('/settings', [requireLogin], async (req: Request, res: Response) => {
|
|
try {
|
|
let user = req.user.id;
|
|
let settings: memberSettings = req.body;
|
|
await setUserSettings(user, settings);
|
|
logger.info('app', 'User updated profile settings', { user: user })
|
|
res.sendStatus(200);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to update user settings',
|
|
{
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
); res.status(500).json(error);
|
|
}
|
|
})
|
|
|
|
router.get('/lite', [requireLogin], async (req: Request, res: Response) => {
|
|
try {
|
|
let out = await getAllMembersLite();
|
|
res.status(200).json(out);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to get lite users',
|
|
{
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
);
|
|
res.status(500).json(error);
|
|
}
|
|
})
|
|
|
|
router.post('/lite/bulk', async (req: Request, res: Response) => {
|
|
try {
|
|
let ids = req.body.ids;
|
|
let out = await getMembersLite(ids);
|
|
res.status(200).json(out);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to get batch lite users',
|
|
{
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
);
|
|
res.status(500).json(error);
|
|
}
|
|
})
|
|
|
|
|
|
router.post('/full/bulk', async (req: Request, res: Response) => {
|
|
try {
|
|
let ids = req.body.ids;
|
|
let out = await getMembersFull(ids);
|
|
res.status(200).json(out);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to get batch full users',
|
|
{
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
); res.status(500).json(error);
|
|
}
|
|
})
|
|
|
|
router.get('/:id', [requireLogin], async (req, res) => {
|
|
const userId = req.params.id;
|
|
|
|
try {
|
|
const result = await pool.query('SELECT * FROM view_member_rank_unit_status_latest WHERE id = $1;', [userId]);
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ error: 'User not found' });
|
|
}
|
|
return res.status(200).json(result.rows[0]);
|
|
} catch (error) {
|
|
logger.error(
|
|
'app',
|
|
'Failed to get user',
|
|
{
|
|
user: userId,
|
|
error: error instanceof Error ? error.message : String(error),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
}
|
|
); return res.status(500).json({ error: 'Failed to fetch user' });
|
|
}
|
|
});
|
|
|
|
//update a user's display name (stub)
|
|
router.put('/:id/displayname', async (req, res) => {
|
|
// Stub: not implemented yet
|
|
return res.status(501);
|
|
});
|
|
|
|
|
|
export const memberRouter = router;
|