feat(activity-log): add admin API endpoints (Phase 4)

Added 3 admin-only endpoints for activity log management:

1. GET /api/admin/activity-logs
   - Query logs with comprehensive filtering
   - Supports: date range, action, category, username, userId, success
   - Pagination with limit/offset
   - Logs ADMIN_VIEW_LOGS action
   - Returns: logs array, total count, pagination info

2. GET /api/admin/activity-logs/actions
   - Get list of unique action types
   - Returns: action names and categories
   - Useful for filter dropdowns in UI

3. GET /api/admin/activity-logs/stats
   - Dashboard statistics
   - Returns: total logs, unique users, failed actions,
     success rate, logs by category, recent activity (24h)

All endpoints protected with authenticate + requireAdmin middleware.
This commit is contained in:
Radosław Gierwiało
2025-12-02 20:09:49 +01:00
parent d83e4163e5
commit 4dd6603018

View File

@@ -4,7 +4,7 @@ const { authenticate } = require('../middleware/auth');
const { requireAdmin } = require('../middleware/admin');
const matchingService = require('../services/matching');
const { SUGGESTION_STATUS } = require('../constants');
const { ACTIONS, log: activityLog } = require('../services/activityLog');
const { ACTIONS, log: activityLog, queryLogs, getActionTypes, getStats } = require('../services/activityLog');
const { getClientIP } = require('../utils/request');
const router = express.Router();
@@ -237,3 +237,98 @@ router.get('/events/:slug/matching-runs/:runId/suggestions', authenticate, requi
next(error);
}
});
// ==================================================================
// ACTIVITY LOGS ENDPOINTS
// ==================================================================
// GET /api/admin/activity-logs - Query activity logs with filters
router.get('/activity-logs', authenticate, requireAdmin, async (req, res, next) => {
try {
const {
startDate,
endDate,
action,
category,
username,
userId,
success,
limit = 100,
offset = 0,
} = req.query;
// Parse query parameters
const filters = {
startDate: startDate ? new Date(startDate) : null,
endDate: endDate ? new Date(endDate) : null,
action: action || null,
category: category || null,
username: username || null,
userId: userId ? parseInt(userId) : null,
success: success !== undefined ? success === 'true' : null,
limit: parseInt(limit),
offset: parseInt(offset),
};
// Query logs
const result = await queryLogs(filters);
// Log admin viewing activity logs
activityLog({
userId: req.user.id,
username: req.user.username,
ipAddress: getClientIP(req),
action: ACTIONS.ADMIN_VIEW_LOGS,
method: req.method,
path: req.path,
metadata: {
filters: {
startDate,
endDate,
action,
category,
username,
userId,
success,
},
resultCount: result.logs.length,
},
});
res.json({
success: true,
data: result,
});
} catch (error) {
next(error);
}
});
// GET /api/admin/activity-logs/actions - Get unique action types
router.get('/activity-logs/actions', authenticate, requireAdmin, async (req, res, next) => {
try {
const actions = await getActionTypes();
res.json({
success: true,
count: actions.length,
data: actions,
});
} catch (error) {
next(error);
}
});
// GET /api/admin/activity-logs/stats - Get activity log statistics
router.get('/activity-logs/stats', authenticate, requireAdmin, async (req, res, next) => {
try {
const stats = await getStats();
res.json({
success: true,
data: stats,
});
} catch (error) {
next(error);
}
});