132 lines
3.4 KiB
Go
132 lines
3.4 KiB
Go
package audit
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/csv"
|
|
"fmt"
|
|
"time"
|
|
|
|
"hyapp-admin-server/internal/model"
|
|
"hyapp-admin-server/internal/modules/shared"
|
|
"hyapp-admin-server/internal/repository"
|
|
)
|
|
|
|
type AuditService struct {
|
|
store *repository.Store
|
|
}
|
|
|
|
type CSVExport struct {
|
|
FileName string
|
|
Content []byte
|
|
Count int
|
|
}
|
|
|
|
func NewService(store *repository.Store) *AuditService {
|
|
return &AuditService{store: store}
|
|
}
|
|
|
|
func (s *AuditService) CreateOperationLog(log model.OperationLog) error {
|
|
return s.store.CreateOperationLog(log)
|
|
}
|
|
|
|
func (s *AuditService) LogOperation(event shared.OperationEvent) error {
|
|
if event.Status == "" {
|
|
event.Status = "success"
|
|
}
|
|
if event.RiskLevel == "" {
|
|
event.RiskLevel = riskLevel(event.Action, event.Method)
|
|
}
|
|
return s.store.CreateOperationLog(model.OperationLog{
|
|
RequestID: event.RequestID,
|
|
UserID: event.UserID,
|
|
Username: event.Username,
|
|
Action: event.Action,
|
|
Resource: event.Resource,
|
|
ResourceID: event.ResourceID,
|
|
Method: event.Method,
|
|
Path: event.Path,
|
|
IP: event.IP,
|
|
UserAgent: event.UserAgent,
|
|
Status: event.Status,
|
|
HTTPStatus: event.HTTPStatus,
|
|
RiskLevel: event.RiskLevel,
|
|
LatencyMS: event.LatencyMS,
|
|
Detail: event.Detail,
|
|
})
|
|
}
|
|
|
|
func (s *AuditService) ListLoginLogs(options repository.ListOptions) ([]model.LoginLog, int64, error) {
|
|
return s.store.ListLoginLogs(options)
|
|
}
|
|
|
|
func (s *AuditService) ListOperationLogs(options repository.ListOptions) ([]model.OperationLog, int64, error) {
|
|
return s.store.ListOperationLogs(options)
|
|
}
|
|
|
|
func (s *AuditService) ExportLoginLogs(options repository.ListOptions) (CSVExport, error) {
|
|
logs, err := s.store.ExportLoginLogs(options)
|
|
if err != nil {
|
|
return CSVExport{}, err
|
|
}
|
|
var buf bytes.Buffer
|
|
writer := csv.NewWriter(&buf)
|
|
_ = writer.Write([]string{"ID", "用户", "IP", "状态", "消息", "时间"})
|
|
for _, item := range logs {
|
|
_ = writer.Write([]string{
|
|
fmt.Sprintf("%d", item.ID),
|
|
item.Username,
|
|
item.IP,
|
|
item.Status,
|
|
item.Message,
|
|
time.UnixMilli(item.CreatedAtMS).UTC().Format(time.RFC3339),
|
|
})
|
|
}
|
|
writer.Flush()
|
|
return CSVExport{FileName: "hyapp-login-logs.csv", Content: buf.Bytes(), Count: len(logs)}, writer.Error()
|
|
}
|
|
|
|
func (s *AuditService) ExportOperationLogs(options repository.ListOptions) (CSVExport, error) {
|
|
logs, err := s.store.ExportOperationLogs(options)
|
|
if err != nil {
|
|
return CSVExport{}, err
|
|
}
|
|
var buf bytes.Buffer
|
|
writer := csv.NewWriter(&buf)
|
|
_ = writer.Write([]string{"ID", "RequestID", "用户", "动作", "资源", "资源ID", "方法", "路径", "IP", "状态", "HTTP", "风险", "耗时ms", "详情", "时间"})
|
|
for _, item := range logs {
|
|
_ = writer.Write([]string{
|
|
fmt.Sprintf("%d", item.ID),
|
|
item.RequestID,
|
|
item.Username,
|
|
item.Action,
|
|
item.Resource,
|
|
item.ResourceID,
|
|
item.Method,
|
|
item.Path,
|
|
item.IP,
|
|
item.Status,
|
|
fmt.Sprintf("%d", item.HTTPStatus),
|
|
item.RiskLevel,
|
|
fmt.Sprintf("%d", item.LatencyMS),
|
|
item.Detail,
|
|
time.UnixMilli(item.CreatedAtMS).UTC().Format(time.RFC3339),
|
|
})
|
|
}
|
|
writer.Flush()
|
|
return CSVExport{FileName: "hyapp-operation-logs.csv", Content: buf.Bytes(), Count: len(logs)}, writer.Error()
|
|
}
|
|
|
|
func riskLevel(action string, method string) string {
|
|
switch method {
|
|
case "DELETE":
|
|
return "high"
|
|
case "POST", "PUT", "PATCH":
|
|
if action == "reset-user-password" || action == "replace-role-permissions" || action == "replace-role-data-scopes" {
|
|
return "high"
|
|
}
|
|
return "normal"
|
|
default:
|
|
return "low"
|
|
}
|
|
}
|