- new resp package (OK/Page/Fail/BadRequest/.../InternalErr): unified error
envelope {detail, code?}, sanitized 500s (full error logged server-side,
generic message to client - stops DB error leakage), pagination envelope
{items,total,page,page_size}; migrate 200+ inline c.JSON error sites
- refresh token: 7d rotation tokens (SHA-256 hashed at rest), public
POST /auth/refresh with single-use rotation, POST /auth/logout revokes
all user refresh tokens (endpoint previously missing - frontend 404)
- security: gh-ost command line password masked in task status payload;
Instance.MarshalJSON guarantees encrypted passwords never leave the API
(removes reliance on per-handler manual masking); production (DEBUG=false)
with default JWT secret now auto-generates and persists a random secret
- safe.Go recover wrapper for background goroutines (instance probe,
gh-ost async)
- delete dead service layer (zero callers)
- fix pre-existing go vet unkeyed bson.E literals
547 lines
25 KiB
Go
547 lines
25 KiB
Go
package model
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// ==================== User ====================
|
|
|
|
type User struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Username string `gorm:"size:50;uniqueIndex;not null" json:"username"`
|
|
DisplayName string `gorm:"size:100;not null" json:"display_name"`
|
|
Email *string `gorm:"size:100" json:"email"`
|
|
Phone *string `gorm:"size:20" json:"phone"`
|
|
HashedPassword string `gorm:"size:200;not null" json:"-"`
|
|
AuthSource string `gorm:"size:20;default:'local'" json:"auth_source"` // local / ldap
|
|
Role string `gorm:"size:20;not null" json:"role"` // admin, dba, developer, auditor
|
|
IsActive *bool `gorm:"default:true" json:"is_active"`
|
|
Preferences *string `gorm:"type:text" json:"preferences"` // JSON: {"theme":"system","login_style":"split"}
|
|
LastLogin *time.Time `json:"last_login"`
|
|
FailedLoginAttempts int `gorm:"default:0" json:"failed_login_attempts"`
|
|
LockedUntil *time.Time `json:"locked_until"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
}
|
|
|
|
func (User) TableName() string { return "users" }
|
|
|
|
// ==================== Instance ====================
|
|
|
|
type Instance struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
DBType string `gorm:"size:20;not null" json:"db_type"`
|
|
Host string `gorm:"size:200;not null" json:"host"`
|
|
Port int `gorm:"not null" json:"port"`
|
|
Username string `gorm:"size:100;not null" json:"username"`
|
|
Password string `gorm:"size:500;not null" json:"password,omitempty"`
|
|
Database *string `gorm:"size:100" json:"database"`
|
|
Env *string `gorm:"size:20" json:"env"`
|
|
Description *string `gorm:"type:text" json:"description"`
|
|
Status *string `gorm:"size:20" json:"status"`
|
|
Version *string `gorm:"size:50" json:"version"`
|
|
ClusterMode *bool `gorm:"default:false" json:"cluster_mode"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
AccessMode *string `gorm:"size:20;default:readwrite" json:"access_mode"`
|
|
Workflow *string `gorm:"type:text" json:"workflow"`
|
|
ExcludedDatabases *string `gorm:"type:text" json:"excluded_databases"`
|
|
MaskFields *string `gorm:"type:text" json:"mask_fields"`
|
|
GroupID *int `json:"group_id"`
|
|
WorkflowID *int `json:"workflow_id"`
|
|
}
|
|
|
|
func (Instance) TableName() string { return "instances" }
|
|
|
|
// MarshalJSON 保证实例密文密码在任何响应中都不出站,
|
|
// 消除各 handler 手动遮蔽遗漏的隐患(入站绑定不受影响)。
|
|
func (i Instance) MarshalJSON() ([]byte, error) {
|
|
type instanceAlias Instance
|
|
a := instanceAlias(i)
|
|
a.Password = ""
|
|
return json.Marshal(a)
|
|
}
|
|
|
|
// ==================== Ticket ====================
|
|
|
|
type Ticket struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Title string `gorm:"size:200;not null" json:"title"`
|
|
DBType string `gorm:"size:20;not null" json:"db_type"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
TargetDatabase string `gorm:"size:100;not null" json:"target_database"`
|
|
SQLContent string `gorm:"type:text;not null" json:"sql_content"`
|
|
RollbackSQL *string `gorm:"type:text" json:"rollback_sql"`
|
|
Status *string `gorm:"size:20" json:"status"`
|
|
Priority *string `gorm:"size:10" json:"priority"`
|
|
ApplicantID int `gorm:"not null" json:"applicant_id"`
|
|
ApproverID *int `json:"approver_id"`
|
|
Reason *string `gorm:"type:text" json:"reason"`
|
|
AuditResult *string `gorm:"type:text" json:"audit_result"`
|
|
ExecuteResult *string `gorm:"type:text" json:"execute_result"`
|
|
CreateTime time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"create_time"`
|
|
ReviewTime *time.Time `json:"review_time"`
|
|
ExecuteTime *time.Time `json:"execute_time"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
TicketNo *string `gorm:"size:20" json:"ticket_no"`
|
|
ScheduledAt sql.NullTime `json:"scheduled_at"`
|
|
WorkflowID *int `json:"workflow_id"`
|
|
RiskLevel *string `gorm:"size:20;default:low" json:"risk_level"`
|
|
ExecStrategy *string `gorm:"size:20;default:stop_on_error" json:"exec_strategy"`
|
|
}
|
|
|
|
func (Ticket) TableName() string { return "tickets" }
|
|
|
|
// ==================== TicketApproval ====================
|
|
|
|
type TicketApproval struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
TicketID int `gorm:"not null" json:"ticket_id"`
|
|
WorkflowID *int `json:"workflow_id"`
|
|
VersionID *int `json:"version_id"`
|
|
StepNumber int `gorm:"not null" json:"step_number"`
|
|
StepName *string `gorm:"size:100" json:"step_name"`
|
|
StepType *string `gorm:"size:20" json:"step_type"`
|
|
ApproverID *int `json:"approver_id"`
|
|
ApproverRole *string `gorm:"size:20" json:"approver_role"`
|
|
ActualApproverID *int `json:"actual_approver_id"`
|
|
Action *string `gorm:"size:20" json:"action"`
|
|
Comment *string `gorm:"type:text" json:"comment"`
|
|
TransferFrom *int `json:"transfer_from"`
|
|
TransferReason *string `gorm:"type:text" json:"transfer_reason"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
CompletedAt *time.Time `json:"completed_at"`
|
|
IsTimeout *bool `json:"is_timeout"`
|
|
TimeoutHandledAt *time.Time `json:"timeout_handled_at"`
|
|
}
|
|
|
|
func (TicketApproval) TableName() string { return "ticket_approvals" }
|
|
|
|
// ==================== TicketSQLItem ====================
|
|
|
|
type TicketSQLItem struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
TicketID int `gorm:"not null" json:"ticket_id"`
|
|
Seq int `gorm:"not null" json:"seq"`
|
|
SQLText string `gorm:"type:text;not null" json:"sql_text"`
|
|
SQLType *string `gorm:"size:20" json:"sql_type"`
|
|
Status *string `gorm:"size:20;default:pending" json:"status"`
|
|
AffectedRows *int `gorm:"default:0" json:"affected_rows"`
|
|
DurationMs *int `gorm:"default:0" json:"duration_ms"`
|
|
ErrorMessage *string `gorm:"type:text" json:"error_message"`
|
|
StartedAt *time.Time `json:"started_at"`
|
|
FinishedAt *time.Time `json:"finished_at"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (TicketSQLItem) TableName() string { return "ticket_sql_items" }
|
|
|
|
// ==================== AuditRule ====================
|
|
|
|
type AuditRule struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
Desc *string `gorm:"type:text" json:"description"`
|
|
RuleType string `gorm:"size:50;not null" json:"rule_type"`
|
|
Severity *string `gorm:"size:20" json:"severity"`
|
|
DBType *string `gorm:"size:20" json:"db_type"`
|
|
Pattern *string `gorm:"type:text" json:"pattern"`
|
|
IsEnabled *bool `json:"is_enabled"`
|
|
Message string `gorm:"size:500;not null" json:"message"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
Value *string `gorm:"size:255" json:"value"`
|
|
Code *string `gorm:"size:50" json:"code"`
|
|
ConfigJSON *string `gorm:"type:text;column:config_json" json:"config_json"`
|
|
}
|
|
|
|
func (AuditRule) TableName() string { return "audit_rules" }
|
|
|
|
// ==================== AuditLog ====================
|
|
|
|
type AuditLog struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
UserID int `gorm:"not null" json:"user_id"`
|
|
Action string `gorm:"size:50;not null" json:"action"`
|
|
TargetType string `gorm:"size:50;not null" json:"target_type"`
|
|
TargetID *int `json:"target_id"`
|
|
Detail *string `gorm:"type:text" json:"detail"`
|
|
IPAddress *string `gorm:"size:50" json:"ip_address"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
Username *string `gorm:"size:50" json:"username"`
|
|
DBType *string `gorm:"size:20" json:"db_type"`
|
|
DatabaseName *string `gorm:"size:100" json:"database_name"`
|
|
InstanceName *string `gorm:"size:100" json:"instance_name"`
|
|
ExecutionTimeMs *int `json:"execution_time_ms"`
|
|
RowsAffected *int `json:"rows_affected"`
|
|
ResultStatus *string `gorm:"size:20" json:"result_status"`
|
|
QueryContent *string `gorm:"type:text" json:"query_content"`
|
|
UserAgent *string `gorm:"size:200" json:"user_agent"`
|
|
IsRisky *bool `gorm:"default:false" json:"is_risky"`
|
|
}
|
|
|
|
func (AuditLog) TableName() string { return "audit_logs" }
|
|
|
|
// ==================== QueryHistory ====================
|
|
|
|
type QueryHistory struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
UserID int `gorm:"not null" json:"user_id"`
|
|
Username string `gorm:"size:100;not null" json:"username"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
InstanceName string `gorm:"size:100;not null" json:"instance_name"`
|
|
DBType string `gorm:"size:20;not null" json:"db_type"`
|
|
DatabaseName string `gorm:"size:100;not null" json:"database_name"`
|
|
QueryContent string `gorm:"type:text;not null" json:"query_content"`
|
|
QueryType string `gorm:"size:50;not null" json:"query_type"`
|
|
ExecutionTimeMs int `gorm:"not null" json:"execution_time_ms"`
|
|
ResultRows int `gorm:"not null" json:"result_rows"`
|
|
IsSuccess bool `gorm:"not null" json:"is_success"`
|
|
ErrorMessage *string `gorm:"type:text" json:"error_message"`
|
|
IsFavorite bool `gorm:"not null" json:"is_favorite"`
|
|
Note string `gorm:"type:text;not null" json:"note"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (QueryHistory) TableName() string { return "query_histories" }
|
|
|
|
// ==================== Workflow ====================
|
|
|
|
type WorkflowDefinition struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
Description *string `gorm:"type:text" json:"description"`
|
|
Category *string `gorm:"size:50" json:"category"`
|
|
IsDefault *bool `json:"is_default"`
|
|
IsActive *bool `json:"is_active"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
CreatedBy *int `json:"created_by"`
|
|
FlowConfig *string `gorm:"type:json" json:"flow_config"`
|
|
TriggerConditions *string `gorm:"type:json" json:"trigger_conditions"`
|
|
}
|
|
|
|
func (WorkflowDefinition) TableName() string { return "workflow_definitions" }
|
|
|
|
type WorkflowStep struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
WorkflowID int `gorm:"not null" json:"workflow_id"`
|
|
StepNumber int `gorm:"not null" json:"step_number"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
Description *string `gorm:"type:text" json:"description"`
|
|
StepType string `gorm:"size:20;not null" json:"step_type"`
|
|
ApproverRole *string `gorm:"size:20" json:"approver_role"`
|
|
ApproverIDs *string `gorm:"type:json" json:"approver_ids"`
|
|
ApproverAssignment *string `gorm:"type:json" json:"approver_assignment"`
|
|
IsRequired *bool `json:"is_required"`
|
|
TimeoutHours *int `json:"timeout_hours"`
|
|
AutoApproveOnTimeout *bool `json:"auto_approve_on_timeout"`
|
|
EntryConditions *string `gorm:"type:json" json:"entry_conditions"`
|
|
TransitionConditions *string `gorm:"type:json" json:"transition_conditions"`
|
|
FieldPermissions *string `gorm:"type:json" json:"field_permissions"`
|
|
}
|
|
|
|
func (WorkflowStep) TableName() string { return "workflow_steps" }
|
|
|
|
type WorkflowVersion struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
WorkflowID int `gorm:"not null" json:"workflow_id"`
|
|
VersionNumber int `gorm:"not null" json:"version_number"`
|
|
VersionName *string `gorm:"size:100" json:"version_name"`
|
|
IsActive *bool `json:"is_active"`
|
|
StepsSnapshot *string `gorm:"type:json" json:"steps_snapshot"`
|
|
FlowConfigSnapshot *string `gorm:"type:json" json:"flow_config_snapshot"`
|
|
ChangeSummary *string `gorm:"type:text" json:"change_summary"`
|
|
CreatedBy *int `json:"created_by"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (WorkflowVersion) TableName() string { return "workflow_versions" }
|
|
|
|
type WorkflowExecutionLog struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
WorkflowID int `gorm:"not null" json:"workflow_id"`
|
|
TicketID *int `json:"ticket_id"`
|
|
StepID *int `json:"step_id"`
|
|
ApprovalID *int `json:"approval_id"`
|
|
EventType string `gorm:"size:50;not null" json:"event_type"`
|
|
EventDescription *string `gorm:"type:text" json:"event_description"`
|
|
ActorID *int `json:"actor_id"`
|
|
ActorName *string `gorm:"size:100" json:"actor_name"`
|
|
ContextData *string `gorm:"type:json" json:"context_data"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (WorkflowExecutionLog) TableName() string { return "workflow_execution_logs" }
|
|
|
|
// ==================== Announcement ====================
|
|
|
|
type Announcement struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Title string `gorm:"size:200;not null" json:"title"`
|
|
Content string `gorm:"type:text;not null" json:"content"`
|
|
IsPublished *bool `json:"is_published"`
|
|
PublishedAt *time.Time `json:"published_at"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
}
|
|
|
|
func (Announcement) TableName() string { return "announcements" }
|
|
|
|
// ==================== InstanceGroup ====================
|
|
|
|
type InstanceGroup struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
Description *string `gorm:"type:text" json:"description"`
|
|
DBType string `gorm:"size:20;not null" json:"db_type"`
|
|
Permissions *string `gorm:"type:text" json:"permissions"`
|
|
IsActive *bool `json:"is_active"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
WorkflowID *int `json:"workflow_id"`
|
|
AccessType *string `gorm:"size:20;default:readonly" json:"access_type"`
|
|
AllowedDatabases *string `gorm:"type:text" json:"allowed_databases"`
|
|
}
|
|
|
|
func (InstanceGroup) TableName() string { return "instance_groups" }
|
|
|
|
type InstanceGroupMember struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
GroupID int `gorm:"not null" json:"group_id"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
AccessType string `gorm:"default:readonly" json:"access_type"`
|
|
}
|
|
|
|
func (InstanceGroupMember) TableName() string { return "instance_group_members" }
|
|
|
|
// ==================== LDAP Config ====================
|
|
|
|
type LDAPConfig struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
LDAPHost string `gorm:"size:200;not null" json:"ldap_host"`
|
|
LDAPPort *int `json:"ldap_port"`
|
|
UseLDAPS *bool `json:"use_ldaps"`
|
|
AdminDN string `gorm:"size:500;not null" json:"admin_dn"`
|
|
AdminPassword string `gorm:"size:500;not null" json:"admin_password"`
|
|
SearchFilter *string `gorm:"size:500" json:"search_filter"`
|
|
BaseDN string `gorm:"size:500;not null" json:"base_dn"`
|
|
UserMapping *string `gorm:"type:text" json:"user_mapping"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
}
|
|
|
|
func (LDAPConfig) TableName() string { return "ldap_config" }
|
|
|
|
// ==================== Notification ====================
|
|
|
|
type NotificationChannel struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
ChannelType string `gorm:"size:30;not null" json:"channel_type"`
|
|
Config string `gorm:"type:text;not null" json:"config"`
|
|
IsEnabled *bool `json:"is_enabled"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
}
|
|
|
|
func (NotificationChannel) TableName() string { return "notification_channels" }
|
|
|
|
type NotificationTemplate struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
EventType string `gorm:"size:50;not null" json:"event_type"`
|
|
ChannelType string `gorm:"size:30;not null" json:"channel_type"`
|
|
TitleTemplate *string `gorm:"type:text" json:"title_template"`
|
|
BodyTemplate *string `gorm:"type:text" json:"body_template"`
|
|
IsEnabled *bool `json:"is_enabled"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (NotificationTemplate) TableName() string { return "notification_templates" }
|
|
|
|
// ==================== Other Models ====================
|
|
|
|
type SystemSetting struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Key string `gorm:"size:100;not null" json:"key"`
|
|
Value string `gorm:"type:text;not null" json:"value"`
|
|
ValueType string `gorm:"size:20;not null" json:"value_type"`
|
|
Group string `gorm:"size:50;not null" json:"group"`
|
|
Label string `gorm:"size:100;not null" json:"label"`
|
|
Desc *string `gorm:"type:text" json:"description"`
|
|
DefaultValue *string `gorm:"type:text" json:"default_value"`
|
|
SortOrder int `gorm:"not null" json:"sort_order"`
|
|
UpdatedAt *time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (SystemSetting) TableName() string { return "system_settings" }
|
|
|
|
type OperationLog struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
UserID *int `json:"user_id"`
|
|
Username *string `gorm:"size:50" json:"username"`
|
|
Action string `gorm:"size:50;not null" json:"action"`
|
|
ResourceType *string `gorm:"size:50" json:"resource_type"`
|
|
ResourceID *int `json:"resource_id"`
|
|
Detail *string `gorm:"type:text" json:"detail"`
|
|
IPAddress *string `gorm:"size:50" json:"ip_address"`
|
|
UserAgent *string `gorm:"size:255" json:"user_agent"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (OperationLog) TableName() string { return "operation_logs" }
|
|
|
|
type MaskingRule struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
Database string `gorm:"size:100;not null" json:"database"`
|
|
TblName string `gorm:"size:100;not null;column:table_name" json:"table_name"`
|
|
ColumnName string `gorm:"size:100;not null" json:"column_name"`
|
|
MaskType string `gorm:"size:30;not null" json:"mask_type"`
|
|
MaskConfig *string `gorm:"type:text" json:"mask_config"`
|
|
IsEnabled *bool `json:"is_enabled"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
}
|
|
|
|
func (MaskingRule) TableName() string { return "masking_rules" }
|
|
|
|
type Backup struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
Title string `gorm:"size:200;not null" json:"title"`
|
|
Database string `gorm:"size:100;not null" json:"database"`
|
|
Filename string `gorm:"size:500;not null" json:"filename"`
|
|
SizeBytes *int64 `json:"size_bytes"`
|
|
Status *string `gorm:"size:20" json:"status"`
|
|
CreatedBy *int `json:"created_by"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
CompletedAt *time.Time `json:"completed_at"`
|
|
Remark *string `gorm:"type:text" json:"remark"`
|
|
}
|
|
|
|
func (Backup) TableName() string { return "backups" }
|
|
|
|
type SchemaRevision struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
Database string `gorm:"size:100;not null" json:"database"`
|
|
Revision string `gorm:"size:64;not null" json:"revision"`
|
|
DDLContent *string `gorm:"type:text" json:"ddl_content"`
|
|
Checksum string `gorm:"size:64;not null" json:"checksum"`
|
|
AppliedBy *int `json:"applied_by"`
|
|
AppliedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"applied_at"`
|
|
Status *string `gorm:"size:20" json:"status"`
|
|
}
|
|
|
|
func (SchemaRevision) TableName() string { return "schema_revisions" }
|
|
|
|
type SlowLog struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
Database *string `gorm:"size:100" json:"database"`
|
|
SQLDigest *string `gorm:"size:64" json:"sql_digest"`
|
|
SQLText *string `gorm:"type:text" json:"sql_text"`
|
|
ExecutionCount *int `json:"execution_count"`
|
|
AvgTimeMs *int `json:"avg_time_ms"`
|
|
MaxTimeMs *int `json:"max_time_ms"`
|
|
RowsExamined *int `json:"rows_examined"`
|
|
RowsSent *int `json:"rows_sent"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (SlowLog) TableName() string { return "slow_logs" }
|
|
|
|
type ScheduledTask struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
Name string `gorm:"size:100;not null" json:"name"`
|
|
Description *string `gorm:"type:text" json:"description"`
|
|
TaskSQLType string `gorm:"size:20;not null" json:"task_sql_type"`
|
|
InstanceID int `gorm:"not null" json:"instance_id"`
|
|
TargetDB *string `gorm:"size:100" json:"target_db"`
|
|
TargetTable *string `gorm:"size:100" json:"target_table"`
|
|
SQLContent string `gorm:"type:text;not null" json:"sql_content"`
|
|
CronExpression string `gorm:"size:50;not null" json:"cron_expression"`
|
|
IsEnabled *bool `json:"is_enabled"`
|
|
LastRunAt *time.Time `json:"last_run_at"`
|
|
LastRunStatus *string `gorm:"size:20" json:"last_run_status"`
|
|
LastRunMessage *string `gorm:"type:text" json:"last_run_message"`
|
|
NextRunAt *time.Time `json:"next_run_at"`
|
|
RunCount *int `json:"run_count"`
|
|
CreatedBy *int `json:"created_by"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
|
}
|
|
|
|
func (ScheduledTask) TableName() string { return "scheduled_tasks" }
|
|
|
|
type ScheduledTaskLog struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
TaskID int `gorm:"not null" json:"task_id"`
|
|
Status string `gorm:"size:20;not null" json:"status"`
|
|
SQLContent *string `gorm:"type:text" json:"sql_content"`
|
|
AffectedRows *int `json:"affected_rows"`
|
|
DurationMs *int `json:"duration_ms"`
|
|
ErrorMessage *string `gorm:"type:text" json:"error_message"`
|
|
StartedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"started_at"`
|
|
FinishedAt *time.Time `json:"finished_at"`
|
|
}
|
|
|
|
func (ScheduledTaskLog) TableName() string { return "scheduled_task_logs" }
|
|
|
|
type UserGroup struct {
|
|
UserID int `gorm:"primaryKey" json:"user_id"`
|
|
GroupID int `gorm:"primaryKey" json:"group_id"`
|
|
Permissions *string `gorm:"type:text" json:"permissions"`
|
|
}
|
|
|
|
func (UserGroup) TableName() string { return "user_groups" }
|
|
|
|
// ==================== RefreshToken ====================
|
|
|
|
// RefreshToken 持久化 refresh token 的 SHA-256 摘要(明文不落库),支持过期与撤销。
|
|
type RefreshToken struct {
|
|
ID int `gorm:"primaryKey" json:"id"`
|
|
UserID int `gorm:"index;not null" json:"user_id"`
|
|
TokenHash string `gorm:"size:64;uniqueIndex;not null" json:"-"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
RevokedAt *time.Time `json:"revoked_at"`
|
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
|
}
|
|
|
|
func (RefreshToken) TableName() string { return "refresh_tokens" }
|
|
|
|
// ==================== DTO ====================
|
|
|
|
type LoginRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
}
|
|
|
|
type LoginResponse struct {
|
|
AccessToken string `json:"access_token"`
|
|
RefreshToken string `json:"refresh_token,omitempty"`
|
|
TokenType string `json:"token_type"`
|
|
User User `json:"user"`
|
|
}
|
|
|
|
type TicketStatistics struct {
|
|
Total int `json:"total"`
|
|
Pending int `json:"pending"`
|
|
Reviewing int `json:"reviewing"`
|
|
Executing int `json:"executing"`
|
|
Completed int `json:"success"`
|
|
Failed int `json:"failed"`
|
|
Rejected int `json:"rejected"`
|
|
}
|
|
|
|
// DB is the global database instance
|
|
var DB *gorm.DB
|