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:
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user