58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
package auditing
|
|
|
|
import (
|
|
"RenewCMS/internal/domain/audit"
|
|
"context"
|
|
"log"
|
|
"time"
|
|
)
|
|
|
|
type Recorder struct {
|
|
repository audit.Repository
|
|
now func() time.Time
|
|
logger *log.Logger
|
|
}
|
|
|
|
var _ audit.Recorder = &Recorder{}
|
|
|
|
func NewRecorder(repository audit.Repository, now func() time.Time, logger *log.Logger) *Recorder {
|
|
return &Recorder{repository, now, logger}
|
|
}
|
|
|
|
func (r *Recorder) Record(ctx context.Context, event audit.Event) {
|
|
defer func() {
|
|
if recovered := recover(); recovered != nil {
|
|
r.logger.Printf("audit: writing the %s event panicked: %v", event.Action, recovered)
|
|
}
|
|
}()
|
|
|
|
event = r.complete(ctx, event).Truncated()
|
|
if err := event.Validate(); err != nil {
|
|
r.logger.Printf("audit: dropped the %s event: %v", event.Action, err)
|
|
return
|
|
}
|
|
if _, err := r.repository.Append(event); err != nil {
|
|
r.logger.Printf("audit: failed to write the %s event: %v", event.Action, err)
|
|
}
|
|
}
|
|
|
|
func (r *Recorder) complete(ctx context.Context, event audit.Event) audit.Event {
|
|
origin, _ := audit.OriginFrom(ctx)
|
|
if event.Actor.Type == "" {
|
|
event.Actor = origin.Actor
|
|
}
|
|
if event.Source == "" {
|
|
event.Source = origin.Source
|
|
}
|
|
if event.IP == nil && origin.IP != "" {
|
|
ip := origin.IP
|
|
event.IP = &ip
|
|
}
|
|
if event.UserAgent == nil && origin.UserAgent != "" {
|
|
userAgent := origin.UserAgent
|
|
event.UserAgent = &userAgent
|
|
}
|
|
event.CreatedAt = r.now().UTC()
|
|
return event
|
|
}
|