Spaces:
Running
Running
| using System; | |
| using System.Threading.Tasks; | |
| using Microsoft.AspNetCore.Http; | |
| using TaskTrackingSystem.Database.AppDbContextModels; | |
| namespace TaskTrackingSystem.WebApi.Infrastructure | |
| { | |
| public class AuditLogService | |
| { | |
| private readonly AppDbContext _db; | |
| private readonly IHttpContextAccessor _httpContextAccessor; | |
| public AuditLogService(AppDbContext db, IHttpContextAccessor httpContextAccessor) | |
| { | |
| _db = db; | |
| _httpContextAccessor = httpContextAccessor; | |
| } | |
| public async System.Threading.Tasks.Task LogAsync(string action, string module, string description) | |
| { | |
| try | |
| { | |
| var httpContext = _httpContextAccessor.HttpContext; | |
| long? userId = null; | |
| string? ipAddress = null; | |
| if (httpContext != null) | |
| { | |
| var user = httpContext.User; | |
| if (user != null) | |
| { | |
| var id = user.GetUserId(); | |
| if (id > 0) | |
| { | |
| userId = id; | |
| } | |
| } | |
| // Get remote IP address | |
| ipAddress = httpContext.Connection?.RemoteIpAddress?.ToString(); | |
| // Fallback to check X-Forwarded-For if behind reverse proxy | |
| if (httpContext.Request.Headers.TryGetValue("X-Forwarded-For", out var forwardedFor)) | |
| { | |
| ipAddress = forwardedFor.ToString().Split(',')[0].Trim(); | |
| } | |
| } | |
| var log = new AuditLog | |
| { | |
| UserId = userId, | |
| Action = action, | |
| Module = module, | |
| Description = description, | |
| IpAddress = ipAddress, | |
| CreatedAt = DateTime.UtcNow | |
| }; | |
| _db.AuditLogs.Add(log); | |
| await _db.SaveChangesAsync(); | |
| } | |
| catch (Exception ex) | |
| { | |
| // Never let audit logging failure block critical operations | |
| Console.WriteLine($"[AuditLog Error] Failed to write audit log: {ex.Message}"); | |
| } | |
| } | |
| } | |
| } | |