tailly_back_v2/internal/repository/audit_repository.go
madipo2611 6f5298d420 v0.0.3
2025-05-03 02:37:08 +03:00

171 lines
3.0 KiB
Go

package repository
import (
"context"
"database/sql"
"fmt"
"tailly_back_v2/internal/domain"
)
type AuditRepository interface {
Save(ctx context.Context, log *domain.AuditLog) error
Get(ctx context.Context, filter domain.AuditFilter) ([]*domain.AuditLog, error)
}
type auditRepository struct {
db *sql.DB
}
func NewAuditRepository(db *sql.DB) AuditRepository {
return &auditRepository{db: db}
}
func (r *auditRepository) Save(ctx context.Context, log *domain.AuditLog) error {
query := `
INSERT INTO audit_logs (
user_id,
action,
entity_type,
entity_id,
ip_address,
user_agent,
metadata,
status,
created_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id
`
var userID, entityID interface{}
if log.UserID != nil {
userID = *log.UserID
} else {
userID = nil
}
if log.EntityID != nil {
entityID = *log.EntityID
} else {
entityID = nil
}
err := r.db.QueryRowContext(ctx, query,
userID,
log.Action,
log.EntityType,
entityID,
log.IPAddress,
log.UserAgent,
log.Metadata,
log.Status,
log.CreatedAt,
).Scan(&log.ID)
return err
}
func (r *auditRepository) Get(ctx context.Context, filter domain.AuditFilter) ([]*domain.AuditLog, error) {
query := `
SELECT
id,
user_id,
action,
entity_type,
entity_id,
ip_address,
user_agent,
metadata,
status,
created_at
FROM audit_logs
WHERE 1=1
`
args := []interface{}{}
argPos := 1
if filter.UserID != nil {
query += fmt.Sprintf(" AND user_id = $%d", argPos)
args = append(args, *filter.UserID)
argPos++
}
if filter.Action != "" {
query += fmt.Sprintf(" AND action = $%d", argPos)
args = append(args, filter.Action)
argPos++
}
if filter.EntityType != "" {
query += fmt.Sprintf(" AND entity_type = $%d", argPos)
args = append(args, filter.EntityType)
argPos++
}
if !filter.DateFrom.IsZero() {
query += fmt.Sprintf(" AND created_at >= $%d", argPos)
args = append(args, filter.DateFrom)
argPos++
}
if !filter.DateTo.IsZero() {
query += fmt.Sprintf(" AND created_at <= $%d", argPos)
args = append(args, filter.DateTo)
argPos++
}
query += " ORDER BY created_at DESC"
if filter.Limit > 0 {
query += fmt.Sprintf(" LIMIT $%d", argPos)
args = append(args, filter.Limit)
argPos++
}
if filter.Offset > 0 {
query += fmt.Sprintf(" OFFSET $%d", argPos)
args = append(args, filter.Offset)
}
rows, err := r.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var logs []*domain.AuditLog
for rows.Next() {
var log domain.AuditLog
var userID, entityID sql.NullInt64
err := rows.Scan(
&log.ID,
&userID,
&log.Action,
&log.EntityType,
&entityID,
&log.IPAddress,
&log.UserAgent,
&log.Metadata,
&log.Status,
&log.CreatedAt,
)
if err != nil {
return nil, err
}
if userID.Valid {
uid := int(userID.Int64)
log.UserID = &uid
}
if entityID.Valid {
eid := int(entityID.Int64)
log.EntityID = &eid
}
logs = append(logs, &log)
}
return logs, nil
}