权限整改:接入项目任务路由与证书任务判权

提交当前任务权限开发检查点,保持总体验收位置为 P0-03 完成待复审。
This commit is contained in:
xuans 2026-09-29 18:09:58 +08:00
parent 17101da46b
commit 802109e96a
3 changed files with 23 additions and 11 deletions

View File

@ -213,6 +213,11 @@ func (s *Server) registerRoutes() {
domainAPI.PUT("/domains/:id", s.dnsOperation, s.updateDomain)
domainAPI.DELETE("/domains/:id", s.deleteDomain)
domainAPI.POST("/domains/:id/issue", s.longOperation(certificateTaskTimeout), s.issueDomain)
api := s.router.Group("/api/v1", privateProjectResponse, s.requireAuthenticated)
api.GET("/tasks", s.listTasks)
api.GET("/tasks/:id", s.getTask)
api.DELETE("/tasks/:id", s.cancelTask)
api.GET("/tasks/:id/attempts", s.listTaskAttempts)
adminAPI.GET("/settings", s.getSettings)
adminAPI.PUT("/settings", s.updateSettings)

View File

@ -20,8 +20,12 @@ func (s *Server) issueDomainAsTask(c *gin.Context) {
s.writeError(c, http.StatusNotImplemented, "证书申请接口尚未配置", errors.New("证书申请工作流未配置"))
return
}
if s.tasks == nil || s.projectResources == nil || s.projectMembers == nil {
s.writeError(c, http.StatusServiceUnavailable, "证书任务权限服务尚未就绪", errors.New("任务、项目资源或项目权限服务未配置"))
if s.tasks == nil {
s.writeError(c, http.StatusNotImplemented, "证书任务接口尚未配置", errors.New("任务仓储未配置"))
return
}
if s.projectResources == nil || s.projectMembers == nil {
s.writeError(c, http.StatusServiceUnavailable, "证书任务权限服务尚未就绪", errors.New("项目资源或项目权限服务未配置"))
return
}
domainID := strings.TrimSpace(c.Param("id"))

View File

@ -21,11 +21,14 @@ type ProjectTaskReader interface {
var _ ProjectTaskReader = (*SQLTaskRepository)(nil)
func taskVisibilityPredicate(alias string) (string, []any) {
roles := []domain.ProjectRole{
domain.ProjectRoleAdmin,
domain.ProjectRoleAuditViewer,
domain.ProjectRoleReadOnly,
func taskVisibilityPredicate(alias string, permission domain.ProjectPermission) (string, []any) {
roles := []domain.ProjectRole{domain.ProjectRoleAdmin}
if permission == domain.PermissionTaskRead {
roles = []domain.ProjectRole{
domain.ProjectRoleAdmin,
domain.ProjectRoleAuditViewer,
domain.ProjectRoleReadOnly,
}
}
placeholders := make([]string, 0, len(roles))
args := []any{""}
@ -55,7 +58,7 @@ func (r *SQLTaskRepository) ListVisibleTasks(ctx context.Context, actorID, domai
if limit <= 0 || limit > 200 {
limit = 50
}
predicate, args := taskVisibilityPredicate("tasks")
predicate, args := taskVisibilityPredicate("tasks", domain.PermissionTaskRead)
args[0] = strings.TrimSpace(actorID)
query := taskSelect + ` WHERE ` + predicate
if domainID = strings.TrimSpace(domainID); domainID != "" {
@ -86,7 +89,7 @@ func (r *SQLTaskRepository) GetVisibleTask(ctx context.Context, actorID, taskID
if r == nil || r.db == nil {
return Task{}, errors.New("数据库连接不能为空")
}
predicate, args := taskVisibilityPredicate("tasks")
predicate, args := taskVisibilityPredicate("tasks", domain.PermissionTaskRead)
args[0] = strings.TrimSpace(actorID)
args = append(args, strings.TrimSpace(taskID))
return scanTask(r.db.QueryRowContext(ctx, r.query(taskSelect+` WHERE `+predicate+` AND tasks.id = ?`), args...))
@ -96,7 +99,7 @@ func (r *SQLTaskRepository) ListVisibleTaskAttempts(ctx context.Context, actorID
if r == nil || r.db == nil {
return nil, errors.New("数据库连接不能为空")
}
predicate, args := taskVisibilityPredicate("tasks")
predicate, args := taskVisibilityPredicate("tasks", domain.PermissionTaskRead)
args[0] = strings.TrimSpace(actorID)
args = append(args, strings.TrimSpace(taskID))
rows, err := r.db.QueryContext(ctx, r.query(`SELECT attempts.id, attempts.task_id, attempts.attempt_number,
@ -131,7 +134,7 @@ func (r *SQLTaskRepository) CancelVisibleTask(ctx context.Context, actorID, task
return fmt.Errorf("开始取消任务事务失败:%w", err)
}
rollback := func() { _ = tx.Rollback() }
predicate, predicateArgs := taskVisibilityPredicate("tasks")
predicate, predicateArgs := taskVisibilityPredicate("tasks", domain.PermissionTaskCancel)
predicateArgs[0] = strings.TrimSpace(actorID)
args := []any{message, nullableTime(finishedAt), time.Now().UTC(), strings.TrimSpace(taskID)}
args = append(args, predicateArgs...)