主题: - 深色/浅色/跟随系统(useTheme:本地缓存先行+远端同步+matchMedia), 侧边栏快捷切换,设置页三档即选即生效 LLM(参考 opsxdb/aiops): - llm.Client.ChatStream 流式(SSE 增量解析,透传 reasoning_content, ctx 控制超时);POST /api/ai/chat/stream(平台实时数据注入降幻觉, 未配 LLM 降级规则 JSON,指令解析 action 不变) - test-llm 支持草稿直测(保存前验证,apiKey 空/掩码回退已存) - 发布失败自动 AI 分析日志尾部(结论/根因/建议),发布记录与发布 Tab 展示分析卡片 - 设置页 Provider 预设(DeepSeek/GLM/GLM编码/Qwen/Kimi/Ollama/自定义) 自动填 endpoint+模型+获取 Key 直达链接 登录与会话: - HMAC 签名 token(7 天,密钥派生自 encryption.key); authMiddleware 保护 /api/*(豁免登录/健康/SSE日志流/入站webhook) - 登录页 /login + 未登录跳转 + 登出;401 自动清理跳登录 用户管理与 LDAP(借鉴 LokiStack): - /users 页面:本地用户 CRUD、一次性密码、角色切换、来源徽章 (本地·蓝 | LDAP导入·紫);LDAP 导入按钮仅在启用且配置齐备时显示 - LDAP 配置卡(未启用仅提示语)、测试连接草稿直测+可选测试账号 - go-ldap:管理 Bind/用户搜索(防注入)/用户 DN 直连验证; 批量导入冲突策略(已LDAP跳过/本地同名转LDAP/新建); 登录分流本地 argon2id 或 LDAP 目录验证 + 首登 JIT 建号
305 lines
15 KiB
Go
305 lines
15 KiB
Go
package model
|
||
|
||
import "time"
|
||
|
||
// User 系统用户
|
||
type User struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Username string `gorm:"uniqueIndex" json:"username"`
|
||
Password string `json:"-"` // argon2id 哈希,绝不返回给前端
|
||
Nickname string `json:"nickname"`
|
||
Email string `json:"email"`
|
||
AuthSource string `gorm:"default:local" json:"authSource"` // local | ldap
|
||
Role string `gorm:"default:user" json:"role"` // admin | user
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// Pipeline 流水线定义
|
||
type Pipeline struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"index" json:"name"`
|
||
Description string `json:"description"`
|
||
Type string `gorm:"default:native" json:"type"` // native | jenkins | tekton
|
||
SourceRepo string `json:"sourceRepo"`
|
||
SourceBranch string `gorm:"default:main" json:"sourceBranch"`
|
||
GitopsRepo string `json:"gitopsRepo"`
|
||
GitopsPath string `json:"gitopsPath"`
|
||
DeployType string `gorm:"default:host" json:"deployType"` // host | k8s | gitops
|
||
Env string `gorm:"default:staging" json:"env"`
|
||
TriggerMode string `gorm:"default:manual" json:"triggerMode"` // manual | git_push | cron | webhook
|
||
CronExpr string `json:"cronExpr"`
|
||
WebhookToken string `json:"webhookToken"`
|
||
WatchBranches string `json:"watchBranches"`
|
||
Variables string `gorm:"type:text" json:"variables"` // JSON [{key,value,remark}]
|
||
CachePaths string `gorm:"type:text" json:"cachePaths"` // JSON [{path,key}]
|
||
NotifyWebhook string `json:"notifyWebhookURL"`
|
||
JenkinsJobName string `json:"jenkinsJobName"`
|
||
JenkinsServerID uint `json:"jenkinsServerId"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// PipelineNode 画布节点(JSON 字段名与前端 React Flow 对齐)
|
||
type PipelineNode struct {
|
||
ID uint `gorm:"primaryKey" json:"dbId"`
|
||
PipelineID uint `gorm:"index" json:"pipelineId"`
|
||
NodeID string `gorm:"index" json:"nodeId"`
|
||
Type string `json:"type"`
|
||
Name string `json:"name"`
|
||
PositionX float64 `json:"positionX"`
|
||
PositionY float64 `json:"positionY"`
|
||
Width float64 `json:"width"`
|
||
Height float64 `json:"height"`
|
||
Category string `json:"category"` // source|build|test|security|deploy|gitops|custom
|
||
Config map[string]interface{} `gorm:"serializer:json" json:"config"`
|
||
}
|
||
|
||
// PipelineEdge 画布连线
|
||
type PipelineEdge struct {
|
||
ID uint `gorm:"primaryKey" json:"dbId"`
|
||
PipelineID uint `gorm:"index" json:"pipelineId"`
|
||
EdgeID string `gorm:"index" json:"edgeId"`
|
||
Source string `json:"source"`
|
||
Target string `json:"target"`
|
||
Label string `json:"label"`
|
||
Animated bool `json:"animated"`
|
||
}
|
||
|
||
// PipelineRun 一次流水线运行
|
||
type PipelineRun struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
RunID string `gorm:"uniqueIndex" json:"runId"` // pr-<timestamp>
|
||
PipelineID uint `gorm:"index" json:"pipelineId"`
|
||
PipelineName string `json:"pipelineName"`
|
||
Branch string `gorm:"default:main" json:"branch"`
|
||
Env string `gorm:"default:staging" json:"env"`
|
||
DeployType string `gorm:"default:host" json:"deployType"`
|
||
Type string `gorm:"default:native" json:"type"`
|
||
TriggerBy string `gorm:"default:system" json:"triggerBy"`
|
||
TriggerType string `gorm:"default:manual" json:"triggerType"` // manual|webhook|cron|batch
|
||
Status string `gorm:"default:pending" json:"status"` // pending|queued|running|success|failed|cancelled
|
||
DurationMs int64 `json:"durationMs"`
|
||
BuildNumber int `json:"buildNumber"`
|
||
Analysis string `gorm:"type:text" json:"analysis"` // 发布失败时的 AI 分析
|
||
ExternalRunID string `json:"externalRunId"`
|
||
ExternalURL string `json:"externalUrl"`
|
||
NodesSnapshot string `json:"nodesSnapshot"`
|
||
EdgesSnapshot string `json:"edgesSnapshot"`
|
||
StartedAt time.Time `json:"startedAt"`
|
||
CompletedAt *time.Time `json:"completedAt"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// RunStage 运行中的阶段(对应一个节点)
|
||
type RunStage struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
RunID uint `gorm:"index" json:"runId"`
|
||
NodeID string `json:"nodeId"`
|
||
Name string `json:"name"`
|
||
PodName string `json:"podName"`
|
||
Status string `gorm:"default:pending" json:"status"` // pending|running|success|failed|skipped
|
||
ExitCode *int `json:"exitCode"`
|
||
StartedAt *time.Time `json:"startedAt"`
|
||
CompletedAt *time.Time `json:"completedAt"`
|
||
}
|
||
|
||
// LogEntry 运行日志
|
||
type LogEntry struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
RunID uint `gorm:"index" json:"runId"`
|
||
StageID uint `json:"stageId"`
|
||
Level string `gorm:"default:info" json:"level"` // debug|info|warn|error
|
||
Message string `json:"message"`
|
||
Source string `gorm:"default:runner" json:"source"`
|
||
Timestamp time.Time `json:"timestamp"`
|
||
}
|
||
|
||
// Application GitOps 应用
|
||
type Application struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"uniqueIndex" json:"name"`
|
||
Repo string `json:"repo"`
|
||
Branch string `gorm:"default:main" json:"branch"`
|
||
Path string `json:"path"`
|
||
Cluster string `gorm:"default:default" json:"cluster"`
|
||
Namespace string `gorm:"default:default" json:"namespace"`
|
||
ManifestType string `gorm:"default:plain" json:"manifestType"` // helm|kustomize|plain
|
||
SyncPolicy string `gorm:"default:manual" json:"syncPolicy"` // manual|automated
|
||
AutoPrune bool `json:"autoPrune"`
|
||
SelfHeal bool `json:"selfHeal"`
|
||
SyncStatus string `gorm:"default:Synced" json:"syncStatus"` // Synced|OutOfSync|Syncing
|
||
HealthStatus string `gorm:"default:Healthy" json:"healthStatus"` // Healthy|Progressing|Degraded
|
||
LastSyncAt *time.Time `json:"lastSyncAt"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// Plugin 插件
|
||
type Plugin struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
PluginID string `gorm:"uniqueIndex" json:"pluginId"`
|
||
Name string `json:"name"`
|
||
Description string `json:"description"`
|
||
Version string `json:"version"`
|
||
Author string `json:"author"`
|
||
Category string `gorm:"default:general" json:"category"`
|
||
EntryPath string `json:"entryPath"`
|
||
Installed bool `gorm:"default:true" json:"installed"`
|
||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||
Config map[string]interface{} `gorm:"serializer:json" json:"config"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
}
|
||
|
||
// Host 主机资源
|
||
type Host struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"uniqueIndex" json:"name"`
|
||
IP string `json:"ip"`
|
||
SSHPort int `gorm:"default:22" json:"port"`
|
||
Username string `gorm:"default:root" json:"username"`
|
||
Tags string `gorm:"type:text" json:"tags"` // JSON ["production","web"]
|
||
Status string `gorm:"default:offline" json:"status"` // online|offline
|
||
OS string `json:"os"`
|
||
Remark string `json:"remark"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// K8sCluster 集群资源
|
||
type K8sCluster struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"uniqueIndex" json:"name"`
|
||
Context string `json:"context"`
|
||
APIServer string `json:"apiServer"`
|
||
Version string `json:"version"`
|
||
Kubeconfig string `gorm:"type:text" json:"-"` // enc:v1: 加密,不回显
|
||
KubeconfigSet bool `gorm:"-" json:"kubeconfigSet"`
|
||
NodeCount int `json:"nodes"`
|
||
Namespaces string `gorm:"type:text" json:"namespaces"` // JSON []
|
||
Status string `gorm:"default:disconnected" json:"status"` // connected|disconnected
|
||
LastHeartbeat *time.Time `json:"lastHeartbeat"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// Credential 凭证(内容 AES-GCM 加密,只写不读)
|
||
type Credential struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"uniqueIndex" json:"name"`
|
||
Type string `gorm:"index" json:"type"` // ssh|password|docker|git|kubeconfig|aksk
|
||
Scope string `gorm:"default:全局" json:"scope"`
|
||
Content string `gorm:"type:text" json:"-"` // enc:v1: 加密 JSON
|
||
ContentSet bool `gorm:"-" json:"contentSet"`
|
||
Summary string `json:"summary"` // 脱敏摘要
|
||
UsageCount int `gorm:"default:0" json:"usageCount"`
|
||
LastUsedAt *time.Time `json:"lastUsedAt"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// BuildNode 构建节点
|
||
type BuildNode struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"uniqueIndex" json:"name"`
|
||
IP string `json:"ip"`
|
||
Labels string `gorm:"type:text" json:"labels"` // JSON ["docker","go"]
|
||
MaxConcurrency int `gorm:"default:2" json:"maxConcurrency"`
|
||
WorkspacePath string `gorm:"default:/data/flowstack-workspace" json:"workspacePath"`
|
||
DiskInfo string `json:"diskInfo"` // 如 "45G/200G"
|
||
CredentialID *uint `json:"credentialId"` // SSH 凭证(磁盘性能测试等远程操作)
|
||
DiskWriteMBps float64 `gorm:"column:disk_write_mbps" json:"diskWriteMBps"`
|
||
DiskReadMBps float64 `gorm:"column:disk_read_mbps" json:"diskReadMBps"`
|
||
DiskTestMode string `json:"diskTestMode"` // local|ssh + /direct|/cache
|
||
DiskTestedAt *time.Time `json:"diskTestedAt"`
|
||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||
Status string `gorm:"default:offline" json:"status"` // online|offline|busy
|
||
CurrentJobs int `gorm:"default:0" json:"currentJobs"`
|
||
LastHeartbeat *time.Time `json:"lastHeartbeat"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// DeployTool 构建工具(检测命令真实执行;安装为保守策略:仅检测不下载)
|
||
type DeployTool struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
ToolKey string `gorm:"uniqueIndex" json:"key"`
|
||
DisplayName string `json:"name"`
|
||
Category string `gorm:"default:build" json:"category"` // build|deploy
|
||
Status string `gorm:"default:not-installed" json:"status"` // not-installed|installed|installing|failed
|
||
Version string `json:"version"` // 默认/期望版本
|
||
InstalledVersion string `json:"installedVersion"` // 真实探测到的版本
|
||
InstallMode string `gorm:"default:lazy" json:"installMode"` // preinstalled|lazy|disabled
|
||
Path string `json:"path"`
|
||
CheckCommand string `gorm:"type:text" json:"checkCommand"` // 真实版本探测命令
|
||
InstallHint string `gorm:"type:text" json:"installHint"` // 安装命令提示(Ubuntu apt / nvm)
|
||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||
LastCheck *time.Time `json:"lastCheck"`
|
||
ErrorMsg string `json:"errorMsg"`
|
||
SortOrder int `json:"sortOrder"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// WebhookEndpoint 出站 Webhook(HMAC-SHA256 签名)
|
||
type WebhookEndpoint struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `json:"name"`
|
||
URL string `json:"url"`
|
||
Secret string `gorm:"type:text" json:"-"` // enc:v1: 加密
|
||
SecretSet bool `gorm:"-" json:"secretSet"`
|
||
Events string `gorm:"type:text" json:"events"` // JSON ["pipeline.success",...]
|
||
Active bool `gorm:"default:true" json:"active"`
|
||
LastTriggeredAt *time.Time `json:"lastTriggered"`
|
||
LastStatus string `gorm:"default:none" json:"lastStatus"` // success|failed|none
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// JenkinsServer Jenkins 实例
|
||
type JenkinsServer struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Name string `gorm:"uniqueIndex" json:"name"`
|
||
BaseURL string `json:"baseUrl"`
|
||
Username string `json:"username"`
|
||
Token string `gorm:"type:text" json:"-"` // enc:v1: 加密
|
||
TokenSet bool `gorm:"-" json:"tokenSet"`
|
||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||
Remark string `json:"remark"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// SystemSetting 系统设置(单行,ID 恒为 1)
|
||
type SystemSetting struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
Theme string `gorm:"type:text" json:"theme"` // JSON {mode,primaryColor,...}
|
||
Notification string `gorm:"type:text" json:"notification"` // JSON {email,browser,...}
|
||
ToolMode string `gorm:"default:local" json:"toolMode"` // local|jenkins
|
||
LlmEnabled bool `gorm:"default:false" json:"llmEnabled"`
|
||
LlmEndpoint string `gorm:"default:https://api.deepseek.com/v1" json:"llmEndpoint"`
|
||
LlmModel string `gorm:"default:deepseek-chat" json:"llmModel"`
|
||
LlmApiKey string `gorm:"type:text" json:"-"` // enc:v1: 加密,只写不读
|
||
LlmApiKeySet bool `gorm:"-" json:"llmApiKeySet"`
|
||
LlmMaxTokens int `gorm:"default:1200" json:"llmMaxTokens"`
|
||
LarkEnabled bool `gorm:"default:false" json:"larkEnabled"`
|
||
LarkWebhook string `json:"larkWebhook"` // 飞书群自定义机器人 Webhook
|
||
LarkSecret string `gorm:"type:text" json:"-"` // 加签密钥(可选),enc:v1: 加密
|
||
LarkSecretSet bool `gorm:"-" json:"larkSecretSet"`
|
||
LdapEnabled bool `json:"ldapEnabled"`
|
||
LdapHost string `json:"ldapHost"`
|
||
LdapPort int `gorm:"default:389" json:"ldapPort"`
|
||
LdapUseSSL bool `json:"ldapUseSSL"`
|
||
LdapBindDN string `json:"ldapBindDN"`
|
||
LdapBindPassword string `gorm:"type:text" json:"-"` // enc:v1: 加密只写
|
||
LdapBindPasswordSet bool `gorm:"-" json:"ldapBindPasswordSet"`
|
||
LdapBaseDN string `json:"ldapBaseDN"`
|
||
LdapUserFilter string `json:"ldapUserFilter"`
|
||
LdapUsernameAttr string `json:"ldapUsernameAttr"`
|
||
LdapNameAttr string `json:"ldapNameAttr"`
|
||
LdapEmailAttr string `json:"ldapEmailAttr"`
|
||
Extra string `gorm:"type:text" json:"extra"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|