fix(projectinstance): resolve author_only duties in ABAC gates

Use ResolveDocTaskDuty so normalized author-only plans (author ID only)
are treated as full A/A/A for access, stage visibility, and readiness.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-17 13:15:05 +00:00
co-authored by Cursor
parent c6c07263c7
commit f02600d75c
3 changed files with 17 additions and 9 deletions
+3 -2
View File
@@ -63,7 +63,8 @@ func classifyAccess(dt DocTaskPlan, action string, userID int64, isCreator bool,
if !dt.Enabled {
return DocAccessDecision{Allowed: false, Code: AccessCodeDocTaskDisabled, Message: "该文档已被创建者禁用"}
}
switch classifyDocDuty(dt.Duties) {
mode, effective, _ := ResolveDocTaskDuty(dt)
switch mode {
case DutyModeNone:
switch action {
case DocAccessActionRun, DocAccessActionEdit:
@@ -90,7 +91,7 @@ func classifyAccess(dt DocTaskPlan, action string, userID int64, isCreator bool,
}
case DutyModeFull:
role := requiredDutyRole(action)
if userHoldsDuty(dt.Duties, userID, role) {
if userHoldsDuty(effective, userID, role) {
return allow
}
return DocAccessDecision{
+2 -1
View File
@@ -25,7 +25,8 @@ func evaluateStageReadiness(
continue
}
td, hasDef := taskDefMap[dt.TaskKey]
approvalManaged := classifyDocDuty(dt.Duties) != DutyModeNone
mode, _, _ := ResolveDocTaskDuty(dt)
approvalManaged := mode != DutyModeNone
required := approvalManaged && (!hasDef || td.BlocksWhenEnabled())
state := docStates[dt.TaskKey]
if state == "" {
+12 -6
View File
@@ -83,7 +83,7 @@ func (s *Service) ResolveStageAccess(ctx context.Context, projectID int64, userI
if !dt.Enabled {
continue
}
if docTaskDutyForUser(dt, userID) || (isCreator && classifyDocDuty(dt.Duties) == DutyModeNone) {
if docTaskDutyForUser(dt, userID) || (isCreator && docTaskDutyMode(dt) == DutyModeNone) {
out.AllowedTaskKeys[dt.TaskKey] = true
}
}
@@ -100,18 +100,24 @@ func stageDutyForUser(st StagePlan, userID int64) bool {
return false
}
func docTaskDutyMode(dt DocTaskPlan) DutyMode {
mode, _, _ := ResolveDocTaskDuty(dt)
return mode
}
func docTaskDutyForUser(dt DocTaskPlan, userID int64) bool {
if classifyDocDuty(dt.Duties) != DutyModeFull {
mode, effective, _ := ResolveDocTaskDuty(dt)
if mode != DutyModeFull {
return false
}
return dt.Duties.AuthorUserID == userID ||
dt.Duties.ReviewerUserID == userID ||
dt.Duties.ApproverUserID == userID
return effective.AuthorUserID == userID ||
effective.ReviewerUserID == userID ||
effective.ApproverUserID == userID
}
func stageHasUnmanagedDoc(st StagePlan) bool {
for _, dt := range st.DocTasks {
if dt.Enabled && classifyDocDuty(dt.Duties) == DutyModeNone {
if dt.Enabled && docTaskDutyMode(dt) == DutyModeNone {
return true
}
}