171 lines
3.0 KiB
Go
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
|
|
}
|