package server import ( "context" "net/http" "chat-agent-system/internal/auth" ) type taskRunAction string const ( taskRunView taskRunAction = "view" taskRunCancel taskRunAction = "cancel" taskRunResume taskRunAction = "resume" ) func (s *Server) assertTaskRunAccess(w http.ResponseWriter, ctx context.Context, runID string, user *auth.UserAccount, action taskRunAction) bool { if user == nil { writeJSONResponse(w, http.StatusUnauthorized, map[string]string{ "error_code": "ERR_UNAUTHENTICATED", "message": "请先登录", }) return false } rec, err := s.taskRuns().GetRun(runID) if err != nil { writeSafeError(w, nil, http.StatusNotFound, "run not found") return false } if s.isSystemAdminUser(ctx, user) { return true } isOwner := rec.UserID > 0 && rec.UserID == user.ID isProjectOwner := false isProjectMember := false if rec.ProjectID > 0 && s.authorizer() != nil { isProjectOwner, _ = s.authorizer().IsProjectOwner(ctx, rec.ProjectID, user.ID) isProjectMember, _ = s.authorizer().IsProjectMember(ctx, rec.ProjectID, user.ID) } switch action { case taskRunView: // Align with create-run RequireProjectAccess: any active project member may view. if isOwner || isProjectOwner || isProjectMember { return true } case taskRunCancel, taskRunResume: if isOwner || isProjectOwner { return true } } writeJSONResponse(w, http.StatusForbidden, map[string]string{ "error_code": "ERR_FORBIDDEN", "message": "无权访问该任务", }) return false } func (s *Server) assertTaskRunOwnedByUser(w http.ResponseWriter, ctx context.Context, runID string, user *auth.UserAccount) bool { return s.assertTaskRunAccess(w, ctx, runID, user, taskRunView) } func (s *Server) isSystemAdminUser(ctx context.Context, user *auth.UserAccount) bool { if user == nil { return false } admin, err := s.authzSvc().IsSystemAdmin(ctx, user.ID, user.RoleID) return err == nil && admin }