init bootstrap
This commit is contained in:
271
local/model/audit_log.go
Normal file
271
local/model/audit_log.go
Normal file
@@ -0,0 +1,271 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AuditLog represents an audit log entry in the system
|
||||
type AuditLog struct {
|
||||
BaseModel
|
||||
UserID string `json:"userId" gorm:"type:varchar(36);index"`
|
||||
Action string `json:"action" gorm:"not null;type:varchar(100);index"`
|
||||
Resource string `json:"resource" gorm:"not null;type:varchar(100);index"`
|
||||
ResourceID string `json:"resourceId" gorm:"type:varchar(36);index"`
|
||||
Details map[string]interface{} `json:"details" gorm:"type:text"`
|
||||
IPAddress string `json:"ipAddress" gorm:"type:varchar(45)"`
|
||||
UserAgent string `json:"userAgent" gorm:"type:text"`
|
||||
Success bool `json:"success" gorm:"default:true;index"`
|
||||
ErrorMsg string `json:"errorMsg,omitempty" gorm:"type:text"`
|
||||
Duration int64 `json:"duration,omitempty"` // Duration in milliseconds
|
||||
SessionID string `json:"sessionId,omitempty" gorm:"type:varchar(255)"`
|
||||
RequestID string `json:"requestId,omitempty" gorm:"type:varchar(255)"`
|
||||
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
||||
}
|
||||
|
||||
// AuditLogCreateRequest represents the request to create a new audit log
|
||||
type AuditLogCreateRequest struct {
|
||||
UserID string `json:"userId"`
|
||||
Action string `json:"action" validate:"required,max=100"`
|
||||
Resource string `json:"resource" validate:"required,max=100"`
|
||||
ResourceID string `json:"resourceId"`
|
||||
Details map[string]interface{} `json:"details"`
|
||||
IPAddress string `json:"ipAddress" validate:"max=45"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
Success bool `json:"success"`
|
||||
ErrorMsg string `json:"errorMsg"`
|
||||
Duration int64 `json:"duration"`
|
||||
SessionID string `json:"sessionId"`
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
|
||||
// AuditLogInfo represents public audit log information
|
||||
type AuditLogInfo struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"userId"`
|
||||
UserEmail string `json:"userEmail,omitempty"`
|
||||
UserName string `json:"userName,omitempty"`
|
||||
Action string `json:"action"`
|
||||
Resource string `json:"resource"`
|
||||
ResourceID string `json:"resourceId"`
|
||||
Details map[string]interface{} `json:"details"`
|
||||
IPAddress string `json:"ipAddress"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
Success bool `json:"success"`
|
||||
ErrorMsg string `json:"errorMsg,omitempty"`
|
||||
Duration int64 `json:"duration,omitempty"`
|
||||
SessionID string `json:"sessionId,omitempty"`
|
||||
RequestID string `json:"requestId,omitempty"`
|
||||
DateCreated string `json:"dateCreated"`
|
||||
}
|
||||
|
||||
// BeforeCreate is called before creating an audit log
|
||||
func (al *AuditLog) BeforeCreate(tx *gorm.DB) error {
|
||||
al.BaseModel.BeforeCreate()
|
||||
|
||||
// Normalize fields
|
||||
al.Action = strings.ToLower(strings.TrimSpace(al.Action))
|
||||
al.Resource = strings.ToLower(strings.TrimSpace(al.Resource))
|
||||
al.IPAddress = strings.TrimSpace(al.IPAddress)
|
||||
al.UserAgent = strings.TrimSpace(al.UserAgent)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetDetails sets the details field from a map
|
||||
func (al *AuditLog) SetDetails(details map[string]interface{}) error {
|
||||
al.Details = details
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDetails returns the details as a map
|
||||
func (al *AuditLog) GetDetails() map[string]interface{} {
|
||||
if al.Details == nil {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
return al.Details
|
||||
}
|
||||
|
||||
// SetDetailsFromJSON sets the details field from a JSON string
|
||||
func (al *AuditLog) SetDetailsFromJSON(jsonStr string) error {
|
||||
if jsonStr == "" {
|
||||
al.Details = make(map[string]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
var details map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(jsonStr), &details); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
al.Details = details
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDetailsAsJSON returns the details as a JSON string
|
||||
func (al *AuditLog) GetDetailsAsJSON() (string, error) {
|
||||
if al.Details == nil || len(al.Details) == 0 {
|
||||
return "{}", nil
|
||||
}
|
||||
|
||||
bytes, err := json.Marshal(al.Details)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
// ToAuditLogInfo converts AuditLog to AuditLogInfo (public information)
|
||||
func (al *AuditLog) ToAuditLogInfo() AuditLogInfo {
|
||||
info := AuditLogInfo{
|
||||
ID: al.ID,
|
||||
UserID: al.UserID,
|
||||
Action: al.Action,
|
||||
Resource: al.Resource,
|
||||
ResourceID: al.ResourceID,
|
||||
Details: al.GetDetails(),
|
||||
IPAddress: al.IPAddress,
|
||||
UserAgent: al.UserAgent,
|
||||
Success: al.Success,
|
||||
ErrorMsg: al.ErrorMsg,
|
||||
Duration: al.Duration,
|
||||
SessionID: al.SessionID,
|
||||
RequestID: al.RequestID,
|
||||
DateCreated: al.DateCreated.Format("2006-01-02T15:04:05Z"),
|
||||
}
|
||||
|
||||
// Include user information if available
|
||||
if al.User != nil {
|
||||
info.UserEmail = al.User.Email
|
||||
info.UserName = al.User.Name
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// AddDetail adds a single detail to the details map
|
||||
func (al *AuditLog) AddDetail(key string, value interface{}) {
|
||||
if al.Details == nil {
|
||||
al.Details = make(map[string]interface{})
|
||||
}
|
||||
al.Details[key] = value
|
||||
}
|
||||
|
||||
// GetDetail gets a single detail from the details map
|
||||
func (al *AuditLog) GetDetail(key string) (interface{}, bool) {
|
||||
if al.Details == nil {
|
||||
return nil, false
|
||||
}
|
||||
value, exists := al.Details[key]
|
||||
return value, exists
|
||||
}
|
||||
|
||||
// Common audit log actions
|
||||
const (
|
||||
AuditActionCreate = "create"
|
||||
AuditActionRead = "read"
|
||||
AuditActionUpdate = "update"
|
||||
AuditActionDelete = "delete"
|
||||
AuditActionLogin = "login"
|
||||
AuditActionLogout = "logout"
|
||||
AuditActionAccess = "access"
|
||||
AuditActionExport = "export"
|
||||
AuditActionImport = "import"
|
||||
AuditActionConfig = "config"
|
||||
)
|
||||
|
||||
// Common audit log resources
|
||||
const (
|
||||
AuditResourceUser = "user"
|
||||
AuditResourceRole = "role"
|
||||
AuditResourcePermission = "permission"
|
||||
AuditResourceSystemConfig = "system_config"
|
||||
AuditResourceAuth = "auth"
|
||||
AuditResourceAPI = "api"
|
||||
AuditResourceFile = "file"
|
||||
AuditResourceDatabase = "database"
|
||||
AuditResourceSystem = "system"
|
||||
)
|
||||
|
||||
// CreateAuditLog creates a new audit log entry
|
||||
func CreateAuditLog(userID, action, resource, resourceID string, success bool) *AuditLog {
|
||||
auditLog := &AuditLog{
|
||||
UserID: userID,
|
||||
Action: action,
|
||||
Resource: resource,
|
||||
ResourceID: resourceID,
|
||||
Success: success,
|
||||
Details: make(map[string]interface{}),
|
||||
}
|
||||
auditLog.Init()
|
||||
return auditLog
|
||||
}
|
||||
|
||||
// CreateAuditLogWithDetails creates a new audit log entry with details
|
||||
func CreateAuditLogWithDetails(userID, action, resource, resourceID string, success bool, details map[string]interface{}) *AuditLog {
|
||||
auditLog := CreateAuditLog(userID, action, resource, resourceID, success)
|
||||
auditLog.Details = details
|
||||
return auditLog
|
||||
}
|
||||
|
||||
// CreateAuditLogWithError creates a new audit log entry for an error
|
||||
func CreateAuditLogWithError(userID, action, resource, resourceID, errorMsg string) *AuditLog {
|
||||
auditLog := CreateAuditLog(userID, action, resource, resourceID, false)
|
||||
auditLog.ErrorMsg = errorMsg
|
||||
return auditLog
|
||||
}
|
||||
|
||||
// SetRequestInfo sets request-related information
|
||||
func (al *AuditLog) SetRequestInfo(ipAddress, userAgent, sessionID, requestID string) {
|
||||
al.IPAddress = ipAddress
|
||||
al.UserAgent = userAgent
|
||||
al.SessionID = sessionID
|
||||
al.RequestID = requestID
|
||||
}
|
||||
|
||||
// SetDuration sets the operation duration
|
||||
func (al *AuditLog) SetDuration(start time.Time) {
|
||||
al.Duration = time.Since(start).Milliseconds()
|
||||
}
|
||||
|
||||
// IsSuccess returns whether the audit log represents a successful operation
|
||||
func (al *AuditLog) IsSuccess() bool {
|
||||
return al.Success
|
||||
}
|
||||
|
||||
// IsFailure returns whether the audit log represents a failed operation
|
||||
func (al *AuditLog) IsFailure() bool {
|
||||
return !al.Success
|
||||
}
|
||||
|
||||
// GetActionDescription returns a human-readable description of the action
|
||||
func (al *AuditLog) GetActionDescription() string {
|
||||
switch al.Action {
|
||||
case AuditActionCreate:
|
||||
return "Created " + al.Resource
|
||||
case AuditActionRead:
|
||||
return "Viewed " + al.Resource
|
||||
case AuditActionUpdate:
|
||||
return "Updated " + al.Resource
|
||||
case AuditActionDelete:
|
||||
return "Deleted " + al.Resource
|
||||
case AuditActionLogin:
|
||||
return "Logged in"
|
||||
case AuditActionLogout:
|
||||
return "Logged out"
|
||||
case AuditActionAccess:
|
||||
return "Accessed " + al.Resource
|
||||
case AuditActionExport:
|
||||
return "Exported " + al.Resource
|
||||
case AuditActionImport:
|
||||
return "Imported " + al.Resource
|
||||
case AuditActionConfig:
|
||||
return "Configured " + al.Resource
|
||||
default:
|
||||
return strings.Title(al.Action) + " " + al.Resource
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user