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 { requireAdmin } = require('../middleware/admin');
|
||||||
const matchingService = require('../services/matching');
|
const matchingService = require('../services/matching');
|
||||||
const { SUGGESTION_STATUS } = require('../constants');
|
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 { getClientIP } = require('../utils/request');
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@@ -237,3 +237,98 @@ router.get('/events/:slug/matching-runs/:runId/suggestions', authenticate, requi
|
|||||||
next(error);
|
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