From 58cc7e0d9a80cd7a028ade8c273c633cb8d118f0 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 17 Feb 2026 18:29:37 +0100 Subject: [PATCH] allow org tokens to create contracts Signed-off-by: Jose I. Paris --- .../internal/service/workflowcontract.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/controlplane/internal/service/workflowcontract.go b/app/controlplane/internal/service/workflowcontract.go index fe9c613e8..d3bcaa112 100644 --- a/app/controlplane/internal/service/workflowcontract.go +++ b/app/controlplane/internal/service/workflowcontract.go @@ -121,8 +121,8 @@ func (s *WorkflowContractService) Create(ctx context.Context, req *pb.WorkflowCo // If setting is enabled, only org admins can create contracts (org-level or project-level) if org.RestrictContractCreationToOrgAdmins { - if !isUserOrgAdmin(ctx) { - return nil, errors.Forbidden("forbidden", "contract creation is restricted to organization administrators. Please contact your administrator") + if !canCreateContractsInRestrictedMode(ctx) { + return nil, errors.Forbidden("forbidden", "contract creation is restricted to organization administrators and service accounts. Please contact your administrator") } } @@ -170,6 +170,17 @@ func (s *WorkflowContractService) Create(ctx context.Context, req *pb.WorkflowCo return &pb.WorkflowContractServiceCreateResponse{Result: bizWorkFlowContractToPb(schema)}, nil } +func canCreateContractsInRestrictedMode(ctx context.Context) bool { + // it's an org-scoped API token + token := entities.CurrentAPIToken(ctx) + if token != nil { + return token.ProjectID == nil + } + + // or it's an admin user + return isUserOrgAdmin(ctx) +} + func (s *WorkflowContractService) Update(ctx context.Context, req *pb.WorkflowContractServiceUpdateRequest) (*pb.WorkflowContractServiceUpdateResponse, error) { currentOrg, err := requireCurrentOrg(ctx) if err != nil {