From bef2f98f285349946bb50785d28fd1c00040952f Mon Sep 17 00:00:00 2001 From: logan Date: Sun, 31 May 2026 22:20:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=A1=E6=89=B9/=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E6=9D=83=E9=99=90=E6=A0=A1=E9=AA=8C=20+=20LD?= =?UTF-8?q?AP=E7=94=A8=E6=88=B7=E7=A6=81=E6=AD=A2=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ticket.go: ApproveTicket 前置角色检查(admin/dba/auditor),ExecuteTicket 前置角色检查(admin/dba) - ticket.go: 创建工单时自动从 instance.workflow_id 读取关联审批流程 - UsersPage.tsx: LDAP 用户重置密码按钮置灰(disabled+opacity-30+提示文案) - 权限模型: 审核=管理员/DBA/审核员, 执行=管理员/DBA, 提交=所有角色 --- backend/internal/handler/ticket.go | 63 ++++++++++++++++++------------ frontend/src/pages/UsersPage.tsx | 7 ++-- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/backend/internal/handler/ticket.go b/backend/internal/handler/ticket.go index f017ceb..08c7f5b 100644 --- a/backend/internal/handler/ticket.go +++ b/backend/internal/handler/ticket.go @@ -217,6 +217,14 @@ func CreateTicket(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()}) return } + + // Auto-fill workflow_id from instance if not provided + if input.WorkflowID == nil || *input.WorkflowID == 0 { + var inst model.Instance + if model.DB.First(&inst, input.InstanceID).Error == nil && inst.WorkflowID != nil { + input.WorkflowID = inst.WorkflowID + } + } status := "pending" priority := "medium" @@ -348,14 +356,20 @@ func CreateTicket(c *gin.Context) { // POST /api/v1/tickets/:id/approve func ApproveTicket(c *gin.Context) { id := c.Param("id") - userID, _, _ := middleware.GetCurrentUser(c) - + userID, userRole, _ := middleware.GetCurrentUser(c) + + // Role check: only admin/dba/auditor can approve + if userRole != "admin" && userRole != "dba" && userRole != "auditor" { + c.JSON(http.StatusForbidden, gin.H{"detail": "权限不足:审核操作需要管理员、DBA 或审核员角色"}) + return + } + var ticket model.Ticket if err := model.DB.First(&ticket, id).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"detail": "Ticket not found"}) return } - + var input struct { Action string `json:"action" binding:"required"` // approve, reject Comment *string `json:"comment"` @@ -364,31 +378,25 @@ func ApproveTicket(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()}) return } - + now := time.Now() - + // Update approval record — auto-create if missing (legacy tickets) var approval model.TicketApproval if err := model.DB.Where("ticket_id = ? AND approver_id = ? AND action IS NULL", id, userID).First(&approval).Error; err != nil { - // No approval record — check if user is authorized to review - _, userRole, _ := middleware.GetCurrentUser(c) - if userRole == "admin" || userRole == "dba" { - stepName := "审核" - stepType := "audit" - approverRole := userRole - approval = model.TicketApproval{ - TicketID: ticket.ID, - StepNumber: 1, - StepName: &stepName, - StepType: &stepType, - ApproverID: &userID, - ApproverRole: &approverRole, - } - model.DB.Create(&approval) - } else { - c.JSON(http.StatusBadRequest, gin.H{"detail": "No pending approval for you"}) - return + // No approval record — authorized role can create one + stepName := "审核" + stepType := "audit" + approverRole := userRole + approval = model.TicketApproval{ + TicketID: ticket.ID, + StepNumber: 1, + StepName: &stepName, + StepType: &stepType, + ApproverID: &userID, + ApproverRole: &approverRole, } + model.DB.Create(&approval) } approval.Action = &input.Action @@ -420,7 +428,14 @@ func ApproveTicket(c *gin.Context) { // POST /api/v1/tickets/:id/execute func ExecuteTicket(c *gin.Context) { id := c.Param("id") - + + // Role check: only admin/dba can execute + _, userRole, _ := middleware.GetCurrentUser(c) + if userRole != "admin" && userRole != "dba" { + c.JSON(http.StatusForbidden, gin.H{"detail": "权限不足:执行操作需要管理员或 DBA 角色"}) + return + } + var ticket model.Ticket if err := model.DB.First(&ticket, id).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"detail": "Ticket not found"}) diff --git a/frontend/src/pages/UsersPage.tsx b/frontend/src/pages/UsersPage.tsx index d7e16f7..5087b78 100644 --- a/frontend/src/pages/UsersPage.tsx +++ b/frontend/src/pages/UsersPage.tsx @@ -487,9 +487,10 @@ export default function UsersPage() {