Add audit logs.
ci-cd-vm / ci-cd (push) Successful in 4m2s

This commit is contained in:
Chris Chen
2026-06-23 12:13:47 -07:00
parent 870eeec82a
commit 62592c29ae
106 changed files with 2522 additions and 311 deletions
+32
View File
@@ -4,6 +4,8 @@ using Microsoft.Extensions.Configuration;
using ROLAC.API.Data;
using ROLAC.API.DTOs.Auth;
using ROLAC.API.Entities;
using ROLAC.API.Entities.Logging;
using ROLAC.API.Services.Logging;
namespace ROLAC.API.Services;
@@ -13,6 +15,7 @@ public class AuthService : IAuthService
private readonly ITokenService _tokenService;
private readonly AppDbContext _db;
private readonly IPermissionService _permissions;
private readonly IAuditLogger _audit;
private readonly int _refreshTokenExpiryDays;
public AuthService(
@@ -20,12 +23,14 @@ public class AuthService : IAuthService
ITokenService tokenService,
AppDbContext db,
IPermissionService permissions,
IAuditLogger audit,
IConfiguration config)
{
_userManager = userManager;
_tokenService = tokenService;
_db = db;
_permissions = permissions;
_audit = audit;
_refreshTokenExpiryDays = int.Parse(config["Jwt:RefreshTokenExpiryDays"] ?? "30");
}
@@ -38,13 +43,22 @@ public class AuthService : IAuthService
{
var user = await _userManager.FindByEmailAsync(request.Email);
if (user is null)
{
AuditLoginFailed(request.Email, "Unknown email", ipAddress);
throw new UnauthorizedAccessException("Invalid credentials.");
}
if (!await _userManager.CheckPasswordAsync(user, request.Password))
{
AuditLoginFailed(request.Email, "Wrong password", ipAddress, user.Id);
throw new UnauthorizedAccessException("Invalid credentials.");
}
if (!user.IsActive)
{
AuditLoginFailed(request.Email, "Account inactive", ipAddress, user.Id);
throw new UnauthorizedAccessException("Account is inactive.");
}
var roles = await _userManager.GetRolesAsync(user);
var accessToken = _tokenService.GenerateAccessToken(user, roles);
@@ -65,9 +79,22 @@ public class AuthService : IAuthService
await _userManager.UpdateAsync(user);
await _db.SaveChangesAsync();
_audit.Write(
AuditActions.Login, AuditCategories.Security, LogLevelEnum.Information,
entityName: nameof(AppUser), entityId: user.Id,
summary: $"Login succeeded: {user.Email}",
userId: user.Id, userEmail: user.Email, ipAddress: ipAddress);
return (await BuildResponseAsync(accessToken, user, roles), rawRefresh);
}
private void AuditLoginFailed(string email, string reason, string? ipAddress, string? userId = null)
=> _audit.Write(
AuditActions.LoginFailed, AuditCategories.Security, LogLevelEnum.Warning,
entityName: nameof(AppUser), entityId: userId,
summary: $"Login failed ({reason}): {email}",
userId: userId, userEmail: email, ipAddress: ipAddress);
// -------------------------------------------------------------------------
// Refresh
// -------------------------------------------------------------------------
@@ -124,6 +151,11 @@ public class AuthService : IAuthService
{
token.RevokedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
_audit.Write(
AuditActions.Logout, AuditCategories.Security, LogLevelEnum.Information,
entityName: nameof(AppUser), entityId: token.UserId,
summary: "Logout", userId: token.UserId);
}
}