75 lines
1.6 KiB
Go
75 lines
1.6 KiB
Go
package audit
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/bams/backend/internal/config"
|
|
"github.com/bams/backend/internal/logger"
|
|
)
|
|
|
|
type AuditEntry struct {
|
|
Timestamp time.Time `json:"timestamp"`
|
|
User string `json:"user"`
|
|
Action string `json:"action"`
|
|
Resource string `json:"resource"`
|
|
Result string `json:"result"` // "success" or "failure"
|
|
Details string `json:"details,omitempty"`
|
|
}
|
|
|
|
type Service struct {
|
|
config *config.Config
|
|
logger *logger.Logger
|
|
logFile *os.File
|
|
}
|
|
|
|
func NewService(cfg *config.Config, log *logger.Logger) *Service {
|
|
auditDir := filepath.Join(cfg.DataDir, "audit")
|
|
os.MkdirAll(auditDir, 0755)
|
|
|
|
logPath := filepath.Join(auditDir, fmt.Sprintf("audit-%s.log", time.Now().Format("2006-01-02")))
|
|
file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0640)
|
|
if err != nil {
|
|
log.Error("Failed to open audit log", "error", err)
|
|
}
|
|
|
|
return &Service{
|
|
config: cfg,
|
|
logger: log,
|
|
logFile: file,
|
|
}
|
|
}
|
|
|
|
func (s *Service) Log(user, action, resource, result, details string) {
|
|
entry := AuditEntry{
|
|
Timestamp: time.Now(),
|
|
User: user,
|
|
Action: action,
|
|
Resource: resource,
|
|
Result: result,
|
|
Details: details,
|
|
}
|
|
|
|
data, err := json.Marshal(entry)
|
|
if err != nil {
|
|
s.logger.Error("Failed to marshal audit entry", "error", err)
|
|
return
|
|
}
|
|
|
|
if s.logFile != nil {
|
|
s.logFile.WriteString(string(data) + "\n")
|
|
s.logFile.Sync()
|
|
}
|
|
|
|
s.logger.Info("Audit log", "user", user, "action", action, "resource", resource, "result", result)
|
|
}
|
|
|
|
func (s *Service) Close() {
|
|
if s.logFile != nil {
|
|
s.logFile.Close()
|
|
}
|
|
}
|