feat(activity-log): integrate logging across all endpoints (Phase 3)
Added comprehensive activity logging to 14 integration points: Auth Controller (4 actions): - AUTH_REGISTER: User registration - AUTH_LOGIN: User login - AUTH_VERIFY_EMAIL: Email verification (token & code) - AUTH_PASSWORD_RESET: Password reset Events Routes (2 actions): - EVENT_CHECKIN: User checks into event - EVENT_LEAVE: User leaves event Socket Handlers (3 actions): - EVENT_JOIN_CHAT: User joins event chat room - EVENT_LEAVE_CHAT: User leaves event chat room - CHAT_JOIN_ROOM: User joins private match chat Matches Routes (3 actions): - MATCH_CREATE: Match request created - MATCH_ACCEPT: Match request accepted - MATCH_REJECT: Match request rejected/cancelled Admin Routes (1 action + security): - ADMIN_MATCHING_RUN: Admin runs matching algorithm - Added requireAdmin middleware to all admin routes All logs include: - User ID and username (denormalized) - IP address (X-Forwarded-For aware) - Action type and resource ID - HTTP method and path (or SOCKET for WebSocket) - Contextual metadata (event slugs, match IDs, etc.) Fire-and-forget pattern ensures logging never blocks requests.
This commit is contained in:
@@ -10,6 +10,8 @@ const {
|
||||
const { sendVerificationEmail, sendWelcomeEmail, sendPasswordResetEmail } = require('../emails');
|
||||
const { sanitizeForEmail, timingSafeEqual } = require('../utils/sanitize');
|
||||
const securityConfig = require('../config/security');
|
||||
const { ACTIONS, log: activityLog } = require('../services/activityLog');
|
||||
const { getClientIP } = require('../utils/request');
|
||||
|
||||
// Register new user (Phase 1.5 - with WSDC support and email verification)
|
||||
async function register(req, res, next) {
|
||||
@@ -92,6 +94,20 @@ async function register(req, res, next) {
|
||||
// Generate JWT token
|
||||
const token = generateToken({ userId: user.id });
|
||||
|
||||
// Log registration activity
|
||||
activityLog({
|
||||
userId: user.id,
|
||||
username: user.username,
|
||||
ipAddress: getClientIP(req),
|
||||
action: ACTIONS.AUTH_REGISTER,
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
metadata: {
|
||||
email: user.email,
|
||||
hasWsdcId: !!user.wsdcId,
|
||||
},
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'User registered successfully. Please check your email to verify your account.',
|
||||
@@ -199,6 +215,20 @@ async function login(req, res, next) {
|
||||
// Return user without password
|
||||
const { passwordHash, ...userWithoutPassword } = user;
|
||||
|
||||
// Log login activity
|
||||
activityLog({
|
||||
userId: user.id,
|
||||
username: user.username,
|
||||
ipAddress: getClientIP(req),
|
||||
action: ACTIONS.AUTH_LOGIN,
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
metadata: {
|
||||
email: user.email,
|
||||
emailVerified: user.emailVerified,
|
||||
},
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Login successful',
|
||||
@@ -276,6 +306,19 @@ async function verifyEmailByToken(req, res, next) {
|
||||
// Remove sensitive data
|
||||
const { passwordHash, verificationToken, verificationCode, verificationTokenExpiry, resetToken, resetTokenExpiry, ...userWithoutPassword } = updatedUser;
|
||||
|
||||
// Log email verification activity
|
||||
activityLog({
|
||||
userId: updatedUser.id,
|
||||
username: updatedUser.username,
|
||||
ipAddress: getClientIP(req),
|
||||
action: ACTIONS.AUTH_VERIFY_EMAIL,
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
metadata: {
|
||||
verificationMethod: 'token',
|
||||
},
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Email verified successfully!',
|
||||
@@ -356,6 +399,19 @@ async function verifyEmailByCode(req, res, next) {
|
||||
// Remove sensitive data
|
||||
const { passwordHash, verificationToken, verificationCode, verificationTokenExpiry, resetToken, resetTokenExpiry, ...userWithoutPassword } = updatedUser;
|
||||
|
||||
// Log email verification activity
|
||||
activityLog({
|
||||
userId: updatedUser.id,
|
||||
username: updatedUser.username,
|
||||
ipAddress: getClientIP(req),
|
||||
action: ACTIONS.AUTH_VERIFY_EMAIL,
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
metadata: {
|
||||
verificationMethod: 'code',
|
||||
},
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Email verified successfully!',
|
||||
@@ -543,6 +599,19 @@ async function resetPassword(req, res, next) {
|
||||
},
|
||||
});
|
||||
|
||||
// Log password reset activity
|
||||
activityLog({
|
||||
userId: user.id,
|
||||
username: user.username,
|
||||
ipAddress: getClientIP(req),
|
||||
action: ACTIONS.AUTH_PASSWORD_RESET,
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
metadata: {
|
||||
email: user.email,
|
||||
},
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Password reset successfully',
|
||||
|
||||
Reference in New Issue
Block a user