Skip to content

Commit 48f71ca

Browse files
ryansavaraRyan Savara
andauthored
Allow Filtering of Log (#153)
Co-authored-by: Ryan Savara <ryan.savara@vatusa.net>
1 parent 4067a2c commit 48f71ca

14 files changed

Lines changed: 184 additions & 36 deletions

File tree

src/controllers/controller/absence.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getCacheInstance } from '../../app.js';
44
import { isManagement } from '../../middleware/auth.js';
55
import getUser from '../../middleware/user.js';
66
import { AbsenceModel } from '../../models/absence.js';
7-
import { DossierModel } from '../../models/dossier.js';
7+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
88
import { NotificationModel } from '../../models/notification.js';
99
import status from '../../types/status.js';
1010

@@ -76,6 +76,7 @@ router.post('/', getUser, isManagement, async (req: Request, res: Response, next
7676
by: req.user.cid,
7777
affected: req.body.controller,
7878
action: `%b added a leave of absence for %a until ${new Date(req.body.expirationDate).toLocaleDateString()}: ${req.body.reason}`,
79+
actionType: ACTION_TYPE.CREATE_LOA,
7980
});
8081

8182
return res.status(status.CREATED).json();
@@ -115,6 +116,7 @@ router.delete(
115116
by: req.user.cid,
116117
affected: absence.controller,
117118
action: `%b deleted the leave of absence for %a.`,
119+
actionType: ACTION_TYPE.DELETE_LOA,
118120
});
119121

120122
return res.status(status.NO_CONTENT).json();

src/controllers/controller/controller.ts

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import internalAuth from '../../middleware/internalAuth.js';
1717
import getUser from '../../middleware/user.js';
1818
import { CertificationModel } from '../../models/certification.js';
1919
import { ControllerHoursModel } from '../../models/controllerHours.js';
20-
import { DossierModel } from '../../models/dossier.js';
20+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
2121
import { RoleModel } from '../../models/role.js';
2222
import { UserModel, type IUser } from '../../models/user.js';
2323
import status from '../../types/status.js';
@@ -204,10 +204,17 @@ router.get('/oi', async (_req: Request, res: Response, next: NextFunction) => {
204204
router.get('/log', getUser, isStaff, async (req: Request, res: Response, next: NextFunction) => {
205205
const page = +(req.query['page'] as string) || 1;
206206
const limit = +(req.query['limit'] as string) || 20;
207-
const amount = await DossierModel.countDocuments().cache('5 minutes').exec();
207+
const action = +(req.query['action'] as string);
208+
209+
const actionQuery = {} as any;
210+
if (!isNaN(action) && action > 0) {
211+
actionQuery.actionType = action;
212+
}
213+
214+
const amount = await DossierModel.countDocuments(actionQuery).cache('5 minutes').exec();
208215

209216
try {
210-
const dossier = await DossierModel.find()
217+
const dossier = await DossierModel.find(actionQuery)
211218
.sort({
212219
createdAt: 'desc',
213220
})
@@ -228,6 +235,67 @@ router.get('/log', getUser, isStaff, async (req: Request, res: Response, next: N
228235
}
229236
});
230237

238+
router.get(
239+
'/log/types',
240+
getUser,
241+
isStaff,
242+
async (_req: Request, res: Response, next: NextFunction) => {
243+
try {
244+
return res
245+
.status(status.OK)
246+
.json([
247+
'All Actions',
248+
'Created User',
249+
'Updated User',
250+
'Removed User',
251+
'Updated Bio',
252+
'Set Membership',
253+
'Set Visit Status',
254+
'Created LOA',
255+
'Removed LOA',
256+
'Set Rating',
257+
'Approved Visit Application',
258+
'Rejected Visit Application',
259+
'Created Event Signup',
260+
'Deleted Event Signup',
261+
'Created Manual Event Signup',
262+
'Deleted Manual Event Signup',
263+
'Assigned Event Position',
264+
'Unassigned Event Position',
265+
'Created Event',
266+
'Updated Event',
267+
'Deleted Event',
268+
'Sent Notification for Event',
269+
'Approved Staffing Request',
270+
'Rejected Staffing Request',
271+
'Submitted Feedback',
272+
'Approved Feedback',
273+
'Rejected Feedback',
274+
'Created Document',
275+
'Updated Document',
276+
'Deleted Document',
277+
'Created File',
278+
'Updated File',
279+
'Deleted File',
280+
'Created News',
281+
'Updated News',
282+
'Deleted News',
283+
'Issued Solo Endorsement',
284+
'Extended Solo Endorsement',
285+
'Deleted Solo Endorsement',
286+
'Generated IDS Token',
287+
'Connected Discord',
288+
'Disconnect Discord',
289+
]);
290+
} catch (e) {
291+
if (!(e as any).code) {
292+
captureException(e);
293+
}
294+
return next(e);
295+
}
296+
},
297+
);
298+
231299
router.get('/:cid', userOrInternal, async (req: Request, res: Response, next: NextFunction) => {
232300
try {
233301
if (
@@ -320,6 +388,7 @@ router.patch(
320388
by: -1,
321389
affected: req.params['cid'],
322390
action: `%a was set as Rating ${req.body.rating} by an external service.`,
391+
actionType: ACTION_TYPE.SET_RATING,
323392
});
324393
}
325394

@@ -509,6 +578,7 @@ router.post('/:cid', internalAuth, async (req: Request, res: Response, next: Nex
509578
by: -1,
510579
affected: req.body.cid,
511580
action: `%a was created by an external service.`,
581+
actionType: ACTION_TYPE.CREATE_USER,
512582
});
513583

514584
return res.status(status.CREATED).json();
@@ -602,6 +672,7 @@ router.patch(
602672
by: -1,
603673
affected: req.params['cid'],
604674
action: `%a was ${req.body.member ? 'added to' : 'removed from'} the roster by an external service.`,
675+
actionType: ACTION_TYPE.SET_MEMBERSHIP,
605676
});
606677

607678
return res.status(status.OK).json();
@@ -667,6 +738,7 @@ router.patch(
667738
by: -1,
668739
affected: req.params['cid'],
669740
action: `%a was set as a ${req.body.vis ? 'visiting controller' : 'home controller'} by an external service.`,
741+
actionType: ACTION_TYPE.SET_VISIT_STATUS,
670742
});
671743

672744
return res.status(status.OK).json();
@@ -766,6 +838,7 @@ router.put(
766838
by: req.user.cid,
767839
affected: req.params['cid'],
768840
action: `%a was updated by %b.`,
841+
actionType: ACTION_TYPE.UPDATE_USER,
769842
});
770843

771844
return res.status(status.OK).json();
@@ -892,6 +965,7 @@ router.delete(
892965
by: req.user.cid,
893966
affected: req.params['cid'],
894967
action: `%a was removed from the roster by %b, reason: ${req.body.reason}`,
968+
actionType: ACTION_TYPE.DELETE_USER,
895969
});
896970

897971
return res.status(status.NO_CONTENT).json();

src/controllers/controller/visitapplications.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { sendMail } from '../../helpers/mailer.js';
55
import { vatusaApi, type IVisitingStatus } from '../../helpers/vatusa.js';
66
import { isManagement } from '../../middleware/auth.js';
77
import getUser from '../../middleware/user.js';
8-
import { DossierModel } from '../../models/dossier.js';
8+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
99
import { UserModel } from '../../models/user.js';
1010
import { VisitApplicationModel } from '../../models/visitApplication.js';
1111
import status from '../../types/status.js';
@@ -229,6 +229,7 @@ router.put(
229229
by: req.user.cid,
230230
affected: user.cid,
231231
action: `%b approved the visiting application for %a.`,
232+
actionType: ACTION_TYPE.APPROVE_VISIT,
232233
});
233234

234235
return res.status(status.OK).json();
@@ -295,6 +296,7 @@ router.delete(
295296
by: req.user.cid,
296297
affected: user.cid,
297298
action: `%b rejected the visiting application for %a: ${req.body.reason}`,
299+
type: ACTION_TYPE.REJECT_VISIT,
298300
});
299301

300302
return res.status(status.NO_CONTENT).json();

src/controllers/discord/discord.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Router, type NextFunction, type Request, type Response } from 'express'
33
import discord from '../../helpers/discord.js';
44
import internalAuth from '../../middleware/internalAuth.js';
55
import getUser from '../../middleware/user.js';
6-
import { DossierModel } from '../../models/dossier.js';
6+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
77
import { UserModel } from '../../models/user.js';
88
import status from '../../types/status.js';
99
import { clearUserCache } from '../controller/utils.js';
@@ -116,6 +116,7 @@ router.post('/info', async (req: Request, res: Response, next: NextFunction) =>
116116
by: user.cid,
117117
affected: -1,
118118
action: `%b connected their Discord.`,
119+
actionType: ACTION_TYPE.CONNECT_DISCORD,
119120
});
120121

121122
return res.status(status.CREATED).json();
@@ -132,6 +133,13 @@ router.delete('/user', getUser, async (req: Request, res: Response, next: NextFu
132133
await UserModel.updateOne({ cid: req.user.cid }, { $unset: { discord: '', discordInfo: '' } });
133134
clearUserCache(req.user.cid);
134135

136+
await DossierModel.create({
137+
by: req.user.cid,
138+
affected: -1,
139+
action: `%b disconnected their Discord.`,
140+
actionType: ACTION_TYPE.DISCONNECT_DISCORD,
141+
});
142+
135143
res.status(status.OK).json();
136144
} catch (e) {
137145
if (!(e as any).code) {

src/controllers/event/event.ts

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { sendMail } from '../../helpers/mailer.js';
99
import { deleteFromS3, setUploadStatus, uploadToS3 } from '../../helpers/s3.js';
1010
import { isEventsTeam } from '../../middleware/auth.js';
1111
import getUser from '../../middleware/user.js';
12-
import { DossierModel } from '../../models/dossier.js';
12+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
1313
import EventModel from '../../models/event.js';
1414
import type { IEventPosition, IEventPositionData } from '../../models/eventPosition.js';
1515
import type { IEventSignup } from '../../models/eventSignup.js';
@@ -211,6 +211,7 @@ router.patch('/:slug/signup', getUser, async (req: Request, res: Response, next:
211211
by: req.user.cid,
212212
affected: -1,
213213
action: `%b signed up for the event *${event.name}*.`,
214+
actionType: ACTION_TYPE.CREATE_EVENT_SIGNUP,
214215
});
215216

216217
return res.status(status.OK).json();
@@ -256,6 +257,7 @@ router.delete('/:slug/signup', getUser, async (req: Request, res: Response, next
256257
by: req.user.cid,
257258
affected: -1,
258259
action: `%b deleted their signup for the event *${event.name}*.`,
260+
actionType: ACTION_TYPE.DELETE_EVENT_SIGNUP,
259261
});
260262

261263
return res.status(status.NO_CONTENT).json();
@@ -328,6 +330,7 @@ router.delete(
328330
by: req.user.cid,
329331
affected: req.params['cid'],
330332
action: `%b manually deleted the event signup for %a for the event *${signup.name}*.`,
333+
actionType: ACTION_TYPE.MANUAL_DELETE_EVENT_SIGNUP,
331334
});
332335

333336
return res.status(status.NO_CONTENT).json();
@@ -414,6 +417,7 @@ router.patch(
414417
by: req.user.cid,
415418
affected: req.params['cid'],
416419
action: `%b manually signed up %a for the event *${event.name}*.`,
420+
actionType: ACTION_TYPE.MANUAL_EVENT_SIGNUP,
417421
});
418422

419423
return res.status(status.OK).json();
@@ -479,12 +483,14 @@ router.patch(
479483
by: req.user.cid,
480484
affected: cid,
481485
action: `%b assigned %a to *${assignedPosition.pos}* for *${eventData.name}*.`,
486+
actionType: ACTION_TYPE.ASSIGN_EVENT_POSITION,
482487
});
483488
} else {
484489
await DossierModel.create({
485490
by: req.user.cid,
486491
affected: -1,
487492
action: `%b unassigned *${assignedPosition.pos}* for *${eventData.name}*.`,
493+
actionType: ACTION_TYPE.UNASSIGN_EVENT_POSITION,
488494
});
489495
}
490496

@@ -747,6 +753,7 @@ router.post(
747753
by: req.user.cid,
748754
affected: -1,
749755
action: `%b created the event *${req.body.name}*.`,
756+
actionType: ACTION_TYPE.CREATE_EVENT,
750757
});
751758

752759
return res.status(status.CREATED).json();
@@ -923,6 +930,7 @@ router.put(
923930
by: req.user.cid,
924931
affected: -1,
925932
action: `%b updated the event *${eventData.name}*.`,
933+
actionType: ACTION_TYPE.UPDATE_EVENT,
926934
});
927935

928936
return res.status(status.OK).json();
@@ -973,6 +981,7 @@ router.delete(
973981
by: req.user.cid,
974982
affected: -1,
975983
action: `%b deleted the event *${deleteEvent.name}*.`,
984+
actionType: ACTION_TYPE.DELETE_EVENT,
976985
});
977986

978987
return res.status(status.NO_CONTENT).json();
@@ -985,27 +994,6 @@ router.delete(
985994
},
986995
);
987996

988-
// router.put('/:slug/assign', getUser, isEventsTeam, async (req: Request, res: Response) => {
989-
// try {
990-
// const event = await Event.findOneAndUpdate({url: req.params.slug}, {
991-
// $set: {
992-
// positions: req.body.assignment
993-
// }
994-
// });
995-
996-
// await DossierModel.create({
997-
// by: req.user.cid,
998-
// affected: -1,
999-
// action: `%b updated the positions assignments for the event *${event.name}*.`
1000-
// });
1001-
// } catch (e) {
1002-
// res.stdRes.ret_det = convertToReturnDetails(e);
1003-
// captureException(e);
1004-
// } finally {
1005-
// return res.json(res.stdRes);
1006-
// }
1007-
// });
1008-
1009997
router.patch(
1010998
'/:slug/notify',
1011999
getUser,
@@ -1059,6 +1047,7 @@ router.patch(
10591047
by: req.user.cid,
10601048
affected: -1,
10611049
action: `%b notified controllers of positions for the event *${eventData.name}*.`,
1050+
actionType: ACTION_TYPE.NOTIFY_EVENT,
10621051
});
10631052

10641053
return res.status(status.OK).json();

src/controllers/event/staffingrequest.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getCacheInstance } from '../../app.js';
44
import { sendMail } from '../../helpers/mailer.js';
55
import { isEventsTeam } from '../../middleware/auth.js';
66
import getUser from '../../middleware/user.js';
7-
import { DossierModel } from '../../models/dossier.js';
7+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
88
import { StaffingRequestModel } from '../../models/staffingRequest.js';
99
import status from '../../types/status.js';
1010

@@ -204,6 +204,14 @@ router.put(
204204
by: req.user.cid,
205205
affected: -1,
206206
action: `%b approved a staffing request for ${req.body.vaName}.`,
207+
actionType: ACTION_TYPE.APPROVE_STAFFING_REQUEST,
208+
});
209+
} else {
210+
await DossierModel.create({
211+
by: req.user.cid,
212+
affected: -1,
213+
action: `%b rejected a staffing request for ${req.body.vaName}.`,
214+
actionType: ACTION_TYPE.REJECT_STAFFING_REQUEST,
207215
});
208216
}
209217

src/controllers/feedback/feedback.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getCacheInstance } from '../../app.js';
44
import { getUsersWithPrivacy } from '../../helpers/mongodb.js';
55
import { isSeniorStaff } from '../../middleware/auth.js';
66
import getUser from '../../middleware/user.js';
7-
import { DossierModel } from '../../models/dossier.js';
7+
import { ACTION_TYPE, DossierModel } from '../../models/dossier.js';
88
import { FeedbackModel } from '../../models/feedback.js';
99
import { NotificationModel } from '../../models/notification.js';
1010
import status from '../../types/status.js';
@@ -129,6 +129,7 @@ router.post('/', async (req: Request, res: Response, next: NextFunction) => {
129129
by: req.body.cid,
130130
affected: req.body.controller,
131131
action: `%b submitted feedback about %a.`,
132+
actionType: ACTION_TYPE.SUBMIT_FEEDBACK,
132133
});
133134

134135
return res.status(status.CREATED).json();
@@ -257,6 +258,7 @@ router.patch(
257258
by: req.user.cid,
258259
affected: approved.controllerCid,
259260
action: `%b approved feedback for %a.`,
261+
actionType: ACTION_TYPE.APPROVE_FEEDBACK,
260262
});
261263

262264
return res.status(status.OK).json();
@@ -302,6 +304,7 @@ router.patch(
302304
by: req.user.cid,
303305
affected: feedback.controllerCid,
304306
action: `%b rejected feedback for %a.`,
307+
type: ACTION_TYPE.REJECT_FEEDBACK,
305308
});
306309

307310
return res.status(status.OK).json();

0 commit comments

Comments
 (0)