mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 08:01:16 +00:00
119 lines
4.2 KiB
Go
119 lines
4.2 KiB
Go
package audit
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/warmbly/warmbly/internal/errx"
|
|
"github.com/warmbly/warmbly/internal/models"
|
|
"github.com/warmbly/warmbly/internal/repository"
|
|
)
|
|
|
|
type AuditService interface {
|
|
// Log a new audit entry
|
|
Log(ctx context.Context, log *models.CreateAuditLog) error
|
|
|
|
// Log from gin context (extracts IP, user agent)
|
|
LogAction(ctx context.Context, userID uuid.UUID, action models.AuditAction, entityType models.AuditEntityType, entityID *uuid.UUID, ipAddress, userAgent string, changes, metadata map[string]string)
|
|
|
|
// Query logs
|
|
GetUserLogs(ctx context.Context, userID uuid.UUID, params *models.AuditLogSearch) (*models.AuditLogsResult, *errx.Error)
|
|
GetEntityLogs(ctx context.Context, entityType models.AuditEntityType, entityID uuid.UUID, limit int, cursor string) (*models.AuditLogsResult, *errx.Error)
|
|
}
|
|
|
|
type auditService struct {
|
|
repo repository.AuditRepository
|
|
}
|
|
|
|
func NewService(repo repository.AuditRepository) AuditService {
|
|
return &auditService{
|
|
repo: repo,
|
|
}
|
|
}
|
|
|
|
func (s *auditService) Log(ctx context.Context, log *models.CreateAuditLog) error {
|
|
return s.repo.Log(ctx, log)
|
|
}
|
|
|
|
func (s *auditService) LogAction(ctx context.Context, userID uuid.UUID, action models.AuditAction, entityType models.AuditEntityType, entityID *uuid.UUID, ipAddress, userAgent string, changes, metadata map[string]string) {
|
|
// Fire and forget - don't block the request
|
|
go func() {
|
|
log := &models.CreateAuditLog{
|
|
UserID: userID,
|
|
Action: action,
|
|
EntityType: entityType,
|
|
EntityID: entityID,
|
|
IPAddress: ipAddress,
|
|
UserAgent: userAgent,
|
|
Changes: changes,
|
|
Metadata: metadata,
|
|
}
|
|
_ = s.repo.Log(context.Background(), log)
|
|
}()
|
|
}
|
|
|
|
func (s *auditService) GetUserLogs(ctx context.Context, userID uuid.UUID, params *models.AuditLogSearch) (*models.AuditLogsResult, *errx.Error) {
|
|
if params == nil {
|
|
params = &models.AuditLogSearch{}
|
|
}
|
|
params.UserID = &userID
|
|
|
|
if params.Limit <= 0 || params.Limit > 100 {
|
|
params.Limit = 50
|
|
}
|
|
|
|
// Default to today if no date range
|
|
if params.Since == nil {
|
|
today := time.Now().Truncate(24 * time.Hour)
|
|
params.Since = &today
|
|
}
|
|
|
|
result, err := s.repo.Search(ctx, params)
|
|
if err != nil {
|
|
return nil, errx.InternalError()
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (s *auditService) GetEntityLogs(ctx context.Context, entityType models.AuditEntityType, entityID uuid.UUID, limit int, cursor string) (*models.AuditLogsResult, *errx.Error) {
|
|
if limit <= 0 || limit > 100 {
|
|
limit = 50
|
|
}
|
|
|
|
result, err := s.repo.GetByEntity(ctx, string(entityType), entityID, limit, cursor)
|
|
if err != nil {
|
|
return nil, errx.InternalError()
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// Helper functions for common audit log scenarios
|
|
|
|
// LogCreate logs a create action
|
|
func LogCreate(s AuditService, ctx context.Context, userID uuid.UUID, entityType models.AuditEntityType, entityID uuid.UUID, ipAddress, userAgent string, metadata map[string]string) {
|
|
s.LogAction(ctx, userID, models.AuditActionCreate, entityType, &entityID, ipAddress, userAgent, nil, metadata)
|
|
}
|
|
|
|
// LogUpdate logs an update action with changes
|
|
func LogUpdate(s AuditService, ctx context.Context, userID uuid.UUID, entityType models.AuditEntityType, entityID uuid.UUID, ipAddress, userAgent string, changes map[string]string) {
|
|
s.LogAction(ctx, userID, models.AuditActionUpdate, entityType, &entityID, ipAddress, userAgent, changes, nil)
|
|
}
|
|
|
|
// LogDelete logs a delete action
|
|
func LogDelete(s AuditService, ctx context.Context, userID uuid.UUID, entityType models.AuditEntityType, entityID uuid.UUID, ipAddress, userAgent string) {
|
|
s.LogAction(ctx, userID, models.AuditActionDelete, entityType, &entityID, ipAddress, userAgent, nil, nil)
|
|
}
|
|
|
|
// LogLogin logs a login action
|
|
func LogLogin(s AuditService, ctx context.Context, userID uuid.UUID, ipAddress, userAgent string, metadata map[string]string) {
|
|
s.LogAction(ctx, userID, models.AuditActionLogin, models.AuditEntitySession, nil, ipAddress, userAgent, nil, metadata)
|
|
}
|
|
|
|
// LogLogout logs a logout action
|
|
func LogLogout(s AuditService, ctx context.Context, userID uuid.UUID, ipAddress, userAgent string) {
|
|
s.LogAction(ctx, userID, models.AuditActionLogout, models.AuditEntitySession, nil, ipAddress, userAgent, nil, nil)
|
|
}
|