package projectinstance import ( "context" ) const ( DocAccessActionView = "view" DocAccessActionEdit = "edit" DocAccessActionSubmit = "submit" DocAccessActionReview = "review" DocAccessActionApprove = "approve" DocAccessActionRun = "run" AccessCodeDocTaskDisabled = "DOC_TASK_DISABLED" AccessCodeNotCurrentStage = "DOC_TASK_NOT_IN_ACTIVE_STAGE" AccessCodeForbiddenDuty = "DOC_DUTY_FORBIDDEN" AccessCodeDutyNotManaged = "DOC_DUTY_NOT_MANAGED" AccessCodeInstanceClosed = "WORKFLOW_INSTANCE_CLOSED" ) // DocAccessDecision 统一文档任务访问判定结果。 type DocAccessDecision struct { Allowed bool `json:"allowed"` Code string `json:"code,omitempty"` Message string `json:"message,omitempty"` } // CheckDocTaskAccess 对治理实例下的文档任务做判定。 // // GetGoverningInstanceForAccess:从未激活 → view 放行、run 带 WORKFLOW_NOT_ACTIVATED(HTTP 转 202-blocked)、其余拒绝; // completed/terminated → InstanceClosed;存储错误 fail-closed。full 文档按动作对应单一职责,创建者不隐式越权。 func (s *Service) CheckDocTaskAccess( ctx context.Context, projectID int64, userID int64, taskKey string, action string, isCreator bool, ) DocAccessDecision { allow := DocAccessDecision{Allowed: true} if s == nil || s.store == nil || projectID <= 0 || userID <= 0 || taskKey == "" { return allow } gov, err := s.store.GetGoverningInstanceForAccess(ctx, projectID) if err != nil { return DocAccessDecision{Allowed: false, Code: AccessCodeInstanceClosed, Message: "工作流实例不可用"} } if gov == nil { return classifyAccess(DocTaskPlan{Enabled: true}, action, userID, isCreator, false) } if IsClosedInstanceStatus(gov.Status) { return DocAccessDecision{ Allowed: false, Code: AccessCodeInstanceClosed, Message: "工作流实例已结束", } } detail, err := s.store.GetInstanceByID(ctx, gov.ID) if err != nil || detail == nil { return DocAccessDecision{Allowed: false, Code: AccessCodeInstanceClosed, Message: "工作流实例不可用"} } var docInst *DocTaskInstance var stageKey string for _, st := range detail.Stages { for i := range st.DocTasks { if st.DocTasks[i].TaskKey == taskKey { copyDoc := st.DocTasks[i] docInst = ©Doc stageKey = st.StageKey break } } if docInst != nil { break } } if docInst == nil { return allow } if docInst.Status == "skipped_disabled" { return DocAccessDecision{ Allowed: false, Code: AccessCodeDocTaskDisabled, Message: "该文档已被创建者禁用", } } if stageKey != "" && stageKey != detail.ActiveStageKey { if action != DocAccessActionView { return DocAccessDecision{ Allowed: false, Code: AccessCodeNotCurrentStage, Message: "文档不在当前活动阶段", } } } if action == DocAccessActionView { return allow } planTask := findDocTaskPlan(gov.ConfigSnapshot, taskKey) if planTask == nil || !planTask.Enabled { return DocAccessDecision{ Allowed: false, Code: AccessCodeDocTaskDisabled, Message: "该文档已被创建者禁用", } } return classifyAccess(*planTask, action, userID, isCreator, true) } func findDocTaskPlan(plan WorkflowPlan, taskKey string) *DocTaskPlan { for _, st := range plan.Stages { for i := range st.DocTasks { if st.DocTasks[i].TaskKey == taskKey { return &st.DocTasks[i] } } } return nil }