From f580ad554c9efe024ba3648046a41572e84cd37b Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 3 Jul 2025 23:19:12 +0200 Subject: [PATCH 01/24] chore; fix Signed-off-by: Miguel Martinez --- app/controlplane/pkg/biz/workflowcontract.go | 18 ++++++++++++++++++ .../pkg/data/ent/schema/workflowcontract.go | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index 96f3f7ad8..c835a4fa6 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -594,3 +594,21 @@ func SchemaToRawContract(contract *schemav1.CraftingSchema) (*Contract, error) { return &Contract{Raw: r, Format: unmarshal.RawFormatJSON, Schema: contract}, nil } + +// ContractScope represents a polymorphic relationship between a contract and a project or organization +type ContractScope string + +const ( + ContractScopeProject ContractScope = "project" + ContractScopeOrg ContractScope = "org" +) + +// Values implement https://pkg.go.dev/entgo.io/ent/schema/field#EnumValues +func (ContractScope) Values() (values []string) { + values = append(values, + string(ContractScopeProject), + string(ContractScopeOrg), + ) + + return +} diff --git a/app/controlplane/pkg/data/ent/schema/workflowcontract.go b/app/controlplane/pkg/data/ent/schema/workflowcontract.go index 885c7495f..69fc1265a 100644 --- a/app/controlplane/pkg/data/ent/schema/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/schema/workflowcontract.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import ( "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" "entgo.io/ent/schema/index" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/google/uuid" ) @@ -44,6 +45,9 @@ func (WorkflowContract) Fields() []ent.Field { }), field.Time("deleted_at").Optional(), field.String("description").Optional(), + // If this value is set, the contract is scoped to a project or organization + field.Enum("scoped_resource_type").GoType(biz.ContractScope("")).Optional(), + field.UUID("scoped_resource_id", uuid.UUID{}).Optional(), } } From 85c7f2a160bde6972ff786c97b2ef30e46da1815 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 3 Jul 2025 23:29:09 +0200 Subject: [PATCH 02/24] feat: add columns Signed-off-by: Miguel Martinez --- .../frontend/google/protobuf/descriptor.ts | 16 +- .../api/gen/temp-openapi/apidocs.swagger.json | 236 ++++++++++++++++++ app/controlplane/pkg/biz/workflowcontract.go | 18 -- app/controlplane/pkg/data/ent/client.go | 16 ++ .../ent/migrate/migrations/20250703212753.sql | 8 + .../pkg/data/ent/migrate/migrations/atlas.sum | 8 + .../pkg/data/ent/migrate/schema.go | 18 +- app/controlplane/pkg/data/ent/mutation.go | 127 +++++++++- app/controlplane/pkg/data/ent/schema-viz.html | 4 + .../pkg/data/ent/schema/workflowcontract.go | 14 +- .../pkg/data/ent/workflowcontract.go | 34 ++- .../pkg/data/ent/workflowcontract/where.go | 58 +++++ .../ent/workflowcontract/workflowcontract.go | 31 +++ .../pkg/data/ent/workflowcontract_create.go | 97 +++++++ .../pkg/data/ent/workflowcontract_query.go | 77 +++++- .../pkg/data/ent/workflowcontract_update.go | 121 +++++++++ 16 files changed, 846 insertions(+), 37 deletions(-) create mode 100644 app/controlplane/api/gen/temp-openapi/apidocs.swagger.json create mode 100644 app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql diff --git a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts index d59b21da4..0d2d2fb32 100644 --- a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts +++ b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts @@ -30,7 +30,7 @@ export enum Edition { EDITION_2024 = 1001, /** * EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be - * used or relied on outside of tests. + * used or relyed on outside of tests. */ EDITION_1_TEST_ONLY = 1, EDITION_2_TEST_ONLY = 2, @@ -875,13 +875,12 @@ export interface MessageOptions { export interface FieldOptions { /** - * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific * options below. This option is only implemented to support use of * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of - * type "bytes" in the open source release. - * TODO: make ctype actually deprecated. + * type "bytes" in the open source release -- sorry, we'll try to include + * other types in a future version! */ ctype: FieldOptions_CType; /** @@ -1053,7 +1052,11 @@ export function fieldOptions_JSTypeToJSON(object: FieldOptions_JSType): string { } } -/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */ +/** + * If set to RETENTION_SOURCE, the option will be omitted from the binary. + * Note: as of January 2023, support for this is in progress and does not yet + * have an effect (b/264593489). + */ export enum FieldOptions_OptionRetention { RETENTION_UNKNOWN = 0, RETENTION_RUNTIME = 1, @@ -1096,7 +1099,8 @@ export function fieldOptions_OptionRetentionToJSON(object: FieldOptions_OptionRe /** * This indicates the types of entities that the field may apply to when used * as an option. If it is unset, then the field may be freely used as an - * option on any kind of entity. + * option on any kind of entity. Note: as of January 2023, support for this is + * in progress and does not yet have an effect (b/264593489). */ export enum FieldOptions_OptionTargetType { TARGET_TYPE_UNKNOWN = 0, diff --git a/app/controlplane/api/gen/temp-openapi/apidocs.swagger.json b/app/controlplane/api/gen/temp-openapi/apidocs.swagger.json new file mode 100644 index 000000000..876e2ba97 --- /dev/null +++ b/app/controlplane/api/gen/temp-openapi/apidocs.swagger.json @@ -0,0 +1,236 @@ +{ + "swagger": "2.0", + "info": { + "title": "Chainloop Controlplane API", + "termsOfService": "https://chainloop.dev/terms", + "version": "1.0", + "contact": { + "name": "Chainloop Support", + "url": "https://chainloop.dev", + "email": "support@chainloop.dev" + } + }, + "tags": [ + { + "name": "ReferrerService", + "description": "Referrer service for discovering referred content by digest" + } + ], + "host": "cp.chainloop.dev", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/discover/shared/{digest}": { + "get": { + "summary": "Discover public shared referrer", + "description": "Returns the referrer item for a given digest in the public shared index", + "operationId": "ReferrerService_DiscoverPublicShared", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1DiscoverPublicSharedResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "digest", + "description": "Digest is the unique identifier of the referrer to discover", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "kind", + "description": "Kind is the optional type of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ...\nUsed to filter and resolve ambiguities", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "ReferrerService" + ], + "produces": [ + "application/json" + ] + } + }, + "/discover/{digest}": { + "get": { + "summary": "Discover private referrer", + "description": "Returns the referrer item for a given digest in the organizations of the logged-in user", + "operationId": "ReferrerService_DiscoverPrivate", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ReferrerServiceDiscoverPrivateResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "digest", + "description": "Digest is the unique identifier of the referrer to discover", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "kind", + "description": "Kind is the optional type of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ...\nUsed to filter and resolve ambiguities", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "ReferrerService" + ], + "produces": [ + "application/json" + ] + } + } + }, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + }, + "v1DiscoverPublicSharedResponse": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/v1ReferrerItem", + "title": "Result is the discovered referrer item" + } + }, + "description": "Response for the DiscoverPublicShared method", + "title": "DiscoverPublicSharedResponse" + }, + "v1ReferrerItem": { + "type": "object", + "properties": { + "digest": { + "type": "string", + "title": "Digest of the referrer, i.e sha256:deadbeef or sha1:beefdead" + }, + "kind": { + "type": "string", + "description": "Kind of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ..." + }, + "downloadable": { + "type": "boolean", + "title": "Downloadable indicates whether the referrer is downloadable or not from CAS" + }, + "public": { + "type": "boolean", + "title": "Public indicates whether the referrer is public since it belongs to a public workflow" + }, + "references": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ReferrerItem" + }, + "title": "References contains the list of related referrer items" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "CreatedAt is the timestamp when the referrer was created" + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Metadata contains additional descriptive information about the referrer" + }, + "annotations": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "title": "Annotations are key-value pairs associated with the referrer" + } + }, + "description": "It represents a referrer object in the system", + "title": "ReferrerItem" + }, + "v1ReferrerServiceDiscoverPrivateResponse": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/v1ReferrerItem", + "title": "Result is the discovered referrer item" + } + }, + "description": "Response for the DiscoverPrivate method", + "title": "ReferrerServiceDiscoverPrivateResponse" + } + }, + "securityDefinitions": { + "bearerToken": { + "type": "apiKey", + "description": "Bearer token for authentication", + "name": "Authorization", + "in": "header" + } + }, + "security": [ + { + "bearerToken": [] + } + ], + "externalDocs": { + "description": "Chainloop Official Documentation", + "url": "https://docs.chainloop.dev" + } +} diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index c835a4fa6..96f3f7ad8 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -594,21 +594,3 @@ func SchemaToRawContract(contract *schemav1.CraftingSchema) (*Contract, error) { return &Contract{Raw: r, Format: unmarshal.RawFormatJSON, Schema: contract}, nil } - -// ContractScope represents a polymorphic relationship between a contract and a project or organization -type ContractScope string - -const ( - ContractScopeProject ContractScope = "project" - ContractScopeOrg ContractScope = "org" -) - -// Values implement https://pkg.go.dev/entgo.io/ent/schema/field#EnumValues -func (ContractScope) Values() (values []string) { - values = append(values, - string(ContractScopeProject), - string(ContractScopeOrg), - ) - - return -} diff --git a/app/controlplane/pkg/data/ent/client.go b/app/controlplane/pkg/data/ent/client.go index e1ed0c1c7..a529e22d8 100644 --- a/app/controlplane/pkg/data/ent/client.go +++ b/app/controlplane/pkg/data/ent/client.go @@ -3567,6 +3567,22 @@ func (c *WorkflowContractClient) QueryWorkflows(wc *WorkflowContract) *WorkflowQ return query } +// QueryProject queries the project edge of a WorkflowContract. +func (c *WorkflowContractClient) QueryProject(wc *WorkflowContract) *ProjectQuery { + query := (&ProjectClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := wc.ID + step := sqlgraph.NewStep( + sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, id), + sqlgraph.To(project.Table, project.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, workflowcontract.ProjectTable, workflowcontract.ProjectColumn), + ) + fromV = sqlgraph.Neighbors(wc.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *WorkflowContractClient) Hooks() []Hook { return c.hooks.WorkflowContract diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql new file mode 100644 index 000000000..95c413acd --- /dev/null +++ b/app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql @@ -0,0 +1,8 @@ +-- Drop index "workflowcontract_name_organization_workflow_contracts" from table: "workflow_contracts" +DROP INDEX "workflowcontract_name_organization_workflow_contracts"; +-- Modify "workflow_contracts" table +ALTER TABLE "workflow_contracts" ADD COLUMN "project_id" uuid NULL; +-- Create index "workflowcontract_name_organization_workflow_contracts" to table: "workflow_contracts" +CREATE UNIQUE INDEX "workflowcontract_name_organization_workflow_contracts" ON "workflow_contracts" ("name", "organization_workflow_contracts") WHERE ((deleted_at IS NULL) AND (project_id IS NULL)); +-- Create index "workflowcontract_name_project_id" to table: "workflow_contracts" +CREATE UNIQUE INDEX "workflowcontract_name_project_id" ON "workflow_contracts" ("name", "project_id") WHERE ((deleted_at IS NULL) AND (project_id IS NOT NULL)); diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index c485b7ad1..fa71a0d66 100644 --- a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum +++ b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum @@ -1,4 +1,8 @@ +<<<<<<< HEAD h1:pewT4SIwZxo6E95TRjOvYvsO2AvVZDBRPljhvi6yN3c= +======= +h1:Nqn7kGmL5Hba+3tAbxdDjH6+KvSmunyHZuDIthoGQiU= +>>>>>>> 9b3f353d (feat: add columns) 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -93,5 +97,9 @@ h1:pewT4SIwZxo6E95TRjOvYvsO2AvVZDBRPljhvi6yN3c= 20250626100818.sql h1:MMCQid88eEs4uyCVBgkf5b0VYjyBd1EYRqRISco0rOI= 20250627143634.sql h1:9UdcOm4HdWyJ8bvU/vYkzCslXIpKSn7pM0l/MJHl8n4= 20250702111701.sql h1:Ni7fuL1qU5RGjBzV0XgJi9NkZINGijF8BumPuQ9conM= +<<<<<<< HEAD 20250702112642.sql h1:wrjVS+5h2hs7KNwPRBece5LgAsoEzxN/zNfvCnjoIUw= 20250704090359.sql h1:a0ksfjy2dtzviJL16HbC4eT1xBxy2qFH5mNFOpYlUrA= +======= +20250703212753.sql h1:Hr4sKsM+tlPRp0I9qRLnnkVUNpZ4xTH/XOQJ5nDdbek= +>>>>>>> 9b3f353d (feat: add columns) diff --git a/app/controlplane/pkg/data/ent/migrate/schema.go b/app/controlplane/pkg/data/ent/migrate/schema.go index 497ed716e..5c84720c7 100644 --- a/app/controlplane/pkg/data/ent/migrate/schema.go +++ b/app/controlplane/pkg/data/ent/migrate/schema.go @@ -642,6 +642,7 @@ var ( {Name: "deleted_at", Type: field.TypeTime, Nullable: true}, {Name: "description", Type: field.TypeString, Nullable: true}, {Name: "organization_workflow_contracts", Type: field.TypeUUID, Nullable: true}, + {Name: "project_id", Type: field.TypeUUID, Nullable: true}, } // WorkflowContractsTable holds the schema information for the "workflow_contracts" table. WorkflowContractsTable = &schema.Table{ @@ -655,6 +656,12 @@ var ( RefColumns: []*schema.Column{OrganizationsColumns[0]}, OnDelete: schema.Cascade, }, + { + Symbol: "workflow_contracts_projects_project", + Columns: []*schema.Column{WorkflowContractsColumns[6]}, + RefColumns: []*schema.Column{ProjectsColumns[0]}, + OnDelete: schema.SetNull, + }, }, Indexes: []*schema.Index{ { @@ -662,7 +669,15 @@ var ( Unique: true, Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[5]}, Annotation: &entsql.IndexAnnotation{ - Where: "deleted_at IS NULL", + Where: "deleted_at IS NULL AND project_id IS NULL", + }, + }, + { + Name: "workflowcontract_name_project_id", + Unique: true, + Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[6]}, + Annotation: &entsql.IndexAnnotation{ + Where: "deleted_at IS NULL AND project_id IS NOT NULL", }, }, }, @@ -933,6 +948,7 @@ func init() { WorkflowsTable.ForeignKeys[2].RefTable = WorkflowContractsTable WorkflowsTable.ForeignKeys[3].RefTable = WorkflowRunsTable WorkflowContractsTable.ForeignKeys[0].RefTable = OrganizationsTable + WorkflowContractsTable.ForeignKeys[1].RefTable = ProjectsTable WorkflowContractVersionsTable.ForeignKeys[0].RefTable = WorkflowContractsTable WorkflowRunsTable.ForeignKeys[0].RefTable = ProjectVersionsTable WorkflowRunsTable.ForeignKeys[1].RefTable = WorkflowsTable diff --git a/app/controlplane/pkg/data/ent/mutation.go b/app/controlplane/pkg/data/ent/mutation.go index 736bfa536..bc1febe77 100644 --- a/app/controlplane/pkg/data/ent/mutation.go +++ b/app/controlplane/pkg/data/ent/mutation.go @@ -15262,6 +15262,8 @@ type WorkflowContractMutation struct { workflows map[uuid.UUID]struct{} removedworkflows map[uuid.UUID]struct{} clearedworkflows bool + project *uuid.UUID + clearedproject bool done bool oldValue func(context.Context) (*WorkflowContract, error) predicates []predicate.WorkflowContract @@ -15541,6 +15543,55 @@ func (m *WorkflowContractMutation) ResetDescription() { delete(m.clearedFields, workflowcontract.FieldDescription) } +// SetProjectID sets the "project_id" field. +func (m *WorkflowContractMutation) SetProjectID(u uuid.UUID) { + m.project = &u +} + +// ProjectID returns the value of the "project_id" field in the mutation. +func (m *WorkflowContractMutation) ProjectID() (r uuid.UUID, exists bool) { + v := m.project + if v == nil { + return + } + return *v, true +} + +// OldProjectID returns the old "project_id" field's value of the WorkflowContract entity. +// If the WorkflowContract object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *WorkflowContractMutation) OldProjectID(ctx context.Context) (v uuid.UUID, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldProjectID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldProjectID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldProjectID: %w", err) + } + return oldValue.ProjectID, nil +} + +// ClearProjectID clears the value of the "project_id" field. +func (m *WorkflowContractMutation) ClearProjectID() { + m.project = nil + m.clearedFields[workflowcontract.FieldProjectID] = struct{}{} +} + +// ProjectIDCleared returns if the "project_id" field was cleared in this mutation. +func (m *WorkflowContractMutation) ProjectIDCleared() bool { + _, ok := m.clearedFields[workflowcontract.FieldProjectID] + return ok +} + +// ResetProjectID resets all changes to the "project_id" field. +func (m *WorkflowContractMutation) ResetProjectID() { + m.project = nil + delete(m.clearedFields, workflowcontract.FieldProjectID) +} + // AddVersionIDs adds the "versions" edge to the WorkflowContractVersion entity by ids. func (m *WorkflowContractMutation) AddVersionIDs(ids ...uuid.UUID) { if m.versions == nil { @@ -15688,6 +15739,33 @@ func (m *WorkflowContractMutation) ResetWorkflows() { m.removedworkflows = nil } +// ClearProject clears the "project" edge to the Project entity. +func (m *WorkflowContractMutation) ClearProject() { + m.clearedproject = true + m.clearedFields[workflowcontract.FieldProjectID] = struct{}{} +} + +// ProjectCleared reports if the "project" edge to the Project entity was cleared. +func (m *WorkflowContractMutation) ProjectCleared() bool { + return m.ProjectIDCleared() || m.clearedproject +} + +// ProjectIDs returns the "project" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ProjectID instead. It exists only for internal usage by the builders. +func (m *WorkflowContractMutation) ProjectIDs() (ids []uuid.UUID) { + if id := m.project; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetProject resets all changes to the "project" edge. +func (m *WorkflowContractMutation) ResetProject() { + m.project = nil + m.clearedproject = false +} + // Where appends a list predicates to the WorkflowContractMutation builder. func (m *WorkflowContractMutation) Where(ps ...predicate.WorkflowContract) { m.predicates = append(m.predicates, ps...) @@ -15722,7 +15800,7 @@ func (m *WorkflowContractMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *WorkflowContractMutation) Fields() []string { - fields := make([]string, 0, 4) + fields := make([]string, 0, 5) if m.name != nil { fields = append(fields, workflowcontract.FieldName) } @@ -15735,6 +15813,9 @@ func (m *WorkflowContractMutation) Fields() []string { if m.description != nil { fields = append(fields, workflowcontract.FieldDescription) } + if m.project != nil { + fields = append(fields, workflowcontract.FieldProjectID) + } return fields } @@ -15751,6 +15832,8 @@ func (m *WorkflowContractMutation) Field(name string) (ent.Value, bool) { return m.DeletedAt() case workflowcontract.FieldDescription: return m.Description() + case workflowcontract.FieldProjectID: + return m.ProjectID() } return nil, false } @@ -15768,6 +15851,8 @@ func (m *WorkflowContractMutation) OldField(ctx context.Context, name string) (e return m.OldDeletedAt(ctx) case workflowcontract.FieldDescription: return m.OldDescription(ctx) + case workflowcontract.FieldProjectID: + return m.OldProjectID(ctx) } return nil, fmt.Errorf("unknown WorkflowContract field %s", name) } @@ -15805,6 +15890,13 @@ func (m *WorkflowContractMutation) SetField(name string, value ent.Value) error } m.SetDescription(v) return nil + case workflowcontract.FieldProjectID: + v, ok := value.(uuid.UUID) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetProjectID(v) + return nil } return fmt.Errorf("unknown WorkflowContract field %s", name) } @@ -15841,6 +15933,9 @@ func (m *WorkflowContractMutation) ClearedFields() []string { if m.FieldCleared(workflowcontract.FieldDescription) { fields = append(fields, workflowcontract.FieldDescription) } + if m.FieldCleared(workflowcontract.FieldProjectID) { + fields = append(fields, workflowcontract.FieldProjectID) + } return fields } @@ -15861,6 +15956,9 @@ func (m *WorkflowContractMutation) ClearField(name string) error { case workflowcontract.FieldDescription: m.ClearDescription() return nil + case workflowcontract.FieldProjectID: + m.ClearProjectID() + return nil } return fmt.Errorf("unknown WorkflowContract nullable field %s", name) } @@ -15881,13 +15979,16 @@ func (m *WorkflowContractMutation) ResetField(name string) error { case workflowcontract.FieldDescription: m.ResetDescription() return nil + case workflowcontract.FieldProjectID: + m.ResetProjectID() + return nil } return fmt.Errorf("unknown WorkflowContract field %s", name) } // AddedEdges returns all edge names that were set/added in this mutation. func (m *WorkflowContractMutation) AddedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.versions != nil { edges = append(edges, workflowcontract.EdgeVersions) } @@ -15897,6 +15998,9 @@ func (m *WorkflowContractMutation) AddedEdges() []string { if m.workflows != nil { edges = append(edges, workflowcontract.EdgeWorkflows) } + if m.project != nil { + edges = append(edges, workflowcontract.EdgeProject) + } return edges } @@ -15920,13 +16024,17 @@ func (m *WorkflowContractMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case workflowcontract.EdgeProject: + if id := m.project; id != nil { + return []ent.Value{*id} + } } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *WorkflowContractMutation) RemovedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.removedversions != nil { edges = append(edges, workflowcontract.EdgeVersions) } @@ -15958,7 +16066,7 @@ func (m *WorkflowContractMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *WorkflowContractMutation) ClearedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.clearedversions { edges = append(edges, workflowcontract.EdgeVersions) } @@ -15968,6 +16076,9 @@ func (m *WorkflowContractMutation) ClearedEdges() []string { if m.clearedworkflows { edges = append(edges, workflowcontract.EdgeWorkflows) } + if m.clearedproject { + edges = append(edges, workflowcontract.EdgeProject) + } return edges } @@ -15981,6 +16092,8 @@ func (m *WorkflowContractMutation) EdgeCleared(name string) bool { return m.clearedorganization case workflowcontract.EdgeWorkflows: return m.clearedworkflows + case workflowcontract.EdgeProject: + return m.clearedproject } return false } @@ -15992,6 +16105,9 @@ func (m *WorkflowContractMutation) ClearEdge(name string) error { case workflowcontract.EdgeOrganization: m.ClearOrganization() return nil + case workflowcontract.EdgeProject: + m.ClearProject() + return nil } return fmt.Errorf("unknown WorkflowContract unique edge %s", name) } @@ -16009,6 +16125,9 @@ func (m *WorkflowContractMutation) ResetEdge(name string) error { case workflowcontract.EdgeWorkflows: m.ResetWorkflows() return nil + case workflowcontract.EdgeProject: + m.ResetProject() + return nil } return fmt.Errorf("unknown WorkflowContract edge %s", name) } diff --git a/app/controlplane/pkg/data/ent/schema-viz.html b/app/controlplane/pkg/data/ent/schema-viz.html index 560c592f4..d0fa73e62 100644 --- a/app/controlplane/pkg/data/ent/schema-viz.html +++ b/app/controlplane/pkg/data/ent/schema-viz.html @@ -70,7 +70,11 @@ } +<<<<<<< HEAD const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"last_used_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"context\",\"type\":\"biz.OrgInvitationContext\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); +======= + const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowContract\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); +>>>>>>> 9b3f353d (feat: add columns) const nodes = new vis.DataSet((entGraph.nodes || []).map(n => ({ id: n.id, diff --git a/app/controlplane/pkg/data/ent/schema/workflowcontract.go b/app/controlplane/pkg/data/ent/schema/workflowcontract.go index 69fc1265a..ad400f107 100644 --- a/app/controlplane/pkg/data/ent/schema/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/schema/workflowcontract.go @@ -23,7 +23,6 @@ import ( "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" "entgo.io/ent/schema/index" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/google/uuid" ) @@ -45,9 +44,8 @@ func (WorkflowContract) Fields() []ent.Field { }), field.Time("deleted_at").Optional(), field.String("description").Optional(), - // If this value is set, the contract is scoped to a project or organization - field.Enum("scoped_resource_type").GoType(biz.ContractScope("")).Optional(), - field.UUID("scoped_resource_id", uuid.UUID{}).Optional(), + // if this value is not set, the contract is an organization level contract + field.UUID("project_id", uuid.UUID{}).Optional(), } } @@ -60,6 +58,7 @@ func (WorkflowContract) Edges() []ent.Edge { Unique(), // A contract can be associated to multiple workflows edge.From("workflows", Workflow.Type).Ref("contract"), + edge.To("project", Project.Type).Field("project_id").Unique(), } } @@ -67,7 +66,12 @@ func (WorkflowContract) Indexes() []ent.Index { return []ent.Index{ // names are unique within a organization and affects only to non-deleted items index.Fields("name").Edges("organization").Unique().Annotations( - entsql.IndexWhere("deleted_at IS NULL"), + entsql.IndexWhere("deleted_at IS NULL AND project_id IS NULL"), + ), + + // for project level contracts, we scope the uniqueness to the project + index.Fields("name").Edges("project").Unique().Annotations( + entsql.IndexWhere("deleted_at IS NULL AND project_id IS NOT NULL"), ), } } diff --git a/app/controlplane/pkg/data/ent/workflowcontract.go b/app/controlplane/pkg/data/ent/workflowcontract.go index f14036398..777421d58 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/workflowcontract.go @@ -10,6 +10,7 @@ import ( "entgo.io/ent" "entgo.io/ent/dialect/sql" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/google/uuid" ) @@ -27,6 +28,8 @@ type WorkflowContract struct { DeletedAt time.Time `json:"deleted_at,omitempty"` // Description holds the value of the "description" field. Description string `json:"description,omitempty"` + // ProjectID holds the value of the "project_id" field. + ProjectID uuid.UUID `json:"project_id,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the WorkflowContractQuery when eager-loading is set. Edges WorkflowContractEdges `json:"edges"` @@ -42,9 +45,11 @@ type WorkflowContractEdges struct { Organization *Organization `json:"organization,omitempty"` // Workflows holds the value of the workflows edge. Workflows []*Workflow `json:"workflows,omitempty"` + // Project holds the value of the project edge. + Project *Project `json:"project,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [3]bool + loadedTypes [4]bool } // VersionsOrErr returns the Versions value or an error if the edge @@ -76,6 +81,17 @@ func (e WorkflowContractEdges) WorkflowsOrErr() ([]*Workflow, error) { return nil, &NotLoadedError{edge: "workflows"} } +// ProjectOrErr returns the Project value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e WorkflowContractEdges) ProjectOrErr() (*Project, error) { + if e.Project != nil { + return e.Project, nil + } else if e.loadedTypes[3] { + return nil, &NotFoundError{label: project.Label} + } + return nil, &NotLoadedError{edge: "project"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*WorkflowContract) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) @@ -85,7 +101,7 @@ func (*WorkflowContract) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullString) case workflowcontract.FieldCreatedAt, workflowcontract.FieldDeletedAt: values[i] = new(sql.NullTime) - case workflowcontract.FieldID: + case workflowcontract.FieldID, workflowcontract.FieldProjectID: values[i] = new(uuid.UUID) case workflowcontract.ForeignKeys[0]: // organization_workflow_contracts values[i] = &sql.NullScanner{S: new(uuid.UUID)} @@ -134,6 +150,12 @@ func (wc *WorkflowContract) assignValues(columns []string, values []any) error { } else if value.Valid { wc.Description = value.String } + case workflowcontract.FieldProjectID: + if value, ok := values[i].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field project_id", values[i]) + } else if value != nil { + wc.ProjectID = *value + } case workflowcontract.ForeignKeys[0]: if value, ok := values[i].(*sql.NullScanner); !ok { return fmt.Errorf("unexpected type %T for field organization_workflow_contracts", values[i]) @@ -169,6 +191,11 @@ func (wc *WorkflowContract) QueryWorkflows() *WorkflowQuery { return NewWorkflowContractClient(wc.config).QueryWorkflows(wc) } +// QueryProject queries the "project" edge of the WorkflowContract entity. +func (wc *WorkflowContract) QueryProject() *ProjectQuery { + return NewWorkflowContractClient(wc.config).QueryProject(wc) +} + // Update returns a builder for updating this WorkflowContract. // Note that you need to call WorkflowContract.Unwrap() before calling this method if this WorkflowContract // was returned from a transaction, and the transaction was committed or rolled back. @@ -203,6 +230,9 @@ func (wc *WorkflowContract) String() string { builder.WriteString(", ") builder.WriteString("description=") builder.WriteString(wc.Description) + builder.WriteString(", ") + builder.WriteString("project_id=") + builder.WriteString(fmt.Sprintf("%v", wc.ProjectID)) builder.WriteByte(')') return builder.String() } diff --git a/app/controlplane/pkg/data/ent/workflowcontract/where.go b/app/controlplane/pkg/data/ent/workflowcontract/where.go index ad978a7b4..8f83a3076 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract/where.go +++ b/app/controlplane/pkg/data/ent/workflowcontract/where.go @@ -76,6 +76,11 @@ func Description(v string) predicate.WorkflowContract { return predicate.WorkflowContract(sql.FieldEQ(FieldDescription, v)) } +// ProjectID applies equality check predicate on the "project_id" field. It's identical to ProjectIDEQ. +func ProjectID(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldEQ(FieldProjectID, v)) +} + // NameEQ applies the EQ predicate on the "name" field. func NameEQ(v string) predicate.WorkflowContract { return predicate.WorkflowContract(sql.FieldEQ(FieldName, v)) @@ -306,6 +311,36 @@ func DescriptionContainsFold(v string) predicate.WorkflowContract { return predicate.WorkflowContract(sql.FieldContainsFold(FieldDescription, v)) } +// ProjectIDEQ applies the EQ predicate on the "project_id" field. +func ProjectIDEQ(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldEQ(FieldProjectID, v)) +} + +// ProjectIDNEQ applies the NEQ predicate on the "project_id" field. +func ProjectIDNEQ(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNEQ(FieldProjectID, v)) +} + +// ProjectIDIn applies the In predicate on the "project_id" field. +func ProjectIDIn(vs ...uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldIn(FieldProjectID, vs...)) +} + +// ProjectIDNotIn applies the NotIn predicate on the "project_id" field. +func ProjectIDNotIn(vs ...uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNotIn(FieldProjectID, vs...)) +} + +// ProjectIDIsNil applies the IsNil predicate on the "project_id" field. +func ProjectIDIsNil() predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldIsNull(FieldProjectID)) +} + +// ProjectIDNotNil applies the NotNil predicate on the "project_id" field. +func ProjectIDNotNil() predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNotNull(FieldProjectID)) +} + // HasVersions applies the HasEdge predicate on the "versions" edge. func HasVersions() predicate.WorkflowContract { return predicate.WorkflowContract(func(s *sql.Selector) { @@ -375,6 +410,29 @@ func HasWorkflowsWith(preds ...predicate.Workflow) predicate.WorkflowContract { }) } +// HasProject applies the HasEdge predicate on the "project" edge. +func HasProject() predicate.WorkflowContract { + return predicate.WorkflowContract(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, ProjectTable, ProjectColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasProjectWith applies the HasEdge predicate on the "project" edge with a given conditions (other predicates). +func HasProjectWith(preds ...predicate.Project) predicate.WorkflowContract { + return predicate.WorkflowContract(func(s *sql.Selector) { + step := newProjectStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.WorkflowContract) predicate.WorkflowContract { return predicate.WorkflowContract(sql.AndPredicates(predicates...)) diff --git a/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go b/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go index 834bb2a81..9cb71a60f 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go @@ -23,12 +23,16 @@ const ( FieldDeletedAt = "deleted_at" // FieldDescription holds the string denoting the description field in the database. FieldDescription = "description" + // FieldProjectID holds the string denoting the project_id field in the database. + FieldProjectID = "project_id" // EdgeVersions holds the string denoting the versions edge name in mutations. EdgeVersions = "versions" // EdgeOrganization holds the string denoting the organization edge name in mutations. EdgeOrganization = "organization" // EdgeWorkflows holds the string denoting the workflows edge name in mutations. EdgeWorkflows = "workflows" + // EdgeProject holds the string denoting the project edge name in mutations. + EdgeProject = "project" // Table holds the table name of the workflowcontract in the database. Table = "workflow_contracts" // VersionsTable is the table that holds the versions relation/edge. @@ -52,6 +56,13 @@ const ( WorkflowsInverseTable = "workflows" // WorkflowsColumn is the table column denoting the workflows relation/edge. WorkflowsColumn = "workflow_contract" + // ProjectTable is the table that holds the project relation/edge. + ProjectTable = "workflow_contracts" + // ProjectInverseTable is the table name for the Project entity. + // It exists in this package in order to avoid circular dependency with the "project" package. + ProjectInverseTable = "projects" + // ProjectColumn is the table column denoting the project relation/edge. + ProjectColumn = "project_id" ) // Columns holds all SQL columns for workflowcontract fields. @@ -61,6 +72,7 @@ var Columns = []string{ FieldCreatedAt, FieldDeletedAt, FieldDescription, + FieldProjectID, } // ForeignKeys holds the SQL foreign-keys that are owned by the "workflow_contracts" @@ -119,6 +131,11 @@ func ByDescription(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldDescription, opts...).ToFunc() } +// ByProjectID orders the results by the project_id field. +func ByProjectID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldProjectID, opts...).ToFunc() +} + // ByVersionsCount orders the results by versions count. func ByVersionsCount(opts ...sql.OrderTermOption) OrderOption { return func(s *sql.Selector) { @@ -153,6 +170,13 @@ func ByWorkflows(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { sqlgraph.OrderByNeighborTerms(s, newWorkflowsStep(), append([]sql.OrderTerm{term}, terms...)...) } } + +// ByProjectField orders the results by project field. +func ByProjectField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newProjectStep(), sql.OrderByField(field, opts...)) + } +} func newVersionsStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -174,3 +198,10 @@ func newWorkflowsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, true, WorkflowsTable, WorkflowsColumn), ) } +func newProjectStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ProjectInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, ProjectTable, ProjectColumn), + ) +} diff --git a/app/controlplane/pkg/data/ent/workflowcontract_create.go b/app/controlplane/pkg/data/ent/workflowcontract_create.go index 9d73e37d8..811d19456 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_create.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_create.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -75,6 +76,20 @@ func (wcc *WorkflowContractCreate) SetNillableDescription(s *string) *WorkflowCo return wcc } +// SetProjectID sets the "project_id" field. +func (wcc *WorkflowContractCreate) SetProjectID(u uuid.UUID) *WorkflowContractCreate { + wcc.mutation.SetProjectID(u) + return wcc +} + +// SetNillableProjectID sets the "project_id" field if the given value is not nil. +func (wcc *WorkflowContractCreate) SetNillableProjectID(u *uuid.UUID) *WorkflowContractCreate { + if u != nil { + wcc.SetProjectID(*u) + } + return wcc +} + // SetID sets the "id" field. func (wcc *WorkflowContractCreate) SetID(u uuid.UUID) *WorkflowContractCreate { wcc.mutation.SetID(u) @@ -138,6 +153,11 @@ func (wcc *WorkflowContractCreate) AddWorkflows(w ...*Workflow) *WorkflowContrac return wcc.AddWorkflowIDs(ids...) } +// SetProject sets the "project" edge to the Project entity. +func (wcc *WorkflowContractCreate) SetProject(p *Project) *WorkflowContractCreate { + return wcc.SetProjectID(p.ID) +} + // Mutation returns the WorkflowContractMutation object of the builder. func (wcc *WorkflowContractCreate) Mutation() *WorkflowContractMutation { return wcc.mutation @@ -292,6 +312,23 @@ func (wcc *WorkflowContractCreate) createSpec() (*WorkflowContract, *sqlgraph.Cr } _spec.Edges = append(_spec.Edges, edge) } + if nodes := wcc.mutation.ProjectIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: workflowcontract.ProjectTable, + Columns: []string{workflowcontract.ProjectColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.ProjectID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } @@ -380,6 +417,24 @@ func (u *WorkflowContractUpsert) ClearDescription() *WorkflowContractUpsert { return u } +// SetProjectID sets the "project_id" field. +func (u *WorkflowContractUpsert) SetProjectID(v uuid.UUID) *WorkflowContractUpsert { + u.Set(workflowcontract.FieldProjectID, v) + return u +} + +// UpdateProjectID sets the "project_id" field to the value that was provided on create. +func (u *WorkflowContractUpsert) UpdateProjectID() *WorkflowContractUpsert { + u.SetExcluded(workflowcontract.FieldProjectID) + return u +} + +// ClearProjectID clears the value of the "project_id" field. +func (u *WorkflowContractUpsert) ClearProjectID() *WorkflowContractUpsert { + u.SetNull(workflowcontract.FieldProjectID) + return u +} + // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. // Using this option is equivalent to using: // @@ -476,6 +531,27 @@ func (u *WorkflowContractUpsertOne) ClearDescription() *WorkflowContractUpsertOn }) } +// SetProjectID sets the "project_id" field. +func (u *WorkflowContractUpsertOne) SetProjectID(v uuid.UUID) *WorkflowContractUpsertOne { + return u.Update(func(s *WorkflowContractUpsert) { + s.SetProjectID(v) + }) +} + +// UpdateProjectID sets the "project_id" field to the value that was provided on create. +func (u *WorkflowContractUpsertOne) UpdateProjectID() *WorkflowContractUpsertOne { + return u.Update(func(s *WorkflowContractUpsert) { + s.UpdateProjectID() + }) +} + +// ClearProjectID clears the value of the "project_id" field. +func (u *WorkflowContractUpsertOne) ClearProjectID() *WorkflowContractUpsertOne { + return u.Update(func(s *WorkflowContractUpsert) { + s.ClearProjectID() + }) +} + // Exec executes the query. func (u *WorkflowContractUpsertOne) Exec(ctx context.Context) error { if len(u.create.conflict) == 0 { @@ -739,6 +815,27 @@ func (u *WorkflowContractUpsertBulk) ClearDescription() *WorkflowContractUpsertB }) } +// SetProjectID sets the "project_id" field. +func (u *WorkflowContractUpsertBulk) SetProjectID(v uuid.UUID) *WorkflowContractUpsertBulk { + return u.Update(func(s *WorkflowContractUpsert) { + s.SetProjectID(v) + }) +} + +// UpdateProjectID sets the "project_id" field to the value that was provided on create. +func (u *WorkflowContractUpsertBulk) UpdateProjectID() *WorkflowContractUpsertBulk { + return u.Update(func(s *WorkflowContractUpsert) { + s.UpdateProjectID() + }) +} + +// ClearProjectID clears the value of the "project_id" field. +func (u *WorkflowContractUpsertBulk) ClearProjectID() *WorkflowContractUpsertBulk { + return u.Update(func(s *WorkflowContractUpsert) { + s.ClearProjectID() + }) +} + // Exec executes the query. func (u *WorkflowContractUpsertBulk) Exec(ctx context.Context) error { if u.create.err != nil { diff --git a/app/controlplane/pkg/data/ent/workflowcontract_query.go b/app/controlplane/pkg/data/ent/workflowcontract_query.go index 1d2e2652c..6056b7dde 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_query.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_query.go @@ -15,6 +15,7 @@ import ( "entgo.io/ent/schema/field" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -31,6 +32,7 @@ type WorkflowContractQuery struct { withVersions *WorkflowContractVersionQuery withOrganization *OrganizationQuery withWorkflows *WorkflowQuery + withProject *ProjectQuery withFKs bool modifiers []func(*sql.Selector) // intermediate query (i.e. traversal path). @@ -135,6 +137,28 @@ func (wcq *WorkflowContractQuery) QueryWorkflows() *WorkflowQuery { return query } +// QueryProject chains the current query on the "project" edge. +func (wcq *WorkflowContractQuery) QueryProject() *ProjectQuery { + query := (&ProjectClient{config: wcq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := wcq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := wcq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, selector), + sqlgraph.To(project.Table, project.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, workflowcontract.ProjectTable, workflowcontract.ProjectColumn), + ) + fromU = sqlgraph.SetNeighbors(wcq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first WorkflowContract entity from the query. // Returns a *NotFoundError when no WorkflowContract was found. func (wcq *WorkflowContractQuery) First(ctx context.Context) (*WorkflowContract, error) { @@ -330,6 +354,7 @@ func (wcq *WorkflowContractQuery) Clone() *WorkflowContractQuery { withVersions: wcq.withVersions.Clone(), withOrganization: wcq.withOrganization.Clone(), withWorkflows: wcq.withWorkflows.Clone(), + withProject: wcq.withProject.Clone(), // clone intermediate query. sql: wcq.sql.Clone(), path: wcq.path, @@ -370,6 +395,17 @@ func (wcq *WorkflowContractQuery) WithWorkflows(opts ...func(*WorkflowQuery)) *W return wcq } +// WithProject tells the query-builder to eager-load the nodes that are connected to +// the "project" edge. The optional arguments are used to configure the query builder of the edge. +func (wcq *WorkflowContractQuery) WithProject(opts ...func(*ProjectQuery)) *WorkflowContractQuery { + query := (&ProjectClient{config: wcq.config}).Query() + for _, opt := range opts { + opt(query) + } + wcq.withProject = query + return wcq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -449,10 +485,11 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook nodes = []*WorkflowContract{} withFKs = wcq.withFKs _spec = wcq.querySpec() - loadedTypes = [3]bool{ + loadedTypes = [4]bool{ wcq.withVersions != nil, wcq.withOrganization != nil, wcq.withWorkflows != nil, + wcq.withProject != nil, } ) if wcq.withOrganization != nil { @@ -502,6 +539,12 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook return nil, err } } + if query := wcq.withProject; query != nil { + if err := wcq.loadProject(ctx, query, nodes, nil, + func(n *WorkflowContract, e *Project) { n.Edges.Project = e }); err != nil { + return nil, err + } + } return nodes, nil } @@ -599,6 +642,35 @@ func (wcq *WorkflowContractQuery) loadWorkflows(ctx context.Context, query *Work } return nil } +func (wcq *WorkflowContractQuery) loadProject(ctx context.Context, query *ProjectQuery, nodes []*WorkflowContract, init func(*WorkflowContract), assign func(*WorkflowContract, *Project)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*WorkflowContract) + for i := range nodes { + fk := nodes[i].ProjectID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(project.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "project_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} func (wcq *WorkflowContractQuery) sqlCount(ctx context.Context) (int, error) { _spec := wcq.querySpec() @@ -628,6 +700,9 @@ func (wcq *WorkflowContractQuery) querySpec() *sqlgraph.QuerySpec { _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) } } + if wcq.withProject != nil { + _spec.Node.AddColumnOnce(workflowcontract.FieldProjectID) + } } if ps := wcq.predicates; len(ps) > 0 { _spec.Predicate = func(selector *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/workflowcontract_update.go b/app/controlplane/pkg/data/ent/workflowcontract_update.go index d83e6f222..3b4059802 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_update.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_update.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/schema/field" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -73,6 +74,26 @@ func (wcu *WorkflowContractUpdate) ClearDescription() *WorkflowContractUpdate { return wcu } +// SetProjectID sets the "project_id" field. +func (wcu *WorkflowContractUpdate) SetProjectID(u uuid.UUID) *WorkflowContractUpdate { + wcu.mutation.SetProjectID(u) + return wcu +} + +// SetNillableProjectID sets the "project_id" field if the given value is not nil. +func (wcu *WorkflowContractUpdate) SetNillableProjectID(u *uuid.UUID) *WorkflowContractUpdate { + if u != nil { + wcu.SetProjectID(*u) + } + return wcu +} + +// ClearProjectID clears the value of the "project_id" field. +func (wcu *WorkflowContractUpdate) ClearProjectID() *WorkflowContractUpdate { + wcu.mutation.ClearProjectID() + return wcu +} + // AddVersionIDs adds the "versions" edge to the WorkflowContractVersion entity by IDs. func (wcu *WorkflowContractUpdate) AddVersionIDs(ids ...uuid.UUID) *WorkflowContractUpdate { wcu.mutation.AddVersionIDs(ids...) @@ -122,6 +143,11 @@ func (wcu *WorkflowContractUpdate) AddWorkflows(w ...*Workflow) *WorkflowContrac return wcu.AddWorkflowIDs(ids...) } +// SetProject sets the "project" edge to the Project entity. +func (wcu *WorkflowContractUpdate) SetProject(p *Project) *WorkflowContractUpdate { + return wcu.SetProjectID(p.ID) +} + // Mutation returns the WorkflowContractMutation object of the builder. func (wcu *WorkflowContractUpdate) Mutation() *WorkflowContractMutation { return wcu.mutation @@ -175,6 +201,12 @@ func (wcu *WorkflowContractUpdate) RemoveWorkflows(w ...*Workflow) *WorkflowCont return wcu.RemoveWorkflowIDs(ids...) } +// ClearProject clears the "project" edge to the Project entity. +func (wcu *WorkflowContractUpdate) ClearProject() *WorkflowContractUpdate { + wcu.mutation.ClearProject() + return wcu +} + // Save executes the query and returns the number of nodes affected by the update operation. func (wcu *WorkflowContractUpdate) Save(ctx context.Context) (int, error) { return withHooks(ctx, wcu.sqlSave, wcu.mutation, wcu.hooks) @@ -348,6 +380,35 @@ func (wcu *WorkflowContractUpdate) sqlSave(ctx context.Context) (n int, err erro } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if wcu.mutation.ProjectCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: workflowcontract.ProjectTable, + Columns: []string{workflowcontract.ProjectColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := wcu.mutation.ProjectIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: workflowcontract.ProjectTable, + Columns: []string{workflowcontract.ProjectColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _spec.AddModifiers(wcu.modifiers...) if n, err = sqlgraph.UpdateNodes(ctx, wcu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { @@ -410,6 +471,26 @@ func (wcuo *WorkflowContractUpdateOne) ClearDescription() *WorkflowContractUpdat return wcuo } +// SetProjectID sets the "project_id" field. +func (wcuo *WorkflowContractUpdateOne) SetProjectID(u uuid.UUID) *WorkflowContractUpdateOne { + wcuo.mutation.SetProjectID(u) + return wcuo +} + +// SetNillableProjectID sets the "project_id" field if the given value is not nil. +func (wcuo *WorkflowContractUpdateOne) SetNillableProjectID(u *uuid.UUID) *WorkflowContractUpdateOne { + if u != nil { + wcuo.SetProjectID(*u) + } + return wcuo +} + +// ClearProjectID clears the value of the "project_id" field. +func (wcuo *WorkflowContractUpdateOne) ClearProjectID() *WorkflowContractUpdateOne { + wcuo.mutation.ClearProjectID() + return wcuo +} + // AddVersionIDs adds the "versions" edge to the WorkflowContractVersion entity by IDs. func (wcuo *WorkflowContractUpdateOne) AddVersionIDs(ids ...uuid.UUID) *WorkflowContractUpdateOne { wcuo.mutation.AddVersionIDs(ids...) @@ -459,6 +540,11 @@ func (wcuo *WorkflowContractUpdateOne) AddWorkflows(w ...*Workflow) *WorkflowCon return wcuo.AddWorkflowIDs(ids...) } +// SetProject sets the "project" edge to the Project entity. +func (wcuo *WorkflowContractUpdateOne) SetProject(p *Project) *WorkflowContractUpdateOne { + return wcuo.SetProjectID(p.ID) +} + // Mutation returns the WorkflowContractMutation object of the builder. func (wcuo *WorkflowContractUpdateOne) Mutation() *WorkflowContractMutation { return wcuo.mutation @@ -512,6 +598,12 @@ func (wcuo *WorkflowContractUpdateOne) RemoveWorkflows(w ...*Workflow) *Workflow return wcuo.RemoveWorkflowIDs(ids...) } +// ClearProject clears the "project" edge to the Project entity. +func (wcuo *WorkflowContractUpdateOne) ClearProject() *WorkflowContractUpdateOne { + wcuo.mutation.ClearProject() + return wcuo +} + // Where appends a list predicates to the WorkflowContractUpdate builder. func (wcuo *WorkflowContractUpdateOne) Where(ps ...predicate.WorkflowContract) *WorkflowContractUpdateOne { wcuo.mutation.Where(ps...) @@ -715,6 +807,35 @@ func (wcuo *WorkflowContractUpdateOne) sqlSave(ctx context.Context) (_node *Work } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if wcuo.mutation.ProjectCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: workflowcontract.ProjectTable, + Columns: []string{workflowcontract.ProjectColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := wcuo.mutation.ProjectIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: workflowcontract.ProjectTable, + Columns: []string{workflowcontract.ProjectColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _spec.AddModifiers(wcuo.modifiers...) _node = &WorkflowContract{config: wcuo.config} _spec.Assign = _node.assignValues From 5dc5b15b0511a6ecdaa3cfaf3034145b52c85000 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Fri, 4 Jul 2025 11:06:27 +0200 Subject: [PATCH 03/24] fix tests Signed-off-by: Miguel Martinez --- app/controlplane/pkg/biz/workflowcontract.go | 18 + app/controlplane/pkg/data/ent/client.go | 32 -- .../ent/migrate/migrations/20250703212753.sql | 8 - .../pkg/data/ent/migrate/migrations/atlas.sum | 8 + .../pkg/data/ent/migrate/schema.go | 26 +- app/controlplane/pkg/data/ent/mutation.go | 296 ++++++++-------- app/controlplane/pkg/data/ent/schema-viz.html | 4 + .../pkg/data/ent/schema/workflowcontract.go | 19 +- .../pkg/data/ent/workflowcontract.go | 72 ++-- .../pkg/data/ent/workflowcontract/where.go | 149 ++++---- .../ent/workflowcontract/workflowcontract.go | 78 ++--- .../pkg/data/ent/workflowcontract_create.go | 214 +++++++----- .../pkg/data/ent/workflowcontract_query.go | 185 +--------- .../pkg/data/ent/workflowcontract_update.go | 317 ++++++------------ go.sum | 1 + 15 files changed, 552 insertions(+), 875 deletions(-) delete mode 100644 app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index 96f3f7ad8..c835a4fa6 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -594,3 +594,21 @@ func SchemaToRawContract(contract *schemav1.CraftingSchema) (*Contract, error) { return &Contract{Raw: r, Format: unmarshal.RawFormatJSON, Schema: contract}, nil } + +// ContractScope represents a polymorphic relationship between a contract and a project or organization +type ContractScope string + +const ( + ContractScopeProject ContractScope = "project" + ContractScopeOrg ContractScope = "org" +) + +// Values implement https://pkg.go.dev/entgo.io/ent/schema/field#EnumValues +func (ContractScope) Values() (values []string) { + values = append(values, + string(ContractScopeProject), + string(ContractScopeOrg), + ) + + return +} diff --git a/app/controlplane/pkg/data/ent/client.go b/app/controlplane/pkg/data/ent/client.go index a529e22d8..5d44cdfa1 100644 --- a/app/controlplane/pkg/data/ent/client.go +++ b/app/controlplane/pkg/data/ent/client.go @@ -3535,22 +3535,6 @@ func (c *WorkflowContractClient) QueryVersions(wc *WorkflowContract) *WorkflowCo return query } -// QueryOrganization queries the organization edge of a WorkflowContract. -func (c *WorkflowContractClient) QueryOrganization(wc *WorkflowContract) *OrganizationQuery { - query := (&OrganizationClient{config: c.config}).Query() - query.path = func(context.Context) (fromV *sql.Selector, _ error) { - id := wc.ID - step := sqlgraph.NewStep( - sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, id), - sqlgraph.To(organization.Table, organization.FieldID), - sqlgraph.Edge(sqlgraph.M2O, true, workflowcontract.OrganizationTable, workflowcontract.OrganizationColumn), - ) - fromV = sqlgraph.Neighbors(wc.driver.Dialect(), step) - return fromV, nil - } - return query -} - // QueryWorkflows queries the workflows edge of a WorkflowContract. func (c *WorkflowContractClient) QueryWorkflows(wc *WorkflowContract) *WorkflowQuery { query := (&WorkflowClient{config: c.config}).Query() @@ -3567,22 +3551,6 @@ func (c *WorkflowContractClient) QueryWorkflows(wc *WorkflowContract) *WorkflowQ return query } -// QueryProject queries the project edge of a WorkflowContract. -func (c *WorkflowContractClient) QueryProject(wc *WorkflowContract) *ProjectQuery { - query := (&ProjectClient{config: c.config}).Query() - query.path = func(context.Context) (fromV *sql.Selector, _ error) { - id := wc.ID - step := sqlgraph.NewStep( - sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, id), - sqlgraph.To(project.Table, project.FieldID), - sqlgraph.Edge(sqlgraph.M2O, false, workflowcontract.ProjectTable, workflowcontract.ProjectColumn), - ) - fromV = sqlgraph.Neighbors(wc.driver.Dialect(), step) - return fromV, nil - } - return query -} - // Hooks returns the client hooks. func (c *WorkflowContractClient) Hooks() []Hook { return c.hooks.WorkflowContract diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql deleted file mode 100644 index 95c413acd..000000000 --- a/app/controlplane/pkg/data/ent/migrate/migrations/20250703212753.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Drop index "workflowcontract_name_organization_workflow_contracts" from table: "workflow_contracts" -DROP INDEX "workflowcontract_name_organization_workflow_contracts"; --- Modify "workflow_contracts" table -ALTER TABLE "workflow_contracts" ADD COLUMN "project_id" uuid NULL; --- Create index "workflowcontract_name_organization_workflow_contracts" to table: "workflow_contracts" -CREATE UNIQUE INDEX "workflowcontract_name_organization_workflow_contracts" ON "workflow_contracts" ("name", "organization_workflow_contracts") WHERE ((deleted_at IS NULL) AND (project_id IS NULL)); --- Create index "workflowcontract_name_project_id" to table: "workflow_contracts" -CREATE UNIQUE INDEX "workflowcontract_name_project_id" ON "workflow_contracts" ("name", "project_id") WHERE ((deleted_at IS NULL) AND (project_id IS NOT NULL)); diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index fa71a0d66..a74777b78 100644 --- a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum +++ b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum @@ -1,8 +1,12 @@ <<<<<<< HEAD +<<<<<<< HEAD h1:pewT4SIwZxo6E95TRjOvYvsO2AvVZDBRPljhvi6yN3c= ======= h1:Nqn7kGmL5Hba+3tAbxdDjH6+KvSmunyHZuDIthoGQiU= >>>>>>> 9b3f353d (feat: add columns) +======= +h1:oR9RWah9qFLH+GgYn2+C1UpTH2Z82Zj36QLGWRG5X+4= +>>>>>>> 7a8275ef (fix tests) 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -102,4 +106,8 @@ h1:Nqn7kGmL5Hba+3tAbxdDjH6+KvSmunyHZuDIthoGQiU= 20250704090359.sql h1:a0ksfjy2dtzviJL16HbC4eT1xBxy2qFH5mNFOpYlUrA= ======= 20250703212753.sql h1:Hr4sKsM+tlPRp0I9qRLnnkVUNpZ4xTH/XOQJ5nDdbek= +<<<<<<< HEAD >>>>>>> 9b3f353d (feat: add columns) +======= +20250704090525.sql h1:VO/Kf+I0GJDfL2FaHk36YZ7f6uY9VrHjrP3EuQAidHM= +>>>>>>> 7a8275ef (fix tests) diff --git a/app/controlplane/pkg/data/ent/migrate/schema.go b/app/controlplane/pkg/data/ent/migrate/schema.go index 5c84720c7..205dcce76 100644 --- a/app/controlplane/pkg/data/ent/migrate/schema.go +++ b/app/controlplane/pkg/data/ent/migrate/schema.go @@ -641,8 +641,9 @@ var ( {Name: "created_at", Type: field.TypeTime, Default: "CURRENT_TIMESTAMP"}, {Name: "deleted_at", Type: field.TypeTime, Nullable: true}, {Name: "description", Type: field.TypeString, Nullable: true}, + {Name: "scoped_resource_type", Type: field.TypeEnum, Nullable: true, Enums: []string{"project", "org"}}, + {Name: "scoped_resource_id", Type: field.TypeUUID, Nullable: true}, {Name: "organization_workflow_contracts", Type: field.TypeUUID, Nullable: true}, - {Name: "project_id", Type: field.TypeUUID, Nullable: true}, } // WorkflowContractsTable holds the schema information for the "workflow_contracts" table. WorkflowContractsTable = &schema.Table{ @@ -652,32 +653,18 @@ var ( ForeignKeys: []*schema.ForeignKey{ { Symbol: "workflow_contracts_organizations_workflow_contracts", - Columns: []*schema.Column{WorkflowContractsColumns[5]}, + Columns: []*schema.Column{WorkflowContractsColumns[7]}, RefColumns: []*schema.Column{OrganizationsColumns[0]}, OnDelete: schema.Cascade, }, - { - Symbol: "workflow_contracts_projects_project", - Columns: []*schema.Column{WorkflowContractsColumns[6]}, - RefColumns: []*schema.Column{ProjectsColumns[0]}, - OnDelete: schema.SetNull, - }, }, Indexes: []*schema.Index{ { - Name: "workflowcontract_name_organization_workflow_contracts", + Name: "workflowcontract_name_scoped_resource_type_scoped_resource_id", Unique: true, - Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[5]}, + Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[5], WorkflowContractsColumns[6]}, Annotation: &entsql.IndexAnnotation{ - Where: "deleted_at IS NULL AND project_id IS NULL", - }, - }, - { - Name: "workflowcontract_name_project_id", - Unique: true, - Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[6]}, - Annotation: &entsql.IndexAnnotation{ - Where: "deleted_at IS NULL AND project_id IS NOT NULL", + Where: "deleted_at IS NULL", }, }, }, @@ -948,7 +935,6 @@ func init() { WorkflowsTable.ForeignKeys[2].RefTable = WorkflowContractsTable WorkflowsTable.ForeignKeys[3].RefTable = WorkflowRunsTable WorkflowContractsTable.ForeignKeys[0].RefTable = OrganizationsTable - WorkflowContractsTable.ForeignKeys[1].RefTable = ProjectsTable WorkflowContractVersionsTable.ForeignKeys[0].RefTable = WorkflowContractsTable WorkflowRunsTable.ForeignKeys[0].RefTable = ProjectVersionsTable WorkflowRunsTable.ForeignKeys[1].RefTable = WorkflowsTable diff --git a/app/controlplane/pkg/data/ent/mutation.go b/app/controlplane/pkg/data/ent/mutation.go index bc1febe77..376a8d024 100644 --- a/app/controlplane/pkg/data/ent/mutation.go +++ b/app/controlplane/pkg/data/ent/mutation.go @@ -15246,27 +15246,25 @@ func (m *WorkflowMutation) ResetEdge(name string) error { // WorkflowContractMutation represents an operation that mutates the WorkflowContract nodes in the graph. type WorkflowContractMutation struct { config - op Op - typ string - id *uuid.UUID - name *string - created_at *time.Time - deleted_at *time.Time - description *string - clearedFields map[string]struct{} - versions map[uuid.UUID]struct{} - removedversions map[uuid.UUID]struct{} - clearedversions bool - organization *uuid.UUID - clearedorganization bool - workflows map[uuid.UUID]struct{} - removedworkflows map[uuid.UUID]struct{} - clearedworkflows bool - project *uuid.UUID - clearedproject bool - done bool - oldValue func(context.Context) (*WorkflowContract, error) - predicates []predicate.WorkflowContract + op Op + typ string + id *uuid.UUID + name *string + created_at *time.Time + deleted_at *time.Time + description *string + scoped_resource_type *biz.ContractScope + scoped_resource_id *uuid.UUID + clearedFields map[string]struct{} + versions map[uuid.UUID]struct{} + removedversions map[uuid.UUID]struct{} + clearedversions bool + workflows map[uuid.UUID]struct{} + removedworkflows map[uuid.UUID]struct{} + clearedworkflows bool + done bool + oldValue func(context.Context) (*WorkflowContract, error) + predicates []predicate.WorkflowContract } var _ ent.Mutation = (*WorkflowContractMutation)(nil) @@ -15543,53 +15541,102 @@ func (m *WorkflowContractMutation) ResetDescription() { delete(m.clearedFields, workflowcontract.FieldDescription) } -// SetProjectID sets the "project_id" field. -func (m *WorkflowContractMutation) SetProjectID(u uuid.UUID) { - m.project = &u +// SetScopedResourceType sets the "scoped_resource_type" field. +func (m *WorkflowContractMutation) SetScopedResourceType(bs biz.ContractScope) { + m.scoped_resource_type = &bs } -// ProjectID returns the value of the "project_id" field in the mutation. -func (m *WorkflowContractMutation) ProjectID() (r uuid.UUID, exists bool) { - v := m.project +// ScopedResourceType returns the value of the "scoped_resource_type" field in the mutation. +func (m *WorkflowContractMutation) ScopedResourceType() (r biz.ContractScope, exists bool) { + v := m.scoped_resource_type if v == nil { return } return *v, true } -// OldProjectID returns the old "project_id" field's value of the WorkflowContract entity. +// OldScopedResourceType returns the old "scoped_resource_type" field's value of the WorkflowContract entity. // If the WorkflowContract object wasn't provided to the builder, the object is fetched from the database. // An error is returned if the mutation operation is not UpdateOne, or the database query fails. -func (m *WorkflowContractMutation) OldProjectID(ctx context.Context) (v uuid.UUID, err error) { +func (m *WorkflowContractMutation) OldScopedResourceType(ctx context.Context) (v biz.ContractScope, err error) { if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldProjectID is only allowed on UpdateOne operations") + return v, errors.New("OldScopedResourceType is only allowed on UpdateOne operations") } if m.id == nil || m.oldValue == nil { - return v, errors.New("OldProjectID requires an ID field in the mutation") + return v, errors.New("OldScopedResourceType requires an ID field in the mutation") } oldValue, err := m.oldValue(ctx) if err != nil { - return v, fmt.Errorf("querying old value for OldProjectID: %w", err) + return v, fmt.Errorf("querying old value for OldScopedResourceType: %w", err) } - return oldValue.ProjectID, nil + return oldValue.ScopedResourceType, nil } -// ClearProjectID clears the value of the "project_id" field. -func (m *WorkflowContractMutation) ClearProjectID() { - m.project = nil - m.clearedFields[workflowcontract.FieldProjectID] = struct{}{} +// ClearScopedResourceType clears the value of the "scoped_resource_type" field. +func (m *WorkflowContractMutation) ClearScopedResourceType() { + m.scoped_resource_type = nil + m.clearedFields[workflowcontract.FieldScopedResourceType] = struct{}{} } -// ProjectIDCleared returns if the "project_id" field was cleared in this mutation. -func (m *WorkflowContractMutation) ProjectIDCleared() bool { - _, ok := m.clearedFields[workflowcontract.FieldProjectID] +// ScopedResourceTypeCleared returns if the "scoped_resource_type" field was cleared in this mutation. +func (m *WorkflowContractMutation) ScopedResourceTypeCleared() bool { + _, ok := m.clearedFields[workflowcontract.FieldScopedResourceType] return ok } -// ResetProjectID resets all changes to the "project_id" field. -func (m *WorkflowContractMutation) ResetProjectID() { - m.project = nil - delete(m.clearedFields, workflowcontract.FieldProjectID) +// ResetScopedResourceType resets all changes to the "scoped_resource_type" field. +func (m *WorkflowContractMutation) ResetScopedResourceType() { + m.scoped_resource_type = nil + delete(m.clearedFields, workflowcontract.FieldScopedResourceType) +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (m *WorkflowContractMutation) SetScopedResourceID(u uuid.UUID) { + m.scoped_resource_id = &u +} + +// ScopedResourceID returns the value of the "scoped_resource_id" field in the mutation. +func (m *WorkflowContractMutation) ScopedResourceID() (r uuid.UUID, exists bool) { + v := m.scoped_resource_id + if v == nil { + return + } + return *v, true +} + +// OldScopedResourceID returns the old "scoped_resource_id" field's value of the WorkflowContract entity. +// If the WorkflowContract object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *WorkflowContractMutation) OldScopedResourceID(ctx context.Context) (v uuid.UUID, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldScopedResourceID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldScopedResourceID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldScopedResourceID: %w", err) + } + return oldValue.ScopedResourceID, nil +} + +// ClearScopedResourceID clears the value of the "scoped_resource_id" field. +func (m *WorkflowContractMutation) ClearScopedResourceID() { + m.scoped_resource_id = nil + m.clearedFields[workflowcontract.FieldScopedResourceID] = struct{}{} +} + +// ScopedResourceIDCleared returns if the "scoped_resource_id" field was cleared in this mutation. +func (m *WorkflowContractMutation) ScopedResourceIDCleared() bool { + _, ok := m.clearedFields[workflowcontract.FieldScopedResourceID] + return ok +} + +// ResetScopedResourceID resets all changes to the "scoped_resource_id" field. +func (m *WorkflowContractMutation) ResetScopedResourceID() { + m.scoped_resource_id = nil + delete(m.clearedFields, workflowcontract.FieldScopedResourceID) } // AddVersionIDs adds the "versions" edge to the WorkflowContractVersion entity by ids. @@ -15646,45 +15693,6 @@ func (m *WorkflowContractMutation) ResetVersions() { m.removedversions = nil } -// SetOrganizationID sets the "organization" edge to the Organization entity by id. -func (m *WorkflowContractMutation) SetOrganizationID(id uuid.UUID) { - m.organization = &id -} - -// ClearOrganization clears the "organization" edge to the Organization entity. -func (m *WorkflowContractMutation) ClearOrganization() { - m.clearedorganization = true -} - -// OrganizationCleared reports if the "organization" edge to the Organization entity was cleared. -func (m *WorkflowContractMutation) OrganizationCleared() bool { - return m.clearedorganization -} - -// OrganizationID returns the "organization" edge ID in the mutation. -func (m *WorkflowContractMutation) OrganizationID() (id uuid.UUID, exists bool) { - if m.organization != nil { - return *m.organization, true - } - return -} - -// OrganizationIDs returns the "organization" edge IDs in the mutation. -// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use -// OrganizationID instead. It exists only for internal usage by the builders. -func (m *WorkflowContractMutation) OrganizationIDs() (ids []uuid.UUID) { - if id := m.organization; id != nil { - ids = append(ids, *id) - } - return -} - -// ResetOrganization resets all changes to the "organization" edge. -func (m *WorkflowContractMutation) ResetOrganization() { - m.organization = nil - m.clearedorganization = false -} - // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by ids. func (m *WorkflowContractMutation) AddWorkflowIDs(ids ...uuid.UUID) { if m.workflows == nil { @@ -15739,33 +15747,6 @@ func (m *WorkflowContractMutation) ResetWorkflows() { m.removedworkflows = nil } -// ClearProject clears the "project" edge to the Project entity. -func (m *WorkflowContractMutation) ClearProject() { - m.clearedproject = true - m.clearedFields[workflowcontract.FieldProjectID] = struct{}{} -} - -// ProjectCleared reports if the "project" edge to the Project entity was cleared. -func (m *WorkflowContractMutation) ProjectCleared() bool { - return m.ProjectIDCleared() || m.clearedproject -} - -// ProjectIDs returns the "project" edge IDs in the mutation. -// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use -// ProjectID instead. It exists only for internal usage by the builders. -func (m *WorkflowContractMutation) ProjectIDs() (ids []uuid.UUID) { - if id := m.project; id != nil { - ids = append(ids, *id) - } - return -} - -// ResetProject resets all changes to the "project" edge. -func (m *WorkflowContractMutation) ResetProject() { - m.project = nil - m.clearedproject = false -} - // Where appends a list predicates to the WorkflowContractMutation builder. func (m *WorkflowContractMutation) Where(ps ...predicate.WorkflowContract) { m.predicates = append(m.predicates, ps...) @@ -15800,7 +15781,7 @@ func (m *WorkflowContractMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *WorkflowContractMutation) Fields() []string { - fields := make([]string, 0, 5) + fields := make([]string, 0, 6) if m.name != nil { fields = append(fields, workflowcontract.FieldName) } @@ -15813,8 +15794,11 @@ func (m *WorkflowContractMutation) Fields() []string { if m.description != nil { fields = append(fields, workflowcontract.FieldDescription) } - if m.project != nil { - fields = append(fields, workflowcontract.FieldProjectID) + if m.scoped_resource_type != nil { + fields = append(fields, workflowcontract.FieldScopedResourceType) + } + if m.scoped_resource_id != nil { + fields = append(fields, workflowcontract.FieldScopedResourceID) } return fields } @@ -15832,8 +15816,10 @@ func (m *WorkflowContractMutation) Field(name string) (ent.Value, bool) { return m.DeletedAt() case workflowcontract.FieldDescription: return m.Description() - case workflowcontract.FieldProjectID: - return m.ProjectID() + case workflowcontract.FieldScopedResourceType: + return m.ScopedResourceType() + case workflowcontract.FieldScopedResourceID: + return m.ScopedResourceID() } return nil, false } @@ -15851,8 +15837,10 @@ func (m *WorkflowContractMutation) OldField(ctx context.Context, name string) (e return m.OldDeletedAt(ctx) case workflowcontract.FieldDescription: return m.OldDescription(ctx) - case workflowcontract.FieldProjectID: - return m.OldProjectID(ctx) + case workflowcontract.FieldScopedResourceType: + return m.OldScopedResourceType(ctx) + case workflowcontract.FieldScopedResourceID: + return m.OldScopedResourceID(ctx) } return nil, fmt.Errorf("unknown WorkflowContract field %s", name) } @@ -15890,12 +15878,19 @@ func (m *WorkflowContractMutation) SetField(name string, value ent.Value) error } m.SetDescription(v) return nil - case workflowcontract.FieldProjectID: + case workflowcontract.FieldScopedResourceType: + v, ok := value.(biz.ContractScope) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetScopedResourceType(v) + return nil + case workflowcontract.FieldScopedResourceID: v, ok := value.(uuid.UUID) if !ok { return fmt.Errorf("unexpected type %T for field %s", value, name) } - m.SetProjectID(v) + m.SetScopedResourceID(v) return nil } return fmt.Errorf("unknown WorkflowContract field %s", name) @@ -15933,8 +15928,11 @@ func (m *WorkflowContractMutation) ClearedFields() []string { if m.FieldCleared(workflowcontract.FieldDescription) { fields = append(fields, workflowcontract.FieldDescription) } - if m.FieldCleared(workflowcontract.FieldProjectID) { - fields = append(fields, workflowcontract.FieldProjectID) + if m.FieldCleared(workflowcontract.FieldScopedResourceType) { + fields = append(fields, workflowcontract.FieldScopedResourceType) + } + if m.FieldCleared(workflowcontract.FieldScopedResourceID) { + fields = append(fields, workflowcontract.FieldScopedResourceID) } return fields } @@ -15956,8 +15954,11 @@ func (m *WorkflowContractMutation) ClearField(name string) error { case workflowcontract.FieldDescription: m.ClearDescription() return nil - case workflowcontract.FieldProjectID: - m.ClearProjectID() + case workflowcontract.FieldScopedResourceType: + m.ClearScopedResourceType() + return nil + case workflowcontract.FieldScopedResourceID: + m.ClearScopedResourceID() return nil } return fmt.Errorf("unknown WorkflowContract nullable field %s", name) @@ -15979,8 +15980,11 @@ func (m *WorkflowContractMutation) ResetField(name string) error { case workflowcontract.FieldDescription: m.ResetDescription() return nil - case workflowcontract.FieldProjectID: - m.ResetProjectID() + case workflowcontract.FieldScopedResourceType: + m.ResetScopedResourceType() + return nil + case workflowcontract.FieldScopedResourceID: + m.ResetScopedResourceID() return nil } return fmt.Errorf("unknown WorkflowContract field %s", name) @@ -15988,19 +15992,13 @@ func (m *WorkflowContractMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *WorkflowContractMutation) AddedEdges() []string { - edges := make([]string, 0, 4) + edges := make([]string, 0, 2) if m.versions != nil { edges = append(edges, workflowcontract.EdgeVersions) } - if m.organization != nil { - edges = append(edges, workflowcontract.EdgeOrganization) - } if m.workflows != nil { edges = append(edges, workflowcontract.EdgeWorkflows) } - if m.project != nil { - edges = append(edges, workflowcontract.EdgeProject) - } return edges } @@ -16014,27 +16012,19 @@ func (m *WorkflowContractMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids - case workflowcontract.EdgeOrganization: - if id := m.organization; id != nil { - return []ent.Value{*id} - } case workflowcontract.EdgeWorkflows: ids := make([]ent.Value, 0, len(m.workflows)) for id := range m.workflows { ids = append(ids, id) } return ids - case workflowcontract.EdgeProject: - if id := m.project; id != nil { - return []ent.Value{*id} - } } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *WorkflowContractMutation) RemovedEdges() []string { - edges := make([]string, 0, 4) + edges := make([]string, 0, 2) if m.removedversions != nil { edges = append(edges, workflowcontract.EdgeVersions) } @@ -16066,19 +16056,13 @@ func (m *WorkflowContractMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *WorkflowContractMutation) ClearedEdges() []string { - edges := make([]string, 0, 4) + edges := make([]string, 0, 2) if m.clearedversions { edges = append(edges, workflowcontract.EdgeVersions) } - if m.clearedorganization { - edges = append(edges, workflowcontract.EdgeOrganization) - } if m.clearedworkflows { edges = append(edges, workflowcontract.EdgeWorkflows) } - if m.clearedproject { - edges = append(edges, workflowcontract.EdgeProject) - } return edges } @@ -16088,12 +16072,8 @@ func (m *WorkflowContractMutation) EdgeCleared(name string) bool { switch name { case workflowcontract.EdgeVersions: return m.clearedversions - case workflowcontract.EdgeOrganization: - return m.clearedorganization case workflowcontract.EdgeWorkflows: return m.clearedworkflows - case workflowcontract.EdgeProject: - return m.clearedproject } return false } @@ -16102,12 +16082,6 @@ func (m *WorkflowContractMutation) EdgeCleared(name string) bool { // if that edge is not defined in the schema. func (m *WorkflowContractMutation) ClearEdge(name string) error { switch name { - case workflowcontract.EdgeOrganization: - m.ClearOrganization() - return nil - case workflowcontract.EdgeProject: - m.ClearProject() - return nil } return fmt.Errorf("unknown WorkflowContract unique edge %s", name) } @@ -16119,15 +16093,9 @@ func (m *WorkflowContractMutation) ResetEdge(name string) error { case workflowcontract.EdgeVersions: m.ResetVersions() return nil - case workflowcontract.EdgeOrganization: - m.ResetOrganization() - return nil case workflowcontract.EdgeWorkflows: m.ResetWorkflows() return nil - case workflowcontract.EdgeProject: - m.ResetProject() - return nil } return fmt.Errorf("unknown WorkflowContract edge %s", name) } diff --git a/app/controlplane/pkg/data/ent/schema-viz.html b/app/controlplane/pkg/data/ent/schema-viz.html index d0fa73e62..c54c7412c 100644 --- a/app/controlplane/pkg/data/ent/schema-viz.html +++ b/app/controlplane/pkg/data/ent/schema-viz.html @@ -70,11 +70,15 @@ } +<<<<<<< HEAD <<<<<<< HEAD const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"last_used_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"context\",\"type\":\"biz.OrgInvitationContext\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); ======= const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowContract\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); >>>>>>> 9b3f353d (feat: add columns) +======= + const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"scoped_resource_type\",\"type\":\"biz.ContractScope\"},{\"name\":\"scoped_resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); +>>>>>>> 7a8275ef (fix tests) const nodes = new vis.DataSet((entGraph.nodes || []).map(n => ({ id: n.id, diff --git a/app/controlplane/pkg/data/ent/schema/workflowcontract.go b/app/controlplane/pkg/data/ent/schema/workflowcontract.go index ad400f107..455ea638f 100644 --- a/app/controlplane/pkg/data/ent/schema/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/schema/workflowcontract.go @@ -23,6 +23,7 @@ import ( "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" "entgo.io/ent/schema/index" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/google/uuid" ) @@ -44,8 +45,9 @@ func (WorkflowContract) Fields() []ent.Field { }), field.Time("deleted_at").Optional(), field.String("description").Optional(), - // if this value is not set, the contract is an organization level contract - field.UUID("project_id", uuid.UUID{}).Optional(), + // If this value is set, the contract is scoped to a project or organization + field.Enum("scoped_resource_type").GoType(biz.ContractScope("")).Optional(), + field.UUID("scoped_resource_id", uuid.UUID{}).Optional(), } } @@ -53,25 +55,16 @@ func (WorkflowContract) Fields() []ent.Field { func (WorkflowContract) Edges() []ent.Edge { return []ent.Edge{ edge.To("versions", WorkflowContractVersion.Type), - edge.From("organization", Organization.Type). - Ref("workflow_contracts"). - Unique(), // A contract can be associated to multiple workflows edge.From("workflows", Workflow.Type).Ref("contract"), - edge.To("project", Project.Type).Field("project_id").Unique(), } } func (WorkflowContract) Indexes() []ent.Index { return []ent.Index{ // names are unique within a organization and affects only to non-deleted items - index.Fields("name").Edges("organization").Unique().Annotations( - entsql.IndexWhere("deleted_at IS NULL AND project_id IS NULL"), - ), - - // for project level contracts, we scope the uniqueness to the project - index.Fields("name").Edges("project").Unique().Annotations( - entsql.IndexWhere("deleted_at IS NULL AND project_id IS NOT NULL"), + index.Fields("name", "scoped_resource_type", "scoped_resource_id").Unique().Annotations( + entsql.IndexWhere("deleted_at IS NULL"), ), } } diff --git a/app/controlplane/pkg/data/ent/workflowcontract.go b/app/controlplane/pkg/data/ent/workflowcontract.go index 777421d58..2a67948fd 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/workflowcontract.go @@ -9,8 +9,7 @@ import ( "entgo.io/ent" "entgo.io/ent/dialect/sql" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/google/uuid" ) @@ -28,8 +27,10 @@ type WorkflowContract struct { DeletedAt time.Time `json:"deleted_at,omitempty"` // Description holds the value of the "description" field. Description string `json:"description,omitempty"` - // ProjectID holds the value of the "project_id" field. - ProjectID uuid.UUID `json:"project_id,omitempty"` + // ScopedResourceType holds the value of the "scoped_resource_type" field. + ScopedResourceType biz.ContractScope `json:"scoped_resource_type,omitempty"` + // ScopedResourceID holds the value of the "scoped_resource_id" field. + ScopedResourceID uuid.UUID `json:"scoped_resource_id,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the WorkflowContractQuery when eager-loading is set. Edges WorkflowContractEdges `json:"edges"` @@ -41,15 +42,11 @@ type WorkflowContract struct { type WorkflowContractEdges struct { // Versions holds the value of the versions edge. Versions []*WorkflowContractVersion `json:"versions,omitempty"` - // Organization holds the value of the organization edge. - Organization *Organization `json:"organization,omitempty"` // Workflows holds the value of the workflows edge. Workflows []*Workflow `json:"workflows,omitempty"` - // Project holds the value of the project edge. - Project *Project `json:"project,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [4]bool + loadedTypes [2]bool } // VersionsOrErr returns the Versions value or an error if the edge @@ -61,47 +58,25 @@ func (e WorkflowContractEdges) VersionsOrErr() ([]*WorkflowContractVersion, erro return nil, &NotLoadedError{edge: "versions"} } -// OrganizationOrErr returns the Organization value or an error if the edge -// was not loaded in eager-loading, or loaded but was not found. -func (e WorkflowContractEdges) OrganizationOrErr() (*Organization, error) { - if e.Organization != nil { - return e.Organization, nil - } else if e.loadedTypes[1] { - return nil, &NotFoundError{label: organization.Label} - } - return nil, &NotLoadedError{edge: "organization"} -} - // WorkflowsOrErr returns the Workflows value or an error if the edge // was not loaded in eager-loading. func (e WorkflowContractEdges) WorkflowsOrErr() ([]*Workflow, error) { - if e.loadedTypes[2] { + if e.loadedTypes[1] { return e.Workflows, nil } return nil, &NotLoadedError{edge: "workflows"} } -// ProjectOrErr returns the Project value or an error if the edge -// was not loaded in eager-loading, or loaded but was not found. -func (e WorkflowContractEdges) ProjectOrErr() (*Project, error) { - if e.Project != nil { - return e.Project, nil - } else if e.loadedTypes[3] { - return nil, &NotFoundError{label: project.Label} - } - return nil, &NotLoadedError{edge: "project"} -} - // scanValues returns the types for scanning values from sql.Rows. func (*WorkflowContract) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) for i := range columns { switch columns[i] { - case workflowcontract.FieldName, workflowcontract.FieldDescription: + case workflowcontract.FieldName, workflowcontract.FieldDescription, workflowcontract.FieldScopedResourceType: values[i] = new(sql.NullString) case workflowcontract.FieldCreatedAt, workflowcontract.FieldDeletedAt: values[i] = new(sql.NullTime) - case workflowcontract.FieldID, workflowcontract.FieldProjectID: + case workflowcontract.FieldID, workflowcontract.FieldScopedResourceID: values[i] = new(uuid.UUID) case workflowcontract.ForeignKeys[0]: // organization_workflow_contracts values[i] = &sql.NullScanner{S: new(uuid.UUID)} @@ -150,11 +125,17 @@ func (wc *WorkflowContract) assignValues(columns []string, values []any) error { } else if value.Valid { wc.Description = value.String } - case workflowcontract.FieldProjectID: + case workflowcontract.FieldScopedResourceType: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field scoped_resource_type", values[i]) + } else if value.Valid { + wc.ScopedResourceType = biz.ContractScope(value.String) + } + case workflowcontract.FieldScopedResourceID: if value, ok := values[i].(*uuid.UUID); !ok { - return fmt.Errorf("unexpected type %T for field project_id", values[i]) + return fmt.Errorf("unexpected type %T for field scoped_resource_id", values[i]) } else if value != nil { - wc.ProjectID = *value + wc.ScopedResourceID = *value } case workflowcontract.ForeignKeys[0]: if value, ok := values[i].(*sql.NullScanner); !ok { @@ -181,21 +162,11 @@ func (wc *WorkflowContract) QueryVersions() *WorkflowContractVersionQuery { return NewWorkflowContractClient(wc.config).QueryVersions(wc) } -// QueryOrganization queries the "organization" edge of the WorkflowContract entity. -func (wc *WorkflowContract) QueryOrganization() *OrganizationQuery { - return NewWorkflowContractClient(wc.config).QueryOrganization(wc) -} - // QueryWorkflows queries the "workflows" edge of the WorkflowContract entity. func (wc *WorkflowContract) QueryWorkflows() *WorkflowQuery { return NewWorkflowContractClient(wc.config).QueryWorkflows(wc) } -// QueryProject queries the "project" edge of the WorkflowContract entity. -func (wc *WorkflowContract) QueryProject() *ProjectQuery { - return NewWorkflowContractClient(wc.config).QueryProject(wc) -} - // Update returns a builder for updating this WorkflowContract. // Note that you need to call WorkflowContract.Unwrap() before calling this method if this WorkflowContract // was returned from a transaction, and the transaction was committed or rolled back. @@ -231,8 +202,11 @@ func (wc *WorkflowContract) String() string { builder.WriteString("description=") builder.WriteString(wc.Description) builder.WriteString(", ") - builder.WriteString("project_id=") - builder.WriteString(fmt.Sprintf("%v", wc.ProjectID)) + builder.WriteString("scoped_resource_type=") + builder.WriteString(fmt.Sprintf("%v", wc.ScopedResourceType)) + builder.WriteString(", ") + builder.WriteString("scoped_resource_id=") + builder.WriteString(fmt.Sprintf("%v", wc.ScopedResourceID)) builder.WriteByte(')') return builder.String() } diff --git a/app/controlplane/pkg/data/ent/workflowcontract/where.go b/app/controlplane/pkg/data/ent/workflowcontract/where.go index 8f83a3076..b7db780dd 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract/where.go +++ b/app/controlplane/pkg/data/ent/workflowcontract/where.go @@ -7,6 +7,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" "github.com/google/uuid" ) @@ -76,9 +77,9 @@ func Description(v string) predicate.WorkflowContract { return predicate.WorkflowContract(sql.FieldEQ(FieldDescription, v)) } -// ProjectID applies equality check predicate on the "project_id" field. It's identical to ProjectIDEQ. -func ProjectID(v uuid.UUID) predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldEQ(FieldProjectID, v)) +// ScopedResourceID applies equality check predicate on the "scoped_resource_id" field. It's identical to ScopedResourceIDEQ. +func ScopedResourceID(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldEQ(FieldScopedResourceID, v)) } // NameEQ applies the EQ predicate on the "name" field. @@ -311,34 +312,94 @@ func DescriptionContainsFold(v string) predicate.WorkflowContract { return predicate.WorkflowContract(sql.FieldContainsFold(FieldDescription, v)) } -// ProjectIDEQ applies the EQ predicate on the "project_id" field. -func ProjectIDEQ(v uuid.UUID) predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldEQ(FieldProjectID, v)) +// ScopedResourceTypeEQ applies the EQ predicate on the "scoped_resource_type" field. +func ScopedResourceTypeEQ(v biz.ContractScope) predicate.WorkflowContract { + vc := v + return predicate.WorkflowContract(sql.FieldEQ(FieldScopedResourceType, vc)) } -// ProjectIDNEQ applies the NEQ predicate on the "project_id" field. -func ProjectIDNEQ(v uuid.UUID) predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldNEQ(FieldProjectID, v)) +// ScopedResourceTypeNEQ applies the NEQ predicate on the "scoped_resource_type" field. +func ScopedResourceTypeNEQ(v biz.ContractScope) predicate.WorkflowContract { + vc := v + return predicate.WorkflowContract(sql.FieldNEQ(FieldScopedResourceType, vc)) } -// ProjectIDIn applies the In predicate on the "project_id" field. -func ProjectIDIn(vs ...uuid.UUID) predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldIn(FieldProjectID, vs...)) +// ScopedResourceTypeIn applies the In predicate on the "scoped_resource_type" field. +func ScopedResourceTypeIn(vs ...biz.ContractScope) predicate.WorkflowContract { + v := make([]any, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.WorkflowContract(sql.FieldIn(FieldScopedResourceType, v...)) } -// ProjectIDNotIn applies the NotIn predicate on the "project_id" field. -func ProjectIDNotIn(vs ...uuid.UUID) predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldNotIn(FieldProjectID, vs...)) +// ScopedResourceTypeNotIn applies the NotIn predicate on the "scoped_resource_type" field. +func ScopedResourceTypeNotIn(vs ...biz.ContractScope) predicate.WorkflowContract { + v := make([]any, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.WorkflowContract(sql.FieldNotIn(FieldScopedResourceType, v...)) } -// ProjectIDIsNil applies the IsNil predicate on the "project_id" field. -func ProjectIDIsNil() predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldIsNull(FieldProjectID)) +// ScopedResourceTypeIsNil applies the IsNil predicate on the "scoped_resource_type" field. +func ScopedResourceTypeIsNil() predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldIsNull(FieldScopedResourceType)) } -// ProjectIDNotNil applies the NotNil predicate on the "project_id" field. -func ProjectIDNotNil() predicate.WorkflowContract { - return predicate.WorkflowContract(sql.FieldNotNull(FieldProjectID)) +// ScopedResourceTypeNotNil applies the NotNil predicate on the "scoped_resource_type" field. +func ScopedResourceTypeNotNil() predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNotNull(FieldScopedResourceType)) +} + +// ScopedResourceIDEQ applies the EQ predicate on the "scoped_resource_id" field. +func ScopedResourceIDEQ(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldEQ(FieldScopedResourceID, v)) +} + +// ScopedResourceIDNEQ applies the NEQ predicate on the "scoped_resource_id" field. +func ScopedResourceIDNEQ(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNEQ(FieldScopedResourceID, v)) +} + +// ScopedResourceIDIn applies the In predicate on the "scoped_resource_id" field. +func ScopedResourceIDIn(vs ...uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldIn(FieldScopedResourceID, vs...)) +} + +// ScopedResourceIDNotIn applies the NotIn predicate on the "scoped_resource_id" field. +func ScopedResourceIDNotIn(vs ...uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNotIn(FieldScopedResourceID, vs...)) +} + +// ScopedResourceIDGT applies the GT predicate on the "scoped_resource_id" field. +func ScopedResourceIDGT(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldGT(FieldScopedResourceID, v)) +} + +// ScopedResourceIDGTE applies the GTE predicate on the "scoped_resource_id" field. +func ScopedResourceIDGTE(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldGTE(FieldScopedResourceID, v)) +} + +// ScopedResourceIDLT applies the LT predicate on the "scoped_resource_id" field. +func ScopedResourceIDLT(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldLT(FieldScopedResourceID, v)) +} + +// ScopedResourceIDLTE applies the LTE predicate on the "scoped_resource_id" field. +func ScopedResourceIDLTE(v uuid.UUID) predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldLTE(FieldScopedResourceID, v)) +} + +// ScopedResourceIDIsNil applies the IsNil predicate on the "scoped_resource_id" field. +func ScopedResourceIDIsNil() predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldIsNull(FieldScopedResourceID)) +} + +// ScopedResourceIDNotNil applies the NotNil predicate on the "scoped_resource_id" field. +func ScopedResourceIDNotNil() predicate.WorkflowContract { + return predicate.WorkflowContract(sql.FieldNotNull(FieldScopedResourceID)) } // HasVersions applies the HasEdge predicate on the "versions" edge. @@ -364,29 +425,6 @@ func HasVersionsWith(preds ...predicate.WorkflowContractVersion) predicate.Workf }) } -// HasOrganization applies the HasEdge predicate on the "organization" edge. -func HasOrganization() predicate.WorkflowContract { - return predicate.WorkflowContract(func(s *sql.Selector) { - step := sqlgraph.NewStep( - sqlgraph.From(Table, FieldID), - sqlgraph.Edge(sqlgraph.M2O, true, OrganizationTable, OrganizationColumn), - ) - sqlgraph.HasNeighbors(s, step) - }) -} - -// HasOrganizationWith applies the HasEdge predicate on the "organization" edge with a given conditions (other predicates). -func HasOrganizationWith(preds ...predicate.Organization) predicate.WorkflowContract { - return predicate.WorkflowContract(func(s *sql.Selector) { - step := newOrganizationStep() - sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { - for _, p := range preds { - p(s) - } - }) - }) -} - // HasWorkflows applies the HasEdge predicate on the "workflows" edge. func HasWorkflows() predicate.WorkflowContract { return predicate.WorkflowContract(func(s *sql.Selector) { @@ -410,29 +448,6 @@ func HasWorkflowsWith(preds ...predicate.Workflow) predicate.WorkflowContract { }) } -// HasProject applies the HasEdge predicate on the "project" edge. -func HasProject() predicate.WorkflowContract { - return predicate.WorkflowContract(func(s *sql.Selector) { - step := sqlgraph.NewStep( - sqlgraph.From(Table, FieldID), - sqlgraph.Edge(sqlgraph.M2O, false, ProjectTable, ProjectColumn), - ) - sqlgraph.HasNeighbors(s, step) - }) -} - -// HasProjectWith applies the HasEdge predicate on the "project" edge with a given conditions (other predicates). -func HasProjectWith(preds ...predicate.Project) predicate.WorkflowContract { - return predicate.WorkflowContract(func(s *sql.Selector) { - step := newProjectStep() - sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { - for _, p := range preds { - p(s) - } - }) - }) -} - // And groups predicates with the AND operator between them. func And(predicates ...predicate.WorkflowContract) predicate.WorkflowContract { return predicate.WorkflowContract(sql.AndPredicates(predicates...)) diff --git a/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go b/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go index 9cb71a60f..e8ee814e2 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go @@ -3,10 +3,12 @@ package workflowcontract import ( + "fmt" "time" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/google/uuid" ) @@ -23,16 +25,14 @@ const ( FieldDeletedAt = "deleted_at" // FieldDescription holds the string denoting the description field in the database. FieldDescription = "description" - // FieldProjectID holds the string denoting the project_id field in the database. - FieldProjectID = "project_id" + // FieldScopedResourceType holds the string denoting the scoped_resource_type field in the database. + FieldScopedResourceType = "scoped_resource_type" + // FieldScopedResourceID holds the string denoting the scoped_resource_id field in the database. + FieldScopedResourceID = "scoped_resource_id" // EdgeVersions holds the string denoting the versions edge name in mutations. EdgeVersions = "versions" - // EdgeOrganization holds the string denoting the organization edge name in mutations. - EdgeOrganization = "organization" // EdgeWorkflows holds the string denoting the workflows edge name in mutations. EdgeWorkflows = "workflows" - // EdgeProject holds the string denoting the project edge name in mutations. - EdgeProject = "project" // Table holds the table name of the workflowcontract in the database. Table = "workflow_contracts" // VersionsTable is the table that holds the versions relation/edge. @@ -42,13 +42,6 @@ const ( VersionsInverseTable = "workflow_contract_versions" // VersionsColumn is the table column denoting the versions relation/edge. VersionsColumn = "workflow_contract_versions" - // OrganizationTable is the table that holds the organization relation/edge. - OrganizationTable = "workflow_contracts" - // OrganizationInverseTable is the table name for the Organization entity. - // It exists in this package in order to avoid circular dependency with the "organization" package. - OrganizationInverseTable = "organizations" - // OrganizationColumn is the table column denoting the organization relation/edge. - OrganizationColumn = "organization_workflow_contracts" // WorkflowsTable is the table that holds the workflows relation/edge. WorkflowsTable = "workflows" // WorkflowsInverseTable is the table name for the Workflow entity. @@ -56,13 +49,6 @@ const ( WorkflowsInverseTable = "workflows" // WorkflowsColumn is the table column denoting the workflows relation/edge. WorkflowsColumn = "workflow_contract" - // ProjectTable is the table that holds the project relation/edge. - ProjectTable = "workflow_contracts" - // ProjectInverseTable is the table name for the Project entity. - // It exists in this package in order to avoid circular dependency with the "project" package. - ProjectInverseTable = "projects" - // ProjectColumn is the table column denoting the project relation/edge. - ProjectColumn = "project_id" ) // Columns holds all SQL columns for workflowcontract fields. @@ -72,7 +58,8 @@ var Columns = []string{ FieldCreatedAt, FieldDeletedAt, FieldDescription, - FieldProjectID, + FieldScopedResourceType, + FieldScopedResourceID, } // ForeignKeys holds the SQL foreign-keys that are owned by the "workflow_contracts" @@ -103,6 +90,16 @@ var ( DefaultID func() uuid.UUID ) +// ScopedResourceTypeValidator is a validator for the "scoped_resource_type" field enum values. It is called by the builders before save. +func ScopedResourceTypeValidator(srt biz.ContractScope) error { + switch srt { + case "project", "org": + return nil + default: + return fmt.Errorf("workflowcontract: invalid enum value for scoped_resource_type field: %q", srt) + } +} + // OrderOption defines the ordering options for the WorkflowContract queries. type OrderOption func(*sql.Selector) @@ -131,9 +128,14 @@ func ByDescription(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldDescription, opts...).ToFunc() } -// ByProjectID orders the results by the project_id field. -func ByProjectID(opts ...sql.OrderTermOption) OrderOption { - return sql.OrderByField(FieldProjectID, opts...).ToFunc() +// ByScopedResourceType orders the results by the scoped_resource_type field. +func ByScopedResourceType(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldScopedResourceType, opts...).ToFunc() +} + +// ByScopedResourceID orders the results by the scoped_resource_id field. +func ByScopedResourceID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldScopedResourceID, opts...).ToFunc() } // ByVersionsCount orders the results by versions count. @@ -150,13 +152,6 @@ func ByVersions(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { } } -// ByOrganizationField orders the results by organization field. -func ByOrganizationField(field string, opts ...sql.OrderTermOption) OrderOption { - return func(s *sql.Selector) { - sqlgraph.OrderByNeighborTerms(s, newOrganizationStep(), sql.OrderByField(field, opts...)) - } -} - // ByWorkflowsCount orders the results by workflows count. func ByWorkflowsCount(opts ...sql.OrderTermOption) OrderOption { return func(s *sql.Selector) { @@ -170,13 +165,6 @@ func ByWorkflows(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { sqlgraph.OrderByNeighborTerms(s, newWorkflowsStep(), append([]sql.OrderTerm{term}, terms...)...) } } - -// ByProjectField orders the results by project field. -func ByProjectField(field string, opts ...sql.OrderTermOption) OrderOption { - return func(s *sql.Selector) { - sqlgraph.OrderByNeighborTerms(s, newProjectStep(), sql.OrderByField(field, opts...)) - } -} func newVersionsStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -184,13 +172,6 @@ func newVersionsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, false, VersionsTable, VersionsColumn), ) } -func newOrganizationStep() *sqlgraph.Step { - return sqlgraph.NewStep( - sqlgraph.From(Table, FieldID), - sqlgraph.To(OrganizationInverseTable, FieldID), - sqlgraph.Edge(sqlgraph.M2O, true, OrganizationTable, OrganizationColumn), - ) -} func newWorkflowsStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -198,10 +179,3 @@ func newWorkflowsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, true, WorkflowsTable, WorkflowsColumn), ) } -func newProjectStep() *sqlgraph.Step { - return sqlgraph.NewStep( - sqlgraph.From(Table, FieldID), - sqlgraph.To(ProjectInverseTable, FieldID), - sqlgraph.Edge(sqlgraph.M2O, false, ProjectTable, ProjectColumn), - ) -} diff --git a/app/controlplane/pkg/data/ent/workflowcontract_create.go b/app/controlplane/pkg/data/ent/workflowcontract_create.go index 811d19456..065783ccd 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_create.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_create.go @@ -12,8 +12,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -76,16 +75,30 @@ func (wcc *WorkflowContractCreate) SetNillableDescription(s *string) *WorkflowCo return wcc } -// SetProjectID sets the "project_id" field. -func (wcc *WorkflowContractCreate) SetProjectID(u uuid.UUID) *WorkflowContractCreate { - wcc.mutation.SetProjectID(u) +// SetScopedResourceType sets the "scoped_resource_type" field. +func (wcc *WorkflowContractCreate) SetScopedResourceType(bs biz.ContractScope) *WorkflowContractCreate { + wcc.mutation.SetScopedResourceType(bs) return wcc } -// SetNillableProjectID sets the "project_id" field if the given value is not nil. -func (wcc *WorkflowContractCreate) SetNillableProjectID(u *uuid.UUID) *WorkflowContractCreate { +// SetNillableScopedResourceType sets the "scoped_resource_type" field if the given value is not nil. +func (wcc *WorkflowContractCreate) SetNillableScopedResourceType(bs *biz.ContractScope) *WorkflowContractCreate { + if bs != nil { + wcc.SetScopedResourceType(*bs) + } + return wcc +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (wcc *WorkflowContractCreate) SetScopedResourceID(u uuid.UUID) *WorkflowContractCreate { + wcc.mutation.SetScopedResourceID(u) + return wcc +} + +// SetNillableScopedResourceID sets the "scoped_resource_id" field if the given value is not nil. +func (wcc *WorkflowContractCreate) SetNillableScopedResourceID(u *uuid.UUID) *WorkflowContractCreate { if u != nil { - wcc.SetProjectID(*u) + wcc.SetScopedResourceID(*u) } return wcc } @@ -119,25 +132,6 @@ func (wcc *WorkflowContractCreate) AddVersions(w ...*WorkflowContractVersion) *W return wcc.AddVersionIDs(ids...) } -// SetOrganizationID sets the "organization" edge to the Organization entity by ID. -func (wcc *WorkflowContractCreate) SetOrganizationID(id uuid.UUID) *WorkflowContractCreate { - wcc.mutation.SetOrganizationID(id) - return wcc -} - -// SetNillableOrganizationID sets the "organization" edge to the Organization entity by ID if the given value is not nil. -func (wcc *WorkflowContractCreate) SetNillableOrganizationID(id *uuid.UUID) *WorkflowContractCreate { - if id != nil { - wcc = wcc.SetOrganizationID(*id) - } - return wcc -} - -// SetOrganization sets the "organization" edge to the Organization entity. -func (wcc *WorkflowContractCreate) SetOrganization(o *Organization) *WorkflowContractCreate { - return wcc.SetOrganizationID(o.ID) -} - // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by IDs. func (wcc *WorkflowContractCreate) AddWorkflowIDs(ids ...uuid.UUID) *WorkflowContractCreate { wcc.mutation.AddWorkflowIDs(ids...) @@ -153,11 +147,6 @@ func (wcc *WorkflowContractCreate) AddWorkflows(w ...*Workflow) *WorkflowContrac return wcc.AddWorkflowIDs(ids...) } -// SetProject sets the "project" edge to the Project entity. -func (wcc *WorkflowContractCreate) SetProject(p *Project) *WorkflowContractCreate { - return wcc.SetProjectID(p.ID) -} - // Mutation returns the WorkflowContractMutation object of the builder. func (wcc *WorkflowContractCreate) Mutation() *WorkflowContractMutation { return wcc.mutation @@ -211,6 +200,11 @@ func (wcc *WorkflowContractCreate) check() error { if _, ok := wcc.mutation.CreatedAt(); !ok { return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "WorkflowContract.created_at"`)} } + if v, ok := wcc.mutation.ScopedResourceType(); ok { + if err := workflowcontract.ScopedResourceTypeValidator(v); err != nil { + return &ValidationError{Name: "scoped_resource_type", err: fmt.Errorf(`ent: validator failed for field "WorkflowContract.scoped_resource_type": %w`, err)} + } + } return nil } @@ -263,6 +257,14 @@ func (wcc *WorkflowContractCreate) createSpec() (*WorkflowContract, *sqlgraph.Cr _spec.SetField(workflowcontract.FieldDescription, field.TypeString, value) _node.Description = value } + if value, ok := wcc.mutation.ScopedResourceType(); ok { + _spec.SetField(workflowcontract.FieldScopedResourceType, field.TypeEnum, value) + _node.ScopedResourceType = value + } + if value, ok := wcc.mutation.ScopedResourceID(); ok { + _spec.SetField(workflowcontract.FieldScopedResourceID, field.TypeUUID, value) + _node.ScopedResourceID = value + } if nodes := wcc.mutation.VersionsIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -279,23 +281,6 @@ func (wcc *WorkflowContractCreate) createSpec() (*WorkflowContract, *sqlgraph.Cr } _spec.Edges = append(_spec.Edges, edge) } - if nodes := wcc.mutation.OrganizationIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: workflowcontract.OrganizationTable, - Columns: []string{workflowcontract.OrganizationColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _node.organization_workflow_contracts = &nodes[0] - _spec.Edges = append(_spec.Edges, edge) - } if nodes := wcc.mutation.WorkflowsIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -312,23 +297,6 @@ func (wcc *WorkflowContractCreate) createSpec() (*WorkflowContract, *sqlgraph.Cr } _spec.Edges = append(_spec.Edges, edge) } - if nodes := wcc.mutation.ProjectIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: false, - Table: workflowcontract.ProjectTable, - Columns: []string{workflowcontract.ProjectColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _node.ProjectID = nodes[0] - _spec.Edges = append(_spec.Edges, edge) - } return _node, _spec } @@ -417,21 +385,39 @@ func (u *WorkflowContractUpsert) ClearDescription() *WorkflowContractUpsert { return u } -// SetProjectID sets the "project_id" field. -func (u *WorkflowContractUpsert) SetProjectID(v uuid.UUID) *WorkflowContractUpsert { - u.Set(workflowcontract.FieldProjectID, v) +// SetScopedResourceType sets the "scoped_resource_type" field. +func (u *WorkflowContractUpsert) SetScopedResourceType(v biz.ContractScope) *WorkflowContractUpsert { + u.Set(workflowcontract.FieldScopedResourceType, v) return u } -// UpdateProjectID sets the "project_id" field to the value that was provided on create. -func (u *WorkflowContractUpsert) UpdateProjectID() *WorkflowContractUpsert { - u.SetExcluded(workflowcontract.FieldProjectID) +// UpdateScopedResourceType sets the "scoped_resource_type" field to the value that was provided on create. +func (u *WorkflowContractUpsert) UpdateScopedResourceType() *WorkflowContractUpsert { + u.SetExcluded(workflowcontract.FieldScopedResourceType) return u } -// ClearProjectID clears the value of the "project_id" field. -func (u *WorkflowContractUpsert) ClearProjectID() *WorkflowContractUpsert { - u.SetNull(workflowcontract.FieldProjectID) +// ClearScopedResourceType clears the value of the "scoped_resource_type" field. +func (u *WorkflowContractUpsert) ClearScopedResourceType() *WorkflowContractUpsert { + u.SetNull(workflowcontract.FieldScopedResourceType) + return u +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (u *WorkflowContractUpsert) SetScopedResourceID(v uuid.UUID) *WorkflowContractUpsert { + u.Set(workflowcontract.FieldScopedResourceID, v) + return u +} + +// UpdateScopedResourceID sets the "scoped_resource_id" field to the value that was provided on create. +func (u *WorkflowContractUpsert) UpdateScopedResourceID() *WorkflowContractUpsert { + u.SetExcluded(workflowcontract.FieldScopedResourceID) + return u +} + +// ClearScopedResourceID clears the value of the "scoped_resource_id" field. +func (u *WorkflowContractUpsert) ClearScopedResourceID() *WorkflowContractUpsert { + u.SetNull(workflowcontract.FieldScopedResourceID) return u } @@ -531,24 +517,45 @@ func (u *WorkflowContractUpsertOne) ClearDescription() *WorkflowContractUpsertOn }) } -// SetProjectID sets the "project_id" field. -func (u *WorkflowContractUpsertOne) SetProjectID(v uuid.UUID) *WorkflowContractUpsertOne { +// SetScopedResourceType sets the "scoped_resource_type" field. +func (u *WorkflowContractUpsertOne) SetScopedResourceType(v biz.ContractScope) *WorkflowContractUpsertOne { + return u.Update(func(s *WorkflowContractUpsert) { + s.SetScopedResourceType(v) + }) +} + +// UpdateScopedResourceType sets the "scoped_resource_type" field to the value that was provided on create. +func (u *WorkflowContractUpsertOne) UpdateScopedResourceType() *WorkflowContractUpsertOne { + return u.Update(func(s *WorkflowContractUpsert) { + s.UpdateScopedResourceType() + }) +} + +// ClearScopedResourceType clears the value of the "scoped_resource_type" field. +func (u *WorkflowContractUpsertOne) ClearScopedResourceType() *WorkflowContractUpsertOne { + return u.Update(func(s *WorkflowContractUpsert) { + s.ClearScopedResourceType() + }) +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (u *WorkflowContractUpsertOne) SetScopedResourceID(v uuid.UUID) *WorkflowContractUpsertOne { return u.Update(func(s *WorkflowContractUpsert) { - s.SetProjectID(v) + s.SetScopedResourceID(v) }) } -// UpdateProjectID sets the "project_id" field to the value that was provided on create. -func (u *WorkflowContractUpsertOne) UpdateProjectID() *WorkflowContractUpsertOne { +// UpdateScopedResourceID sets the "scoped_resource_id" field to the value that was provided on create. +func (u *WorkflowContractUpsertOne) UpdateScopedResourceID() *WorkflowContractUpsertOne { return u.Update(func(s *WorkflowContractUpsert) { - s.UpdateProjectID() + s.UpdateScopedResourceID() }) } -// ClearProjectID clears the value of the "project_id" field. -func (u *WorkflowContractUpsertOne) ClearProjectID() *WorkflowContractUpsertOne { +// ClearScopedResourceID clears the value of the "scoped_resource_id" field. +func (u *WorkflowContractUpsertOne) ClearScopedResourceID() *WorkflowContractUpsertOne { return u.Update(func(s *WorkflowContractUpsert) { - s.ClearProjectID() + s.ClearScopedResourceID() }) } @@ -815,24 +822,45 @@ func (u *WorkflowContractUpsertBulk) ClearDescription() *WorkflowContractUpsertB }) } -// SetProjectID sets the "project_id" field. -func (u *WorkflowContractUpsertBulk) SetProjectID(v uuid.UUID) *WorkflowContractUpsertBulk { +// SetScopedResourceType sets the "scoped_resource_type" field. +func (u *WorkflowContractUpsertBulk) SetScopedResourceType(v biz.ContractScope) *WorkflowContractUpsertBulk { + return u.Update(func(s *WorkflowContractUpsert) { + s.SetScopedResourceType(v) + }) +} + +// UpdateScopedResourceType sets the "scoped_resource_type" field to the value that was provided on create. +func (u *WorkflowContractUpsertBulk) UpdateScopedResourceType() *WorkflowContractUpsertBulk { + return u.Update(func(s *WorkflowContractUpsert) { + s.UpdateScopedResourceType() + }) +} + +// ClearScopedResourceType clears the value of the "scoped_resource_type" field. +func (u *WorkflowContractUpsertBulk) ClearScopedResourceType() *WorkflowContractUpsertBulk { + return u.Update(func(s *WorkflowContractUpsert) { + s.ClearScopedResourceType() + }) +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (u *WorkflowContractUpsertBulk) SetScopedResourceID(v uuid.UUID) *WorkflowContractUpsertBulk { return u.Update(func(s *WorkflowContractUpsert) { - s.SetProjectID(v) + s.SetScopedResourceID(v) }) } -// UpdateProjectID sets the "project_id" field to the value that was provided on create. -func (u *WorkflowContractUpsertBulk) UpdateProjectID() *WorkflowContractUpsertBulk { +// UpdateScopedResourceID sets the "scoped_resource_id" field to the value that was provided on create. +func (u *WorkflowContractUpsertBulk) UpdateScopedResourceID() *WorkflowContractUpsertBulk { return u.Update(func(s *WorkflowContractUpsert) { - s.UpdateProjectID() + s.UpdateScopedResourceID() }) } -// ClearProjectID clears the value of the "project_id" field. -func (u *WorkflowContractUpsertBulk) ClearProjectID() *WorkflowContractUpsertBulk { +// ClearScopedResourceID clears the value of the "scoped_resource_id" field. +func (u *WorkflowContractUpsertBulk) ClearScopedResourceID() *WorkflowContractUpsertBulk { return u.Update(func(s *WorkflowContractUpsert) { - s.ClearProjectID() + s.ClearScopedResourceID() }) } diff --git a/app/controlplane/pkg/data/ent/workflowcontract_query.go b/app/controlplane/pkg/data/ent/workflowcontract_query.go index 6056b7dde..9009f4f0e 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_query.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_query.go @@ -13,9 +13,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -25,16 +23,14 @@ import ( // WorkflowContractQuery is the builder for querying WorkflowContract entities. type WorkflowContractQuery struct { config - ctx *QueryContext - order []workflowcontract.OrderOption - inters []Interceptor - predicates []predicate.WorkflowContract - withVersions *WorkflowContractVersionQuery - withOrganization *OrganizationQuery - withWorkflows *WorkflowQuery - withProject *ProjectQuery - withFKs bool - modifiers []func(*sql.Selector) + ctx *QueryContext + order []workflowcontract.OrderOption + inters []Interceptor + predicates []predicate.WorkflowContract + withVersions *WorkflowContractVersionQuery + withWorkflows *WorkflowQuery + withFKs bool + modifiers []func(*sql.Selector) // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -93,28 +89,6 @@ func (wcq *WorkflowContractQuery) QueryVersions() *WorkflowContractVersionQuery return query } -// QueryOrganization chains the current query on the "organization" edge. -func (wcq *WorkflowContractQuery) QueryOrganization() *OrganizationQuery { - query := (&OrganizationClient{config: wcq.config}).Query() - query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { - if err := wcq.prepareQuery(ctx); err != nil { - return nil, err - } - selector := wcq.sqlQuery(ctx) - if err := selector.Err(); err != nil { - return nil, err - } - step := sqlgraph.NewStep( - sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, selector), - sqlgraph.To(organization.Table, organization.FieldID), - sqlgraph.Edge(sqlgraph.M2O, true, workflowcontract.OrganizationTable, workflowcontract.OrganizationColumn), - ) - fromU = sqlgraph.SetNeighbors(wcq.driver.Dialect(), step) - return fromU, nil - } - return query -} - // QueryWorkflows chains the current query on the "workflows" edge. func (wcq *WorkflowContractQuery) QueryWorkflows() *WorkflowQuery { query := (&WorkflowClient{config: wcq.config}).Query() @@ -137,28 +111,6 @@ func (wcq *WorkflowContractQuery) QueryWorkflows() *WorkflowQuery { return query } -// QueryProject chains the current query on the "project" edge. -func (wcq *WorkflowContractQuery) QueryProject() *ProjectQuery { - query := (&ProjectClient{config: wcq.config}).Query() - query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { - if err := wcq.prepareQuery(ctx); err != nil { - return nil, err - } - selector := wcq.sqlQuery(ctx) - if err := selector.Err(); err != nil { - return nil, err - } - step := sqlgraph.NewStep( - sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, selector), - sqlgraph.To(project.Table, project.FieldID), - sqlgraph.Edge(sqlgraph.M2O, false, workflowcontract.ProjectTable, workflowcontract.ProjectColumn), - ) - fromU = sqlgraph.SetNeighbors(wcq.driver.Dialect(), step) - return fromU, nil - } - return query -} - // First returns the first WorkflowContract entity from the query. // Returns a *NotFoundError when no WorkflowContract was found. func (wcq *WorkflowContractQuery) First(ctx context.Context) (*WorkflowContract, error) { @@ -346,15 +298,13 @@ func (wcq *WorkflowContractQuery) Clone() *WorkflowContractQuery { return nil } return &WorkflowContractQuery{ - config: wcq.config, - ctx: wcq.ctx.Clone(), - order: append([]workflowcontract.OrderOption{}, wcq.order...), - inters: append([]Interceptor{}, wcq.inters...), - predicates: append([]predicate.WorkflowContract{}, wcq.predicates...), - withVersions: wcq.withVersions.Clone(), - withOrganization: wcq.withOrganization.Clone(), - withWorkflows: wcq.withWorkflows.Clone(), - withProject: wcq.withProject.Clone(), + config: wcq.config, + ctx: wcq.ctx.Clone(), + order: append([]workflowcontract.OrderOption{}, wcq.order...), + inters: append([]Interceptor{}, wcq.inters...), + predicates: append([]predicate.WorkflowContract{}, wcq.predicates...), + withVersions: wcq.withVersions.Clone(), + withWorkflows: wcq.withWorkflows.Clone(), // clone intermediate query. sql: wcq.sql.Clone(), path: wcq.path, @@ -373,17 +323,6 @@ func (wcq *WorkflowContractQuery) WithVersions(opts ...func(*WorkflowContractVer return wcq } -// WithOrganization tells the query-builder to eager-load the nodes that are connected to -// the "organization" edge. The optional arguments are used to configure the query builder of the edge. -func (wcq *WorkflowContractQuery) WithOrganization(opts ...func(*OrganizationQuery)) *WorkflowContractQuery { - query := (&OrganizationClient{config: wcq.config}).Query() - for _, opt := range opts { - opt(query) - } - wcq.withOrganization = query - return wcq -} - // WithWorkflows tells the query-builder to eager-load the nodes that are connected to // the "workflows" edge. The optional arguments are used to configure the query builder of the edge. func (wcq *WorkflowContractQuery) WithWorkflows(opts ...func(*WorkflowQuery)) *WorkflowContractQuery { @@ -395,17 +334,6 @@ func (wcq *WorkflowContractQuery) WithWorkflows(opts ...func(*WorkflowQuery)) *W return wcq } -// WithProject tells the query-builder to eager-load the nodes that are connected to -// the "project" edge. The optional arguments are used to configure the query builder of the edge. -func (wcq *WorkflowContractQuery) WithProject(opts ...func(*ProjectQuery)) *WorkflowContractQuery { - query := (&ProjectClient{config: wcq.config}).Query() - for _, opt := range opts { - opt(query) - } - wcq.withProject = query - return wcq -} - // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -485,16 +413,11 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook nodes = []*WorkflowContract{} withFKs = wcq.withFKs _spec = wcq.querySpec() - loadedTypes = [4]bool{ + loadedTypes = [2]bool{ wcq.withVersions != nil, - wcq.withOrganization != nil, wcq.withWorkflows != nil, - wcq.withProject != nil, } ) - if wcq.withOrganization != nil { - withFKs = true - } if withFKs { _spec.Node.Columns = append(_spec.Node.Columns, workflowcontract.ForeignKeys...) } @@ -526,12 +449,6 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook return nil, err } } - if query := wcq.withOrganization; query != nil { - if err := wcq.loadOrganization(ctx, query, nodes, nil, - func(n *WorkflowContract, e *Organization) { n.Edges.Organization = e }); err != nil { - return nil, err - } - } if query := wcq.withWorkflows; query != nil { if err := wcq.loadWorkflows(ctx, query, nodes, func(n *WorkflowContract) { n.Edges.Workflows = []*Workflow{} }, @@ -539,12 +456,6 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook return nil, err } } - if query := wcq.withProject; query != nil { - if err := wcq.loadProject(ctx, query, nodes, nil, - func(n *WorkflowContract, e *Project) { n.Edges.Project = e }); err != nil { - return nil, err - } - } return nodes, nil } @@ -579,38 +490,6 @@ func (wcq *WorkflowContractQuery) loadVersions(ctx context.Context, query *Workf } return nil } -func (wcq *WorkflowContractQuery) loadOrganization(ctx context.Context, query *OrganizationQuery, nodes []*WorkflowContract, init func(*WorkflowContract), assign func(*WorkflowContract, *Organization)) error { - ids := make([]uuid.UUID, 0, len(nodes)) - nodeids := make(map[uuid.UUID][]*WorkflowContract) - for i := range nodes { - if nodes[i].organization_workflow_contracts == nil { - continue - } - fk := *nodes[i].organization_workflow_contracts - if _, ok := nodeids[fk]; !ok { - ids = append(ids, fk) - } - nodeids[fk] = append(nodeids[fk], nodes[i]) - } - if len(ids) == 0 { - return nil - } - query.Where(organization.IDIn(ids...)) - neighbors, err := query.All(ctx) - if err != nil { - return err - } - for _, n := range neighbors { - nodes, ok := nodeids[n.ID] - if !ok { - return fmt.Errorf(`unexpected foreign-key "organization_workflow_contracts" returned %v`, n.ID) - } - for i := range nodes { - assign(nodes[i], n) - } - } - return nil -} func (wcq *WorkflowContractQuery) loadWorkflows(ctx context.Context, query *WorkflowQuery, nodes []*WorkflowContract, init func(*WorkflowContract), assign func(*WorkflowContract, *Workflow)) error { fks := make([]driver.Value, 0, len(nodes)) nodeids := make(map[uuid.UUID]*WorkflowContract) @@ -642,35 +521,6 @@ func (wcq *WorkflowContractQuery) loadWorkflows(ctx context.Context, query *Work } return nil } -func (wcq *WorkflowContractQuery) loadProject(ctx context.Context, query *ProjectQuery, nodes []*WorkflowContract, init func(*WorkflowContract), assign func(*WorkflowContract, *Project)) error { - ids := make([]uuid.UUID, 0, len(nodes)) - nodeids := make(map[uuid.UUID][]*WorkflowContract) - for i := range nodes { - fk := nodes[i].ProjectID - if _, ok := nodeids[fk]; !ok { - ids = append(ids, fk) - } - nodeids[fk] = append(nodeids[fk], nodes[i]) - } - if len(ids) == 0 { - return nil - } - query.Where(project.IDIn(ids...)) - neighbors, err := query.All(ctx) - if err != nil { - return err - } - for _, n := range neighbors { - nodes, ok := nodeids[n.ID] - if !ok { - return fmt.Errorf(`unexpected foreign-key "project_id" returned %v`, n.ID) - } - for i := range nodes { - assign(nodes[i], n) - } - } - return nil -} func (wcq *WorkflowContractQuery) sqlCount(ctx context.Context) (int, error) { _spec := wcq.querySpec() @@ -700,9 +550,6 @@ func (wcq *WorkflowContractQuery) querySpec() *sqlgraph.QuerySpec { _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) } } - if wcq.withProject != nil { - _spec.Node.AddColumnOnce(workflowcontract.FieldProjectID) - } } if ps := wcq.predicates; len(ps) > 0 { _spec.Predicate = func(selector *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/workflowcontract_update.go b/app/controlplane/pkg/data/ent/workflowcontract_update.go index 3b4059802..c7cc64646 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_update.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_update.go @@ -11,9 +11,8 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/project" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -74,23 +73,43 @@ func (wcu *WorkflowContractUpdate) ClearDescription() *WorkflowContractUpdate { return wcu } -// SetProjectID sets the "project_id" field. -func (wcu *WorkflowContractUpdate) SetProjectID(u uuid.UUID) *WorkflowContractUpdate { - wcu.mutation.SetProjectID(u) +// SetScopedResourceType sets the "scoped_resource_type" field. +func (wcu *WorkflowContractUpdate) SetScopedResourceType(bs biz.ContractScope) *WorkflowContractUpdate { + wcu.mutation.SetScopedResourceType(bs) return wcu } -// SetNillableProjectID sets the "project_id" field if the given value is not nil. -func (wcu *WorkflowContractUpdate) SetNillableProjectID(u *uuid.UUID) *WorkflowContractUpdate { +// SetNillableScopedResourceType sets the "scoped_resource_type" field if the given value is not nil. +func (wcu *WorkflowContractUpdate) SetNillableScopedResourceType(bs *biz.ContractScope) *WorkflowContractUpdate { + if bs != nil { + wcu.SetScopedResourceType(*bs) + } + return wcu +} + +// ClearScopedResourceType clears the value of the "scoped_resource_type" field. +func (wcu *WorkflowContractUpdate) ClearScopedResourceType() *WorkflowContractUpdate { + wcu.mutation.ClearScopedResourceType() + return wcu +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (wcu *WorkflowContractUpdate) SetScopedResourceID(u uuid.UUID) *WorkflowContractUpdate { + wcu.mutation.SetScopedResourceID(u) + return wcu +} + +// SetNillableScopedResourceID sets the "scoped_resource_id" field if the given value is not nil. +func (wcu *WorkflowContractUpdate) SetNillableScopedResourceID(u *uuid.UUID) *WorkflowContractUpdate { if u != nil { - wcu.SetProjectID(*u) + wcu.SetScopedResourceID(*u) } return wcu } -// ClearProjectID clears the value of the "project_id" field. -func (wcu *WorkflowContractUpdate) ClearProjectID() *WorkflowContractUpdate { - wcu.mutation.ClearProjectID() +// ClearScopedResourceID clears the value of the "scoped_resource_id" field. +func (wcu *WorkflowContractUpdate) ClearScopedResourceID() *WorkflowContractUpdate { + wcu.mutation.ClearScopedResourceID() return wcu } @@ -109,25 +128,6 @@ func (wcu *WorkflowContractUpdate) AddVersions(w ...*WorkflowContractVersion) *W return wcu.AddVersionIDs(ids...) } -// SetOrganizationID sets the "organization" edge to the Organization entity by ID. -func (wcu *WorkflowContractUpdate) SetOrganizationID(id uuid.UUID) *WorkflowContractUpdate { - wcu.mutation.SetOrganizationID(id) - return wcu -} - -// SetNillableOrganizationID sets the "organization" edge to the Organization entity by ID if the given value is not nil. -func (wcu *WorkflowContractUpdate) SetNillableOrganizationID(id *uuid.UUID) *WorkflowContractUpdate { - if id != nil { - wcu = wcu.SetOrganizationID(*id) - } - return wcu -} - -// SetOrganization sets the "organization" edge to the Organization entity. -func (wcu *WorkflowContractUpdate) SetOrganization(o *Organization) *WorkflowContractUpdate { - return wcu.SetOrganizationID(o.ID) -} - // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by IDs. func (wcu *WorkflowContractUpdate) AddWorkflowIDs(ids ...uuid.UUID) *WorkflowContractUpdate { wcu.mutation.AddWorkflowIDs(ids...) @@ -143,11 +143,6 @@ func (wcu *WorkflowContractUpdate) AddWorkflows(w ...*Workflow) *WorkflowContrac return wcu.AddWorkflowIDs(ids...) } -// SetProject sets the "project" edge to the Project entity. -func (wcu *WorkflowContractUpdate) SetProject(p *Project) *WorkflowContractUpdate { - return wcu.SetProjectID(p.ID) -} - // Mutation returns the WorkflowContractMutation object of the builder. func (wcu *WorkflowContractUpdate) Mutation() *WorkflowContractMutation { return wcu.mutation @@ -174,12 +169,6 @@ func (wcu *WorkflowContractUpdate) RemoveVersions(w ...*WorkflowContractVersion) return wcu.RemoveVersionIDs(ids...) } -// ClearOrganization clears the "organization" edge to the Organization entity. -func (wcu *WorkflowContractUpdate) ClearOrganization() *WorkflowContractUpdate { - wcu.mutation.ClearOrganization() - return wcu -} - // ClearWorkflows clears all "workflows" edges to the Workflow entity. func (wcu *WorkflowContractUpdate) ClearWorkflows() *WorkflowContractUpdate { wcu.mutation.ClearWorkflows() @@ -201,12 +190,6 @@ func (wcu *WorkflowContractUpdate) RemoveWorkflows(w ...*Workflow) *WorkflowCont return wcu.RemoveWorkflowIDs(ids...) } -// ClearProject clears the "project" edge to the Project entity. -func (wcu *WorkflowContractUpdate) ClearProject() *WorkflowContractUpdate { - wcu.mutation.ClearProject() - return wcu -} - // Save executes the query and returns the number of nodes affected by the update operation. func (wcu *WorkflowContractUpdate) Save(ctx context.Context) (int, error) { return withHooks(ctx, wcu.sqlSave, wcu.mutation, wcu.hooks) @@ -234,6 +217,16 @@ func (wcu *WorkflowContractUpdate) ExecX(ctx context.Context) { } } +// check runs all checks and user-defined validators on the builder. +func (wcu *WorkflowContractUpdate) check() error { + if v, ok := wcu.mutation.ScopedResourceType(); ok { + if err := workflowcontract.ScopedResourceTypeValidator(v); err != nil { + return &ValidationError{Name: "scoped_resource_type", err: fmt.Errorf(`ent: validator failed for field "WorkflowContract.scoped_resource_type": %w`, err)} + } + } + return nil +} + // Modify adds a statement modifier for attaching custom logic to the UPDATE statement. func (wcu *WorkflowContractUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *WorkflowContractUpdate { wcu.modifiers = append(wcu.modifiers, modifiers...) @@ -241,6 +234,9 @@ func (wcu *WorkflowContractUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder } func (wcu *WorkflowContractUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := wcu.check(); err != nil { + return n, err + } _spec := sqlgraph.NewUpdateSpec(workflowcontract.Table, workflowcontract.Columns, sqlgraph.NewFieldSpec(workflowcontract.FieldID, field.TypeUUID)) if ps := wcu.mutation.predicates; len(ps) > 0 { _spec.Predicate = func(selector *sql.Selector) { @@ -261,6 +257,18 @@ func (wcu *WorkflowContractUpdate) sqlSave(ctx context.Context) (n int, err erro if wcu.mutation.DescriptionCleared() { _spec.ClearField(workflowcontract.FieldDescription, field.TypeString) } + if value, ok := wcu.mutation.ScopedResourceType(); ok { + _spec.SetField(workflowcontract.FieldScopedResourceType, field.TypeEnum, value) + } + if wcu.mutation.ScopedResourceTypeCleared() { + _spec.ClearField(workflowcontract.FieldScopedResourceType, field.TypeEnum) + } + if value, ok := wcu.mutation.ScopedResourceID(); ok { + _spec.SetField(workflowcontract.FieldScopedResourceID, field.TypeUUID, value) + } + if wcu.mutation.ScopedResourceIDCleared() { + _spec.ClearField(workflowcontract.FieldScopedResourceID, field.TypeUUID) + } if wcu.mutation.VersionsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -306,35 +314,6 @@ func (wcu *WorkflowContractUpdate) sqlSave(ctx context.Context) (n int, err erro } _spec.Edges.Add = append(_spec.Edges.Add, edge) } - if wcu.mutation.OrganizationCleared() { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: workflowcontract.OrganizationTable, - Columns: []string{workflowcontract.OrganizationColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), - }, - } - _spec.Edges.Clear = append(_spec.Edges.Clear, edge) - } - if nodes := wcu.mutation.OrganizationIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: workflowcontract.OrganizationTable, - Columns: []string{workflowcontract.OrganizationColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _spec.Edges.Add = append(_spec.Edges.Add, edge) - } if wcu.mutation.WorkflowsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -380,35 +359,6 @@ func (wcu *WorkflowContractUpdate) sqlSave(ctx context.Context) (n int, err erro } _spec.Edges.Add = append(_spec.Edges.Add, edge) } - if wcu.mutation.ProjectCleared() { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: false, - Table: workflowcontract.ProjectTable, - Columns: []string{workflowcontract.ProjectColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), - }, - } - _spec.Edges.Clear = append(_spec.Edges.Clear, edge) - } - if nodes := wcu.mutation.ProjectIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: false, - Table: workflowcontract.ProjectTable, - Columns: []string{workflowcontract.ProjectColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _spec.Edges.Add = append(_spec.Edges.Add, edge) - } _spec.AddModifiers(wcu.modifiers...) if n, err = sqlgraph.UpdateNodes(ctx, wcu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { @@ -471,23 +421,43 @@ func (wcuo *WorkflowContractUpdateOne) ClearDescription() *WorkflowContractUpdat return wcuo } -// SetProjectID sets the "project_id" field. -func (wcuo *WorkflowContractUpdateOne) SetProjectID(u uuid.UUID) *WorkflowContractUpdateOne { - wcuo.mutation.SetProjectID(u) +// SetScopedResourceType sets the "scoped_resource_type" field. +func (wcuo *WorkflowContractUpdateOne) SetScopedResourceType(bs biz.ContractScope) *WorkflowContractUpdateOne { + wcuo.mutation.SetScopedResourceType(bs) return wcuo } -// SetNillableProjectID sets the "project_id" field if the given value is not nil. -func (wcuo *WorkflowContractUpdateOne) SetNillableProjectID(u *uuid.UUID) *WorkflowContractUpdateOne { +// SetNillableScopedResourceType sets the "scoped_resource_type" field if the given value is not nil. +func (wcuo *WorkflowContractUpdateOne) SetNillableScopedResourceType(bs *biz.ContractScope) *WorkflowContractUpdateOne { + if bs != nil { + wcuo.SetScopedResourceType(*bs) + } + return wcuo +} + +// ClearScopedResourceType clears the value of the "scoped_resource_type" field. +func (wcuo *WorkflowContractUpdateOne) ClearScopedResourceType() *WorkflowContractUpdateOne { + wcuo.mutation.ClearScopedResourceType() + return wcuo +} + +// SetScopedResourceID sets the "scoped_resource_id" field. +func (wcuo *WorkflowContractUpdateOne) SetScopedResourceID(u uuid.UUID) *WorkflowContractUpdateOne { + wcuo.mutation.SetScopedResourceID(u) + return wcuo +} + +// SetNillableScopedResourceID sets the "scoped_resource_id" field if the given value is not nil. +func (wcuo *WorkflowContractUpdateOne) SetNillableScopedResourceID(u *uuid.UUID) *WorkflowContractUpdateOne { if u != nil { - wcuo.SetProjectID(*u) + wcuo.SetScopedResourceID(*u) } return wcuo } -// ClearProjectID clears the value of the "project_id" field. -func (wcuo *WorkflowContractUpdateOne) ClearProjectID() *WorkflowContractUpdateOne { - wcuo.mutation.ClearProjectID() +// ClearScopedResourceID clears the value of the "scoped_resource_id" field. +func (wcuo *WorkflowContractUpdateOne) ClearScopedResourceID() *WorkflowContractUpdateOne { + wcuo.mutation.ClearScopedResourceID() return wcuo } @@ -506,25 +476,6 @@ func (wcuo *WorkflowContractUpdateOne) AddVersions(w ...*WorkflowContractVersion return wcuo.AddVersionIDs(ids...) } -// SetOrganizationID sets the "organization" edge to the Organization entity by ID. -func (wcuo *WorkflowContractUpdateOne) SetOrganizationID(id uuid.UUID) *WorkflowContractUpdateOne { - wcuo.mutation.SetOrganizationID(id) - return wcuo -} - -// SetNillableOrganizationID sets the "organization" edge to the Organization entity by ID if the given value is not nil. -func (wcuo *WorkflowContractUpdateOne) SetNillableOrganizationID(id *uuid.UUID) *WorkflowContractUpdateOne { - if id != nil { - wcuo = wcuo.SetOrganizationID(*id) - } - return wcuo -} - -// SetOrganization sets the "organization" edge to the Organization entity. -func (wcuo *WorkflowContractUpdateOne) SetOrganization(o *Organization) *WorkflowContractUpdateOne { - return wcuo.SetOrganizationID(o.ID) -} - // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by IDs. func (wcuo *WorkflowContractUpdateOne) AddWorkflowIDs(ids ...uuid.UUID) *WorkflowContractUpdateOne { wcuo.mutation.AddWorkflowIDs(ids...) @@ -540,11 +491,6 @@ func (wcuo *WorkflowContractUpdateOne) AddWorkflows(w ...*Workflow) *WorkflowCon return wcuo.AddWorkflowIDs(ids...) } -// SetProject sets the "project" edge to the Project entity. -func (wcuo *WorkflowContractUpdateOne) SetProject(p *Project) *WorkflowContractUpdateOne { - return wcuo.SetProjectID(p.ID) -} - // Mutation returns the WorkflowContractMutation object of the builder. func (wcuo *WorkflowContractUpdateOne) Mutation() *WorkflowContractMutation { return wcuo.mutation @@ -571,12 +517,6 @@ func (wcuo *WorkflowContractUpdateOne) RemoveVersions(w ...*WorkflowContractVers return wcuo.RemoveVersionIDs(ids...) } -// ClearOrganization clears the "organization" edge to the Organization entity. -func (wcuo *WorkflowContractUpdateOne) ClearOrganization() *WorkflowContractUpdateOne { - wcuo.mutation.ClearOrganization() - return wcuo -} - // ClearWorkflows clears all "workflows" edges to the Workflow entity. func (wcuo *WorkflowContractUpdateOne) ClearWorkflows() *WorkflowContractUpdateOne { wcuo.mutation.ClearWorkflows() @@ -598,12 +538,6 @@ func (wcuo *WorkflowContractUpdateOne) RemoveWorkflows(w ...*Workflow) *Workflow return wcuo.RemoveWorkflowIDs(ids...) } -// ClearProject clears the "project" edge to the Project entity. -func (wcuo *WorkflowContractUpdateOne) ClearProject() *WorkflowContractUpdateOne { - wcuo.mutation.ClearProject() - return wcuo -} - // Where appends a list predicates to the WorkflowContractUpdate builder. func (wcuo *WorkflowContractUpdateOne) Where(ps ...predicate.WorkflowContract) *WorkflowContractUpdateOne { wcuo.mutation.Where(ps...) @@ -644,6 +578,16 @@ func (wcuo *WorkflowContractUpdateOne) ExecX(ctx context.Context) { } } +// check runs all checks and user-defined validators on the builder. +func (wcuo *WorkflowContractUpdateOne) check() error { + if v, ok := wcuo.mutation.ScopedResourceType(); ok { + if err := workflowcontract.ScopedResourceTypeValidator(v); err != nil { + return &ValidationError{Name: "scoped_resource_type", err: fmt.Errorf(`ent: validator failed for field "WorkflowContract.scoped_resource_type": %w`, err)} + } + } + return nil +} + // Modify adds a statement modifier for attaching custom logic to the UPDATE statement. func (wcuo *WorkflowContractUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *WorkflowContractUpdateOne { wcuo.modifiers = append(wcuo.modifiers, modifiers...) @@ -651,6 +595,9 @@ func (wcuo *WorkflowContractUpdateOne) Modify(modifiers ...func(u *sql.UpdateBui } func (wcuo *WorkflowContractUpdateOne) sqlSave(ctx context.Context) (_node *WorkflowContract, err error) { + if err := wcuo.check(); err != nil { + return _node, err + } _spec := sqlgraph.NewUpdateSpec(workflowcontract.Table, workflowcontract.Columns, sqlgraph.NewFieldSpec(workflowcontract.FieldID, field.TypeUUID)) id, ok := wcuo.mutation.ID() if !ok { @@ -688,6 +635,18 @@ func (wcuo *WorkflowContractUpdateOne) sqlSave(ctx context.Context) (_node *Work if wcuo.mutation.DescriptionCleared() { _spec.ClearField(workflowcontract.FieldDescription, field.TypeString) } + if value, ok := wcuo.mutation.ScopedResourceType(); ok { + _spec.SetField(workflowcontract.FieldScopedResourceType, field.TypeEnum, value) + } + if wcuo.mutation.ScopedResourceTypeCleared() { + _spec.ClearField(workflowcontract.FieldScopedResourceType, field.TypeEnum) + } + if value, ok := wcuo.mutation.ScopedResourceID(); ok { + _spec.SetField(workflowcontract.FieldScopedResourceID, field.TypeUUID, value) + } + if wcuo.mutation.ScopedResourceIDCleared() { + _spec.ClearField(workflowcontract.FieldScopedResourceID, field.TypeUUID) + } if wcuo.mutation.VersionsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -733,35 +692,6 @@ func (wcuo *WorkflowContractUpdateOne) sqlSave(ctx context.Context) (_node *Work } _spec.Edges.Add = append(_spec.Edges.Add, edge) } - if wcuo.mutation.OrganizationCleared() { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: workflowcontract.OrganizationTable, - Columns: []string{workflowcontract.OrganizationColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), - }, - } - _spec.Edges.Clear = append(_spec.Edges.Clear, edge) - } - if nodes := wcuo.mutation.OrganizationIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: true, - Table: workflowcontract.OrganizationTable, - Columns: []string{workflowcontract.OrganizationColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _spec.Edges.Add = append(_spec.Edges.Add, edge) - } if wcuo.mutation.WorkflowsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -807,35 +737,6 @@ func (wcuo *WorkflowContractUpdateOne) sqlSave(ctx context.Context) (_node *Work } _spec.Edges.Add = append(_spec.Edges.Add, edge) } - if wcuo.mutation.ProjectCleared() { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: false, - Table: workflowcontract.ProjectTable, - Columns: []string{workflowcontract.ProjectColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), - }, - } - _spec.Edges.Clear = append(_spec.Edges.Clear, edge) - } - if nodes := wcuo.mutation.ProjectIDs(); len(nodes) > 0 { - edge := &sqlgraph.EdgeSpec{ - Rel: sqlgraph.M2O, - Inverse: false, - Table: workflowcontract.ProjectTable, - Columns: []string{workflowcontract.ProjectColumn}, - Bidi: false, - Target: &sqlgraph.EdgeTarget{ - IDSpec: sqlgraph.NewFieldSpec(project.FieldID, field.TypeUUID), - }, - } - for _, k := range nodes { - edge.Target.Nodes = append(edge.Target.Nodes, k) - } - _spec.Edges.Add = append(_spec.Edges.Add, edge) - } _spec.AddModifiers(wcuo.modifiers...) _node = &WorkflowContract{config: wcuo.config} _spec.Assign = _node.assignValues diff --git a/go.sum b/go.sum index 10e45e5c7..e16b77962 100644 --- a/go.sum +++ b/go.sum @@ -1079,6 +1079,7 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/oleiade/reflections v1.1.0 h1:D+I/UsXQB4esMathlt0kkZRJZdUDmhv5zGi/HOwYTWo= github.com/oleiade/reflections v1.1.0/go.mod h1:mCxx0QseeVCHs5Um5HhJeCKVC7AwS8kO67tky4rdisA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= From ccf9c0749782d4b6b83c3f16b826a1551ca4e9e4 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Fri, 4 Jul 2025 13:04:01 +0200 Subject: [PATCH 04/24] fix tests Signed-off-by: Miguel Martinez --- app/controlplane/pkg/data/ent/client.go | 16 +++ .../ent/migrate/migrations/20250704092359.sql | 8 ++ .../pkg/data/ent/migrate/migrations/atlas.sum | 8 ++ .../pkg/data/ent/migrate/schema.go | 8 ++ app/controlplane/pkg/data/ent/mutation.go | 65 ++++++++++- .../pkg/data/ent/schema/workflowcontract.go | 15 ++- .../pkg/data/ent/workflowcontract.go | 23 +++- .../pkg/data/ent/workflowcontract/where.go | 23 ++++ .../ent/workflowcontract/workflowcontract.go | 23 ++++ .../pkg/data/ent/workflowcontract_create.go | 37 ++++++ .../pkg/data/ent/workflowcontract_query.go | 110 +++++++++++++++--- .../pkg/data/ent/workflowcontract_update.go | 109 +++++++++++++++++ 12 files changed, 421 insertions(+), 24 deletions(-) create mode 100644 app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql diff --git a/app/controlplane/pkg/data/ent/client.go b/app/controlplane/pkg/data/ent/client.go index 5d44cdfa1..e1ed0c1c7 100644 --- a/app/controlplane/pkg/data/ent/client.go +++ b/app/controlplane/pkg/data/ent/client.go @@ -3535,6 +3535,22 @@ func (c *WorkflowContractClient) QueryVersions(wc *WorkflowContract) *WorkflowCo return query } +// QueryOrganization queries the organization edge of a WorkflowContract. +func (c *WorkflowContractClient) QueryOrganization(wc *WorkflowContract) *OrganizationQuery { + query := (&OrganizationClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := wc.ID + step := sqlgraph.NewStep( + sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, id), + sqlgraph.To(organization.Table, organization.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, workflowcontract.OrganizationTable, workflowcontract.OrganizationColumn), + ) + fromV = sqlgraph.Neighbors(wc.driver.Dialect(), step) + return fromV, nil + } + return query +} + // QueryWorkflows queries the workflows edge of a WorkflowContract. func (c *WorkflowContractClient) QueryWorkflows(wc *WorkflowContract) *WorkflowQuery { query := (&WorkflowClient{config: c.config}).Query() diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql new file mode 100644 index 000000000..87cba251d --- /dev/null +++ b/app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql @@ -0,0 +1,8 @@ +-- Drop index "workflowcontract_name_organization_workflow_contracts" from table: "workflow_contracts" +DROP INDEX "workflowcontract_name_organization_workflow_contracts"; +-- Modify "workflow_contracts" table +ALTER TABLE "workflow_contracts" ADD COLUMN "scoped_resource_type" character varying NULL, ADD COLUMN "scoped_resource_id" uuid NULL; +-- Create index "workflowcontract_name_organization_workflow_contracts" to table: "workflow_contracts" +CREATE UNIQUE INDEX "workflowcontract_name_organization_workflow_contracts" ON "workflow_contracts" ("name", "organization_workflow_contracts") WHERE ((deleted_at IS NULL) AND (scoped_resource_type IS NULL)); +-- Create index "workflowcontract_name_scoped_resource_type_scoped_resource_id" to table: "workflow_contracts" +CREATE UNIQUE INDEX "workflowcontract_name_scoped_resource_type_scoped_resource_id" ON "workflow_contracts" ("name", "scoped_resource_type", "scoped_resource_id") WHERE (deleted_at IS NULL); diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index a74777b78..42ac9c09a 100644 --- a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum +++ b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum @@ -1,5 +1,6 @@ <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD h1:pewT4SIwZxo6E95TRjOvYvsO2AvVZDBRPljhvi6yN3c= ======= h1:Nqn7kGmL5Hba+3tAbxdDjH6+KvSmunyHZuDIthoGQiU= @@ -7,6 +8,9 @@ h1:Nqn7kGmL5Hba+3tAbxdDjH6+KvSmunyHZuDIthoGQiU= ======= h1:oR9RWah9qFLH+GgYn2+C1UpTH2Z82Zj36QLGWRG5X+4= >>>>>>> 7a8275ef (fix tests) +======= +h1:TVyZPOeAizQac42YgtwcW2RP0MefJCyThmt5yVkE/+8= +>>>>>>> a17a71d0 (fix tests) 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -102,6 +106,7 @@ h1:oR9RWah9qFLH+GgYn2+C1UpTH2Z82Zj36QLGWRG5X+4= 20250627143634.sql h1:9UdcOm4HdWyJ8bvU/vYkzCslXIpKSn7pM0l/MJHl8n4= 20250702111701.sql h1:Ni7fuL1qU5RGjBzV0XgJi9NkZINGijF8BumPuQ9conM= <<<<<<< HEAD +<<<<<<< HEAD 20250702112642.sql h1:wrjVS+5h2hs7KNwPRBece5LgAsoEzxN/zNfvCnjoIUw= 20250704090359.sql h1:a0ksfjy2dtzviJL16HbC4eT1xBxy2qFH5mNFOpYlUrA= ======= @@ -111,3 +116,6 @@ h1:oR9RWah9qFLH+GgYn2+C1UpTH2Z82Zj36QLGWRG5X+4= ======= 20250704090525.sql h1:VO/Kf+I0GJDfL2FaHk36YZ7f6uY9VrHjrP3EuQAidHM= >>>>>>> 7a8275ef (fix tests) +======= +20250704092359.sql h1:4WDmb0R+obpATOgDONCxoYPxVLTl9jjpkzzOEfIUPIU= +>>>>>>> a17a71d0 (fix tests) diff --git a/app/controlplane/pkg/data/ent/migrate/schema.go b/app/controlplane/pkg/data/ent/migrate/schema.go index 205dcce76..9a2f43be5 100644 --- a/app/controlplane/pkg/data/ent/migrate/schema.go +++ b/app/controlplane/pkg/data/ent/migrate/schema.go @@ -659,6 +659,14 @@ var ( }, }, Indexes: []*schema.Index{ + { + Name: "workflowcontract_name_organization_workflow_contracts", + Unique: true, + Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[7]}, + Annotation: &entsql.IndexAnnotation{ + Where: "deleted_at IS NULL AND scoped_resource_type IS NULL", + }, + }, { Name: "workflowcontract_name_scoped_resource_type_scoped_resource_id", Unique: true, diff --git a/app/controlplane/pkg/data/ent/mutation.go b/app/controlplane/pkg/data/ent/mutation.go index 376a8d024..4230c0b82 100644 --- a/app/controlplane/pkg/data/ent/mutation.go +++ b/app/controlplane/pkg/data/ent/mutation.go @@ -15259,6 +15259,8 @@ type WorkflowContractMutation struct { versions map[uuid.UUID]struct{} removedversions map[uuid.UUID]struct{} clearedversions bool + organization *uuid.UUID + clearedorganization bool workflows map[uuid.UUID]struct{} removedworkflows map[uuid.UUID]struct{} clearedworkflows bool @@ -15693,6 +15695,45 @@ func (m *WorkflowContractMutation) ResetVersions() { m.removedversions = nil } +// SetOrganizationID sets the "organization" edge to the Organization entity by id. +func (m *WorkflowContractMutation) SetOrganizationID(id uuid.UUID) { + m.organization = &id +} + +// ClearOrganization clears the "organization" edge to the Organization entity. +func (m *WorkflowContractMutation) ClearOrganization() { + m.clearedorganization = true +} + +// OrganizationCleared reports if the "organization" edge to the Organization entity was cleared. +func (m *WorkflowContractMutation) OrganizationCleared() bool { + return m.clearedorganization +} + +// OrganizationID returns the "organization" edge ID in the mutation. +func (m *WorkflowContractMutation) OrganizationID() (id uuid.UUID, exists bool) { + if m.organization != nil { + return *m.organization, true + } + return +} + +// OrganizationIDs returns the "organization" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// OrganizationID instead. It exists only for internal usage by the builders. +func (m *WorkflowContractMutation) OrganizationIDs() (ids []uuid.UUID) { + if id := m.organization; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetOrganization resets all changes to the "organization" edge. +func (m *WorkflowContractMutation) ResetOrganization() { + m.organization = nil + m.clearedorganization = false +} + // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by ids. func (m *WorkflowContractMutation) AddWorkflowIDs(ids ...uuid.UUID) { if m.workflows == nil { @@ -15992,10 +16033,13 @@ func (m *WorkflowContractMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *WorkflowContractMutation) AddedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.versions != nil { edges = append(edges, workflowcontract.EdgeVersions) } + if m.organization != nil { + edges = append(edges, workflowcontract.EdgeOrganization) + } if m.workflows != nil { edges = append(edges, workflowcontract.EdgeWorkflows) } @@ -16012,6 +16056,10 @@ func (m *WorkflowContractMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case workflowcontract.EdgeOrganization: + if id := m.organization; id != nil { + return []ent.Value{*id} + } case workflowcontract.EdgeWorkflows: ids := make([]ent.Value, 0, len(m.workflows)) for id := range m.workflows { @@ -16024,7 +16072,7 @@ func (m *WorkflowContractMutation) AddedIDs(name string) []ent.Value { // RemovedEdges returns all edge names that were removed in this mutation. func (m *WorkflowContractMutation) RemovedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.removedversions != nil { edges = append(edges, workflowcontract.EdgeVersions) } @@ -16056,10 +16104,13 @@ func (m *WorkflowContractMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *WorkflowContractMutation) ClearedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.clearedversions { edges = append(edges, workflowcontract.EdgeVersions) } + if m.clearedorganization { + edges = append(edges, workflowcontract.EdgeOrganization) + } if m.clearedworkflows { edges = append(edges, workflowcontract.EdgeWorkflows) } @@ -16072,6 +16123,8 @@ func (m *WorkflowContractMutation) EdgeCleared(name string) bool { switch name { case workflowcontract.EdgeVersions: return m.clearedversions + case workflowcontract.EdgeOrganization: + return m.clearedorganization case workflowcontract.EdgeWorkflows: return m.clearedworkflows } @@ -16082,6 +16135,9 @@ func (m *WorkflowContractMutation) EdgeCleared(name string) bool { // if that edge is not defined in the schema. func (m *WorkflowContractMutation) ClearEdge(name string) error { switch name { + case workflowcontract.EdgeOrganization: + m.ClearOrganization() + return nil } return fmt.Errorf("unknown WorkflowContract unique edge %s", name) } @@ -16093,6 +16149,9 @@ func (m *WorkflowContractMutation) ResetEdge(name string) error { case workflowcontract.EdgeVersions: m.ResetVersions() return nil + case workflowcontract.EdgeOrganization: + m.ResetOrganization() + return nil case workflowcontract.EdgeWorkflows: m.ResetWorkflows() return nil diff --git a/app/controlplane/pkg/data/ent/schema/workflowcontract.go b/app/controlplane/pkg/data/ent/schema/workflowcontract.go index 455ea638f..94d0d84f7 100644 --- a/app/controlplane/pkg/data/ent/schema/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/schema/workflowcontract.go @@ -1,5 +1,5 @@ // -// Copyright 2024-2025 The Chainloop Authors. +// Copyright 2024 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -45,7 +45,7 @@ func (WorkflowContract) Fields() []ent.Field { }), field.Time("deleted_at").Optional(), field.String("description").Optional(), - // If this value is set, the contract is scoped to a project or organization + // If this value is set, the contract is scoped to a resource field.Enum("scoped_resource_type").GoType(biz.ContractScope("")).Optional(), field.UUID("scoped_resource_id", uuid.UUID{}).Optional(), } @@ -55,6 +55,11 @@ func (WorkflowContract) Fields() []ent.Field { func (WorkflowContract) Edges() []ent.Edge { return []ent.Edge{ edge.To("versions", WorkflowContractVersion.Type), + // We keep the organization edge to be able to easily list all the contracts + // regardless of the scope + edge.From("organization", Organization.Type). + Ref("workflow_contracts"). + Unique(), // A contract can be associated to multiple workflows edge.From("workflows", Workflow.Type).Ref("contract"), } @@ -62,7 +67,11 @@ func (WorkflowContract) Edges() []ent.Edge { func (WorkflowContract) Indexes() []ent.Index { return []ent.Index{ - // names are unique within a organization and affects only to non-deleted items + // names are unique within a organization and affects only to non-scoped and non-deleted items + index.Fields("name").Edges("organization").Unique().Annotations( + entsql.IndexWhere("deleted_at IS NULL AND scoped_resource_type IS NULL"), + ), + // names are unique within a resource and affects only to non-deleted items index.Fields("name", "scoped_resource_type", "scoped_resource_id").Unique().Annotations( entsql.IndexWhere("deleted_at IS NULL"), ), diff --git a/app/controlplane/pkg/data/ent/workflowcontract.go b/app/controlplane/pkg/data/ent/workflowcontract.go index 2a67948fd..b4ba03c94 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/workflowcontract.go @@ -10,6 +10,7 @@ import ( "entgo.io/ent" "entgo.io/ent/dialect/sql" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/google/uuid" ) @@ -42,11 +43,13 @@ type WorkflowContract struct { type WorkflowContractEdges struct { // Versions holds the value of the versions edge. Versions []*WorkflowContractVersion `json:"versions,omitempty"` + // Organization holds the value of the organization edge. + Organization *Organization `json:"organization,omitempty"` // Workflows holds the value of the workflows edge. Workflows []*Workflow `json:"workflows,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [3]bool } // VersionsOrErr returns the Versions value or an error if the edge @@ -58,10 +61,21 @@ func (e WorkflowContractEdges) VersionsOrErr() ([]*WorkflowContractVersion, erro return nil, &NotLoadedError{edge: "versions"} } +// OrganizationOrErr returns the Organization value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e WorkflowContractEdges) OrganizationOrErr() (*Organization, error) { + if e.Organization != nil { + return e.Organization, nil + } else if e.loadedTypes[1] { + return nil, &NotFoundError{label: organization.Label} + } + return nil, &NotLoadedError{edge: "organization"} +} + // WorkflowsOrErr returns the Workflows value or an error if the edge // was not loaded in eager-loading. func (e WorkflowContractEdges) WorkflowsOrErr() ([]*Workflow, error) { - if e.loadedTypes[1] { + if e.loadedTypes[2] { return e.Workflows, nil } return nil, &NotLoadedError{edge: "workflows"} @@ -162,6 +176,11 @@ func (wc *WorkflowContract) QueryVersions() *WorkflowContractVersionQuery { return NewWorkflowContractClient(wc.config).QueryVersions(wc) } +// QueryOrganization queries the "organization" edge of the WorkflowContract entity. +func (wc *WorkflowContract) QueryOrganization() *OrganizationQuery { + return NewWorkflowContractClient(wc.config).QueryOrganization(wc) +} + // QueryWorkflows queries the "workflows" edge of the WorkflowContract entity. func (wc *WorkflowContract) QueryWorkflows() *WorkflowQuery { return NewWorkflowContractClient(wc.config).QueryWorkflows(wc) diff --git a/app/controlplane/pkg/data/ent/workflowcontract/where.go b/app/controlplane/pkg/data/ent/workflowcontract/where.go index b7db780dd..ade940dec 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract/where.go +++ b/app/controlplane/pkg/data/ent/workflowcontract/where.go @@ -425,6 +425,29 @@ func HasVersionsWith(preds ...predicate.WorkflowContractVersion) predicate.Workf }) } +// HasOrganization applies the HasEdge predicate on the "organization" edge. +func HasOrganization() predicate.WorkflowContract { + return predicate.WorkflowContract(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, OrganizationTable, OrganizationColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasOrganizationWith applies the HasEdge predicate on the "organization" edge with a given conditions (other predicates). +func HasOrganizationWith(preds ...predicate.Organization) predicate.WorkflowContract { + return predicate.WorkflowContract(func(s *sql.Selector) { + step := newOrganizationStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // HasWorkflows applies the HasEdge predicate on the "workflows" edge. func HasWorkflows() predicate.WorkflowContract { return predicate.WorkflowContract(func(s *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go b/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go index e8ee814e2..c3b1fa48c 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/workflowcontract/workflowcontract.go @@ -31,6 +31,8 @@ const ( FieldScopedResourceID = "scoped_resource_id" // EdgeVersions holds the string denoting the versions edge name in mutations. EdgeVersions = "versions" + // EdgeOrganization holds the string denoting the organization edge name in mutations. + EdgeOrganization = "organization" // EdgeWorkflows holds the string denoting the workflows edge name in mutations. EdgeWorkflows = "workflows" // Table holds the table name of the workflowcontract in the database. @@ -42,6 +44,13 @@ const ( VersionsInverseTable = "workflow_contract_versions" // VersionsColumn is the table column denoting the versions relation/edge. VersionsColumn = "workflow_contract_versions" + // OrganizationTable is the table that holds the organization relation/edge. + OrganizationTable = "workflow_contracts" + // OrganizationInverseTable is the table name for the Organization entity. + // It exists in this package in order to avoid circular dependency with the "organization" package. + OrganizationInverseTable = "organizations" + // OrganizationColumn is the table column denoting the organization relation/edge. + OrganizationColumn = "organization_workflow_contracts" // WorkflowsTable is the table that holds the workflows relation/edge. WorkflowsTable = "workflows" // WorkflowsInverseTable is the table name for the Workflow entity. @@ -152,6 +161,13 @@ func ByVersions(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { } } +// ByOrganizationField orders the results by organization field. +func ByOrganizationField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newOrganizationStep(), sql.OrderByField(field, opts...)) + } +} + // ByWorkflowsCount orders the results by workflows count. func ByWorkflowsCount(opts ...sql.OrderTermOption) OrderOption { return func(s *sql.Selector) { @@ -172,6 +188,13 @@ func newVersionsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, false, VersionsTable, VersionsColumn), ) } +func newOrganizationStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(OrganizationInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, OrganizationTable, OrganizationColumn), + ) +} func newWorkflowsStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), diff --git a/app/controlplane/pkg/data/ent/workflowcontract_create.go b/app/controlplane/pkg/data/ent/workflowcontract_create.go index 065783ccd..766cd59bb 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_create.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_create.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontractversion" @@ -132,6 +133,25 @@ func (wcc *WorkflowContractCreate) AddVersions(w ...*WorkflowContractVersion) *W return wcc.AddVersionIDs(ids...) } +// SetOrganizationID sets the "organization" edge to the Organization entity by ID. +func (wcc *WorkflowContractCreate) SetOrganizationID(id uuid.UUID) *WorkflowContractCreate { + wcc.mutation.SetOrganizationID(id) + return wcc +} + +// SetNillableOrganizationID sets the "organization" edge to the Organization entity by ID if the given value is not nil. +func (wcc *WorkflowContractCreate) SetNillableOrganizationID(id *uuid.UUID) *WorkflowContractCreate { + if id != nil { + wcc = wcc.SetOrganizationID(*id) + } + return wcc +} + +// SetOrganization sets the "organization" edge to the Organization entity. +func (wcc *WorkflowContractCreate) SetOrganization(o *Organization) *WorkflowContractCreate { + return wcc.SetOrganizationID(o.ID) +} + // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by IDs. func (wcc *WorkflowContractCreate) AddWorkflowIDs(ids ...uuid.UUID) *WorkflowContractCreate { wcc.mutation.AddWorkflowIDs(ids...) @@ -281,6 +301,23 @@ func (wcc *WorkflowContractCreate) createSpec() (*WorkflowContract, *sqlgraph.Cr } _spec.Edges = append(_spec.Edges, edge) } + if nodes := wcc.mutation.OrganizationIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: workflowcontract.OrganizationTable, + Columns: []string{workflowcontract.OrganizationColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.organization_workflow_contracts = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } if nodes := wcc.mutation.WorkflowsIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, diff --git a/app/controlplane/pkg/data/ent/workflowcontract_query.go b/app/controlplane/pkg/data/ent/workflowcontract_query.go index 9009f4f0e..1d2e2652c 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_query.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_query.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" @@ -23,14 +24,15 @@ import ( // WorkflowContractQuery is the builder for querying WorkflowContract entities. type WorkflowContractQuery struct { config - ctx *QueryContext - order []workflowcontract.OrderOption - inters []Interceptor - predicates []predicate.WorkflowContract - withVersions *WorkflowContractVersionQuery - withWorkflows *WorkflowQuery - withFKs bool - modifiers []func(*sql.Selector) + ctx *QueryContext + order []workflowcontract.OrderOption + inters []Interceptor + predicates []predicate.WorkflowContract + withVersions *WorkflowContractVersionQuery + withOrganization *OrganizationQuery + withWorkflows *WorkflowQuery + withFKs bool + modifiers []func(*sql.Selector) // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -89,6 +91,28 @@ func (wcq *WorkflowContractQuery) QueryVersions() *WorkflowContractVersionQuery return query } +// QueryOrganization chains the current query on the "organization" edge. +func (wcq *WorkflowContractQuery) QueryOrganization() *OrganizationQuery { + query := (&OrganizationClient{config: wcq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := wcq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := wcq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(workflowcontract.Table, workflowcontract.FieldID, selector), + sqlgraph.To(organization.Table, organization.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, workflowcontract.OrganizationTable, workflowcontract.OrganizationColumn), + ) + fromU = sqlgraph.SetNeighbors(wcq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // QueryWorkflows chains the current query on the "workflows" edge. func (wcq *WorkflowContractQuery) QueryWorkflows() *WorkflowQuery { query := (&WorkflowClient{config: wcq.config}).Query() @@ -298,13 +322,14 @@ func (wcq *WorkflowContractQuery) Clone() *WorkflowContractQuery { return nil } return &WorkflowContractQuery{ - config: wcq.config, - ctx: wcq.ctx.Clone(), - order: append([]workflowcontract.OrderOption{}, wcq.order...), - inters: append([]Interceptor{}, wcq.inters...), - predicates: append([]predicate.WorkflowContract{}, wcq.predicates...), - withVersions: wcq.withVersions.Clone(), - withWorkflows: wcq.withWorkflows.Clone(), + config: wcq.config, + ctx: wcq.ctx.Clone(), + order: append([]workflowcontract.OrderOption{}, wcq.order...), + inters: append([]Interceptor{}, wcq.inters...), + predicates: append([]predicate.WorkflowContract{}, wcq.predicates...), + withVersions: wcq.withVersions.Clone(), + withOrganization: wcq.withOrganization.Clone(), + withWorkflows: wcq.withWorkflows.Clone(), // clone intermediate query. sql: wcq.sql.Clone(), path: wcq.path, @@ -323,6 +348,17 @@ func (wcq *WorkflowContractQuery) WithVersions(opts ...func(*WorkflowContractVer return wcq } +// WithOrganization tells the query-builder to eager-load the nodes that are connected to +// the "organization" edge. The optional arguments are used to configure the query builder of the edge. +func (wcq *WorkflowContractQuery) WithOrganization(opts ...func(*OrganizationQuery)) *WorkflowContractQuery { + query := (&OrganizationClient{config: wcq.config}).Query() + for _, opt := range opts { + opt(query) + } + wcq.withOrganization = query + return wcq +} + // WithWorkflows tells the query-builder to eager-load the nodes that are connected to // the "workflows" edge. The optional arguments are used to configure the query builder of the edge. func (wcq *WorkflowContractQuery) WithWorkflows(opts ...func(*WorkflowQuery)) *WorkflowContractQuery { @@ -413,11 +449,15 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook nodes = []*WorkflowContract{} withFKs = wcq.withFKs _spec = wcq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [3]bool{ wcq.withVersions != nil, + wcq.withOrganization != nil, wcq.withWorkflows != nil, } ) + if wcq.withOrganization != nil { + withFKs = true + } if withFKs { _spec.Node.Columns = append(_spec.Node.Columns, workflowcontract.ForeignKeys...) } @@ -449,6 +489,12 @@ func (wcq *WorkflowContractQuery) sqlAll(ctx context.Context, hooks ...queryHook return nil, err } } + if query := wcq.withOrganization; query != nil { + if err := wcq.loadOrganization(ctx, query, nodes, nil, + func(n *WorkflowContract, e *Organization) { n.Edges.Organization = e }); err != nil { + return nil, err + } + } if query := wcq.withWorkflows; query != nil { if err := wcq.loadWorkflows(ctx, query, nodes, func(n *WorkflowContract) { n.Edges.Workflows = []*Workflow{} }, @@ -490,6 +536,38 @@ func (wcq *WorkflowContractQuery) loadVersions(ctx context.Context, query *Workf } return nil } +func (wcq *WorkflowContractQuery) loadOrganization(ctx context.Context, query *OrganizationQuery, nodes []*WorkflowContract, init func(*WorkflowContract), assign func(*WorkflowContract, *Organization)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*WorkflowContract) + for i := range nodes { + if nodes[i].organization_workflow_contracts == nil { + continue + } + fk := *nodes[i].organization_workflow_contracts + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(organization.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "organization_workflow_contracts" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} func (wcq *WorkflowContractQuery) loadWorkflows(ctx context.Context, query *WorkflowQuery, nodes []*WorkflowContract, init func(*WorkflowContract), assign func(*WorkflowContract, *Workflow)) error { fks := make([]driver.Value, 0, len(nodes)) nodeids := make(map[uuid.UUID]*WorkflowContract) diff --git a/app/controlplane/pkg/data/ent/workflowcontract_update.go b/app/controlplane/pkg/data/ent/workflowcontract_update.go index c7cc64646..5ea09f64b 100644 --- a/app/controlplane/pkg/data/ent/workflowcontract_update.go +++ b/app/controlplane/pkg/data/ent/workflowcontract_update.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/organization" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/predicate" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflow" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/data/ent/workflowcontract" @@ -128,6 +129,25 @@ func (wcu *WorkflowContractUpdate) AddVersions(w ...*WorkflowContractVersion) *W return wcu.AddVersionIDs(ids...) } +// SetOrganizationID sets the "organization" edge to the Organization entity by ID. +func (wcu *WorkflowContractUpdate) SetOrganizationID(id uuid.UUID) *WorkflowContractUpdate { + wcu.mutation.SetOrganizationID(id) + return wcu +} + +// SetNillableOrganizationID sets the "organization" edge to the Organization entity by ID if the given value is not nil. +func (wcu *WorkflowContractUpdate) SetNillableOrganizationID(id *uuid.UUID) *WorkflowContractUpdate { + if id != nil { + wcu = wcu.SetOrganizationID(*id) + } + return wcu +} + +// SetOrganization sets the "organization" edge to the Organization entity. +func (wcu *WorkflowContractUpdate) SetOrganization(o *Organization) *WorkflowContractUpdate { + return wcu.SetOrganizationID(o.ID) +} + // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by IDs. func (wcu *WorkflowContractUpdate) AddWorkflowIDs(ids ...uuid.UUID) *WorkflowContractUpdate { wcu.mutation.AddWorkflowIDs(ids...) @@ -169,6 +189,12 @@ func (wcu *WorkflowContractUpdate) RemoveVersions(w ...*WorkflowContractVersion) return wcu.RemoveVersionIDs(ids...) } +// ClearOrganization clears the "organization" edge to the Organization entity. +func (wcu *WorkflowContractUpdate) ClearOrganization() *WorkflowContractUpdate { + wcu.mutation.ClearOrganization() + return wcu +} + // ClearWorkflows clears all "workflows" edges to the Workflow entity. func (wcu *WorkflowContractUpdate) ClearWorkflows() *WorkflowContractUpdate { wcu.mutation.ClearWorkflows() @@ -314,6 +340,35 @@ func (wcu *WorkflowContractUpdate) sqlSave(ctx context.Context) (n int, err erro } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if wcu.mutation.OrganizationCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: workflowcontract.OrganizationTable, + Columns: []string{workflowcontract.OrganizationColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := wcu.mutation.OrganizationIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: workflowcontract.OrganizationTable, + Columns: []string{workflowcontract.OrganizationColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if wcu.mutation.WorkflowsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -476,6 +531,25 @@ func (wcuo *WorkflowContractUpdateOne) AddVersions(w ...*WorkflowContractVersion return wcuo.AddVersionIDs(ids...) } +// SetOrganizationID sets the "organization" edge to the Organization entity by ID. +func (wcuo *WorkflowContractUpdateOne) SetOrganizationID(id uuid.UUID) *WorkflowContractUpdateOne { + wcuo.mutation.SetOrganizationID(id) + return wcuo +} + +// SetNillableOrganizationID sets the "organization" edge to the Organization entity by ID if the given value is not nil. +func (wcuo *WorkflowContractUpdateOne) SetNillableOrganizationID(id *uuid.UUID) *WorkflowContractUpdateOne { + if id != nil { + wcuo = wcuo.SetOrganizationID(*id) + } + return wcuo +} + +// SetOrganization sets the "organization" edge to the Organization entity. +func (wcuo *WorkflowContractUpdateOne) SetOrganization(o *Organization) *WorkflowContractUpdateOne { + return wcuo.SetOrganizationID(o.ID) +} + // AddWorkflowIDs adds the "workflows" edge to the Workflow entity by IDs. func (wcuo *WorkflowContractUpdateOne) AddWorkflowIDs(ids ...uuid.UUID) *WorkflowContractUpdateOne { wcuo.mutation.AddWorkflowIDs(ids...) @@ -517,6 +591,12 @@ func (wcuo *WorkflowContractUpdateOne) RemoveVersions(w ...*WorkflowContractVers return wcuo.RemoveVersionIDs(ids...) } +// ClearOrganization clears the "organization" edge to the Organization entity. +func (wcuo *WorkflowContractUpdateOne) ClearOrganization() *WorkflowContractUpdateOne { + wcuo.mutation.ClearOrganization() + return wcuo +} + // ClearWorkflows clears all "workflows" edges to the Workflow entity. func (wcuo *WorkflowContractUpdateOne) ClearWorkflows() *WorkflowContractUpdateOne { wcuo.mutation.ClearWorkflows() @@ -692,6 +772,35 @@ func (wcuo *WorkflowContractUpdateOne) sqlSave(ctx context.Context) (_node *Work } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if wcuo.mutation.OrganizationCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: workflowcontract.OrganizationTable, + Columns: []string{workflowcontract.OrganizationColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := wcuo.mutation.OrganizationIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: workflowcontract.OrganizationTable, + Columns: []string{workflowcontract.OrganizationColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if wcuo.mutation.WorkflowsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, From fd07cac302f14da22c8ff622458bbf14540fa3b9 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Fri, 4 Jul 2025 16:37:57 +0200 Subject: [PATCH 05/24] validate contract Signed-off-by: Miguel Martinez --- .../api/gen/temp-openapi/apidocs.swagger.json | 236 ------------------ .../pkg/data/ent/migrate/migrations/atlas.sum | 27 +- app/controlplane/pkg/data/ent/schema-viz.html | 10 +- 3 files changed, 3 insertions(+), 270 deletions(-) delete mode 100644 app/controlplane/api/gen/temp-openapi/apidocs.swagger.json diff --git a/app/controlplane/api/gen/temp-openapi/apidocs.swagger.json b/app/controlplane/api/gen/temp-openapi/apidocs.swagger.json deleted file mode 100644 index 876e2ba97..000000000 --- a/app/controlplane/api/gen/temp-openapi/apidocs.swagger.json +++ /dev/null @@ -1,236 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "title": "Chainloop Controlplane API", - "termsOfService": "https://chainloop.dev/terms", - "version": "1.0", - "contact": { - "name": "Chainloop Support", - "url": "https://chainloop.dev", - "email": "support@chainloop.dev" - } - }, - "tags": [ - { - "name": "ReferrerService", - "description": "Referrer service for discovering referred content by digest" - } - ], - "host": "cp.chainloop.dev", - "schemes": [ - "https" - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "paths": { - "/discover/shared/{digest}": { - "get": { - "summary": "Discover public shared referrer", - "description": "Returns the referrer item for a given digest in the public shared index", - "operationId": "ReferrerService_DiscoverPublicShared", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/v1DiscoverPublicSharedResponse" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "digest", - "description": "Digest is the unique identifier of the referrer to discover", - "in": "path", - "required": true, - "type": "string" - }, - { - "name": "kind", - "description": "Kind is the optional type of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ...\nUsed to filter and resolve ambiguities", - "in": "query", - "required": false, - "type": "string" - } - ], - "tags": [ - "ReferrerService" - ], - "produces": [ - "application/json" - ] - } - }, - "/discover/{digest}": { - "get": { - "summary": "Discover private referrer", - "description": "Returns the referrer item for a given digest in the organizations of the logged-in user", - "operationId": "ReferrerService_DiscoverPrivate", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/v1ReferrerServiceDiscoverPrivateResponse" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "digest", - "description": "Digest is the unique identifier of the referrer to discover", - "in": "path", - "required": true, - "type": "string" - }, - { - "name": "kind", - "description": "Kind is the optional type of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ...\nUsed to filter and resolve ambiguities", - "in": "query", - "required": false, - "type": "string" - } - ], - "tags": [ - "ReferrerService" - ], - "produces": [ - "application/json" - ] - } - } - }, - "definitions": { - "protobufAny": { - "type": "object", - "properties": { - "@type": { - "type": "string" - } - }, - "additionalProperties": {} - }, - "rpcStatus": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "details": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/protobufAny" - } - } - } - }, - "v1DiscoverPublicSharedResponse": { - "type": "object", - "properties": { - "result": { - "$ref": "#/definitions/v1ReferrerItem", - "title": "Result is the discovered referrer item" - } - }, - "description": "Response for the DiscoverPublicShared method", - "title": "DiscoverPublicSharedResponse" - }, - "v1ReferrerItem": { - "type": "object", - "properties": { - "digest": { - "type": "string", - "title": "Digest of the referrer, i.e sha256:deadbeef or sha1:beefdead" - }, - "kind": { - "type": "string", - "description": "Kind of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ..." - }, - "downloadable": { - "type": "boolean", - "title": "Downloadable indicates whether the referrer is downloadable or not from CAS" - }, - "public": { - "type": "boolean", - "title": "Public indicates whether the referrer is public since it belongs to a public workflow" - }, - "references": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/v1ReferrerItem" - }, - "title": "References contains the list of related referrer items" - }, - "created_at": { - "type": "string", - "format": "date-time", - "title": "CreatedAt is the timestamp when the referrer was created" - }, - "metadata": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "title": "Metadata contains additional descriptive information about the referrer" - }, - "annotations": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "title": "Annotations are key-value pairs associated with the referrer" - } - }, - "description": "It represents a referrer object in the system", - "title": "ReferrerItem" - }, - "v1ReferrerServiceDiscoverPrivateResponse": { - "type": "object", - "properties": { - "result": { - "$ref": "#/definitions/v1ReferrerItem", - "title": "Result is the discovered referrer item" - } - }, - "description": "Response for the DiscoverPrivate method", - "title": "ReferrerServiceDiscoverPrivateResponse" - } - }, - "securityDefinitions": { - "bearerToken": { - "type": "apiKey", - "description": "Bearer token for authentication", - "name": "Authorization", - "in": "header" - } - }, - "security": [ - { - "bearerToken": [] - } - ], - "externalDocs": { - "description": "Chainloop Official Documentation", - "url": "https://docs.chainloop.dev" - } -} diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index 42ac9c09a..40ff393af 100644 --- a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum +++ b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum @@ -1,16 +1,4 @@ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -h1:pewT4SIwZxo6E95TRjOvYvsO2AvVZDBRPljhvi6yN3c= -======= -h1:Nqn7kGmL5Hba+3tAbxdDjH6+KvSmunyHZuDIthoGQiU= ->>>>>>> 9b3f353d (feat: add columns) -======= -h1:oR9RWah9qFLH+GgYn2+C1UpTH2Z82Zj36QLGWRG5X+4= ->>>>>>> 7a8275ef (fix tests) -======= -h1:TVyZPOeAizQac42YgtwcW2RP0MefJCyThmt5yVkE/+8= ->>>>>>> a17a71d0 (fix tests) +h1:+yGkCvepb0rQgYUfTpHC+xRBgJeIOYo6DlhZMe2p76o= 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -105,17 +93,6 @@ h1:TVyZPOeAizQac42YgtwcW2RP0MefJCyThmt5yVkE/+8= 20250626100818.sql h1:MMCQid88eEs4uyCVBgkf5b0VYjyBd1EYRqRISco0rOI= 20250627143634.sql h1:9UdcOm4HdWyJ8bvU/vYkzCslXIpKSn7pM0l/MJHl8n4= 20250702111701.sql h1:Ni7fuL1qU5RGjBzV0XgJi9NkZINGijF8BumPuQ9conM= -<<<<<<< HEAD -<<<<<<< HEAD 20250702112642.sql h1:wrjVS+5h2hs7KNwPRBece5LgAsoEzxN/zNfvCnjoIUw= 20250704090359.sql h1:a0ksfjy2dtzviJL16HbC4eT1xBxy2qFH5mNFOpYlUrA= -======= -20250703212753.sql h1:Hr4sKsM+tlPRp0I9qRLnnkVUNpZ4xTH/XOQJ5nDdbek= -<<<<<<< HEAD ->>>>>>> 9b3f353d (feat: add columns) -======= -20250704090525.sql h1:VO/Kf+I0GJDfL2FaHk36YZ7f6uY9VrHjrP3EuQAidHM= ->>>>>>> 7a8275ef (fix tests) -======= -20250704092359.sql h1:4WDmb0R+obpATOgDONCxoYPxVLTl9jjpkzzOEfIUPIU= ->>>>>>> a17a71d0 (fix tests) +20250704092359.sql h1:LWwcBsaZtqp0AqIVqIirYR+X7ukcXc7fyLUjtv0e8OY= diff --git a/app/controlplane/pkg/data/ent/schema-viz.html b/app/controlplane/pkg/data/ent/schema-viz.html index c54c7412c..bbfda2835 100644 --- a/app/controlplane/pkg/data/ent/schema-viz.html +++ b/app/controlplane/pkg/data/ent/schema-viz.html @@ -70,15 +70,7 @@ } -<<<<<<< HEAD -<<<<<<< HEAD - const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"last_used_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"context\",\"type\":\"biz.OrgInvitationContext\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); -======= - const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowContract\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); ->>>>>>> 9b3f353d (feat: add columns) -======= - const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"scoped_resource_type\",\"type\":\"biz.ContractScope\"},{\"name\":\"scoped_resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); ->>>>>>> 7a8275ef (fix tests) + const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"last_used_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Group\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"member_count\",\"type\":\"int\"}]},{\"id\":\"GroupMembership\",\"fields\":[{\"name\":\"group_id\",\"type\":\"uuid.UUID\"},{\"name\":\"user_id\",\"type\":\"uuid.UUID\"},{\"name\":\"maintainer\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"membership_type\",\"type\":\"authz.MembershipType\"},{\"name\":\"member_id\",\"type\":\"uuid.UUID\"},{\"name\":\"resource_type\",\"type\":\"authz.ResourceType\"},{\"name\":\"resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"},{\"name\":\"context\",\"type\":\"biz.OrgInvitationContext\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"scoped_resource_type\",\"type\":\"biz.ContractScope\"},{\"name\":\"scoped_resource_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"APIToken\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"CASMapping\",\"to\":\"Project\",\"label\":\"project\"},{\"from\":\"Group\",\"to\":\"User\",\"label\":\"members\"},{\"from\":\"GroupMembership\",\"to\":\"Group\",\"label\":\"group\"},{\"from\":\"GroupMembership\",\"to\":\"User\",\"label\":\"user\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Organization\",\"to\":\"Group\",\"label\":\"groups\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); const nodes = new vis.DataSet((entGraph.nodes || []).map(n => ({ id: n.id, From b2689c3b2b8d073905cfd10144f57c739ed34e20 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Fri, 4 Jul 2025 16:48:59 +0200 Subject: [PATCH 06/24] feat: add contract Signed-off-by: Miguel Martinez --- app/controlplane/pkg/biz/workflowcontract.go | 2 ++ app/controlplane/pkg/data/workflow.go | 8 ++++---- app/controlplane/pkg/data/workflowcontract.go | 10 +++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index c835a4fa6..f53137577 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -96,6 +96,8 @@ type ContractCreateOpts struct { Description *string // raw representation of the contract in whatever original format it was (json, yaml, ...) Contract *Contract + // ProjectID indicates the project to be scoped to + ProjectID *uuid.UUID } type ContractUpdateOpts struct { diff --git a/app/controlplane/pkg/data/workflow.go b/app/controlplane/pkg/data/workflow.go index c0bf0b9c2..660239f91 100644 --- a/app/controlplane/pkg/data/workflow.go +++ b/app/controlplane/pkg/data/workflow.go @@ -118,11 +118,11 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts) if err != nil { if ent.IsNotFound(err) { // Create a new contract associated with the workflow - // TODO: associate it with the project soon contract, _, err = r.contractRepo.addCreateToTx(ctx, tx, &biz.ContractCreateOpts{ - OrgID: orgUUID, - Name: defaultContractName, - Contract: opts.DetectedContract, + OrgID: orgUUID, + Name: defaultContractName, + Contract: opts.DetectedContract, + ProjectID: &projectID, }) if err != nil { return fmt.Errorf("creating contract: %w", err) diff --git a/app/controlplane/pkg/data/workflowcontract.go b/app/controlplane/pkg/data/workflowcontract.go index a90b05e42..b25ed071d 100644 --- a/app/controlplane/pkg/data/workflowcontract.go +++ b/app/controlplane/pkg/data/workflowcontract.go @@ -102,11 +102,15 @@ func (r *WorkflowContractRepo) Create(ctx context.Context, opts *biz.ContractCre } func (r *WorkflowContractRepo) addCreateToTx(ctx context.Context, tx *ent.Tx, opts *biz.ContractCreateOpts) (*ent.WorkflowContract, *ent.WorkflowContractVersion, error) { - contract, err := tx.WorkflowContract.Create(). + contractQuery := tx.WorkflowContract.Create(). SetName(opts.Name).SetOrganizationID(opts.OrgID). - SetNillableDescription(opts.Description). - Save(ctx) + SetNillableDescription(opts.Description) + if opts.ProjectID != nil { + contractQuery = contractQuery.SetScopedResourceID(*opts.ProjectID).SetScopedResourceType(biz.ContractScopeProject) + } + + contract, err := contractQuery.Save(ctx) if err != nil { return nil, nil, handleError(err) } From 5c5b9d97b305bcd26628ea19bf38e1dd63020ef7 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Tue, 8 Jul 2025 23:59:01 +0200 Subject: [PATCH 07/24] contracts Signed-off-by: Miguel Martinez --- app/cli/cmd/workflow_contract_create.go | 7 +- app/cli/cmd/workflow_contract_list.go | 10 +- .../action/workflow_contract_create.go | 8 +- .../internal/action/workflow_contract_list.go | 19 +- .../controlplane/v1/response_messages.pb.go | 790 ++++++++++-------- .../controlplane/v1/response_messages.proto | 11 + .../api/controlplane/v1/shared_message.go | 8 + .../controlplane/v1/workflow_contract.pb.go | 340 ++++---- .../controlplane/v1/workflow_contract.proto | 9 +- .../v1/workflow_contract_grpc.pb.go | 2 +- .../controlplane/v1/response_messages.ts | 112 +++ .../controlplane/v1/workflow_contract.ts | 29 +- ...ntrolplane.v1.ScopedEntity.jsonschema.json | 21 + .../controlplane.v1.ScopedEntity.schema.json | 21 + ...ne.v1.WorkflowContractItem.jsonschema.json | 8 + ...lplane.v1.WorkflowContractItem.schema.json | 8 + ...ntractServiceCreateRequest.jsonschema.json | 8 + ...owContractServiceCreateRequest.schema.json | 8 + .../internal/service/workflowcontract.go | 42 +- app/controlplane/pkg/authz/authz.go | 12 +- app/controlplane/pkg/biz/workflowcontract.go | 21 +- app/controlplane/pkg/data/workflowcontract.go | 33 +- 22 files changed, 992 insertions(+), 535 deletions(-) create mode 100644 app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.jsonschema.json create mode 100644 app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.schema.json diff --git a/app/cli/cmd/workflow_contract_create.go b/app/cli/cmd/workflow_contract_create.go index 94265c588..68f5f361b 100644 --- a/app/cli/cmd/workflow_contract_create.go +++ b/app/cli/cmd/workflow_contract_create.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import ( ) func newWorkflowContractCreateCmd() *cobra.Command { - var name, description, contractPath string + var name, description, contractPath, projectName string cmd := &cobra.Command{ Use: "create", @@ -31,7 +31,7 @@ func newWorkflowContractCreateCmd() *cobra.Command { if cmd.Flags().Changed("description") { desc = &description } - res, err := action.NewWorkflowContractCreate(actionOpts).Run(name, desc, contractPath) + res, err := action.NewWorkflowContractCreate(actionOpts).Run(name, desc, contractPath, projectName) if err != nil { return err } @@ -47,6 +47,7 @@ func newWorkflowContractCreateCmd() *cobra.Command { cmd.Flags().StringVarP(&contractPath, "contract", "f", "", "path or URL to the contract schema") cmd.Flags().StringVar(&description, "description", "", "description of the contract") + cmd.Flags().StringVar(&projectName, "project", "", "project name used to scope the contract, if not set the contract will be created in the organization") return cmd } diff --git a/app/cli/cmd/workflow_contract_list.go b/app/cli/cmd/workflow_contract_list.go index b7df5e228..39bb40d6c 100644 --- a/app/cli/cmd/workflow_contract_list.go +++ b/app/cli/cmd/workflow_contract_list.go @@ -16,6 +16,7 @@ package cmd import ( + "fmt" "time" "github.com/chainloop-dev/chainloop/app/cli/internal/action" @@ -48,9 +49,14 @@ func contractItemTableOutput(contract *action.WorkflowContractItem) error { func contractListTableOutput(contracts []*action.WorkflowContractItem) error { t := newTableWriter() - t.AppendHeader(table.Row{"Name", "Latest Revision", "Created At", "Updated At", "# Workflows"}) + t.AppendHeader(table.Row{"Name", "Latest Revision", "Created At", "Updated At", "# Workflows", "Scope"}) for _, p := range contracts { - t.AppendRow(table.Row{p.Name, p.LatestRevision, p.CreatedAt.Format(time.RFC822), p.LatestRevisionCreatedAt.Format(time.RFC822), len(p.WorkflowRefs)}) + scope := "org" + if p.ScopedEntity != nil { + scope = fmt.Sprintf("%s/%s", p.ScopedEntity.Type, p.ScopedEntity.Name) + } + + t.AppendRow(table.Row{p.Name, p.LatestRevision, p.CreatedAt.Format(time.RFC822), p.LatestRevisionCreatedAt.Format(time.RFC822), len(p.WorkflowRefs), scope}) } t.Render() diff --git a/app/cli/internal/action/workflow_contract_create.go b/app/cli/internal/action/workflow_contract_create.go index ce4d96092..d0de3933e 100644 --- a/app/cli/internal/action/workflow_contract_create.go +++ b/app/cli/internal/action/workflow_contract_create.go @@ -29,13 +29,19 @@ func NewWorkflowContractCreate(cfg *ActionsOpts) *WorkflowContractCreate { return &WorkflowContractCreate{cfg} } -func (action *WorkflowContractCreate) Run(name string, description *string, contractPath string) (*WorkflowContractItem, error) { +func (action *WorkflowContractCreate) Run(name string, description *string, contractPath string, projectName string) (*WorkflowContractItem, error) { client := pb.NewWorkflowContractServiceClient(action.cfg.CPConnection) request := &pb.WorkflowContractServiceCreateRequest{ Name: name, Description: description, } + if projectName != "" { + request.ProjectReference = &pb.IdentityReference{ + Name: &projectName, + } + } + if contractPath != "" { rawContract, err := LoadFileOrURL(contractPath) if err != nil { diff --git a/app/cli/internal/action/workflow_contract_list.go b/app/cli/internal/action/workflow_contract_list.go index 159930ba2..fae0d7946 100644 --- a/app/cli/internal/action/workflow_contract_list.go +++ b/app/cli/internal/action/workflow_contract_list.go @@ -36,6 +36,13 @@ type WorkflowContractItem struct { CreatedAt *time.Time `json:"createdAt"` Workflows []string `json:"workflows,omitempty"` // TODO: remove this field after all clients are updated WorkflowRefs []*WorkflowRef `json:"workflowRefs,omitempty"` + ScopedEntity *ScopedEntity `json:"scopedEntity,omitempty"` +} + +type ScopedEntity struct { + Type string `json:"type"` + ID string `json:"id"` + Name string `json:"name"` } type WorkflowRef struct { @@ -82,7 +89,7 @@ func pbWorkflowContractItemToAction(in *pb.WorkflowContractItem) *WorkflowContra for _, w := range in.WorkflowRefs { workflowRefs = append(workflowRefs, pbWorkflowRefToAction(w)) } - return &WorkflowContractItem{ + item := &WorkflowContractItem{ Name: in.GetName(), ID: in.GetId(), LatestRevision: int(in.GetLatestRevision()), @@ -92,6 +99,16 @@ func pbWorkflowContractItemToAction(in *pb.WorkflowContractItem) *WorkflowContra Description: in.GetDescription(), LatestRevisionCreatedAt: toTimePtr(in.GetLatestRevisionCreatedAt().AsTime()), } + + if in.ScopedEntity != nil { + item.ScopedEntity = &ScopedEntity{ + Type: in.ScopedEntity.Type, + ID: in.ScopedEntity.Id, + Name: in.ScopedEntity.Name, + } + } + + return item } func pbWorkflowContractVersionItemToAction(in *pb.WorkflowContractVersionItem) *WorkflowContractVersionItem { diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.go b/app/controlplane/api/controlplane/v1/response_messages.pb.go index 1bbb89a9a..e4349b10a 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.go @@ -385,7 +385,7 @@ func (x WorkflowContractVersionItem_RawBody_Format) Number() protoreflect.EnumNu // Deprecated: Use WorkflowContractVersionItem_RawBody_Format.Descriptor instead. func (WorkflowContractVersionItem_RawBody_Format) EnumDescriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{10, 0, 0} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{11, 0, 0} } type OrgItem_PolicyViolationBlockingStrategy int32 @@ -434,7 +434,7 @@ func (x OrgItem_PolicyViolationBlockingStrategy) Number() protoreflect.EnumNumbe // Deprecated: Use OrgItem_PolicyViolationBlockingStrategy.Descriptor instead. func (OrgItem_PolicyViolationBlockingStrategy) EnumDescriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{13, 0} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{14, 0} } type CASBackendItem_ValidationStatus int32 @@ -483,7 +483,7 @@ func (x CASBackendItem_ValidationStatus) Number() protoreflect.EnumNumber { // Deprecated: Use CASBackendItem_ValidationStatus.Descriptor instead. func (CASBackendItem_ValidationStatus) EnumDescriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{14, 0} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{15, 0} } type WorkflowItem struct { @@ -1310,6 +1310,8 @@ type WorkflowContractItem struct { // Deprecated: Marked as deprecated in controlplane/v1/response_messages.proto. WorkflowNames []string `protobuf:"bytes,5,rep,name=workflow_names,json=workflowNames,proto3" json:"workflow_names,omitempty"` WorkflowRefs []*WorkflowRef `protobuf:"bytes,7,rep,name=workflow_refs,json=workflowRefs,proto3" json:"workflow_refs,omitempty"` + // wether the contract is scoped to an entity in the organization + ScopedEntity *ScopedEntity `protobuf:"bytes,9,opt,name=scoped_entity,json=scopedEntity,proto3" json:"scoped_entity,omitempty"` } func (x *WorkflowContractItem) Reset() { @@ -1401,6 +1403,79 @@ func (x *WorkflowContractItem) GetWorkflowRefs() []*WorkflowRef { return nil } +func (x *WorkflowContractItem) GetScopedEntity() *ScopedEntity { + if x != nil { + return x.ScopedEntity + } + return nil +} + +type ScopedEntity struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Type is the type of the scoped entity i.e project or org + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + // ID is the id of the scoped entity + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + // Name is the name of the scoped entity + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ScopedEntity) Reset() { + *x = ScopedEntity{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ScopedEntity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScopedEntity) ProtoMessage() {} + +func (x *ScopedEntity) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ScopedEntity.ProtoReflect.Descriptor instead. +func (*ScopedEntity) Descriptor() ([]byte, []int) { + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{9} +} + +func (x *ScopedEntity) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *ScopedEntity) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ScopedEntity) GetName() string { + if x != nil { + return x.Name + } + return "" +} + type WorkflowRef struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1414,7 +1489,7 @@ type WorkflowRef struct { func (x *WorkflowRef) Reset() { *x = WorkflowRef{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1427,7 +1502,7 @@ func (x *WorkflowRef) String() string { func (*WorkflowRef) ProtoMessage() {} func (x *WorkflowRef) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[9] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1440,7 +1515,7 @@ func (x *WorkflowRef) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowRef.ProtoReflect.Descriptor instead. func (*WorkflowRef) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{9} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{10} } func (x *WorkflowRef) GetId() string { @@ -1484,7 +1559,7 @@ type WorkflowContractVersionItem struct { func (x *WorkflowContractVersionItem) Reset() { *x = WorkflowContractVersionItem{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1497,7 +1572,7 @@ func (x *WorkflowContractVersionItem) String() string { func (*WorkflowContractVersionItem) ProtoMessage() {} func (x *WorkflowContractVersionItem) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[10] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1510,7 +1585,7 @@ func (x *WorkflowContractVersionItem) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowContractVersionItem.ProtoReflect.Descriptor instead. func (*WorkflowContractVersionItem) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{10} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{11} } func (x *WorkflowContractVersionItem) GetId() string { @@ -1591,7 +1666,7 @@ type User struct { func (x *User) Reset() { *x = User{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1604,7 +1679,7 @@ func (x *User) String() string { func (*User) ProtoMessage() {} func (x *User) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[11] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1617,7 +1692,7 @@ func (x *User) ProtoReflect() protoreflect.Message { // Deprecated: Use User.ProtoReflect.Descriptor instead. func (*User) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{11} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{12} } func (x *User) GetId() string { @@ -1672,7 +1747,7 @@ type OrgMembershipItem struct { func (x *OrgMembershipItem) Reset() { *x = OrgMembershipItem{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[12] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1685,7 +1760,7 @@ func (x *OrgMembershipItem) String() string { func (*OrgMembershipItem) ProtoMessage() {} func (x *OrgMembershipItem) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[12] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1698,7 +1773,7 @@ func (x *OrgMembershipItem) ProtoReflect() protoreflect.Message { // Deprecated: Use OrgMembershipItem.ProtoReflect.Descriptor instead. func (*OrgMembershipItem) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{12} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{13} } func (x *OrgMembershipItem) GetId() string { @@ -1764,7 +1839,7 @@ type OrgItem struct { func (x *OrgItem) Reset() { *x = OrgItem{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[13] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1777,7 +1852,7 @@ func (x *OrgItem) String() string { func (*OrgItem) ProtoMessage() {} func (x *OrgItem) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[13] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1790,7 +1865,7 @@ func (x *OrgItem) ProtoReflect() protoreflect.Message { // Deprecated: Use OrgItem.ProtoReflect.Descriptor instead. func (*OrgItem) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{13} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{14} } func (x *OrgItem) GetId() string { @@ -1848,7 +1923,7 @@ type CASBackendItem struct { func (x *CASBackendItem) Reset() { *x = CASBackendItem{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[14] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1861,7 +1936,7 @@ func (x *CASBackendItem) String() string { func (*CASBackendItem) ProtoMessage() {} func (x *CASBackendItem) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[14] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1874,7 +1949,7 @@ func (x *CASBackendItem) ProtoReflect() protoreflect.Message { // Deprecated: Use CASBackendItem.ProtoReflect.Descriptor instead. func (*CASBackendItem) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{14} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{15} } func (x *CASBackendItem) GetId() string { @@ -1975,7 +2050,7 @@ type APITokenItem struct { func (x *APITokenItem) Reset() { *x = APITokenItem{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[15] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1988,7 +2063,7 @@ func (x *APITokenItem) String() string { func (*APITokenItem) ProtoMessage() {} func (x *APITokenItem) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[15] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2001,7 +2076,7 @@ func (x *APITokenItem) ProtoReflect() protoreflect.Message { // Deprecated: Use APITokenItem.ProtoReflect.Descriptor instead. func (*APITokenItem) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{15} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{16} } func (x *APITokenItem) GetId() string { @@ -2095,7 +2170,7 @@ type AttestationItem_PolicyEvaluationStatus struct { func (x *AttestationItem_PolicyEvaluationStatus) Reset() { *x = AttestationItem_PolicyEvaluationStatus{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[18] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2108,7 +2183,7 @@ func (x *AttestationItem_PolicyEvaluationStatus) String() string { func (*AttestationItem_PolicyEvaluationStatus) ProtoMessage() {} func (x *AttestationItem_PolicyEvaluationStatus) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[18] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2164,7 +2239,7 @@ type AttestationItem_EnvVariable struct { func (x *AttestationItem_EnvVariable) Reset() { *x = AttestationItem_EnvVariable{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[19] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2177,7 +2252,7 @@ func (x *AttestationItem_EnvVariable) String() string { func (*AttestationItem_EnvVariable) ProtoMessage() {} func (x *AttestationItem_EnvVariable) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[19] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2232,7 +2307,7 @@ type AttestationItem_Material struct { func (x *AttestationItem_Material) Reset() { *x = AttestationItem_Material{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[20] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2245,7 +2320,7 @@ func (x *AttestationItem_Material) String() string { func (*AttestationItem_Material) ProtoMessage() {} func (x *AttestationItem_Material) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[20] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2336,7 +2411,7 @@ type WorkflowContractVersionItem_RawBody struct { func (x *WorkflowContractVersionItem_RawBody) Reset() { *x = WorkflowContractVersionItem_RawBody{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[25] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2349,7 +2424,7 @@ func (x *WorkflowContractVersionItem_RawBody) String() string { func (*WorkflowContractVersionItem_RawBody) ProtoMessage() {} func (x *WorkflowContractVersionItem_RawBody) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[25] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2362,7 +2437,7 @@ func (x *WorkflowContractVersionItem_RawBody) ProtoReflect() protoreflect.Messag // Deprecated: Use WorkflowContractVersionItem_RawBody.ProtoReflect.Descriptor instead. func (*WorkflowContractVersionItem_RawBody) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{10, 0} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{11, 0} } func (x *WorkflowContractVersionItem_RawBody) GetBody() []byte { @@ -2391,7 +2466,7 @@ type CASBackendItem_Limits struct { func (x *CASBackendItem_Limits) Reset() { *x = CASBackendItem_Limits{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[26] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2404,7 +2479,7 @@ func (x *CASBackendItem_Limits) String() string { func (*CASBackendItem_Limits) ProtoMessage() {} func (x *CASBackendItem_Limits) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_response_messages_proto_msgTypes[26] + mi := &file_controlplane_v1_response_messages_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2417,7 +2492,7 @@ func (x *CASBackendItem_Limits) ProtoReflect() protoreflect.Message { // Deprecated: Use CASBackendItem_Limits.ProtoReflect.Descriptor instead. func (*CASBackendItem_Limits) Descriptor() ([]byte, []int) { - return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{14, 0} + return file_controlplane_v1_response_messages_proto_rawDescGZIP(), []int{15, 0} } func (x *CASBackendItem_Limits) GetMaxBytes() int64 { @@ -2681,7 +2756,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x87, 0x03, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, + 0x22, 0xcb, 0x03, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, @@ -2705,239 +2780,248 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x66, 0x52, 0x0c, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x66, 0x73, 0x22, 0xed, 0x01, 0x0a, 0x0b, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x66, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, - 0x6d, 0x65, 0x2d, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, - 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, - 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, - 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, - 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, - 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, - 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9d, 0x04, 0x0a, 0x1b, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x74, 0x12, 0x39, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x12, 0x57, 0x0a, 0x0c, - 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, - 0x2e, 0x52, 0x61, 0x77, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0xd1, 0x01, 0x0a, 0x07, 0x52, - 0x61, 0x77, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x5e, 0x0a, 0x06, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x52, 0x61, 0x77, 0x42, 0x6f, 0x64, 0x79, - 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x09, 0xba, 0x48, 0x06, 0x82, 0x01, 0x03, 0x22, - 0x01, 0x00, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x52, 0x0a, 0x06, 0x46, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, - 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, - 0x0b, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x59, 0x41, 0x4d, 0x4c, 0x10, 0x02, 0x12, 0x0e, - 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x43, 0x55, 0x45, 0x10, 0x03, 0x42, 0x0a, - 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x22, 0xa3, 0x01, 0x0a, 0x04, 0x55, - 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, - 0x22, 0xbf, 0x02, 0x0a, 0x11, 0x4f, 0x72, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x03, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x03, 0x6f, - 0x72, 0x67, 0x12, 0x29, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x18, 0x0a, - 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x33, 0x0a, - 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, - 0x6c, 0x65, 0x22, 0xa5, 0x03, 0x0a, 0x07, 0x4f, 0x72, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x66, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x73, 0x63, + 0x6f, 0x70, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x52, 0x0c, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x46, + 0x0a, 0x0c, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xed, 0x01, 0x0a, 0x0b, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x66, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2d, 0x64, + 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, + 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, + 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, + 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, + 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x0c, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9d, 0x04, 0x0a, 0x1b, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x83, 0x01, - 0x0a, 0x21, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x5f, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x65, 0x67, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x49, - 0x74, 0x65, 0x6d, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, + 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, + 0x02, 0x76, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x42, 0x02, + 0x18, 0x01, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x12, 0x57, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x52, 0x61, 0x77, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0xd1, 0x01, 0x0a, 0x07, 0x52, 0x61, 0x77, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x5e, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x52, 0x61, 0x77, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x42, 0x09, 0xba, 0x48, 0x06, 0x82, 0x01, 0x03, 0x22, 0x01, 0x00, 0x52, 0x06, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x52, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x46, 0x4f, 0x52, 0x4d, + 0x41, 0x54, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x46, 0x4f, 0x52, + 0x4d, 0x41, 0x54, 0x5f, 0x59, 0x41, 0x4d, 0x4c, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, + 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x43, 0x55, 0x45, 0x10, 0x03, 0x42, 0x0a, 0x0a, 0x08, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x22, 0xa3, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xbf, 0x02, 0x0a, + 0x11, 0x4f, 0x72, 0x67, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x49, 0x74, + 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x03, 0x6f, 0x72, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x03, 0x6f, 0x72, 0x67, 0x12, 0x29, + 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, + 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x72, 0x6f, 0x6c, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0xa5, + 0x03, 0x0a, 0x07, 0x4f, 0x72, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x83, 0x01, 0x0a, 0x21, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x69, 0x6f, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x2e, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, + 0x1e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x69, + 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, + 0xb4, 0x01, 0x0a, 0x1f, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x61, 0x74, - 0x65, 0x67, 0x79, 0x52, 0x1e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, - 0x65, 0x67, 0x79, 0x22, 0xb4, 0x01, 0x0a, 0x1f, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x69, - 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x53, - 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x32, 0x0a, 0x2e, 0x50, 0x4f, 0x4c, 0x49, 0x43, + 0x65, 0x67, 0x79, 0x12, 0x32, 0x0a, 0x2e, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, + 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x49, 0x4e, 0x47, + 0x5f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, - 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, 0x50, - 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, - 0x59, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x2f, 0x0a, 0x2b, 0x50, 0x4f, 0x4c, - 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, - 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x02, 0x22, 0xf5, 0x04, 0x0a, 0x0e, 0x43, - 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5d, 0x0a, 0x11, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x3e, - 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, - 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x69, 0x73, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x25, 0x0a, 0x06, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, - 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, - 0x10, 0x02, 0x22, 0xdb, 0x03, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, - 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, - 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, - 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, - 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x72, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, - 0x41, 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, 0x41, 0x74, - 0x2a, 0xa6, 0x01, 0x0a, 0x09, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, - 0x0a, 0x16, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x55, - 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, - 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, - 0x12, 0x15, 0x0a, 0x11, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, - 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x55, 0x4e, 0x5f, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x04, 0x12, - 0x18, 0x0a, 0x14, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, - 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xaf, 0x01, 0x0a, 0x0e, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x1b, - 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, - 0x1a, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, - 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1d, 0x0a, - 0x19, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, - 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, - 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, - 0x4f, 0x52, 0x47, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, - 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, - 0x52, 0x47, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x04, 0x2a, 0x60, 0x0a, 0x0e, 0x41, - 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, - 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x26, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, - 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x6d, 0x0a, - 0x12, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x41, 0x75, 0x74, 0x68, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x45, 0x44, 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, - 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2b, 0x0a, 0x21, 0x46, 0x45, 0x44, - 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, - 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x84, 0x01, 0x0a, - 0x19, 0x55, 0x73, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x4e, 0x6f, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x68, 0x69, 0x70, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x29, 0x55, 0x53, - 0x45, 0x52, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, - 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x32, 0x0a, 0x28, 0x55, 0x53, 0x45, - 0x52, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, - 0x53, 0x48, 0x49, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, - 0x4e, 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, - 0x45, 0xf4, 0x03, 0x2a, 0x80, 0x01, 0x0a, 0x17, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4f, 0x72, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x2c, 0x0a, 0x28, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, - 0x45, 0x52, 0x5f, 0x4f, 0x46, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x31, 0x0a, - 0x27, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, - 0x5f, 0x4f, 0x46, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, - 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, - 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, - 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, - 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x42, 0x4c, + 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x2f, 0x0a, 0x2b, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, + 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x49, + 0x4e, 0x47, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x41, 0x44, 0x56, 0x49, + 0x53, 0x4f, 0x52, 0x59, 0x10, 0x02, 0x22, 0xf5, 0x04, 0x0a, 0x0e, 0x43, 0x41, 0x53, 0x42, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5d, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, + 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x3e, 0x0a, 0x06, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x41, 0x53, + 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, + 0x5f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, + 0x73, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x25, 0x0a, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x6e, + 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, + 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x22, 0xdb, + 0x03, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, + 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x72, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x3c, + 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, 0x41, 0x74, 0x2a, 0xa6, 0x01, 0x0a, + 0x09, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x55, + 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, + 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, + 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, + 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x52, + 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, + 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xaf, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x4d, 0x45, 0x4d, 0x42, + 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, + 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, + 0x5f, 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x4d, + 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, + 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x4d, 0x42, + 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x5f, + 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, 0x42, 0x45, + 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x4d, + 0x45, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x04, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, + 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, + 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xa8, + 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x46, 0x65, 0x64, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x41, 0x75, 0x74, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x24, 0x0a, 0x20, 0x46, 0x45, 0x44, 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x55, 0x54, + 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2b, 0x0a, 0x21, 0x46, 0x45, 0x44, 0x45, 0x52, 0x41, 0x54, + 0x45, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, + 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, + 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x84, 0x01, 0x0a, 0x19, 0x55, 0x73, 0x65, + 0x72, 0x57, 0x69, 0x74, 0x68, 0x4e, 0x6f, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x29, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x57, + 0x49, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, + 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x32, 0x0a, 0x28, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x57, 0x49, + 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4f, 0x52, + 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, + 0x80, 0x01, 0x0a, 0x17, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x4f, 0x66, 0x4f, 0x72, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2c, 0x0a, 0x28, 0x55, + 0x53, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x4f, + 0x46, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x31, 0x0a, 0x27, 0x55, 0x53, 0x45, + 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x4f, 0x46, 0x5f, + 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, + 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, + 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2953,7 +3037,7 @@ func file_controlplane_v1_response_messages_proto_rawDescGZIP() []byte { } var file_controlplane_v1_response_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_controlplane_v1_response_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_controlplane_v1_response_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_controlplane_v1_response_messages_proto_goTypes = []interface{}{ (RunStatus)(0), // 0: controlplane.v1.RunStatus (MembershipRole)(0), // 1: controlplane.v1.MembershipRole @@ -2973,82 +3057,84 @@ var file_controlplane_v1_response_messages_proto_goTypes = []interface{}{ (*PolicyViolation)(nil), // 15: controlplane.v1.PolicyViolation (*PolicyReference)(nil), // 16: controlplane.v1.PolicyReference (*WorkflowContractItem)(nil), // 17: controlplane.v1.WorkflowContractItem - (*WorkflowRef)(nil), // 18: controlplane.v1.WorkflowRef - (*WorkflowContractVersionItem)(nil), // 19: controlplane.v1.WorkflowContractVersionItem - (*User)(nil), // 20: controlplane.v1.User - (*OrgMembershipItem)(nil), // 21: controlplane.v1.OrgMembershipItem - (*OrgItem)(nil), // 22: controlplane.v1.OrgItem - (*CASBackendItem)(nil), // 23: controlplane.v1.CASBackendItem - (*APITokenItem)(nil), // 24: controlplane.v1.APITokenItem - nil, // 25: controlplane.v1.AttestationItem.AnnotationsEntry - nil, // 26: controlplane.v1.AttestationItem.PolicyEvaluationsEntry - (*AttestationItem_PolicyEvaluationStatus)(nil), // 27: controlplane.v1.AttestationItem.PolicyEvaluationStatus - (*AttestationItem_EnvVariable)(nil), // 28: controlplane.v1.AttestationItem.EnvVariable - (*AttestationItem_Material)(nil), // 29: controlplane.v1.AttestationItem.Material - nil, // 30: controlplane.v1.AttestationItem.Material.AnnotationsEntry - nil, // 31: controlplane.v1.PolicyEvaluation.AnnotationsEntry - nil, // 32: controlplane.v1.PolicyEvaluation.WithEntry - nil, // 33: controlplane.v1.PolicyReference.DigestEntry - (*WorkflowContractVersionItem_RawBody)(nil), // 34: controlplane.v1.WorkflowContractVersionItem.RawBody - (*CASBackendItem_Limits)(nil), // 35: controlplane.v1.CASBackendItem.Limits - (*timestamppb.Timestamp)(nil), // 36: google.protobuf.Timestamp - (v1.CraftingSchema_Runner_RunnerType)(0), // 37: workflowcontract.v1.CraftingSchema.Runner.RunnerType - (*v1.CraftingSchema)(nil), // 38: workflowcontract.v1.CraftingSchema + (*ScopedEntity)(nil), // 18: controlplane.v1.ScopedEntity + (*WorkflowRef)(nil), // 19: controlplane.v1.WorkflowRef + (*WorkflowContractVersionItem)(nil), // 20: controlplane.v1.WorkflowContractVersionItem + (*User)(nil), // 21: controlplane.v1.User + (*OrgMembershipItem)(nil), // 22: controlplane.v1.OrgMembershipItem + (*OrgItem)(nil), // 23: controlplane.v1.OrgItem + (*CASBackendItem)(nil), // 24: controlplane.v1.CASBackendItem + (*APITokenItem)(nil), // 25: controlplane.v1.APITokenItem + nil, // 26: controlplane.v1.AttestationItem.AnnotationsEntry + nil, // 27: controlplane.v1.AttestationItem.PolicyEvaluationsEntry + (*AttestationItem_PolicyEvaluationStatus)(nil), // 28: controlplane.v1.AttestationItem.PolicyEvaluationStatus + (*AttestationItem_EnvVariable)(nil), // 29: controlplane.v1.AttestationItem.EnvVariable + (*AttestationItem_Material)(nil), // 30: controlplane.v1.AttestationItem.Material + nil, // 31: controlplane.v1.AttestationItem.Material.AnnotationsEntry + nil, // 32: controlplane.v1.PolicyEvaluation.AnnotationsEntry + nil, // 33: controlplane.v1.PolicyEvaluation.WithEntry + nil, // 34: controlplane.v1.PolicyReference.DigestEntry + (*WorkflowContractVersionItem_RawBody)(nil), // 35: controlplane.v1.WorkflowContractVersionItem.RawBody + (*CASBackendItem_Limits)(nil), // 36: controlplane.v1.CASBackendItem.Limits + (*timestamppb.Timestamp)(nil), // 37: google.protobuf.Timestamp + (v1.CraftingSchema_Runner_RunnerType)(0), // 38: workflowcontract.v1.CraftingSchema.Runner.RunnerType + (*v1.CraftingSchema)(nil), // 39: workflowcontract.v1.CraftingSchema } var file_controlplane_v1_response_messages_proto_depIdxs = []int32{ - 36, // 0: controlplane.v1.WorkflowItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 0: controlplane.v1.WorkflowItem.created_at:type_name -> google.protobuf.Timestamp 10, // 1: controlplane.v1.WorkflowItem.last_run:type_name -> controlplane.v1.WorkflowRunItem - 36, // 2: controlplane.v1.WorkflowRunItem.created_at:type_name -> google.protobuf.Timestamp - 36, // 3: controlplane.v1.WorkflowRunItem.finished_at:type_name -> google.protobuf.Timestamp + 37, // 2: controlplane.v1.WorkflowRunItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 3: controlplane.v1.WorkflowRunItem.finished_at:type_name -> google.protobuf.Timestamp 0, // 4: controlplane.v1.WorkflowRunItem.status:type_name -> controlplane.v1.RunStatus 9, // 5: controlplane.v1.WorkflowRunItem.workflow:type_name -> controlplane.v1.WorkflowItem - 37, // 6: controlplane.v1.WorkflowRunItem.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 19, // 7: controlplane.v1.WorkflowRunItem.contract_version:type_name -> controlplane.v1.WorkflowContractVersionItem + 38, // 6: controlplane.v1.WorkflowRunItem.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 20, // 7: controlplane.v1.WorkflowRunItem.contract_version:type_name -> controlplane.v1.WorkflowContractVersionItem 11, // 8: controlplane.v1.WorkflowRunItem.version:type_name -> controlplane.v1.ProjectVersion - 36, // 9: controlplane.v1.ProjectVersion.created_at:type_name -> google.protobuf.Timestamp - 36, // 10: controlplane.v1.ProjectVersion.released_at:type_name -> google.protobuf.Timestamp - 28, // 11: controlplane.v1.AttestationItem.env_vars:type_name -> controlplane.v1.AttestationItem.EnvVariable - 29, // 12: controlplane.v1.AttestationItem.materials:type_name -> controlplane.v1.AttestationItem.Material - 25, // 13: controlplane.v1.AttestationItem.annotations:type_name -> controlplane.v1.AttestationItem.AnnotationsEntry - 26, // 14: controlplane.v1.AttestationItem.policy_evaluations:type_name -> controlplane.v1.AttestationItem.PolicyEvaluationsEntry - 27, // 15: controlplane.v1.AttestationItem.policy_evaluation_status:type_name -> controlplane.v1.AttestationItem.PolicyEvaluationStatus + 37, // 9: controlplane.v1.ProjectVersion.created_at:type_name -> google.protobuf.Timestamp + 37, // 10: controlplane.v1.ProjectVersion.released_at:type_name -> google.protobuf.Timestamp + 29, // 11: controlplane.v1.AttestationItem.env_vars:type_name -> controlplane.v1.AttestationItem.EnvVariable + 30, // 12: controlplane.v1.AttestationItem.materials:type_name -> controlplane.v1.AttestationItem.Material + 26, // 13: controlplane.v1.AttestationItem.annotations:type_name -> controlplane.v1.AttestationItem.AnnotationsEntry + 27, // 14: controlplane.v1.AttestationItem.policy_evaluations:type_name -> controlplane.v1.AttestationItem.PolicyEvaluationsEntry + 28, // 15: controlplane.v1.AttestationItem.policy_evaluation_status:type_name -> controlplane.v1.AttestationItem.PolicyEvaluationStatus 14, // 16: controlplane.v1.PolicyEvaluations.evaluations:type_name -> controlplane.v1.PolicyEvaluation - 31, // 17: controlplane.v1.PolicyEvaluation.annotations:type_name -> controlplane.v1.PolicyEvaluation.AnnotationsEntry - 32, // 18: controlplane.v1.PolicyEvaluation.with:type_name -> controlplane.v1.PolicyEvaluation.WithEntry + 32, // 17: controlplane.v1.PolicyEvaluation.annotations:type_name -> controlplane.v1.PolicyEvaluation.AnnotationsEntry + 33, // 18: controlplane.v1.PolicyEvaluation.with:type_name -> controlplane.v1.PolicyEvaluation.WithEntry 15, // 19: controlplane.v1.PolicyEvaluation.violations:type_name -> controlplane.v1.PolicyViolation 16, // 20: controlplane.v1.PolicyEvaluation.policy_reference:type_name -> controlplane.v1.PolicyReference 16, // 21: controlplane.v1.PolicyEvaluation.group_reference:type_name -> controlplane.v1.PolicyReference - 33, // 22: controlplane.v1.PolicyReference.digest:type_name -> controlplane.v1.PolicyReference.DigestEntry - 36, // 23: controlplane.v1.WorkflowContractItem.created_at:type_name -> google.protobuf.Timestamp - 36, // 24: controlplane.v1.WorkflowContractItem.latest_revision_created_at:type_name -> google.protobuf.Timestamp - 18, // 25: controlplane.v1.WorkflowContractItem.workflow_refs:type_name -> controlplane.v1.WorkflowRef - 36, // 26: controlplane.v1.WorkflowContractVersionItem.created_at:type_name -> google.protobuf.Timestamp - 38, // 27: controlplane.v1.WorkflowContractVersionItem.v1:type_name -> workflowcontract.v1.CraftingSchema - 34, // 28: controlplane.v1.WorkflowContractVersionItem.raw_contract:type_name -> controlplane.v1.WorkflowContractVersionItem.RawBody - 36, // 29: controlplane.v1.User.created_at:type_name -> google.protobuf.Timestamp - 22, // 30: controlplane.v1.OrgMembershipItem.org:type_name -> controlplane.v1.OrgItem - 20, // 31: controlplane.v1.OrgMembershipItem.user:type_name -> controlplane.v1.User - 36, // 32: controlplane.v1.OrgMembershipItem.created_at:type_name -> google.protobuf.Timestamp - 36, // 33: controlplane.v1.OrgMembershipItem.updated_at:type_name -> google.protobuf.Timestamp - 1, // 34: controlplane.v1.OrgMembershipItem.role:type_name -> controlplane.v1.MembershipRole - 36, // 35: controlplane.v1.OrgItem.created_at:type_name -> google.protobuf.Timestamp - 7, // 36: controlplane.v1.OrgItem.default_policy_violation_strategy:type_name -> controlplane.v1.OrgItem.PolicyViolationBlockingStrategy - 36, // 37: controlplane.v1.CASBackendItem.created_at:type_name -> google.protobuf.Timestamp - 36, // 38: controlplane.v1.CASBackendItem.validated_at:type_name -> google.protobuf.Timestamp - 8, // 39: controlplane.v1.CASBackendItem.validation_status:type_name -> controlplane.v1.CASBackendItem.ValidationStatus - 35, // 40: controlplane.v1.CASBackendItem.limits:type_name -> controlplane.v1.CASBackendItem.Limits - 36, // 41: controlplane.v1.APITokenItem.created_at:type_name -> google.protobuf.Timestamp - 36, // 42: controlplane.v1.APITokenItem.revoked_at:type_name -> google.protobuf.Timestamp - 36, // 43: controlplane.v1.APITokenItem.expires_at:type_name -> google.protobuf.Timestamp - 36, // 44: controlplane.v1.APITokenItem.last_used_at:type_name -> google.protobuf.Timestamp - 13, // 45: controlplane.v1.AttestationItem.PolicyEvaluationsEntry.value:type_name -> controlplane.v1.PolicyEvaluations - 30, // 46: controlplane.v1.AttestationItem.Material.annotations:type_name -> controlplane.v1.AttestationItem.Material.AnnotationsEntry - 6, // 47: controlplane.v1.WorkflowContractVersionItem.RawBody.format:type_name -> controlplane.v1.WorkflowContractVersionItem.RawBody.Format - 48, // [48:48] is the sub-list for method output_type - 48, // [48:48] is the sub-list for method input_type - 48, // [48:48] is the sub-list for extension type_name - 48, // [48:48] is the sub-list for extension extendee - 0, // [0:48] is the sub-list for field type_name + 34, // 22: controlplane.v1.PolicyReference.digest:type_name -> controlplane.v1.PolicyReference.DigestEntry + 37, // 23: controlplane.v1.WorkflowContractItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 24: controlplane.v1.WorkflowContractItem.latest_revision_created_at:type_name -> google.protobuf.Timestamp + 19, // 25: controlplane.v1.WorkflowContractItem.workflow_refs:type_name -> controlplane.v1.WorkflowRef + 18, // 26: controlplane.v1.WorkflowContractItem.scoped_entity:type_name -> controlplane.v1.ScopedEntity + 37, // 27: controlplane.v1.WorkflowContractVersionItem.created_at:type_name -> google.protobuf.Timestamp + 39, // 28: controlplane.v1.WorkflowContractVersionItem.v1:type_name -> workflowcontract.v1.CraftingSchema + 35, // 29: controlplane.v1.WorkflowContractVersionItem.raw_contract:type_name -> controlplane.v1.WorkflowContractVersionItem.RawBody + 37, // 30: controlplane.v1.User.created_at:type_name -> google.protobuf.Timestamp + 23, // 31: controlplane.v1.OrgMembershipItem.org:type_name -> controlplane.v1.OrgItem + 21, // 32: controlplane.v1.OrgMembershipItem.user:type_name -> controlplane.v1.User + 37, // 33: controlplane.v1.OrgMembershipItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 34: controlplane.v1.OrgMembershipItem.updated_at:type_name -> google.protobuf.Timestamp + 1, // 35: controlplane.v1.OrgMembershipItem.role:type_name -> controlplane.v1.MembershipRole + 37, // 36: controlplane.v1.OrgItem.created_at:type_name -> google.protobuf.Timestamp + 7, // 37: controlplane.v1.OrgItem.default_policy_violation_strategy:type_name -> controlplane.v1.OrgItem.PolicyViolationBlockingStrategy + 37, // 38: controlplane.v1.CASBackendItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 39: controlplane.v1.CASBackendItem.validated_at:type_name -> google.protobuf.Timestamp + 8, // 40: controlplane.v1.CASBackendItem.validation_status:type_name -> controlplane.v1.CASBackendItem.ValidationStatus + 36, // 41: controlplane.v1.CASBackendItem.limits:type_name -> controlplane.v1.CASBackendItem.Limits + 37, // 42: controlplane.v1.APITokenItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 43: controlplane.v1.APITokenItem.revoked_at:type_name -> google.protobuf.Timestamp + 37, // 44: controlplane.v1.APITokenItem.expires_at:type_name -> google.protobuf.Timestamp + 37, // 45: controlplane.v1.APITokenItem.last_used_at:type_name -> google.protobuf.Timestamp + 13, // 46: controlplane.v1.AttestationItem.PolicyEvaluationsEntry.value:type_name -> controlplane.v1.PolicyEvaluations + 31, // 47: controlplane.v1.AttestationItem.Material.annotations:type_name -> controlplane.v1.AttestationItem.Material.AnnotationsEntry + 6, // 48: controlplane.v1.WorkflowContractVersionItem.RawBody.format:type_name -> controlplane.v1.WorkflowContractVersionItem.RawBody.Format + 49, // [49:49] is the sub-list for method output_type + 49, // [49:49] is the sub-list for method input_type + 49, // [49:49] is the sub-list for extension type_name + 49, // [49:49] is the sub-list for extension extendee + 0, // [0:49] is the sub-list for field type_name } func init() { file_controlplane_v1_response_messages_proto_init() } @@ -3166,7 +3252,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkflowRef); i { + switch v := v.(*ScopedEntity); i { case 0: return &v.state case 1: @@ -3178,7 +3264,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkflowContractVersionItem); i { + switch v := v.(*WorkflowRef); i { case 0: return &v.state case 1: @@ -3190,7 +3276,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*User); i { + switch v := v.(*WorkflowContractVersionItem); i { case 0: return &v.state case 1: @@ -3202,7 +3288,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OrgMembershipItem); i { + switch v := v.(*User); i { case 0: return &v.state case 1: @@ -3214,7 +3300,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OrgItem); i { + switch v := v.(*OrgMembershipItem); i { case 0: return &v.state case 1: @@ -3226,7 +3312,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CASBackendItem); i { + switch v := v.(*OrgItem); i { case 0: return &v.state case 1: @@ -3238,6 +3324,18 @@ func file_controlplane_v1_response_messages_proto_init() { } } file_controlplane_v1_response_messages_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CASBackendItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controlplane_v1_response_messages_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APITokenItem); i { case 0: return &v.state @@ -3249,7 +3347,7 @@ func file_controlplane_v1_response_messages_proto_init() { return nil } } - file_controlplane_v1_response_messages_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_response_messages_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationItem_PolicyEvaluationStatus); i { case 0: return &v.state @@ -3261,7 +3359,7 @@ func file_controlplane_v1_response_messages_proto_init() { return nil } } - file_controlplane_v1_response_messages_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_response_messages_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationItem_EnvVariable); i { case 0: return &v.state @@ -3273,7 +3371,7 @@ func file_controlplane_v1_response_messages_proto_init() { return nil } } - file_controlplane_v1_response_messages_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_response_messages_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationItem_Material); i { case 0: return &v.state @@ -3285,7 +3383,7 @@ func file_controlplane_v1_response_messages_proto_init() { return nil } } - file_controlplane_v1_response_messages_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_response_messages_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WorkflowContractVersionItem_RawBody); i { case 0: return &v.state @@ -3297,7 +3395,7 @@ func file_controlplane_v1_response_messages_proto_init() { return nil } } - file_controlplane_v1_response_messages_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_response_messages_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CASBackendItem_Limits); i { case 0: return &v.state @@ -3310,7 +3408,7 @@ func file_controlplane_v1_response_messages_proto_init() { } } } - file_controlplane_v1_response_messages_proto_msgTypes[10].OneofWrappers = []interface{}{ + file_controlplane_v1_response_messages_proto_msgTypes[11].OneofWrappers = []interface{}{ (*WorkflowContractVersionItem_V1)(nil), } type x struct{} @@ -3319,7 +3417,7 @@ func file_controlplane_v1_response_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controlplane_v1_response_messages_proto_rawDesc, NumEnums: 9, - NumMessages: 27, + NumMessages: 28, NumExtensions: 0, NumServices: 0, }, diff --git a/app/controlplane/api/controlplane/v1/response_messages.proto b/app/controlplane/api/controlplane/v1/response_messages.proto index 9d5600806..80cc8f1d7 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.proto +++ b/app/controlplane/api/controlplane/v1/response_messages.proto @@ -176,6 +176,17 @@ message WorkflowContractItem { // Workflows associated with this contract repeated string workflow_names = 5 [deprecated = true]; repeated WorkflowRef workflow_refs = 7; + // wether the contract is scoped to an entity in the organization + ScopedEntity scoped_entity = 9; +} + +message ScopedEntity { + // Type is the type of the scoped entity i.e project or org + string type = 1; + // ID is the id of the scoped entity + string id = 2; + // Name is the name of the scoped entity + string name = 3; } message WorkflowRef { diff --git a/app/controlplane/api/controlplane/v1/shared_message.go b/app/controlplane/api/controlplane/v1/shared_message.go index 8fd0e8847..9ffd40e0c 100644 --- a/app/controlplane/api/controlplane/v1/shared_message.go +++ b/app/controlplane/api/controlplane/v1/shared_message.go @@ -40,3 +40,11 @@ func (i *IdentityReference) Parse() (*uuid.UUID, *string, error) { return nil, nil, nil } + +func (i *IdentityReference) IsSet() bool { + if i == nil { + return false + } + + return i.GetId() != "" || i.GetName() != "" +} diff --git a/app/controlplane/api/controlplane/v1/workflow_contract.pb.go b/app/controlplane/api/controlplane/v1/workflow_contract.pb.go index 8b5f24bd9..5b65e3d17 100644 --- a/app/controlplane/api/controlplane/v1/workflow_contract.pb.go +++ b/app/controlplane/api/controlplane/v1/workflow_contract.pb.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -130,6 +130,8 @@ type WorkflowContractServiceCreateRequest struct { // Raw representation of the contract in json, yaml or cue RawContract []byte `protobuf:"bytes,4,opt,name=raw_contract,json=rawContract,proto3" json:"raw_contract,omitempty"` Description *string `protobuf:"bytes,3,opt,name=description,proto3,oneof" json:"description,omitempty"` + // You might need to specify a project reference if you want/need to create a contract scoped to a project + ProjectReference *IdentityReference `protobuf:"bytes,5,opt,name=project_reference,json=projectReference,proto3" json:"project_reference,omitempty"` } func (x *WorkflowContractServiceCreateRequest) Reset() { @@ -185,6 +187,13 @@ func (x *WorkflowContractServiceCreateRequest) GetDescription() string { return "" } +func (x *WorkflowContractServiceCreateRequest) GetProjectReference() *IdentityReference { + if x != nil { + return x.ProjectReference + } + return nil +} + type WorkflowContractServiceCreateResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -651,17 +660,116 @@ var file_controlplane_v1_workflow_contract_proto_rawDesc = []byte{ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x24, 0x0a, 0x22, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x64, 0x0a, 0x23, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x1a, 0x24, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, + 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x24, 0x0a, 0x22, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x64, 0x0a, 0x23, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x9a, 0x02, 0x0a, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x22, 0xeb, 0x02, 0x0a, 0x24, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, + 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, + 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, + 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, + 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, + 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, + 0x4f, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x10, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x66, 0x0a, 0x25, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x9a, 0x02, 0x0a, 0x24, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, + 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, + 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, + 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, + 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, + 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x25, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x96, 0x02, 0x0a, 0x25, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x55, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x95, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x41, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x12, 0x48, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xde, + 0x01, 0x0a, 0x26, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, + 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, + 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, + 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, + 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, + 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, + 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x9a, 0x02, 0x0a, 0x27, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x95, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, + 0x41, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x12, 0x48, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, + 0x65, 0x6d, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc0, 0x01, 0x0a, 0x24, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, @@ -671,146 +779,55 @@ var file_controlplane_v1_workflow_contract_proto_rawDesc = []byte{ 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x66, 0x0a, 0x25, 0x57, 0x6f, 0x72, + 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x27, 0x0a, 0x25, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xf6, 0x04, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x22, 0x9a, 0x02, 0x0a, 0x24, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, - 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, - 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, - 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, - 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, - 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, - 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, - 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0e, - 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x96, - 0x02, 0x0a, 0x25, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x71, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, - 0x95, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, - 0x74, 0x65, 0x6d, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x48, 0x0a, - 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x01, 0x0a, 0x26, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, - 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, - 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, - 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, - 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, - 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x9a, 0x02, 0x0a, 0x27, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x95, 0x01, - 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x49, 0x74, 0x65, - 0x6d, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x48, 0x0a, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x72, 0x65, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc0, 0x01, 0x0a, 0x24, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x97, - 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, - 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, - 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, - 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, - 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, - 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, - 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x27, 0x0a, 0x25, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0xf6, 0x04, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x71, 0x0a, - 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x77, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, + 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x77, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x06, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x08, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x37, + 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x08, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x77, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x35, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, - 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, - 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -840,32 +857,34 @@ var file_controlplane_v1_workflow_contract_proto_goTypes = []interface{}{ (*WorkflowContractServiceUpdateResponse_Result)(nil), // 10: controlplane.v1.WorkflowContractServiceUpdateResponse.Result (*WorkflowContractServiceDescribeResponse_Result)(nil), // 11: controlplane.v1.WorkflowContractServiceDescribeResponse.Result (*WorkflowContractItem)(nil), // 12: controlplane.v1.WorkflowContractItem - (*WorkflowContractVersionItem)(nil), // 13: controlplane.v1.WorkflowContractVersionItem + (*IdentityReference)(nil), // 13: controlplane.v1.IdentityReference + (*WorkflowContractVersionItem)(nil), // 14: controlplane.v1.WorkflowContractVersionItem } var file_controlplane_v1_workflow_contract_proto_depIdxs = []int32{ 12, // 0: controlplane.v1.WorkflowContractServiceListResponse.result:type_name -> controlplane.v1.WorkflowContractItem - 12, // 1: controlplane.v1.WorkflowContractServiceCreateResponse.result:type_name -> controlplane.v1.WorkflowContractItem - 10, // 2: controlplane.v1.WorkflowContractServiceUpdateResponse.result:type_name -> controlplane.v1.WorkflowContractServiceUpdateResponse.Result - 11, // 3: controlplane.v1.WorkflowContractServiceDescribeResponse.result:type_name -> controlplane.v1.WorkflowContractServiceDescribeResponse.Result - 12, // 4: controlplane.v1.WorkflowContractServiceUpdateResponse.Result.contract:type_name -> controlplane.v1.WorkflowContractItem - 13, // 5: controlplane.v1.WorkflowContractServiceUpdateResponse.Result.revision:type_name -> controlplane.v1.WorkflowContractVersionItem - 12, // 6: controlplane.v1.WorkflowContractServiceDescribeResponse.Result.contract:type_name -> controlplane.v1.WorkflowContractItem - 13, // 7: controlplane.v1.WorkflowContractServiceDescribeResponse.Result.revision:type_name -> controlplane.v1.WorkflowContractVersionItem - 0, // 8: controlplane.v1.WorkflowContractService.List:input_type -> controlplane.v1.WorkflowContractServiceListRequest - 2, // 9: controlplane.v1.WorkflowContractService.Create:input_type -> controlplane.v1.WorkflowContractServiceCreateRequest - 4, // 10: controlplane.v1.WorkflowContractService.Update:input_type -> controlplane.v1.WorkflowContractServiceUpdateRequest - 6, // 11: controlplane.v1.WorkflowContractService.Describe:input_type -> controlplane.v1.WorkflowContractServiceDescribeRequest - 8, // 12: controlplane.v1.WorkflowContractService.Delete:input_type -> controlplane.v1.WorkflowContractServiceDeleteRequest - 1, // 13: controlplane.v1.WorkflowContractService.List:output_type -> controlplane.v1.WorkflowContractServiceListResponse - 3, // 14: controlplane.v1.WorkflowContractService.Create:output_type -> controlplane.v1.WorkflowContractServiceCreateResponse - 5, // 15: controlplane.v1.WorkflowContractService.Update:output_type -> controlplane.v1.WorkflowContractServiceUpdateResponse - 7, // 16: controlplane.v1.WorkflowContractService.Describe:output_type -> controlplane.v1.WorkflowContractServiceDescribeResponse - 9, // 17: controlplane.v1.WorkflowContractService.Delete:output_type -> controlplane.v1.WorkflowContractServiceDeleteResponse - 13, // [13:18] is the sub-list for method output_type - 8, // [8:13] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 13, // 1: controlplane.v1.WorkflowContractServiceCreateRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 12, // 2: controlplane.v1.WorkflowContractServiceCreateResponse.result:type_name -> controlplane.v1.WorkflowContractItem + 10, // 3: controlplane.v1.WorkflowContractServiceUpdateResponse.result:type_name -> controlplane.v1.WorkflowContractServiceUpdateResponse.Result + 11, // 4: controlplane.v1.WorkflowContractServiceDescribeResponse.result:type_name -> controlplane.v1.WorkflowContractServiceDescribeResponse.Result + 12, // 5: controlplane.v1.WorkflowContractServiceUpdateResponse.Result.contract:type_name -> controlplane.v1.WorkflowContractItem + 14, // 6: controlplane.v1.WorkflowContractServiceUpdateResponse.Result.revision:type_name -> controlplane.v1.WorkflowContractVersionItem + 12, // 7: controlplane.v1.WorkflowContractServiceDescribeResponse.Result.contract:type_name -> controlplane.v1.WorkflowContractItem + 14, // 8: controlplane.v1.WorkflowContractServiceDescribeResponse.Result.revision:type_name -> controlplane.v1.WorkflowContractVersionItem + 0, // 9: controlplane.v1.WorkflowContractService.List:input_type -> controlplane.v1.WorkflowContractServiceListRequest + 2, // 10: controlplane.v1.WorkflowContractService.Create:input_type -> controlplane.v1.WorkflowContractServiceCreateRequest + 4, // 11: controlplane.v1.WorkflowContractService.Update:input_type -> controlplane.v1.WorkflowContractServiceUpdateRequest + 6, // 12: controlplane.v1.WorkflowContractService.Describe:input_type -> controlplane.v1.WorkflowContractServiceDescribeRequest + 8, // 13: controlplane.v1.WorkflowContractService.Delete:input_type -> controlplane.v1.WorkflowContractServiceDeleteRequest + 1, // 14: controlplane.v1.WorkflowContractService.List:output_type -> controlplane.v1.WorkflowContractServiceListResponse + 3, // 15: controlplane.v1.WorkflowContractService.Create:output_type -> controlplane.v1.WorkflowContractServiceCreateResponse + 5, // 16: controlplane.v1.WorkflowContractService.Update:output_type -> controlplane.v1.WorkflowContractServiceUpdateResponse + 7, // 17: controlplane.v1.WorkflowContractService.Describe:output_type -> controlplane.v1.WorkflowContractServiceDescribeResponse + 9, // 18: controlplane.v1.WorkflowContractService.Delete:output_type -> controlplane.v1.WorkflowContractServiceDeleteResponse + 14, // [14:19] is the sub-list for method output_type + 9, // [9:14] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_controlplane_v1_workflow_contract_proto_init() } @@ -874,6 +893,7 @@ func file_controlplane_v1_workflow_contract_proto_init() { return } file_controlplane_v1_response_messages_proto_init() + file_controlplane_v1_shared_message_proto_init() if !protoimpl.UnsafeEnabled { file_controlplane_v1_workflow_contract_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WorkflowContractServiceListRequest); i { diff --git a/app/controlplane/api/controlplane/v1/workflow_contract.proto b/app/controlplane/api/controlplane/v1/workflow_contract.proto index a56b6fe75..d96eb00dc 100644 --- a/app/controlplane/api/controlplane/v1/workflow_contract.proto +++ b/app/controlplane/api/controlplane/v1/workflow_contract.proto @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package controlplane.v1; import "buf/validate/validate.proto"; import "controlplane/v1/response_messages.proto"; +import "controlplane/v1/shared_message.proto"; option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1"; @@ -49,6 +50,9 @@ message WorkflowContractServiceCreateRequest { bytes raw_contract = 4; optional string description = 3; + + // You might need to specify a project reference if you want/need to create a contract scoped to a project + IdentityReference project_reference = 5; } message WorkflowContractServiceCreateResponse { @@ -87,6 +91,9 @@ message WorkflowContractServiceDescribeRequest { } }]; int32 revision = 2; + + // You might need to specify a project reference if you want/need to describe a contract scoped to a project + IdentityReference project_reference = 5; } message WorkflowContractServiceDescribeResponse { diff --git a/app/controlplane/api/controlplane/v1/workflow_contract_grpc.pb.go b/app/controlplane/api/controlplane/v1/workflow_contract_grpc.pb.go index 2572b676a..83ec2a572 100644 --- a/app/controlplane/api/controlplane/v1/workflow_contract_grpc.pb.go +++ b/app/controlplane/api/controlplane/v1/workflow_contract_grpc.pb.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts index cefad198a..e69eedfe2 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts @@ -437,6 +437,17 @@ export interface WorkflowContractItem { */ workflowNames: string[]; workflowRefs: WorkflowRef[]; + /** wether the contract is scoped to an entity in the organization */ + scopedEntity?: ScopedEntity; +} + +export interface ScopedEntity { + /** Type is the type of the scoped entity i.e project or org */ + type: string; + /** ID is the id of the scoped entity */ + id: string; + /** Name is the name of the scoped entity */ + name: string; } export interface WorkflowRef { @@ -2806,6 +2817,7 @@ function createBaseWorkflowContractItem(): WorkflowContractItem { latestRevisionCreatedAt: undefined, workflowNames: [], workflowRefs: [], + scopedEntity: undefined, }; } @@ -2835,6 +2847,9 @@ export const WorkflowContractItem = { for (const v of message.workflowRefs) { WorkflowRef.encode(v!, writer.uint32(58).fork()).ldelim(); } + if (message.scopedEntity !== undefined) { + ScopedEntity.encode(message.scopedEntity, writer.uint32(74).fork()).ldelim(); + } return writer; }, @@ -2901,6 +2916,13 @@ export const WorkflowContractItem = { message.workflowRefs.push(WorkflowRef.decode(reader, reader.uint32())); continue; + case 9: + if (tag !== 74) { + break; + } + + message.scopedEntity = ScopedEntity.decode(reader, reader.uint32()); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -2924,6 +2946,7 @@ export const WorkflowContractItem = { workflowRefs: Array.isArray(object?.workflowRefs) ? object.workflowRefs.map((e: any) => WorkflowRef.fromJSON(e)) : [], + scopedEntity: isSet(object.scopedEntity) ? ScopedEntity.fromJSON(object.scopedEntity) : undefined, }; }, @@ -2946,6 +2969,8 @@ export const WorkflowContractItem = { } else { obj.workflowRefs = []; } + message.scopedEntity !== undefined && + (obj.scopedEntity = message.scopedEntity ? ScopedEntity.toJSON(message.scopedEntity) : undefined); return obj; }, @@ -2963,6 +2988,93 @@ export const WorkflowContractItem = { message.latestRevisionCreatedAt = object.latestRevisionCreatedAt ?? undefined; message.workflowNames = object.workflowNames?.map((e) => e) || []; message.workflowRefs = object.workflowRefs?.map((e) => WorkflowRef.fromPartial(e)) || []; + message.scopedEntity = (object.scopedEntity !== undefined && object.scopedEntity !== null) + ? ScopedEntity.fromPartial(object.scopedEntity) + : undefined; + return message; + }, +}; + +function createBaseScopedEntity(): ScopedEntity { + return { type: "", id: "", name: "" }; +} + +export const ScopedEntity = { + encode(message: ScopedEntity, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.type !== "") { + writer.uint32(10).string(message.type); + } + if (message.id !== "") { + writer.uint32(18).string(message.id); + } + if (message.name !== "") { + writer.uint32(26).string(message.name); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ScopedEntity { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseScopedEntity(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.type = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.id = reader.string(); + continue; + case 3: + if (tag !== 26) { + break; + } + + message.name = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): ScopedEntity { + return { + type: isSet(object.type) ? String(object.type) : "", + id: isSet(object.id) ? String(object.id) : "", + name: isSet(object.name) ? String(object.name) : "", + }; + }, + + toJSON(message: ScopedEntity): unknown { + const obj: any = {}; + message.type !== undefined && (obj.type = message.type); + message.id !== undefined && (obj.id = message.id); + message.name !== undefined && (obj.name = message.name); + return obj; + }, + + create, I>>(base?: I): ScopedEntity { + return ScopedEntity.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): ScopedEntity { + const message = createBaseScopedEntity(); + message.type = object.type ?? ""; + message.id = object.id ?? ""; + message.name = object.name ?? ""; return message; }, }; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/workflow_contract.ts b/app/controlplane/api/gen/frontend/controlplane/v1/workflow_contract.ts index 56c63f0fd..60260f75b 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/workflow_contract.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/workflow_contract.ts @@ -3,6 +3,7 @@ import { grpc } from "@improbable-eng/grpc-web"; import { BrowserHeaders } from "browser-headers"; import _m0 from "protobufjs/minimal"; import { WorkflowContractItem, WorkflowContractVersionItem } from "./response_messages"; +import { IdentityReference } from "./shared_message"; export const protobufPackage = "controlplane.v1"; @@ -17,7 +18,11 @@ export interface WorkflowContractServiceCreateRequest { name: string; /** Raw representation of the contract in json, yaml or cue */ rawContract: Uint8Array; - description?: string | undefined; + description?: + | string + | undefined; + /** You might need to specify a project reference if you want/need to create a contract scoped to a project */ + projectReference?: IdentityReference; } export interface WorkflowContractServiceCreateResponse { @@ -176,7 +181,7 @@ export const WorkflowContractServiceListResponse = { }; function createBaseWorkflowContractServiceCreateRequest(): WorkflowContractServiceCreateRequest { - return { name: "", rawContract: new Uint8Array(0), description: undefined }; + return { name: "", rawContract: new Uint8Array(0), description: undefined, projectReference: undefined }; } export const WorkflowContractServiceCreateRequest = { @@ -190,6 +195,9 @@ export const WorkflowContractServiceCreateRequest = { if (message.description !== undefined) { writer.uint32(26).string(message.description); } + if (message.projectReference !== undefined) { + IdentityReference.encode(message.projectReference, writer.uint32(42).fork()).ldelim(); + } return writer; }, @@ -221,6 +229,13 @@ export const WorkflowContractServiceCreateRequest = { message.description = reader.string(); continue; + case 5: + if (tag !== 42) { + break; + } + + message.projectReference = IdentityReference.decode(reader, reader.uint32()); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -235,6 +250,9 @@ export const WorkflowContractServiceCreateRequest = { name: isSet(object.name) ? String(object.name) : "", rawContract: isSet(object.rawContract) ? bytesFromBase64(object.rawContract) : new Uint8Array(0), description: isSet(object.description) ? String(object.description) : undefined, + projectReference: isSet(object.projectReference) + ? IdentityReference.fromJSON(object.projectReference) + : undefined, }; }, @@ -244,6 +262,10 @@ export const WorkflowContractServiceCreateRequest = { message.rawContract !== undefined && (obj.rawContract = base64FromBytes(message.rawContract !== undefined ? message.rawContract : new Uint8Array(0))); message.description !== undefined && (obj.description = message.description); + message.projectReference !== undefined && + (obj.projectReference = message.projectReference + ? IdentityReference.toJSON(message.projectReference) + : undefined); return obj; }, @@ -260,6 +282,9 @@ export const WorkflowContractServiceCreateRequest = { message.name = object.name ?? ""; message.rawContract = object.rawContract ?? new Uint8Array(0); message.description = object.description ?? undefined; + message.projectReference = (object.projectReference !== undefined && object.projectReference !== null) + ? IdentityReference.fromPartial(object.projectReference) + : undefined; return message; }, }; diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.jsonschema.json new file mode 100644 index 000000000..2925be4e1 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.jsonschema.json @@ -0,0 +1,21 @@ +{ + "$id": "controlplane.v1.ScopedEntity.jsonschema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "id": { + "description": "ID is the id of the scoped entity", + "type": "string" + }, + "name": { + "description": "Name is the name of the scoped entity", + "type": "string" + }, + "type": { + "description": "Type is the type of the scoped entity i.e project or org", + "type": "string" + } + }, + "title": "Scoped Entity", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.schema.json new file mode 100644 index 000000000..c4b5f2591 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.ScopedEntity.schema.json @@ -0,0 +1,21 @@ +{ + "$id": "controlplane.v1.ScopedEntity.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "id": { + "description": "ID is the id of the scoped entity", + "type": "string" + }, + "name": { + "description": "Name is the name of the scoped entity", + "type": "string" + }, + "type": { + "description": "Type is the type of the scoped entity i.e project or org", + "type": "string" + } + }, + "title": "Scoped Entity", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.jsonschema.json index 1af502336..4b840f5ab 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.jsonschema.json @@ -14,6 +14,10 @@ "^(latest_revision_created_at)$": { "$ref": "google.protobuf.Timestamp.jsonschema.json" }, + "^(scoped_entity)$": { + "$ref": "controlplane.v1.ScopedEntity.jsonschema.json", + "description": "wether the contract is scoped to an entity in the organization" + }, "^(workflow_names)$": { "description": "Workflows associated with this contract", "items": { @@ -49,6 +53,10 @@ "name": { "type": "string" }, + "scopedEntity": { + "$ref": "controlplane.v1.ScopedEntity.jsonschema.json", + "description": "wether the contract is scoped to an entity in the organization" + }, "workflowNames": { "description": "Workflows associated with this contract", "items": { diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.schema.json index 216dcf46f..675fad47e 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractItem.schema.json @@ -14,6 +14,10 @@ "^(latestRevisionCreatedAt)$": { "$ref": "google.protobuf.Timestamp.schema.json" }, + "^(scopedEntity)$": { + "$ref": "controlplane.v1.ScopedEntity.schema.json", + "description": "wether the contract is scoped to an entity in the organization" + }, "^(workflowNames)$": { "description": "Workflows associated with this contract", "items": { @@ -49,6 +53,10 @@ "name": { "type": "string" }, + "scoped_entity": { + "$ref": "controlplane.v1.ScopedEntity.schema.json", + "description": "wether the contract is scoped to an entity in the organization" + }, "workflow_names": { "description": "Workflows associated with this contract", "items": { diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.jsonschema.json index db0042de6..4574d5258 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.jsonschema.json @@ -3,6 +3,10 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, "patternProperties": { + "^(project_reference)$": { + "$ref": "controlplane.v1.IdentityReference.jsonschema.json", + "description": "You might need to specify a project reference if you want/need to create a contract scoped to a project" + }, "^(raw_contract)$": { "description": "Raw representation of the contract in json, yaml or cue", "pattern": "^[A-Za-z0-9+/]*={0,2}$", @@ -16,6 +20,10 @@ "name": { "type": "string" }, + "projectReference": { + "$ref": "controlplane.v1.IdentityReference.jsonschema.json", + "description": "You might need to specify a project reference if you want/need to create a contract scoped to a project" + }, "rawContract": { "description": "Raw representation of the contract in json, yaml or cue", "pattern": "^[A-Za-z0-9+/]*={0,2}$", diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.schema.json index 7e5437859..2e3c8ec1b 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowContractServiceCreateRequest.schema.json @@ -3,6 +3,10 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, "patternProperties": { + "^(projectReference)$": { + "$ref": "controlplane.v1.IdentityReference.schema.json", + "description": "You might need to specify a project reference if you want/need to create a contract scoped to a project" + }, "^(rawContract)$": { "description": "Raw representation of the contract in json, yaml or cue", "pattern": "^[A-Za-z0-9+/]*={0,2}$", @@ -16,6 +20,10 @@ "name": { "type": "string" }, + "project_reference": { + "$ref": "controlplane.v1.IdentityReference.schema.json", + "description": "You might need to specify a project reference if you want/need to create a contract scoped to a project" + }, "raw_contract": { "description": "Raw representation of the contract in json, yaml or cue", "pattern": "^[A-Za-z0-9+/]*={0,2}$", diff --git a/app/controlplane/internal/service/workflowcontract.go b/app/controlplane/internal/service/workflowcontract.go index e3659f6aa..17bc05801 100644 --- a/app/controlplane/internal/service/workflowcontract.go +++ b/app/controlplane/internal/service/workflowcontract.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,9 +20,11 @@ import ( pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" "github.com/chainloop-dev/chainloop/app/controlplane/internal/usercontext/entities" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/authz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/unmarshal" errors "github.com/go-kratos/kratos/v2/errors" + "github.com/google/uuid" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -93,6 +95,23 @@ func (s *WorkflowContractService) Create(ctx context.Context, req *pb.WorkflowCo return nil, err } + // Force project if RBAC is enabled + if rbacEnabled(ctx) && !req.ProjectReference.IsSet() { + return nil, errors.BadRequest("invalid", "project is required") + } + + // if the project is provided we make sure it exists and the user has permission to it + var projectID *uuid.UUID + if req.ProjectReference.IsSet() { + // Make sure the provided project exists and the user has permission to create tokens in it + project, err := s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProjectReference(), authz.PolicyWorkflowContractCreate) + if err != nil { + return nil, err + } + + projectID = &project.ID + } + // we need this token to forward it to the provider service next token, err := entities.GetRawToken(ctx) if err != nil { @@ -107,9 +126,12 @@ func (s *WorkflowContractService) Create(ctx context.Context, req *pb.WorkflowCo // Currently supporting only v1 version schema, err := s.contractUseCase.Create(ctx, &biz.WorkflowContractCreateOpts{ - OrgID: currentOrg.ID, - Name: req.Name, Description: req.Description, - RawSchema: req.RawContract}) + OrgID: currentOrg.ID, + Name: req.Name, + Description: req.Description, + RawSchema: req.RawContract, + ProjectID: projectID, + }) if err != nil { return nil, handleUseCaseErr(err, s.log) } @@ -178,7 +200,7 @@ func bizWorkFlowContractToPb(schema *biz.WorkflowContract) *pb.WorkflowContractI workflowNames = append(workflowNames, ref.Name) } - return &pb.WorkflowContractItem{ + result := &pb.WorkflowContractItem{ Id: schema.ID.String(), CreatedAt: timestamppb.New(*schema.CreatedAt), Name: schema.Name, @@ -188,6 +210,16 @@ func bizWorkFlowContractToPb(schema *biz.WorkflowContract) *pb.WorkflowContractI WorkflowRefs: workflowRefs, Description: schema.Description, } + + if schema.ScopedEntity != nil { + result.ScopedEntity = &pb.ScopedEntity{ + Type: schema.ScopedEntity.Type, + Id: schema.ScopedEntity.ID.String(), + Name: schema.ScopedEntity.Name, + } + } + + return result } func bizWorkFlowContractVersionToPb(schema *biz.WorkflowContractVersion) *pb.WorkflowContractVersionItem { diff --git a/app/controlplane/pkg/authz/authz.go b/app/controlplane/pkg/authz/authz.go index 4da273a17..1eb64343e 100644 --- a/app/controlplane/pkg/authz/authz.go +++ b/app/controlplane/pkg/authz/authz.go @@ -275,19 +275,27 @@ var RolesMap = map[Role][]*Policy{ RoleProjectViewer: { PolicyWorkflowRead, PolicyWorkflowRunRead, + // workflow contracts + PolicyWorkflowContractList, + PolicyWorkflowContractRead, }, // RoleProjectAdmin: represents a project administrator. It's the higher role in project resources, // and it's only considered when the org-level role is `RoleOrgMember` RoleProjectAdmin: { - // attestations + // workflow contracts + PolicyWorkflowContractList, + PolicyWorkflowContractRead, + PolicyWorkflowContractCreate, + PolicyWorkflowContractUpdate, + PolicyWorkflowContractDelete, + // attestations PolicyWorkflowRead, PolicyWorkflowCreate, PolicyWorkflowRunCreate, PolicyWorkflowRunUpdate, // to reset attestations // workflow operations - PolicyWorkflowUpdate, PolicyWorkflowDelete, diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index f53137577..0a36e2946 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -41,6 +41,17 @@ type WorkflowContract struct { CreatedAt *time.Time // WorkflowRefs is the list of workflows associated with this contract WorkflowRefs []*WorkflowRef + // entity the contract is scoped to, if not set it's scoped to the organization + ScopedEntity *ScopedEntity +} + +type ScopedEntity struct { + // Type is the type of the scoped entity i.e project or org + Type string + // ID is the id of the scoped entity + ID uuid.UUID + // Name is the name of the scoped entity + Name string } type WorkflowContractVersion struct { @@ -153,6 +164,7 @@ type WorkflowContractCreateOpts struct { OrgID, Name string RawSchema []byte Description *string + ProjectID *uuid.UUID // Make sure that the name is unique in the organization AddUniquePrefix bool } @@ -192,8 +204,11 @@ func (uc *WorkflowContractUseCase) Create(ctx context.Context, opts *WorkflowCon // Create a workflow with a unique name if needed args := &ContractCreateOpts{ - OrgID: orgUUID, Name: opts.Name, Description: opts.Description, - Contract: contract, + OrgID: orgUUID, + Name: opts.Name, + Description: opts.Description, + Contract: contract, + ProjectID: opts.ProjectID, } var c *WorkflowContract diff --git a/app/controlplane/pkg/data/workflowcontract.go b/app/controlplane/pkg/data/workflowcontract.go index b25ed071d..017c01818 100644 --- a/app/controlplane/pkg/data/workflowcontract.go +++ b/app/controlplane/pkg/data/workflowcontract.go @@ -72,7 +72,7 @@ func (r *WorkflowContractRepo) List(ctx context.Context, orgID uuid.UUID) ([]*bi if err != nil { return nil, err } - res := entContractToBizContract(s, latestV, workflowReferences) + res := r.entContractToBizContract(ctx, s, latestV, workflowReferences) result = append(result, res) } @@ -97,7 +97,7 @@ func (r *WorkflowContractRepo) Create(ctx context.Context, opts *biz.ContractCre return nil, err } - res := entContractToBizContract(contract, version, nil) + res := r.entContractToBizContract(ctx, contract, version, nil) return res, nil } @@ -141,7 +141,7 @@ func (r *WorkflowContractRepo) FindVersionByID(ctx context.Context, versionID uu } return &biz.WorkflowContractWithVersion{ - Contract: entContractToBizContract(version.Edges.Contract, version, nil), + Contract: r.entContractToBizContract(ctx, version.Edges.Contract, version, nil), Version: contractVersion, }, nil } @@ -188,7 +188,7 @@ func (r *WorkflowContractRepo) Describe(ctx context.Context, orgID, contractID u } } - s := entContractToBizContract(contract, latestV, workflowReferences) + s := r.entContractToBizContract(ctx, contract, latestV, workflowReferences) return &biz.WorkflowContractWithVersion{ Contract: s, Version: v, @@ -262,7 +262,7 @@ func (r *WorkflowContractRepo) Update(ctx context.Context, orgID uuid.UUID, name } return &biz.WorkflowContractWithVersion{ - Contract: entContractToBizContract(contract, lv, workflowReferences), + Contract: r.entContractToBizContract(ctx, contract, lv, workflowReferences), Version: v, }, nil } @@ -285,7 +285,7 @@ func (r *WorkflowContractRepo) FindByIDInOrg(ctx context.Context, orgID, contrac return nil, err } - return entContractToBizContract(contract, latestV, workflowReferences), nil + return r.entContractToBizContract(ctx, contract, latestV, workflowReferences), nil } func (r *WorkflowContractRepo) FindByNameInOrg(ctx context.Context, orgID uuid.UUID, name string) (*biz.WorkflowContract, error) { @@ -306,7 +306,7 @@ func (r *WorkflowContractRepo) FindByNameInOrg(ctx context.Context, orgID uuid.U return nil, fmt.Errorf("failed to get latest version: %w", err) } - return entContractToBizContract(contract, latestV, workflowReferences), nil + return r.entContractToBizContract(ctx, contract, latestV, workflowReferences), nil } func (r *WorkflowContractRepo) SoftDelete(ctx context.Context, id uuid.UUID) error { @@ -403,7 +403,7 @@ func contractInOrgQuery(ctx context.Context, q *ent.OrganizationQuery, orgID uui return query.Only(ctx) } -func entContractToBizContract(w *ent.WorkflowContract, version *ent.WorkflowContractVersion, workflowReferences []*biz.WorkflowRef) *biz.WorkflowContract { +func (r *WorkflowContractRepo) entContractToBizContract(ctx context.Context, w *ent.WorkflowContract, version *ent.WorkflowContractVersion, workflowReferences []*biz.WorkflowRef) *biz.WorkflowContract { c := &biz.WorkflowContract{ Name: w.Name, ID: w.ID, @@ -413,6 +413,23 @@ func entContractToBizContract(w *ent.WorkflowContract, version *ent.WorkflowCont Description: w.Description, } + if w.ScopedResourceID != uuid.Nil { + c.ScopedEntity = &biz.ScopedEntity{ + Type: string(w.ScopedResourceType), + ID: w.ScopedResourceID, + } + } + + // preload the project name if the contract is scoped to a project + if w.ScopedResourceType == biz.ContractScopeProject { + project, err := r.data.DB.Project.Get(ctx, w.ScopedResourceID) + if err != nil { + r.log.Errorf("failed to get project: %w", err) + return c + } + c.ScopedEntity.Name = project.Name + } + c.LatestRevision = version.Revision return c } From 270576bec251cc5818971a06287abc7a46d93589 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 13:27:08 +0200 Subject: [PATCH 08/24] RBAC contract access Signed-off-by: Miguel Martinez --- .../controlplane/v1/workflow_contract.proto | 3 -- app/controlplane/internal/service/service.go | 5 +- .../internal/service/workflowcontract.go | 51 +++++++++++++++++-- app/controlplane/pkg/biz/workflowcontract.go | 8 +++ .../ent/migrate/migrations/20250704092359.sql | 8 --- .../ent/migrate/migrations/20250710105502.sql | 2 + .../pkg/data/ent/migrate/migrations/atlas.sum | 4 +- .../pkg/data/ent/migrate/schema.go | 8 --- .../pkg/data/ent/schema/workflowcontract.go | 7 +-- 9 files changed, 65 insertions(+), 31 deletions(-) delete mode 100644 app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql create mode 100644 app/controlplane/pkg/data/ent/migrate/migrations/20250710105502.sql diff --git a/app/controlplane/api/controlplane/v1/workflow_contract.proto b/app/controlplane/api/controlplane/v1/workflow_contract.proto index d96eb00dc..b78f29796 100644 --- a/app/controlplane/api/controlplane/v1/workflow_contract.proto +++ b/app/controlplane/api/controlplane/v1/workflow_contract.proto @@ -91,9 +91,6 @@ message WorkflowContractServiceDescribeRequest { } }]; int32 revision = 2; - - // You might need to specify a project reference if you want/need to describe a contract scoped to a project - IdentityReference project_reference = 5; } message WorkflowContractServiceDescribeResponse { diff --git a/app/controlplane/internal/service/service.go b/app/controlplane/internal/service/service.go index 18fbbc28d..9329dd224 100644 --- a/app/controlplane/internal/service/service.go +++ b/app/controlplane/internal/service/service.go @@ -200,9 +200,10 @@ func (s *service) authorizeResource(ctx context.Context, op *authz.Policy, resou } } + var defaultMessage = fmt.Sprintf("you do not have permissions to access to the %s associated with this resource", resourceType) // If no matching resources were found, return forbidden error if len(matchingResources) == 0 { - return errors.Forbidden("forbidden", "operation not allowed") + return errors.Forbidden("forbidden", defaultMessage) } // Try to enforce the policy with each matching role @@ -220,7 +221,7 @@ func (s *service) authorizeResource(ctx context.Context, op *authz.Policy, resou } // If none of the roles pass, return forbidden error - return errors.Forbidden("forbidden", "operation not allowed") + return errors.Forbidden("forbidden", defaultMessage) } // userHasPermissionOnProject is a helper method that checks if a policy can be applied to a project. It looks for a project diff --git a/app/controlplane/internal/service/workflowcontract.go b/app/controlplane/internal/service/workflowcontract.go index 17bc05801..a21ecabd9 100644 --- a/app/controlplane/internal/service/workflowcontract.go +++ b/app/controlplane/internal/service/workflowcontract.go @@ -74,6 +74,13 @@ func (s *WorkflowContractService) Describe(ctx context.Context, req *pb.Workflow return nil, errors.NotFound("not found", "contract not found") } + // 1 - If the contract is scoped to a project, make sure the user has permission to read it + // otherwise everyone can read it, use it + if err := s.checkContractAccess(ctx, contract, true); err != nil { + return nil, err + } + + // 2 - Get the contract version contractWithVersion, err := s.contractUseCase.Describe(ctx, currentOrg.ID, contract.ID.String(), int(req.GetRevision())) if err != nil { return nil, handleUseCaseErr(err, s.log) @@ -95,7 +102,8 @@ func (s *WorkflowContractService) Create(ctx context.Context, req *pb.WorkflowCo return nil, err } - // Force project if RBAC is enabled + // Authorization checks + // Force setting a project scope if RBAC is enabled if rbacEnabled(ctx) && !req.ProjectReference.IsSet() { return nil, errors.BadRequest("invalid", "project is required") } @@ -145,13 +153,27 @@ func (s *WorkflowContractService) Update(ctx context.Context, req *pb.WorkflowCo return nil, err } + contract, err := s.contractUseCase.FindByNameInOrg(ctx, currentOrg.ID, req.GetName()) + if err != nil { + return nil, handleUseCaseErr(err, s.log) + } else if contract == nil { + return nil, errors.NotFound("not found", "contract not found") + } + + if err := s.checkContractAccess(ctx, contract, false); err != nil { + return nil, err + } + token, err := entities.GetRawToken(ctx) if err != nil { return nil, err } - if err = s.contractUseCase.ValidateContractPolicies(req.RawContract, token); err != nil { - return nil, handleUseCaseErr(err, s.log) + // Validate the contract policies if the raw contract is provided + if len(req.RawContract) != 0 { + if err = s.contractUseCase.ValidateContractPolicies(req.RawContract, token); err != nil { + return nil, handleUseCaseErr(err, s.log) + } } schemaWithVersion, err := s.contractUseCase.Update(ctx, currentOrg.ID, req.Name, @@ -184,6 +206,10 @@ func (s *WorkflowContractService) Delete(ctx context.Context, req *pb.WorkflowCo return nil, errors.NotFound("not found", "contract not found") } + if err := s.checkContractAccess(ctx, contract, false); err != nil { + return nil, err + } + if err := s.contractUseCase.Delete(ctx, currentOrg.ID, contract.ID.String()); err != nil { return nil, handleUseCaseErr(err, s.log) } @@ -249,3 +275,22 @@ func bizWorkFlowContractVersionToPb(schema *biz.WorkflowContractVersion) *pb.Wor }, } } + +// checkContractAccess checks if the current user can manage a contract +// if the contract is global it makes sure that the user is an admin +// if the contract is scoped to a project it makes sure that the user has permission in the project +func (s *WorkflowContractService) checkContractAccess(ctx context.Context, contract *biz.WorkflowContract, allowGlobalAccess bool) error { + // 1 - Only admins can manage global contracts unless allowGlobalAccess is true + if contract.IsGlobalScoped() && rbacEnabled(ctx) && !allowGlobalAccess { + return errors.BadRequest("invalid", "you can not manage a global contract") + } + + // 2 - If the contract is scoped to a project, make sure the user has permission to read it + if contract.IsProjectScoped() { + if err := s.authorizeResource(ctx, authz.PolicyWorkflowContractRead, authz.ResourceTypeProject, contract.ScopedEntity.ID); err != nil { + return err + } + } + + return nil +} diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index 0a36e2946..640524fe4 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -160,6 +160,14 @@ func (uc *WorkflowContractUseCase) FindByNameInOrg(ctx context.Context, orgID, n return uc.repo.FindByNameInOrg(ctx, orgUUID, name) } +func (c *WorkflowContract) IsGlobalScoped() bool { + return c.ScopedEntity == nil +} + +func (c *WorkflowContract) IsProjectScoped() bool { + return c.ScopedEntity != nil && c.ScopedEntity.Type == string(ContractScopeProject) +} + type WorkflowContractCreateOpts struct { OrgID, Name string RawSchema []byte diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql deleted file mode 100644 index 87cba251d..000000000 --- a/app/controlplane/pkg/data/ent/migrate/migrations/20250704092359.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Drop index "workflowcontract_name_organization_workflow_contracts" from table: "workflow_contracts" -DROP INDEX "workflowcontract_name_organization_workflow_contracts"; --- Modify "workflow_contracts" table -ALTER TABLE "workflow_contracts" ADD COLUMN "scoped_resource_type" character varying NULL, ADD COLUMN "scoped_resource_id" uuid NULL; --- Create index "workflowcontract_name_organization_workflow_contracts" to table: "workflow_contracts" -CREATE UNIQUE INDEX "workflowcontract_name_organization_workflow_contracts" ON "workflow_contracts" ("name", "organization_workflow_contracts") WHERE ((deleted_at IS NULL) AND (scoped_resource_type IS NULL)); --- Create index "workflowcontract_name_scoped_resource_type_scoped_resource_id" to table: "workflow_contracts" -CREATE UNIQUE INDEX "workflowcontract_name_scoped_resource_type_scoped_resource_id" ON "workflow_contracts" ("name", "scoped_resource_type", "scoped_resource_id") WHERE (deleted_at IS NULL); diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20250710105502.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20250710105502.sql new file mode 100644 index 000000000..e2e7526b1 --- /dev/null +++ b/app/controlplane/pkg/data/ent/migrate/migrations/20250710105502.sql @@ -0,0 +1,2 @@ +-- Modify "workflow_contracts" table +ALTER TABLE "workflow_contracts" ADD COLUMN "scoped_resource_type" character varying NULL, ADD COLUMN "scoped_resource_id" uuid NULL; diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index 40ff393af..887b83c74 100644 --- a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum +++ b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:+yGkCvepb0rQgYUfTpHC+xRBgJeIOYo6DlhZMe2p76o= +h1:i8q/MAG0rdlc1GCi0fAagiO70ZEhj6wvvFp8kgM+l50= 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -95,4 +95,4 @@ h1:+yGkCvepb0rQgYUfTpHC+xRBgJeIOYo6DlhZMe2p76o= 20250702111701.sql h1:Ni7fuL1qU5RGjBzV0XgJi9NkZINGijF8BumPuQ9conM= 20250702112642.sql h1:wrjVS+5h2hs7KNwPRBece5LgAsoEzxN/zNfvCnjoIUw= 20250704090359.sql h1:a0ksfjy2dtzviJL16HbC4eT1xBxy2qFH5mNFOpYlUrA= -20250704092359.sql h1:LWwcBsaZtqp0AqIVqIirYR+X7ukcXc7fyLUjtv0e8OY= +20250710105502.sql h1:EA6Ta1qsZcrNoOrO5zUNgiweHDtjl0HUlobukRuruko= diff --git a/app/controlplane/pkg/data/ent/migrate/schema.go b/app/controlplane/pkg/data/ent/migrate/schema.go index 9a2f43be5..fa48502c0 100644 --- a/app/controlplane/pkg/data/ent/migrate/schema.go +++ b/app/controlplane/pkg/data/ent/migrate/schema.go @@ -663,14 +663,6 @@ var ( Name: "workflowcontract_name_organization_workflow_contracts", Unique: true, Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[7]}, - Annotation: &entsql.IndexAnnotation{ - Where: "deleted_at IS NULL AND scoped_resource_type IS NULL", - }, - }, - { - Name: "workflowcontract_name_scoped_resource_type_scoped_resource_id", - Unique: true, - Columns: []*schema.Column{WorkflowContractsColumns[1], WorkflowContractsColumns[5], WorkflowContractsColumns[6]}, Annotation: &entsql.IndexAnnotation{ Where: "deleted_at IS NULL", }, diff --git a/app/controlplane/pkg/data/ent/schema/workflowcontract.go b/app/controlplane/pkg/data/ent/schema/workflowcontract.go index 94d0d84f7..59ea1b40a 100644 --- a/app/controlplane/pkg/data/ent/schema/workflowcontract.go +++ b/app/controlplane/pkg/data/ent/schema/workflowcontract.go @@ -67,12 +67,9 @@ func (WorkflowContract) Edges() []ent.Edge { func (WorkflowContract) Indexes() []ent.Index { return []ent.Index{ - // names are unique within a organization and affects only to non-scoped and non-deleted items + // TODO: add a unique index on name and scoped_resource_type and scoped_resource_id + // for now keeping a global one for backward compatibility index.Fields("name").Edges("organization").Unique().Annotations( - entsql.IndexWhere("deleted_at IS NULL AND scoped_resource_type IS NULL"), - ), - // names are unique within a resource and affects only to non-deleted items - index.Fields("name", "scoped_resource_type", "scoped_resource_id").Unique().Annotations( entsql.IndexWhere("deleted_at IS NULL"), ), } From ec365e7a58b10fd5f098d885304f9054c5ba84f3 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 13:50:01 +0200 Subject: [PATCH 09/24] RBAC contract access Signed-off-by: Miguel Martinez --- .../internal/service/workflowcontract.go | 2 +- app/controlplane/pkg/biz/workflowcontract.go | 25 ++++++++++++++++--- .../biz/workflowcontract_integration_test.go | 2 +- app/controlplane/pkg/data/workflowcontract.go | 25 ++++++++++++++++--- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/app/controlplane/internal/service/workflowcontract.go b/app/controlplane/internal/service/workflowcontract.go index a21ecabd9..de6370264 100644 --- a/app/controlplane/internal/service/workflowcontract.go +++ b/app/controlplane/internal/service/workflowcontract.go @@ -48,7 +48,7 @@ func (s *WorkflowContractService) List(ctx context.Context, _ *pb.WorkflowContra return nil, err } - contracts, err := s.contractUseCase.List(ctx, currentOrg.ID) + contracts, err := s.contractUseCase.List(ctx, currentOrg.ID, biz.WithProjectFilter(s.visibleProjects(ctx))) if err != nil { return nil, handleUseCaseErr(err, s.log) } diff --git a/app/controlplane/pkg/biz/workflowcontract.go b/app/controlplane/pkg/biz/workflowcontract.go index 640524fe4..ecb2c56d4 100644 --- a/app/controlplane/pkg/biz/workflowcontract.go +++ b/app/controlplane/pkg/biz/workflowcontract.go @@ -78,7 +78,7 @@ type WorkflowContractWithVersion struct { type WorkflowContractRepo interface { Create(ctx context.Context, opts *ContractCreateOpts) (*WorkflowContract, error) - List(ctx context.Context, orgID uuid.UUID) ([]*WorkflowContract, error) + List(ctx context.Context, orgID uuid.UUID, filter *WorkflowContractListFilters) ([]*WorkflowContract, error) FindByIDInOrg(ctx context.Context, orgID, ID uuid.UUID) (*WorkflowContract, error) FindByNameInOrg(ctx context.Context, orgID uuid.UUID, name string) (*WorkflowContract, error) Describe(ctx context.Context, orgID, contractID uuid.UUID, revision int, opts ...ContractQueryOpt) (*WorkflowContractWithVersion, error) @@ -128,13 +128,32 @@ func NewWorkflowContractUseCase(repo WorkflowContractRepo, policyRegistry *polic return &WorkflowContractUseCase{repo: repo, policyRegistry: policyRegistry, auditorUC: auditorUC, logger: log.NewHelper(logger)} } -func (uc *WorkflowContractUseCase) List(ctx context.Context, orgID string) ([]*WorkflowContract, error) { +type WorkflowContractListFilters struct { + // FilterByProjects is used to filter the result by a project list + // If it's empty, no filter will be applied + FilterByProjects []uuid.UUID +} + +type WorkflowListOpt func(opts *WorkflowContractListFilters) + +func WithProjectFilter(projectIDs []uuid.UUID) WorkflowListOpt { + return func(opts *WorkflowContractListFilters) { + opts.FilterByProjects = projectIDs + } +} + +func (uc *WorkflowContractUseCase) List(ctx context.Context, orgID string, opts ...WorkflowListOpt) ([]*WorkflowContract, error) { orgUUID, err := uuid.Parse(orgID) if err != nil { return nil, NewErrInvalidUUID(err) } - return uc.repo.List(ctx, orgUUID) + filters := &WorkflowContractListFilters{} + for _, opt := range opts { + opt(filters) + } + + return uc.repo.List(ctx, orgUUID, filters) } func (uc *WorkflowContractUseCase) FindByIDInOrg(ctx context.Context, orgID, contractID string) (*WorkflowContract, error) { diff --git a/app/controlplane/pkg/biz/workflowcontract_integration_test.go b/app/controlplane/pkg/biz/workflowcontract_integration_test.go index d91a21fbf..d4d45729b 100644 --- a/app/controlplane/pkg/biz/workflowcontract_integration_test.go +++ b/app/controlplane/pkg/biz/workflowcontract_integration_test.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/app/controlplane/pkg/data/workflowcontract.go b/app/controlplane/pkg/data/workflowcontract.go index 017c01818..0f6a8234a 100644 --- a/app/controlplane/pkg/data/workflowcontract.go +++ b/app/controlplane/pkg/data/workflowcontract.go @@ -48,10 +48,29 @@ func NewWorkflowContractRepo(data *Data, logger log.Logger) biz.WorkflowContract } } -func (r *WorkflowContractRepo) List(ctx context.Context, orgID uuid.UUID) ([]*biz.WorkflowContract, error) { - contracts, err := orgScopedQuery(r.data.DB, orgID). +// List returns a list of workflow contracts for a given organization +// If no project filters are provided, we return all the contracts scoped to the organization +// otherwise we return the global contracts alongside the org scoped projects +func (r *WorkflowContractRepo) List(ctx context.Context, orgID uuid.UUID, filter *biz.WorkflowContractListFilters) ([]*biz.WorkflowContract, error) { + wcontractQuery := orgScopedQuery(r.data.DB, orgID). QueryWorkflowContracts(). - Where(workflowcontract.DeletedAtIsNil()). + Where(workflowcontract.DeletedAtIsNil()) + + // If specific projects are provided + // we return the global contracts alongside the org scoped projects + if len(filter.FilterByProjects) > 0 { + wcontractQuery = wcontractQuery.Where( + workflowcontract.Or( + workflowcontract.And( + workflowcontract.ScopedResourceTypeIn(biz.ContractScopeProject), + workflowcontract.ScopedResourceIDIn(filter.FilterByProjects...), + ), + workflowcontract.ScopedResourceIDIsNil(), + ), + ) + } + + contracts, err := wcontractQuery. WithWorkflows(func(q *ent.WorkflowQuery) { q.Where(workflow.DeletedAtIsNil()) }). From 2296ed44dc8c22e399485e3ad7fd88f23336336d Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 13:59:02 +0200 Subject: [PATCH 10/24] RBAC contract access Signed-off-by: Miguel Martinez --- .../biz/workflowcontract_integration_test.go | 36 ++++++++++++++++++- go.sum | 1 - 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/app/controlplane/pkg/biz/workflowcontract_integration_test.go b/app/controlplane/pkg/biz/workflowcontract_integration_test.go index d4d45729b..e350920ae 100644 --- a/app/controlplane/pkg/biz/workflowcontract_integration_test.go +++ b/app/controlplane/pkg/biz/workflowcontract_integration_test.go @@ -240,6 +240,26 @@ func (s *workflowContractIntegrationTestSuite) TestCreate() { } } +func (s *workflowContractIntegrationTestSuite) TestList() { + ctx := context.Background() + + s.Run("by default it returns all the contracts from the org both global and scoped", func() { + contracts, err := s.WorkflowContract.List(ctx, s.org.ID) + s.NoError(err) + s.Equal(3, len(contracts)) + }) + + s.Run("if filtered by project it returns the contracts scoped to the project alongside the global contracts", func() { + contracts, err := s.WorkflowContract.List(ctx, s.org.ID, biz.WithProjectFilter([]uuid.UUID{s.p1.ID})) + s.NoError(err) + s.Equal(2, len(contracts)) + s.Equal(s.contractScopedToProject.ID, contracts[0].ID) + s.True(contracts[0].IsProjectScoped()) + s.Equal(s.contractOrg1.ID, contracts[1].ID) + s.True(contracts[1].IsGlobalScoped()) + }) +} + func (s *workflowContractIntegrationTestSuite) TestCreateWithCustomContract() { ctx := context.Background() @@ -315,8 +335,10 @@ func TestWorkflowContractUseCase(t *testing.T) { type workflowContractIntegrationTestSuite struct { testhelpers.UseCasesEachTestSuite org, org2 *biz.Organization + p1, p2 *biz.Project - contractOrg1 *biz.WorkflowContract + contractOrg1 *biz.WorkflowContract + contractScopedToProject *biz.WorkflowContract } func (s *workflowContractIntegrationTestSuite) SetupTest() { @@ -329,6 +351,18 @@ func (s *workflowContractIntegrationTestSuite) SetupTest() { s.org2, err = s.Organization.CreateWithRandomName(ctx) s.NoError(err) + s.p1, err = s.Project.Create(ctx, s.org.ID, "a-valid-project") + s.NoError(err) + + p2, err := s.Project.Create(ctx, s.org.ID, "a-valid-project-2") + s.NoError(err) + s.contractOrg1, err = s.WorkflowContract.Create(ctx, &biz.WorkflowContractCreateOpts{OrgID: s.org.ID, Name: "a-valid-contract"}) s.NoError(err) + + s.contractScopedToProject, err = s.WorkflowContract.Create(ctx, &biz.WorkflowContractCreateOpts{OrgID: s.org.ID, Name: "a-valid-contract-scoped-to-project", ProjectID: &s.p1.ID}) + s.NoError(err) + + _, err = s.WorkflowContract.Create(ctx, &biz.WorkflowContractCreateOpts{OrgID: s.org.ID, Name: "a-valid-contract-scoped-to-project-2", ProjectID: &p2.ID}) + s.Require().NoError(err) } diff --git a/go.sum b/go.sum index e16b77962..10e45e5c7 100644 --- a/go.sum +++ b/go.sum @@ -1079,7 +1079,6 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/oleiade/reflections v1.1.0 h1:D+I/UsXQB4esMathlt0kkZRJZdUDmhv5zGi/HOwYTWo= github.com/oleiade/reflections v1.1.0/go.mod h1:mCxx0QseeVCHs5Um5HhJeCKVC7AwS8kO67tky4rdisA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= From da40bfa8878c5d3aeb7ce4c1e881ae4be2eb4633 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 14:03:15 +0200 Subject: [PATCH 11/24] RBAC contract access Signed-off-by: Miguel Martinez --- app/controlplane/internal/service/workflowcontract.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controlplane/internal/service/workflowcontract.go b/app/controlplane/internal/service/workflowcontract.go index de6370264..9438c2caa 100644 --- a/app/controlplane/internal/service/workflowcontract.go +++ b/app/controlplane/internal/service/workflowcontract.go @@ -76,7 +76,7 @@ func (s *WorkflowContractService) Describe(ctx context.Context, req *pb.Workflow // 1 - If the contract is scoped to a project, make sure the user has permission to read it // otherwise everyone can read it, use it - if err := s.checkContractAccess(ctx, contract, true); err != nil { + if err := s.checkContractAccess(ctx, contract, authz.PolicyWorkflowContractRead, true); err != nil { return nil, err } @@ -160,7 +160,7 @@ func (s *WorkflowContractService) Update(ctx context.Context, req *pb.WorkflowCo return nil, errors.NotFound("not found", "contract not found") } - if err := s.checkContractAccess(ctx, contract, false); err != nil { + if err := s.checkContractAccess(ctx, contract, authz.PolicyWorkflowContractUpdate, false); err != nil { return nil, err } @@ -206,7 +206,7 @@ func (s *WorkflowContractService) Delete(ctx context.Context, req *pb.WorkflowCo return nil, errors.NotFound("not found", "contract not found") } - if err := s.checkContractAccess(ctx, contract, false); err != nil { + if err := s.checkContractAccess(ctx, contract, authz.PolicyWorkflowContractDelete, false); err != nil { return nil, err } @@ -279,7 +279,7 @@ func bizWorkFlowContractVersionToPb(schema *biz.WorkflowContractVersion) *pb.Wor // checkContractAccess checks if the current user can manage a contract // if the contract is global it makes sure that the user is an admin // if the contract is scoped to a project it makes sure that the user has permission in the project -func (s *WorkflowContractService) checkContractAccess(ctx context.Context, contract *biz.WorkflowContract, allowGlobalAccess bool) error { +func (s *WorkflowContractService) checkContractAccess(ctx context.Context, contract *biz.WorkflowContract, policy *authz.Policy, allowGlobalAccess bool) error { // 1 - Only admins can manage global contracts unless allowGlobalAccess is true if contract.IsGlobalScoped() && rbacEnabled(ctx) && !allowGlobalAccess { return errors.BadRequest("invalid", "you can not manage a global contract") @@ -287,7 +287,7 @@ func (s *WorkflowContractService) checkContractAccess(ctx context.Context, contr // 2 - If the contract is scoped to a project, make sure the user has permission to read it if contract.IsProjectScoped() { - if err := s.authorizeResource(ctx, authz.PolicyWorkflowContractRead, authz.ResourceTypeProject, contract.ScopedEntity.ID); err != nil { + if err := s.authorizeResource(ctx, policy, authz.ResourceTypeProject, contract.ScopedEntity.ID); err != nil { return err } } From 9e597d0c1b0f0e287bdd51e8495b58b60c900883 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 14:08:36 +0200 Subject: [PATCH 12/24] RBAC contract access Signed-off-by: Miguel Martinez --- app/cli/documentation/cli-reference.mdx | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/app/cli/documentation/cli-reference.mdx b/app/cli/documentation/cli-reference.mdx index b94a21bed..7b1e13a70 100755 --- a/app/cli/documentation/cli-reference.mdx +++ b/app/cli/documentation/cli-reference.mdx @@ -1460,6 +1460,48 @@ Options inherited from parent commands -y, --yes Skip confirmation ``` +## chainloop gather-runner-context + +Gather runner context data from a given provider. + +Synopsis + +Gather runner context data from a given provider. + +Provided by plugin: platform v0.218.0-SNAPSHOT-bd8099ad + +``` +chainloop gather-runner-context [flags] +``` + +Options + +``` +-h, --help help for gather-runner-context +--output-file string Output file path for the protection data (JSON format) (default "runner-context.json") +--runner-api-url string Provider API URL +--runner-org string Provider organization name +--runner-provider string Provider name +--runner-repo string Provider repository name +--runner-token string Provider access token with read rights to the given repository. +``` + +Options inherited from parent commands + +``` +--artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") +--artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) +-c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) +--control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") +--control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) +--debug Enable debug/verbose logging mode +-i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) +-n, --org string organization name +-o, --output string Output format, valid options are json and table (default "table") +-t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN +-y, --yes Skip confirmation +``` + ## chainloop integration Third party integrations @@ -2965,6 +3007,7 @@ Options --description string description of the contract -h, --help help for create --name string contract name +--project string project name used to scope the contract, if not set the contract will be created in the organization ``` Options inherited from parent commands From 64a6e931946e2d9a6636f5c99e9d1a29adae381b Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 14:19:11 +0200 Subject: [PATCH 13/24] RBAC contract access Signed-off-by: Miguel Martinez --- app/controlplane/pkg/biz/workflowcontract_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controlplane/pkg/biz/workflowcontract_integration_test.go b/app/controlplane/pkg/biz/workflowcontract_integration_test.go index e350920ae..837690afa 100644 --- a/app/controlplane/pkg/biz/workflowcontract_integration_test.go +++ b/app/controlplane/pkg/biz/workflowcontract_integration_test.go @@ -335,7 +335,7 @@ func TestWorkflowContractUseCase(t *testing.T) { type workflowContractIntegrationTestSuite struct { testhelpers.UseCasesEachTestSuite org, org2 *biz.Organization - p1, p2 *biz.Project + p1 *biz.Project contractOrg1 *biz.WorkflowContract contractScopedToProject *biz.WorkflowContract From 8798176ea6dc465933c080d33d7757d56cadd5fe Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 14:21:21 +0200 Subject: [PATCH 14/24] RBAC contract access Signed-off-by: Miguel Martinez --- app/cli/documentation/cli-reference.mdx | 42 ------------------------- 1 file changed, 42 deletions(-) diff --git a/app/cli/documentation/cli-reference.mdx b/app/cli/documentation/cli-reference.mdx index 7b1e13a70..c9d05bb4d 100755 --- a/app/cli/documentation/cli-reference.mdx +++ b/app/cli/documentation/cli-reference.mdx @@ -1460,48 +1460,6 @@ Options inherited from parent commands -y, --yes Skip confirmation ``` -## chainloop gather-runner-context - -Gather runner context data from a given provider. - -Synopsis - -Gather runner context data from a given provider. - -Provided by plugin: platform v0.218.0-SNAPSHOT-bd8099ad - -``` -chainloop gather-runner-context [flags] -``` - -Options - -``` --h, --help help for gather-runner-context ---output-file string Output file path for the protection data (JSON format) (default "runner-context.json") ---runner-api-url string Provider API URL ---runner-org string Provider organization name ---runner-provider string Provider name ---runner-repo string Provider repository name ---runner-token string Provider access token with read rights to the given repository. -``` - -Options inherited from parent commands - -``` ---artifact-cas string URL for the Artifacts Content Addressable Storage API ($CHAINLOOP_ARTIFACT_CAS_API) (default "api.cas.chainloop.dev:443") ---artifact-cas-ca string CUSTOM CA file for the Artifacts CAS API (optional) ($CHAINLOOP_ARTIFACT_CAS_API_CA) --c, --config string Path to an existing config file (default is $HOME/.config/chainloop/config.toml) ---control-plane string URL for the Control Plane API ($CHAINLOOP_CONTROL_PLANE_API) (default "api.cp.chainloop.dev:443") ---control-plane-ca string CUSTOM CA file for the Control Plane API (optional) ($CHAINLOOP_CONTROL_PLANE_API_CA) ---debug Enable debug/verbose logging mode --i, --insecure Skip TLS transport during connection to the control plane ($CHAINLOOP_API_INSECURE) --n, --org string organization name --o, --output string Output format, valid options are json and table (default "table") --t, --token string API token. NOTE: Alternatively use the env variable CHAINLOOP_TOKEN --y, --yes Skip confirmation -``` - ## chainloop integration Third party integrations From 050a55c817df4e84731a56929369ebed65e9d798 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 14:39:54 +0200 Subject: [PATCH 15/24] scope down attestation contract Signed-off-by: Miguel Martinez --- app/controlplane/pkg/data/workflow.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/controlplane/pkg/data/workflow.go b/app/controlplane/pkg/data/workflow.go index 660239f91..bd35652eb 100644 --- a/app/controlplane/pkg/data/workflow.go +++ b/app/controlplane/pkg/data/workflow.go @@ -62,6 +62,7 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts) return nil, fmt.Errorf("contract name and ID cannot be provided at the same time") } + // Load an existing contract reference if provided var contractUUID uuid.UUID if opts.ContractID != "" { contractUUID, err = uuid.Parse(opts.ContractID) @@ -133,6 +134,17 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts) } contractUUID = contract.ID + } else { + // We want to use an existing contract, let's make sure it's scoped to the project or org + existingContract, err := contractInOrg(ctx, r.data.DB, orgUUID, &contractUUID, nil) + if err != nil { + return err + } + + // Fail if it's scoped to a different project + if existingContract.ScopedResourceID != uuid.Nil && existingContract.ScopedResourceID != projectID && existingContract.ScopedResourceType == biz.ContractScopeProject { + return biz.NewErrUnauthorizedStr(fmt.Sprintf("contract %q is scoped to a different project", opts.ContractName)) + } } entwf, err = tx.Workflow.Create(). From 5b450a5efad05f72a21d7cc55d9d5df56e41a19d Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 14:55:00 +0200 Subject: [PATCH 16/24] scope down attestation contract Signed-off-by: Miguel Martinez --- .../gen/frontend/google/protobuf/descriptor.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts index 0d2d2fb32..d59b21da4 100644 --- a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts +++ b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts @@ -30,7 +30,7 @@ export enum Edition { EDITION_2024 = 1001, /** * EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be - * used or relyed on outside of tests. + * used or relied on outside of tests. */ EDITION_1_TEST_ONLY = 1, EDITION_2_TEST_ONLY = 2, @@ -875,12 +875,13 @@ export interface MessageOptions { export interface FieldOptions { /** + * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific * options below. This option is only implemented to support use of * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of - * type "bytes" in the open source release -- sorry, we'll try to include - * other types in a future version! + * type "bytes" in the open source release. + * TODO: make ctype actually deprecated. */ ctype: FieldOptions_CType; /** @@ -1052,11 +1053,7 @@ export function fieldOptions_JSTypeToJSON(object: FieldOptions_JSType): string { } } -/** - * If set to RETENTION_SOURCE, the option will be omitted from the binary. - * Note: as of January 2023, support for this is in progress and does not yet - * have an effect (b/264593489). - */ +/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */ export enum FieldOptions_OptionRetention { RETENTION_UNKNOWN = 0, RETENTION_RUNTIME = 1, @@ -1099,8 +1096,7 @@ export function fieldOptions_OptionRetentionToJSON(object: FieldOptions_OptionRe /** * This indicates the types of entities that the field may apply to when used * as an option. If it is unset, then the field may be freely used as an - * option on any kind of entity. Note: as of January 2023, support for this is - * in progress and does not yet have an effect (b/264593489). + * option on any kind of entity. */ export enum FieldOptions_OptionTargetType { TARGET_TYPE_UNKNOWN = 0, From d40e603d91f43ca64498c58053f89c592af61210 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 17:37:16 +0200 Subject: [PATCH 17/24] feat: allow to get group by name Signed-off-by: Miguel Martinez --- app/cli/cmd/organization_apitoken_create.go | 13 +- app/cli/cmd/workflow_contract_describe.go | 4 +- app/cli/cmd/workflow_contract_list.go | 8 +- app/cli/internal/action/apitoken_create.go | 33 +-- .../internal/action/workflow_contract_list.go | 9 + .../api/controlplane/v1/api_token.pb.go | 206 +++++++++-------- .../api/controlplane/v1/api_token.proto | 3 + .../api/controlplane/v1/project.proto | 1 + .../api/controlplane/v1/project_grpc.pb.go | 2 + .../controlplane/v1/response_messages.pb.go | 210 +++++++++--------- .../controlplane/v1/response_messages.proto | 4 +- .../gen/frontend/controlplane/v1/api_token.ts | 29 ++- .../gen/frontend/controlplane/v1/project.ts | 5 +- .../controlplane/v1/response_messages.ts | 35 +-- .../frontend/google/protobuf/descriptor.ts | 16 +- ...ntrolplane.v1.APITokenItem.jsonschema.json | 20 +- .../controlplane.v1.APITokenItem.schema.json | 20 +- ...ITokenServiceCreateRequest.jsonschema.json | 8 + ...1.APITokenServiceCreateRequest.schema.json | 8 + app/controlplane/internal/service/apitoken.go | 32 ++- app/controlplane/internal/service/project.go | 2 +- app/controlplane/pkg/biz/apitoken.go | 54 +++-- .../pkg/biz/apitoken_integration_test.go | 16 +- app/controlplane/pkg/data/apitoken.go | 22 +- 24 files changed, 419 insertions(+), 341 deletions(-) diff --git a/app/cli/cmd/organization_apitoken_create.go b/app/cli/cmd/organization_apitoken_create.go index eb773111d..b5c0d5def 100644 --- a/app/cli/cmd/organization_apitoken_create.go +++ b/app/cli/cmd/organization_apitoken_create.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,8 +27,8 @@ import ( func newAPITokenCreateCmd() *cobra.Command { var ( - description, name string - expiresIn time.Duration + description, name, projectName string + expiresIn time.Duration ) cmd := &cobra.Command{ @@ -40,7 +40,7 @@ func newAPITokenCreateCmd() *cobra.Command { duration = &expiresIn } - res, err := action.NewAPITokenCreate(actionOpts).Run(context.Background(), name, description, duration) + res, err := action.NewAPITokenCreate(actionOpts).Run(context.Background(), name, description, projectName, duration) if err != nil { return fmt.Errorf("creating API token: %w", err) } @@ -61,6 +61,7 @@ func newAPITokenCreateCmd() *cobra.Command { cmd.InheritedFlags().StringVarP(&flagOutputFormat, "output", "o", "table", "output format, valid options are table, json, token") err := cmd.MarkFlagRequired("name") cobra.CheckErr(err) + cmd.Flags().StringVar(&projectName, "project", "", "project name used to scope the token, if not set the token will be created at the organization level") return cmd } @@ -77,9 +78,9 @@ func apiTokenListTableOutput(tokens []*action.APITokenItem) error { t := newTableWriter() - t.AppendHeader(table.Row{"Name", "Description", "Created At", "Expires At", "Revoked At", "Last used at"}) + t.AppendHeader(table.Row{"Name", "Scope", "Description", "Created At", "Expires At", "Revoked At", "Last used at"}) for _, p := range tokens { - r := table.Row{p.Name, p.Description, p.CreatedAt.Format(time.RFC822)} + r := table.Row{p.Name, p.ScopedEntity.String(), p.Description, p.CreatedAt.Format(time.RFC822)} if p.ExpiresAt != nil { r = append(r, p.ExpiresAt.Format(time.RFC822)) } else { diff --git a/app/cli/cmd/workflow_contract_describe.go b/app/cli/cmd/workflow_contract_describe.go index 60aa56205..16251af4f 100644 --- a/app/cli/cmd/workflow_contract_describe.go +++ b/app/cli/cmd/workflow_contract_describe.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -86,6 +86,8 @@ func contractDescribeTableOutput(contractWithVersion *action.WorkflowContractWit t.SetTitle("Contract") t.AppendRow(table.Row{"Name", c.Name}) t.AppendSeparator() + t.AppendRow(table.Row{"Scope", c.ScopedEntity.String()}) + t.AppendSeparator() t.AppendRow(table.Row{"Description", c.Description}) t.AppendSeparator() t.AppendRow(table.Row{"Associated Workflows", stringifyAssociatedWorkflows(contractWithVersion)}) diff --git a/app/cli/cmd/workflow_contract_list.go b/app/cli/cmd/workflow_contract_list.go index 39bb40d6c..becf759dd 100644 --- a/app/cli/cmd/workflow_contract_list.go +++ b/app/cli/cmd/workflow_contract_list.go @@ -16,7 +16,6 @@ package cmd import ( - "fmt" "time" "github.com/chainloop-dev/chainloop/app/cli/internal/action" @@ -51,12 +50,7 @@ func contractListTableOutput(contracts []*action.WorkflowContractItem) error { t.AppendHeader(table.Row{"Name", "Latest Revision", "Created At", "Updated At", "# Workflows", "Scope"}) for _, p := range contracts { - scope := "org" - if p.ScopedEntity != nil { - scope = fmt.Sprintf("%s/%s", p.ScopedEntity.Type, p.ScopedEntity.Name) - } - - t.AppendRow(table.Row{p.Name, p.LatestRevision, p.CreatedAt.Format(time.RFC822), p.LatestRevisionCreatedAt.Format(time.RFC822), len(p.WorkflowRefs), scope}) + t.AppendRow(table.Row{p.Name, p.LatestRevision, p.CreatedAt.Format(time.RFC822), p.LatestRevisionCreatedAt.Format(time.RFC822), len(p.WorkflowRefs), p.ScopedEntity.String()}) } t.Render() diff --git a/app/cli/internal/action/apitoken_create.go b/app/cli/internal/action/apitoken_create.go index 21d2209ce..b19421b48 100644 --- a/app/cli/internal/action/apitoken_create.go +++ b/app/cli/internal/action/apitoken_create.go @@ -33,7 +33,7 @@ func NewAPITokenCreate(cfg *ActionsOpts) *APITokenCreate { return &APITokenCreate{cfg} } -func (action *APITokenCreate) Run(ctx context.Context, name, description string, expiresIn *time.Duration) (*APITokenItem, error) { +func (action *APITokenCreate) Run(ctx context.Context, name, description, projectName string, expiresIn *time.Duration) (*APITokenItem, error) { client := pb.NewAPITokenServiceClient(action.cfg.CPConnection) req := &pb.APITokenServiceCreateRequest{Name: name, Description: &description} @@ -41,6 +41,12 @@ func (action *APITokenCreate) Run(ctx context.Context, name, description string, req.ExpiresIn = durationpb.New(*expiresIn) } + if projectName != "" { + req.ProjectReference = &pb.IdentityReference{ + Name: &projectName, + } + } + resp, err := client.Create(ctx, req) if err != nil { return nil, fmt.Errorf("creating API token: %w", err) @@ -62,13 +68,12 @@ type APITokenItem struct { Name string `json:"name"` Description string `json:"description"` // JWT is returned only during the creation - JWT string `json:"jwt,omitempty"` - CreatedAt *time.Time `json:"createdAt"` - RevokedAt *time.Time `json:"revokedAt,omitempty"` - ExpiresAt *time.Time `json:"expiresAt,omitempty"` - LastUsedAt *time.Time `json:"lastUsedAt,omitempty"` - ProjectID string `json:"projectId,omitempty"` - ProjectName string `json:"projectName,omitempty"` + JWT string `json:"jwt,omitempty"` + CreatedAt *time.Time `json:"createdAt"` + RevokedAt *time.Time `json:"revokedAt,omitempty"` + ExpiresAt *time.Time `json:"expiresAt,omitempty"` + LastUsedAt *time.Time `json:"lastUsedAt,omitempty"` + ScopedEntity *ScopedEntity `json:"scopedEntity,omitempty"` } func pbAPITokenItemToAPITokenItem(p *pb.APITokenItem) *APITokenItem { @@ -95,12 +100,12 @@ func pbAPITokenItemToAPITokenItem(p *pb.APITokenItem) *APITokenItem { item.LastUsedAt = toTimePtr(p.LastUsedAt.AsTime()) } - if p.ProjectId != "" { - item.ProjectID = p.ProjectId - } - - if p.ProjectName != "" { - item.ProjectName = p.ProjectName + if p.ScopedEntity != nil { + item.ScopedEntity = &ScopedEntity{ + Type: p.ScopedEntity.Type, + ID: p.ScopedEntity.Id, + Name: p.ScopedEntity.Name, + } } return item diff --git a/app/cli/internal/action/workflow_contract_list.go b/app/cli/internal/action/workflow_contract_list.go index fae0d7946..87989c9dd 100644 --- a/app/cli/internal/action/workflow_contract_list.go +++ b/app/cli/internal/action/workflow_contract_list.go @@ -17,6 +17,7 @@ package action import ( "context" + "fmt" "time" pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" @@ -45,6 +46,14 @@ type ScopedEntity struct { Name string `json:"name"` } +func (s *ScopedEntity) String() string { + if s == nil { + return "global" + } + + return fmt.Sprintf("%s/%s", s.Type, s.Name) +} + type WorkflowRef struct { ID string `json:"id"` Name string `json:"name"` diff --git a/app/controlplane/api/controlplane/v1/api_token.pb.go b/app/controlplane/api/controlplane/v1/api_token.pb.go index d205bc5b9..b45fefd0e 100644 --- a/app/controlplane/api/controlplane/v1/api_token.pb.go +++ b/app/controlplane/api/controlplane/v1/api_token.pb.go @@ -42,9 +42,11 @@ type APITokenServiceCreateRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Description *string `protobuf:"bytes,1,opt,name=description,proto3,oneof" json:"description,omitempty"` - ExpiresIn *durationpb.Duration `protobuf:"bytes,2,opt,name=expires_in,json=expiresIn,proto3,oneof" json:"expires_in,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Description *string `protobuf:"bytes,1,opt,name=description,proto3,oneof" json:"description,omitempty"` + // You might need to specify a project reference if you want/need to create a token scoped to a project + ProjectReference *IdentityReference `protobuf:"bytes,4,opt,name=project_reference,json=projectReference,proto3" json:"project_reference,omitempty"` + ExpiresIn *durationpb.Duration `protobuf:"bytes,2,opt,name=expires_in,json=expiresIn,proto3,oneof" json:"expires_in,omitempty"` } func (x *APITokenServiceCreateRequest) Reset() { @@ -93,6 +95,13 @@ func (x *APITokenServiceCreateRequest) GetDescription() string { return "" } +func (x *APITokenServiceCreateRequest) GetProjectReference() *IdentityReference { + if x != nil { + return x.ProjectReference + } + return nil +} + func (x *APITokenServiceCreateRequest) GetExpiresIn() *durationpb.Duration { if x != nil { return x.ExpiresIn @@ -391,83 +400,91 @@ var file_controlplane_v1_api_token_proto_rawDesc = []byte{ 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x01, 0x0a, 0x1c, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, - 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x09, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, - 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0d, 0x0a, 0x0b, - 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x22, 0xc9, 0x01, 0x0a, 0x1d, - 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x50, - 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x1a, 0x53, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x75, - 0x6c, 0x6c, 0x12, 0x31, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, + 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x91, + 0x02, 0x0a, 0x1c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x88, 0x01, 0x01, 0x12, 0x4f, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, + 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x49, 0x6e, + 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, + 0x69, 0x6e, 0x22, 0xc9, 0x01, 0x0a, 0x1d, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x75, 0x6c, + 0x6c, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x53, 0x0a, 0x0c, 0x41, 0x50, 0x49, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x12, 0x31, 0x0a, 0x04, 0x69, 0x74, 0x65, + 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, + 0x6a, 0x77, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0xb8, + 0x01, 0x0a, 0x1c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, + 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, + 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, + 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, + 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, + 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, + 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, + 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x41, 0x50, 0x49, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1a, 0x41, 0x50, + 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x64, 0x22, 0x54, 0x0a, 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x35, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, - 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x77, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0xb8, 0x01, 0x0a, 0x1c, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, - 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, - 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, - 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, - 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, - 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, - 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, - 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x22, 0x54, 0x0a, 0x1b, 0x41, 0x50, - 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x2d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, - 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, - 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, - 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, + 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -491,25 +508,27 @@ var file_controlplane_v1_api_token_proto_goTypes = []interface{}{ (*APITokenServiceListRequest)(nil), // 4: controlplane.v1.APITokenServiceListRequest (*APITokenServiceListResponse)(nil), // 5: controlplane.v1.APITokenServiceListResponse (*APITokenServiceCreateResponse_APITokenFull)(nil), // 6: controlplane.v1.APITokenServiceCreateResponse.APITokenFull - (*durationpb.Duration)(nil), // 7: google.protobuf.Duration - (*APITokenItem)(nil), // 8: controlplane.v1.APITokenItem + (*IdentityReference)(nil), // 7: controlplane.v1.IdentityReference + (*durationpb.Duration)(nil), // 8: google.protobuf.Duration + (*APITokenItem)(nil), // 9: controlplane.v1.APITokenItem } var file_controlplane_v1_api_token_proto_depIdxs = []int32{ - 7, // 0: controlplane.v1.APITokenServiceCreateRequest.expires_in:type_name -> google.protobuf.Duration - 6, // 1: controlplane.v1.APITokenServiceCreateResponse.result:type_name -> controlplane.v1.APITokenServiceCreateResponse.APITokenFull - 8, // 2: controlplane.v1.APITokenServiceListResponse.result:type_name -> controlplane.v1.APITokenItem - 8, // 3: controlplane.v1.APITokenServiceCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem - 0, // 4: controlplane.v1.APITokenService.Create:input_type -> controlplane.v1.APITokenServiceCreateRequest - 4, // 5: controlplane.v1.APITokenService.List:input_type -> controlplane.v1.APITokenServiceListRequest - 2, // 6: controlplane.v1.APITokenService.Revoke:input_type -> controlplane.v1.APITokenServiceRevokeRequest - 1, // 7: controlplane.v1.APITokenService.Create:output_type -> controlplane.v1.APITokenServiceCreateResponse - 5, // 8: controlplane.v1.APITokenService.List:output_type -> controlplane.v1.APITokenServiceListResponse - 3, // 9: controlplane.v1.APITokenService.Revoke:output_type -> controlplane.v1.APITokenServiceRevokeResponse - 7, // [7:10] is the sub-list for method output_type - 4, // [4:7] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 7, // 0: controlplane.v1.APITokenServiceCreateRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 8, // 1: controlplane.v1.APITokenServiceCreateRequest.expires_in:type_name -> google.protobuf.Duration + 6, // 2: controlplane.v1.APITokenServiceCreateResponse.result:type_name -> controlplane.v1.APITokenServiceCreateResponse.APITokenFull + 9, // 3: controlplane.v1.APITokenServiceListResponse.result:type_name -> controlplane.v1.APITokenItem + 9, // 4: controlplane.v1.APITokenServiceCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem + 0, // 5: controlplane.v1.APITokenService.Create:input_type -> controlplane.v1.APITokenServiceCreateRequest + 4, // 6: controlplane.v1.APITokenService.List:input_type -> controlplane.v1.APITokenServiceListRequest + 2, // 7: controlplane.v1.APITokenService.Revoke:input_type -> controlplane.v1.APITokenServiceRevokeRequest + 1, // 8: controlplane.v1.APITokenService.Create:output_type -> controlplane.v1.APITokenServiceCreateResponse + 5, // 9: controlplane.v1.APITokenService.List:output_type -> controlplane.v1.APITokenServiceListResponse + 3, // 10: controlplane.v1.APITokenService.Revoke:output_type -> controlplane.v1.APITokenServiceRevokeResponse + 8, // [8:11] is the sub-list for method output_type + 5, // [5:8] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_controlplane_v1_api_token_proto_init() } @@ -518,6 +537,7 @@ func file_controlplane_v1_api_token_proto_init() { return } file_controlplane_v1_response_messages_proto_init() + file_controlplane_v1_shared_message_proto_init() if !protoimpl.UnsafeEnabled { file_controlplane_v1_api_token_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APITokenServiceCreateRequest); i { diff --git a/app/controlplane/api/controlplane/v1/api_token.proto b/app/controlplane/api/controlplane/v1/api_token.proto index b7f160a4e..3eaa7e542 100644 --- a/app/controlplane/api/controlplane/v1/api_token.proto +++ b/app/controlplane/api/controlplane/v1/api_token.proto @@ -19,6 +19,7 @@ package controlplane.v1; import "buf/validate/validate.proto"; import "controlplane/v1/response_messages.proto"; +import "controlplane/v1/shared_message.proto"; import "google/protobuf/duration.proto"; option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1"; @@ -33,6 +34,8 @@ message APITokenServiceCreateRequest { string name = 3 [(buf.validate.field).string.min_len = 1]; optional string description = 1; + // You might need to specify a project reference if you want/need to create a token scoped to a project + IdentityReference project_reference = 4; optional google.protobuf.Duration expires_in = 2; } diff --git a/app/controlplane/api/controlplane/v1/project.proto b/app/controlplane/api/controlplane/v1/project.proto index 2be530715..ddff21970 100644 --- a/app/controlplane/api/controlplane/v1/project.proto +++ b/app/controlplane/api/controlplane/v1/project.proto @@ -29,6 +29,7 @@ option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/con service ProjectService { // Project level API tokens + // DEPRECATED: Use the API token service instead rpc APITokenCreate(ProjectServiceAPITokenCreateRequest) returns (ProjectServiceAPITokenCreateResponse); rpc APITokenList(ProjectServiceAPITokenListRequest) returns (ProjectServiceAPITokenListResponse); rpc APITokenRevoke(ProjectServiceAPITokenRevokeRequest) returns (ProjectServiceAPITokenRevokeResponse); diff --git a/app/controlplane/api/controlplane/v1/project_grpc.pb.go b/app/controlplane/api/controlplane/v1/project_grpc.pb.go index 5849aff8b..9453b6974 100644 --- a/app/controlplane/api/controlplane/v1/project_grpc.pb.go +++ b/app/controlplane/api/controlplane/v1/project_grpc.pb.go @@ -49,6 +49,7 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ProjectServiceClient interface { // Project level API tokens + // DEPRECATED: Use the API token service instead APITokenCreate(ctx context.Context, in *ProjectServiceAPITokenCreateRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenCreateResponse, error) APITokenList(ctx context.Context, in *ProjectServiceAPITokenListRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenListResponse, error) APITokenRevoke(ctx context.Context, in *ProjectServiceAPITokenRevokeRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenRevokeResponse, error) @@ -145,6 +146,7 @@ func (c *projectServiceClient) ListPendingInvitations(ctx context.Context, in *P // for forward compatibility type ProjectServiceServer interface { // Project level API tokens + // DEPRECATED: Use the API token service instead APITokenCreate(context.Context, *ProjectServiceAPITokenCreateRequest) (*ProjectServiceAPITokenCreateResponse, error) APITokenList(context.Context, *ProjectServiceAPITokenListRequest) (*ProjectServiceAPITokenListResponse, error) APITokenRevoke(context.Context, *ProjectServiceAPITokenRevokeRequest) (*ProjectServiceAPITokenRevokeResponse, error) diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.go b/app/controlplane/api/controlplane/v1/response_messages.pb.go index e4349b10a..7fb519a63 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.go @@ -2034,17 +2034,17 @@ type APITokenItem struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,7,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - OrganizationId string `protobuf:"bytes,3,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` - OrganizationName string `protobuf:"bytes,8,opt,name=organization_name,json=organizationName,proto3" json:"organization_name,omitempty"` - ProjectId string `protobuf:"bytes,9,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"` - ProjectName string `protobuf:"bytes,10,opt,name=project_name,json=projectName,proto3" json:"project_name,omitempty"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` - RevokedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=revoked_at,json=revokedAt,proto3" json:"revoked_at,omitempty"` - ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"` - LastUsedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=last_used_at,json=lastUsedAt,proto3" json:"last_used_at,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,7,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + OrganizationId string `protobuf:"bytes,3,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` + OrganizationName string `protobuf:"bytes,8,opt,name=organization_name,json=organizationName,proto3" json:"organization_name,omitempty"` + // wether the token is scoped to an entity in the organization + ScopedEntity *ScopedEntity `protobuf:"bytes,10,opt,name=scoped_entity,json=scopedEntity,proto3" json:"scoped_entity,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + RevokedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=revoked_at,json=revokedAt,proto3" json:"revoked_at,omitempty"` + ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"` + LastUsedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=last_used_at,json=lastUsedAt,proto3" json:"last_used_at,omitempty"` } func (x *APITokenItem) Reset() { @@ -2114,18 +2114,11 @@ func (x *APITokenItem) GetOrganizationName() string { return "" } -func (x *APITokenItem) GetProjectId() string { +func (x *APITokenItem) GetScopedEntity() *ScopedEntity { if x != nil { - return x.ProjectId - } - return "" -} - -func (x *APITokenItem) GetProjectName() string { - if x != nil { - return x.ProjectName + return x.ScopedEntity } - return "" + return nil } func (x *APITokenItem) GetCreatedAt() *timestamppb.Timestamp { @@ -2934,7 +2927,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x22, 0xdb, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x22, 0xdd, 0x03, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, @@ -2945,83 +2938,83 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x72, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x3c, - 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, 0x41, 0x74, 0x2a, 0xa6, 0x01, 0x0a, - 0x09, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x55, - 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, - 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, - 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x52, - 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, - 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xaf, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x4d, 0x45, 0x4d, 0x42, - 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, - 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, - 0x5f, 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x4d, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x52, 0x0c, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, + 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x72, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, + 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, + 0x12, 0x3c, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, 0x41, 0x74, 0x2a, 0xa6, + 0x01, 0x0a, 0x09, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x16, + 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x55, 0x4e, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x15, + 0x0a, 0x11, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, + 0x4c, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x04, 0x12, 0x18, 0x0a, + 0x14, 0x52, 0x55, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, + 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xaf, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x4d, 0x45, + 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, + 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, + 0x52, 0x47, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, + 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, + 0x52, 0x47, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, + 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, + 0x47, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, - 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x4d, 0x42, - 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x5f, - 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, 0x42, 0x45, - 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x4d, - 0x45, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x04, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, - 0x4c, 0x69, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, - 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x1c, 0x41, + 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x04, 0x2a, 0x60, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, + 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, - 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, 0x04, 0xa8, - 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x46, 0x65, 0x64, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x41, 0x75, 0x74, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x24, 0x0a, 0x20, 0x46, 0x45, 0x44, 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x55, 0x54, - 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2b, 0x0a, 0x21, 0x46, 0x45, 0x44, 0x45, 0x52, 0x41, 0x54, - 0x45, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, - 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, - 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x84, 0x01, 0x0a, 0x19, 0x55, 0x73, 0x65, - 0x72, 0x57, 0x69, 0x74, 0x68, 0x4e, 0x6f, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x29, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x57, - 0x49, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, - 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x32, 0x0a, 0x28, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x57, 0x49, - 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4f, 0x52, - 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, - 0x80, 0x01, 0x0a, 0x17, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x4f, 0x66, 0x4f, 0x72, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2c, 0x0a, 0x28, 0x55, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, + 0x1c, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x1a, + 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x46, + 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x41, 0x75, 0x74, 0x68, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x45, 0x44, 0x45, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, + 0x55, 0x54, 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2b, 0x0a, 0x21, 0x46, 0x45, 0x44, 0x45, 0x52, + 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x04, + 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, 0x03, 0x2a, 0x84, 0x01, 0x0a, 0x19, 0x55, + 0x73, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x4e, 0x6f, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x29, 0x55, 0x53, 0x45, 0x52, + 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, + 0x48, 0x49, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x32, 0x0a, 0x28, 0x55, 0x53, 0x45, 0x52, 0x5f, + 0x57, 0x49, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, + 0x49, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, 0x5f, + 0x4f, 0x52, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, 0xf4, + 0x03, 0x2a, 0x80, 0x01, 0x0a, 0x17, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x4f, 0x66, 0x4f, 0x72, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2c, 0x0a, + 0x28, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, + 0x5f, 0x4f, 0x46, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x31, 0x0a, 0x27, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x4f, - 0x46, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x31, 0x0a, 0x27, 0x55, 0x53, 0x45, - 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x4f, 0x46, 0x5f, - 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4e, - 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, 0xa0, 0x45, - 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x46, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, + 0x49, 0x4e, 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x93, 0x03, 0x1a, 0x04, + 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, + 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3123,18 +3116,19 @@ var file_controlplane_v1_response_messages_proto_depIdxs = []int32{ 37, // 39: controlplane.v1.CASBackendItem.validated_at:type_name -> google.protobuf.Timestamp 8, // 40: controlplane.v1.CASBackendItem.validation_status:type_name -> controlplane.v1.CASBackendItem.ValidationStatus 36, // 41: controlplane.v1.CASBackendItem.limits:type_name -> controlplane.v1.CASBackendItem.Limits - 37, // 42: controlplane.v1.APITokenItem.created_at:type_name -> google.protobuf.Timestamp - 37, // 43: controlplane.v1.APITokenItem.revoked_at:type_name -> google.protobuf.Timestamp - 37, // 44: controlplane.v1.APITokenItem.expires_at:type_name -> google.protobuf.Timestamp - 37, // 45: controlplane.v1.APITokenItem.last_used_at:type_name -> google.protobuf.Timestamp - 13, // 46: controlplane.v1.AttestationItem.PolicyEvaluationsEntry.value:type_name -> controlplane.v1.PolicyEvaluations - 31, // 47: controlplane.v1.AttestationItem.Material.annotations:type_name -> controlplane.v1.AttestationItem.Material.AnnotationsEntry - 6, // 48: controlplane.v1.WorkflowContractVersionItem.RawBody.format:type_name -> controlplane.v1.WorkflowContractVersionItem.RawBody.Format - 49, // [49:49] is the sub-list for method output_type - 49, // [49:49] is the sub-list for method input_type - 49, // [49:49] is the sub-list for extension type_name - 49, // [49:49] is the sub-list for extension extendee - 0, // [0:49] is the sub-list for field type_name + 18, // 42: controlplane.v1.APITokenItem.scoped_entity:type_name -> controlplane.v1.ScopedEntity + 37, // 43: controlplane.v1.APITokenItem.created_at:type_name -> google.protobuf.Timestamp + 37, // 44: controlplane.v1.APITokenItem.revoked_at:type_name -> google.protobuf.Timestamp + 37, // 45: controlplane.v1.APITokenItem.expires_at:type_name -> google.protobuf.Timestamp + 37, // 46: controlplane.v1.APITokenItem.last_used_at:type_name -> google.protobuf.Timestamp + 13, // 47: controlplane.v1.AttestationItem.PolicyEvaluationsEntry.value:type_name -> controlplane.v1.PolicyEvaluations + 31, // 48: controlplane.v1.AttestationItem.Material.annotations:type_name -> controlplane.v1.AttestationItem.Material.AnnotationsEntry + 6, // 49: controlplane.v1.WorkflowContractVersionItem.RawBody.format:type_name -> controlplane.v1.WorkflowContractVersionItem.RawBody.Format + 50, // [50:50] is the sub-list for method output_type + 50, // [50:50] is the sub-list for method input_type + 50, // [50:50] is the sub-list for extension type_name + 50, // [50:50] is the sub-list for extension extendee + 0, // [0:50] is the sub-list for field type_name } func init() { file_controlplane_v1_response_messages_proto_init() } diff --git a/app/controlplane/api/controlplane/v1/response_messages.proto b/app/controlplane/api/controlplane/v1/response_messages.proto index 80cc8f1d7..a6cdba957 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.proto +++ b/app/controlplane/api/controlplane/v1/response_messages.proto @@ -330,8 +330,8 @@ message APITokenItem { string description = 2; string organization_id = 3; string organization_name = 8; - string project_id = 9; - string project_name = 10; + // wether the token is scoped to an entity in the organization + ScopedEntity scoped_entity = 10; google.protobuf.Timestamp created_at = 4; google.protobuf.Timestamp revoked_at = 5; google.protobuf.Timestamp expires_at = 6; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts index 6fd14efee..24c8e995b 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts @@ -4,12 +4,17 @@ import { BrowserHeaders } from "browser-headers"; import _m0 from "protobufjs/minimal"; import { Duration } from "../../google/protobuf/duration"; import { APITokenItem } from "./response_messages"; +import { IdentityReference } from "./shared_message"; export const protobufPackage = "controlplane.v1"; export interface APITokenServiceCreateRequest { name: string; - description?: string | undefined; + description?: + | string + | undefined; + /** You might need to specify a project reference if you want/need to create a token scoped to a project */ + projectReference?: IdentityReference; expiresIn?: Duration | undefined; } @@ -38,7 +43,7 @@ export interface APITokenServiceListResponse { } function createBaseAPITokenServiceCreateRequest(): APITokenServiceCreateRequest { - return { name: "", description: undefined, expiresIn: undefined }; + return { name: "", description: undefined, projectReference: undefined, expiresIn: undefined }; } export const APITokenServiceCreateRequest = { @@ -49,6 +54,9 @@ export const APITokenServiceCreateRequest = { if (message.description !== undefined) { writer.uint32(10).string(message.description); } + if (message.projectReference !== undefined) { + IdentityReference.encode(message.projectReference, writer.uint32(34).fork()).ldelim(); + } if (message.expiresIn !== undefined) { Duration.encode(message.expiresIn, writer.uint32(18).fork()).ldelim(); } @@ -76,6 +84,13 @@ export const APITokenServiceCreateRequest = { message.description = reader.string(); continue; + case 4: + if (tag !== 34) { + break; + } + + message.projectReference = IdentityReference.decode(reader, reader.uint32()); + continue; case 2: if (tag !== 18) { break; @@ -96,6 +111,9 @@ export const APITokenServiceCreateRequest = { return { name: isSet(object.name) ? String(object.name) : "", description: isSet(object.description) ? String(object.description) : undefined, + projectReference: isSet(object.projectReference) + ? IdentityReference.fromJSON(object.projectReference) + : undefined, expiresIn: isSet(object.expiresIn) ? Duration.fromJSON(object.expiresIn) : undefined, }; }, @@ -104,6 +122,10 @@ export const APITokenServiceCreateRequest = { const obj: any = {}; message.name !== undefined && (obj.name = message.name); message.description !== undefined && (obj.description = message.description); + message.projectReference !== undefined && + (obj.projectReference = message.projectReference + ? IdentityReference.toJSON(message.projectReference) + : undefined); message.expiresIn !== undefined && (obj.expiresIn = message.expiresIn ? Duration.toJSON(message.expiresIn) : undefined); return obj; @@ -117,6 +139,9 @@ export const APITokenServiceCreateRequest = { const message = createBaseAPITokenServiceCreateRequest(); message.name = object.name ?? ""; message.description = object.description ?? undefined; + message.projectReference = (object.projectReference !== undefined && object.projectReference !== null) + ? IdentityReference.fromPartial(object.projectReference) + : undefined; message.expiresIn = (object.expiresIn !== undefined && object.expiresIn !== null) ? Duration.fromPartial(object.expiresIn) : undefined; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/project.ts b/app/controlplane/api/gen/frontend/controlplane/v1/project.ts index 7aa351392..e6f207486 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/project.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/project.ts @@ -1782,7 +1782,10 @@ export const PendingProjectInvitation = { }; export interface ProjectService { - /** Project level API tokens */ + /** + * Project level API tokens + * DEPRECATED: Use the API token service instead + */ APITokenCreate( request: DeepPartial, metadata?: grpc.Metadata, diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts index e69eedfe2..5c579c249 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts @@ -661,8 +661,8 @@ export interface APITokenItem { description: string; organizationId: string; organizationName: string; - projectId: string; - projectName: string; + /** wether the token is scoped to an entity in the organization */ + scopedEntity?: ScopedEntity; createdAt?: Date; revokedAt?: Date; expiresAt?: Date; @@ -3993,8 +3993,7 @@ function createBaseAPITokenItem(): APITokenItem { description: "", organizationId: "", organizationName: "", - projectId: "", - projectName: "", + scopedEntity: undefined, createdAt: undefined, revokedAt: undefined, expiresAt: undefined, @@ -4019,11 +4018,8 @@ export const APITokenItem = { if (message.organizationName !== "") { writer.uint32(66).string(message.organizationName); } - if (message.projectId !== "") { - writer.uint32(74).string(message.projectId); - } - if (message.projectName !== "") { - writer.uint32(82).string(message.projectName); + if (message.scopedEntity !== undefined) { + ScopedEntity.encode(message.scopedEntity, writer.uint32(82).fork()).ldelim(); } if (message.createdAt !== undefined) { Timestamp.encode(toTimestamp(message.createdAt), writer.uint32(34).fork()).ldelim(); @@ -4082,19 +4078,12 @@ export const APITokenItem = { message.organizationName = reader.string(); continue; - case 9: - if (tag !== 74) { - break; - } - - message.projectId = reader.string(); - continue; case 10: if (tag !== 82) { break; } - message.projectName = reader.string(); + message.scopedEntity = ScopedEntity.decode(reader, reader.uint32()); continue; case 4: if (tag !== 34) { @@ -4140,8 +4129,7 @@ export const APITokenItem = { description: isSet(object.description) ? String(object.description) : "", organizationId: isSet(object.organizationId) ? String(object.organizationId) : "", organizationName: isSet(object.organizationName) ? String(object.organizationName) : "", - projectId: isSet(object.projectId) ? String(object.projectId) : "", - projectName: isSet(object.projectName) ? String(object.projectName) : "", + scopedEntity: isSet(object.scopedEntity) ? ScopedEntity.fromJSON(object.scopedEntity) : undefined, createdAt: isSet(object.createdAt) ? fromJsonTimestamp(object.createdAt) : undefined, revokedAt: isSet(object.revokedAt) ? fromJsonTimestamp(object.revokedAt) : undefined, expiresAt: isSet(object.expiresAt) ? fromJsonTimestamp(object.expiresAt) : undefined, @@ -4156,8 +4144,8 @@ export const APITokenItem = { message.description !== undefined && (obj.description = message.description); message.organizationId !== undefined && (obj.organizationId = message.organizationId); message.organizationName !== undefined && (obj.organizationName = message.organizationName); - message.projectId !== undefined && (obj.projectId = message.projectId); - message.projectName !== undefined && (obj.projectName = message.projectName); + message.scopedEntity !== undefined && + (obj.scopedEntity = message.scopedEntity ? ScopedEntity.toJSON(message.scopedEntity) : undefined); message.createdAt !== undefined && (obj.createdAt = message.createdAt.toISOString()); message.revokedAt !== undefined && (obj.revokedAt = message.revokedAt.toISOString()); message.expiresAt !== undefined && (obj.expiresAt = message.expiresAt.toISOString()); @@ -4176,8 +4164,9 @@ export const APITokenItem = { message.description = object.description ?? ""; message.organizationId = object.organizationId ?? ""; message.organizationName = object.organizationName ?? ""; - message.projectId = object.projectId ?? ""; - message.projectName = object.projectName ?? ""; + message.scopedEntity = (object.scopedEntity !== undefined && object.scopedEntity !== null) + ? ScopedEntity.fromPartial(object.scopedEntity) + : undefined; message.createdAt = object.createdAt ?? undefined; message.revokedAt = object.revokedAt ?? undefined; message.expiresAt = object.expiresAt ?? undefined; diff --git a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts index d59b21da4..0d2d2fb32 100644 --- a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts +++ b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts @@ -30,7 +30,7 @@ export enum Edition { EDITION_2024 = 1001, /** * EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be - * used or relied on outside of tests. + * used or relyed on outside of tests. */ EDITION_1_TEST_ONLY = 1, EDITION_2_TEST_ONLY = 2, @@ -875,13 +875,12 @@ export interface MessageOptions { export interface FieldOptions { /** - * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific * options below. This option is only implemented to support use of * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of - * type "bytes" in the open source release. - * TODO: make ctype actually deprecated. + * type "bytes" in the open source release -- sorry, we'll try to include + * other types in a future version! */ ctype: FieldOptions_CType; /** @@ -1053,7 +1052,11 @@ export function fieldOptions_JSTypeToJSON(object: FieldOptions_JSType): string { } } -/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */ +/** + * If set to RETENTION_SOURCE, the option will be omitted from the binary. + * Note: as of January 2023, support for this is in progress and does not yet + * have an effect (b/264593489). + */ export enum FieldOptions_OptionRetention { RETENTION_UNKNOWN = 0, RETENTION_RUNTIME = 1, @@ -1096,7 +1099,8 @@ export function fieldOptions_OptionRetentionToJSON(object: FieldOptions_OptionRe /** * This indicates the types of entities that the field may apply to when used * as an option. If it is unset, then the field may be freely used as an - * option on any kind of entity. + * option on any kind of entity. Note: as of January 2023, support for this is + * in progress and does not yet have an effect (b/264593489). */ export enum FieldOptions_OptionTargetType { TARGET_TYPE_UNKNOWN = 0, diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.jsonschema.json index 40641b6e2..c1e730ef0 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.jsonschema.json @@ -18,14 +18,12 @@ "^(organization_name)$": { "type": "string" }, - "^(project_id)$": { - "type": "string" - }, - "^(project_name)$": { - "type": "string" - }, "^(revoked_at)$": { "$ref": "google.protobuf.Timestamp.jsonschema.json" + }, + "^(scoped_entity)$": { + "$ref": "controlplane.v1.ScopedEntity.jsonschema.json", + "description": "wether the token is scoped to an entity in the organization" } }, "properties": { @@ -53,14 +51,12 @@ "organizationName": { "type": "string" }, - "projectId": { - "type": "string" - }, - "projectName": { - "type": "string" - }, "revokedAt": { "$ref": "google.protobuf.Timestamp.jsonschema.json" + }, + "scopedEntity": { + "$ref": "controlplane.v1.ScopedEntity.jsonschema.json", + "description": "wether the token is scoped to an entity in the organization" } }, "title": "API Token Item", diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.schema.json index a80f39e1d..78f54ddc0 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenItem.schema.json @@ -18,14 +18,12 @@ "^(organizationName)$": { "type": "string" }, - "^(projectId)$": { - "type": "string" - }, - "^(projectName)$": { - "type": "string" - }, "^(revokedAt)$": { "$ref": "google.protobuf.Timestamp.schema.json" + }, + "^(scopedEntity)$": { + "$ref": "controlplane.v1.ScopedEntity.schema.json", + "description": "wether the token is scoped to an entity in the organization" } }, "properties": { @@ -53,14 +51,12 @@ "organization_name": { "type": "string" }, - "project_id": { - "type": "string" - }, - "project_name": { - "type": "string" - }, "revoked_at": { "$ref": "google.protobuf.Timestamp.schema.json" + }, + "scoped_entity": { + "$ref": "controlplane.v1.ScopedEntity.schema.json", + "description": "wether the token is scoped to an entity in the organization" } }, "title": "API Token Item", diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.jsonschema.json index d8f48fce5..fb74fd2fa 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.jsonschema.json @@ -5,6 +5,10 @@ "patternProperties": { "^(expires_in)$": { "$ref": "google.protobuf.Duration.jsonschema.json" + }, + "^(project_reference)$": { + "$ref": "controlplane.v1.IdentityReference.jsonschema.json", + "description": "You might need to specify a project reference if you want/need to create a token scoped to a project" } }, "properties": { @@ -17,6 +21,10 @@ "name": { "minLength": 1, "type": "string" + }, + "projectReference": { + "$ref": "controlplane.v1.IdentityReference.jsonschema.json", + "description": "You might need to specify a project reference if you want/need to create a token scoped to a project" } }, "title": "API Token Service Create Request", diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.schema.json index 0fcaba7ca..43ca1809c 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceCreateRequest.schema.json @@ -5,6 +5,10 @@ "patternProperties": { "^(expiresIn)$": { "$ref": "google.protobuf.Duration.schema.json" + }, + "^(projectReference)$": { + "$ref": "controlplane.v1.IdentityReference.schema.json", + "description": "You might need to specify a project reference if you want/need to create a token scoped to a project" } }, "properties": { @@ -17,6 +21,10 @@ "name": { "minLength": 1, "type": "string" + }, + "project_reference": { + "$ref": "controlplane.v1.IdentityReference.schema.json", + "description": "You might need to specify a project reference if you want/need to create a token scoped to a project" } }, "title": "API Token Service Create Request", diff --git a/app/controlplane/internal/service/apitoken.go b/app/controlplane/internal/service/apitoken.go index d724dbc58..27eebf443 100644 --- a/app/controlplane/internal/service/apitoken.go +++ b/app/controlplane/internal/service/apitoken.go @@ -20,7 +20,9 @@ import ( "time" pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" + "github.com/chainloop-dev/chainloop/app/controlplane/pkg/authz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" + errors "github.com/go-kratos/kratos/v2/errors" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -44,13 +46,29 @@ func (s *APITokenService) Create(ctx context.Context, req *pb.APITokenServiceCre return nil, err } + // Authorization checks + // Force setting a project scope if RBAC is enabled + if rbacEnabled(ctx) && !req.ProjectReference.IsSet() { + return nil, errors.BadRequest("invalid", "project is required") + } + + // if the project is provided we make sure it exists and the user has permission to it + var project *biz.Project + if req.ProjectReference.IsSet() { + // Make sure the provided project exists and the user has permission to create tokens in it + project, err = s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProjectReference(), authz.PolicyWorkflowContractCreate) + if err != nil { + return nil, err + } + } + var expiresIn *time.Duration if req.ExpiresIn != nil { expiresIn = new(time.Duration) *expiresIn = req.ExpiresIn.AsDuration() } - token, err := s.APITokenUseCase.Create(ctx, req.Name, req.Description, expiresIn, currentOrg.ID) + token, err := s.APITokenUseCase.Create(ctx, req.Name, req.Description, expiresIn, currentOrg.ID, biz.APITokenWithProject(project)) if err != nil { return nil, handleUseCaseErr(err, s.log) } @@ -70,7 +88,7 @@ func (s *APITokenService) List(ctx context.Context, req *pb.APITokenServiceListR } // Only expose system tokens - tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, req.IncludeRevoked, biz.APITokenShowOnlySystemTokens(true)) + tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenRevoked(req.IncludeRevoked), biz.WithApiTokenProjectFilter(s.visibleProjects(ctx))) if err != nil { return nil, handleUseCaseErr(err, s.log) } @@ -124,11 +142,11 @@ func apiTokenBizToPb(in *biz.APIToken) *pb.APITokenItem { } if in.ProjectID != nil { - res.ProjectId = in.ProjectID.String() - } - - if in.ProjectName != nil { - res.ProjectName = *in.ProjectName + res.ScopedEntity = &pb.ScopedEntity{ + Type: string(biz.ContractScopeProject), + Id: in.ProjectID.String(), + Name: *in.ProjectName, + } } return res diff --git a/app/controlplane/internal/service/project.go b/app/controlplane/internal/service/project.go index a5f535193..f2a24e488 100644 --- a/app/controlplane/internal/service/project.go +++ b/app/controlplane/internal/service/project.go @@ -87,7 +87,7 @@ func (s *ProjectService) APITokenList(ctx context.Context, req *pb.ProjectServic return nil, err } - tokens, err := s.apiTokenUseCase.List(ctx, currentOrg.ID, req.IncludeRevoked, biz.APITokenWithProject(project)) + tokens, err := s.apiTokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenProjectFilter([]uuid.UUID{project.ID}), biz.WithApiTokenRevoked(req.IncludeRevoked)) if err != nil { return nil, handleUseCaseErr(err, s.log) } diff --git a/app/controlplane/pkg/biz/apitoken.go b/app/controlplane/pkg/biz/apitoken.go index a66a6a87e..5a5abd660 100644 --- a/app/controlplane/pkg/biz/apitoken.go +++ b/app/controlplane/pkg/biz/apitoken.go @@ -57,8 +57,7 @@ type APIToken struct { type APITokenRepo interface { Create(ctx context.Context, name string, description *string, expiresAt *time.Time, organizationID uuid.UUID, projectID *uuid.UUID) (*APIToken, error) - // List all the tokens optionally filtering it by organization and including revoked tokens - List(ctx context.Context, orgID *uuid.UUID, projectID *uuid.UUID, includeRevoked bool, showOnlySystemTokens bool) ([]*APIToken, error) + List(ctx context.Context, orgID *uuid.UUID, filters *APITokenListFilters) ([]*APIToken, error) Revoke(ctx context.Context, orgID, ID uuid.UUID) error UpdateExpiration(ctx context.Context, ID uuid.UUID, expiresAt time.Time) error UpdateLastUsedAt(ctx context.Context, ID uuid.UUID, lastUsedAt time.Time) error @@ -134,22 +133,16 @@ type apiTokenOptions struct { showOnlySystemTokens bool } -type APITokenUseCaseOpt func(*apiTokenOptions) +type APITokenCreateOpt func(*apiTokenOptions) -func APITokenWithProject(project *Project) APITokenUseCaseOpt { +func APITokenWithProject(project *Project) APITokenCreateOpt { return func(o *apiTokenOptions) { o.project = project } } -func APITokenShowOnlySystemTokens(show bool) APITokenUseCaseOpt { - return func(o *apiTokenOptions) { - o.showOnlySystemTokens = show - } -} - // expires in is a string that can be parsed by time.ParseDuration -func (uc *APITokenUseCase) Create(ctx context.Context, name string, description *string, expiresIn *time.Duration, orgID string, opts ...APITokenUseCaseOpt) (*APIToken, error) { +func (uc *APITokenUseCase) Create(ctx context.Context, name string, description *string, expiresIn *time.Duration, orgID string, opts ...APITokenCreateOpt) (*APIToken, error) { options := &apiTokenOptions{} for _, opt := range opts { opt(options) @@ -277,10 +270,32 @@ func (uc *APITokenUseCase) RegenerateJWT(ctx context.Context, tokenID uuid.UUID, return token, nil } -func (uc *APITokenUseCase) List(ctx context.Context, orgID string, includeRevoked bool, opts ...APITokenUseCaseOpt) ([]*APIToken, error) { - options := &apiTokenOptions{} +type APITokenListOpt func(*APITokenListFilters) + +func WithApiTokenProjectFilter(projectIDs []uuid.UUID) APITokenListOpt { + return func(opts *APITokenListFilters) { + opts.FilterByProjects = projectIDs + } +} + +func WithApiTokenRevoked(includeRevoked bool) APITokenListOpt { + return func(opts *APITokenListFilters) { + opts.IncludeRevoked = includeRevoked + } +} + +type APITokenListFilters struct { + // FilterByProjects is used to filter the result by a project list + // If it's empty, no filter will be applied + FilterByProjects []uuid.UUID + // IncludeRevoked is used to include revoked tokens in the result + IncludeRevoked bool +} + +func (uc *APITokenUseCase) List(ctx context.Context, orgID string, opts ...APITokenListOpt) ([]*APIToken, error) { + filters := &APITokenListFilters{} for _, opt := range opts { - opt(options) + opt(filters) } orgUUID, err := uuid.Parse(orgID) @@ -288,12 +303,7 @@ func (uc *APITokenUseCase) List(ctx context.Context, orgID string, includeRevoke return nil, NewErrInvalidUUID(err) } - var projectID *uuid.UUID - if options.project != nil { - projectID = ToPtr(options.project.ID) - } - - return uc.apiTokenRepo.List(ctx, &orgUUID, projectID, includeRevoked, options.showOnlySystemTokens) + return uc.apiTokenRepo.List(ctx, &orgUUID, filters) } func (uc *APITokenUseCase) Revoke(ctx context.Context, orgID, id string) error { @@ -332,7 +342,7 @@ func (uc *APITokenUseCase) Revoke(ctx context.Context, orgID, id string) error { return nil } -func (uc *APITokenUseCase) FindByNameInOrg(ctx context.Context, orgID, name string, opts ...APITokenUseCaseOpt) (*APIToken, error) { +func (uc *APITokenUseCase) FindByNameInOrg(ctx context.Context, orgID, name string, opts ...APITokenCreateOpt) (*APIToken, error) { options := &apiTokenOptions{} for _, opt := range opts { opt(options) @@ -384,7 +394,7 @@ func (suc *APITokenSyncerUseCase) SyncPolicies() error { suc.base.logger.Info("syncing policies for all the API tokens") // List all the non-revoked tokens from all the orgs - tokens, err := suc.base.apiTokenRepo.List(context.Background(), nil, nil, false, false) + tokens, err := suc.base.apiTokenRepo.List(context.Background(), nil, nil) if err != nil { return fmt.Errorf("listing tokens: %w", err) } diff --git a/app/controlplane/pkg/biz/apitoken_integration_test.go b/app/controlplane/pkg/biz/apitoken_integration_test.go index 169e8f606..12605d830 100644 --- a/app/controlplane/pkg/biz/apitoken_integration_test.go +++ b/app/controlplane/pkg/biz/apitoken_integration_test.go @@ -124,7 +124,7 @@ func (s *apiTokenTestSuite) TestCreate() { for _, tc := range testCases { s.Run(tc.name, func() { - var opts []biz.APITokenUseCaseOpt + var opts []biz.APITokenCreateOpt if tc.project != nil { opts = append(opts, biz.APITokenWithProject(tc.project)) } @@ -201,7 +201,7 @@ func (s *apiTokenTestSuite) TestRevoke() { s.Run("token can be revoked once", func() { err := s.APIToken.Revoke(ctx, s.org.ID, s.t1.ID.String()) s.NoError(err) - tokens, err := s.APIToken.List(ctx, s.org.ID, true) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenRevoked(true)) s.NoError(err) s.Equal(s.t1.ID, tokens[0].ID) // It's revoked @@ -240,7 +240,7 @@ func (s *apiTokenTestSuite) TestFindByID() { func (s *apiTokenTestSuite) TestList() { ctx := context.Background() s.Run("invalid org ID", func() { - tokens, err := s.APIToken.List(ctx, "deadbeef", false) + tokens, err := s.APIToken.List(ctx, "deadbeef") s.Error(err) s.True(biz.IsErrInvalidUUID(err)) s.Nil(tokens) @@ -249,14 +249,14 @@ func (s *apiTokenTestSuite) TestList() { s.Run("returns empty list", func() { emptyOrg, err := s.Organization.CreateWithRandomName(ctx) require.NoError(s.T(), err) - tokens, err := s.APIToken.List(ctx, emptyOrg.ID, false) + tokens, err := s.APIToken.List(ctx, emptyOrg.ID) s.NoError(err) s.Len(tokens, 0) }) s.Run("returns all tokens for that org both system and project scoped", func() { var err error - tokens, err := s.APIToken.List(ctx, s.org.ID, false) + tokens, err := s.APIToken.List(ctx, s.org.ID) s.NoError(err) require.Len(s.T(), tokens, 4) s.Equal(s.t1.ID, tokens[0].ID) @@ -265,7 +265,7 @@ func (s *apiTokenTestSuite) TestList() { s.NotEmpty(tokens[1].Name) s.Equal(s.t2.Name, tokens[1].Name) - tokens, err = s.APIToken.List(ctx, s.org2.ID, false) + tokens, err = s.APIToken.List(ctx, s.org2.ID) s.NoError(err) require.Len(s.T(), tokens, 1) s.Equal(s.t3.ID, tokens[0].ID) @@ -273,7 +273,7 @@ func (s *apiTokenTestSuite) TestList() { s.Run("can return only for a specific project", func() { var err error - tokens, err := s.APIToken.List(ctx, s.org.ID, false, biz.APITokenWithProject(s.p1)) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenProjectFilter([]uuid.UUID{s.p1.ID})) s.NoError(err) require.Len(s.T(), tokens, 2) s.Equal(s.t4.ID, tokens[0].ID) @@ -282,7 +282,7 @@ func (s *apiTokenTestSuite) TestList() { s.Run("or just the system tokens", func() { var err error - tokens, err := s.APIToken.List(ctx, s.org.ID, false, biz.APITokenShowOnlySystemTokens(true)) + tokens, err := s.APIToken.List(ctx, s.org.ID) s.NoError(err) require.Len(s.T(), tokens, 2) s.Equal(s.t1.ID, tokens[0].ID) diff --git a/app/controlplane/pkg/data/apitoken.go b/app/controlplane/pkg/data/apitoken.go index 88c909550..6713f17a4 100644 --- a/app/controlplane/pkg/data/apitoken.go +++ b/app/controlplane/pkg/data/apitoken.go @@ -92,28 +92,18 @@ func (r *APITokenRepo) FindByNameInOrg(ctx context.Context, orgID uuid.UUID, nam return entAPITokenToBiz(token), nil } -func (r *APITokenRepo) List(ctx context.Context, orgID *uuid.UUID, projectID *uuid.UUID, includeRevoked bool, showOnlySystemTokens bool) ([]*biz.APIToken, error) { +func (r *APITokenRepo) List(ctx context.Context, orgID *uuid.UUID, filters *biz.APITokenListFilters) ([]*biz.APIToken, error) { query := r.data.DB.APIToken.Query().WithProject().WithOrganization() - if orgID != nil { - query = query.Where(apitoken.OrganizationIDEQ(*orgID)) + if orgID == nil { + return nil, fmt.Errorf("organizationID is required") } - if showOnlySystemTokens && projectID != nil { - return nil, fmt.Errorf("projectID cannot be provided when skipProjectScopedTokens is true") + if len(filters.FilterByProjects) > 0 { + query = query.Where(apitoken.ProjectIDIn(filters.FilterByProjects...)) } - if showOnlySystemTokens { - query = query.Where(apitoken.ProjectIDIsNil()) - } else if projectID != nil { - query = query.Where(apitoken.ProjectIDEQ(*projectID)) - } - - if projectID != nil { - query = query.Where(apitoken.ProjectIDEQ(*projectID)) - } - - if !includeRevoked { + if !filters.IncludeRevoked { query = query.Where(apitoken.RevokedAtIsNil()) } From 625aa972f6e6d4534363769a1c6af72d4e57463f Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 18:40:21 +0200 Subject: [PATCH 18/24] add api token Signed-off-by: Miguel Martinez --- app/cli/cmd/organization_apitoken_create.go | 4 +- app/cli/cmd/organization_apitoken_list.go | 2 +- app/cli/cmd/organization_apitoken_revoke.go | 10 +- app/cli/internal/action/apitoken_revoke.go | 4 +- .../api/controlplane/v1/api_token.pb.go | 96 +- .../api/controlplane/v1/api_token.proto | 9 +- .../api/controlplane/v1/project.pb.go | 1178 +++++------------ .../api/controlplane/v1/project.proto | 44 - .../api/controlplane/v1/project_grpc.pb.go | 115 -- .../gen/frontend/controlplane/v1/api_token.ts | 16 +- .../gen/frontend/controlplane/v1/project.ts | 692 +--------- ...ITokenServiceRevokeRequest.jsonschema.json | 3 +- ...1.APITokenServiceRevokeRequest.schema.json | 3 +- app/controlplane/cmd/wire_gen.go | 2 +- app/controlplane/internal/service/apitoken.go | 18 +- app/controlplane/internal/service/project.go | 89 +- app/controlplane/pkg/authz/authz.go | 31 +- app/controlplane/pkg/biz/apitoken.go | 17 +- app/controlplane/pkg/data/apitoken.go | 12 +- 19 files changed, 420 insertions(+), 1925 deletions(-) diff --git a/app/cli/cmd/organization_apitoken_create.go b/app/cli/cmd/organization_apitoken_create.go index b5c0d5def..4f04aa2c5 100644 --- a/app/cli/cmd/organization_apitoken_create.go +++ b/app/cli/cmd/organization_apitoken_create.go @@ -78,9 +78,9 @@ func apiTokenListTableOutput(tokens []*action.APITokenItem) error { t := newTableWriter() - t.AppendHeader(table.Row{"Name", "Scope", "Description", "Created At", "Expires At", "Revoked At", "Last used at"}) + t.AppendHeader(table.Row{"ID", "Name", "Scope", "Description", "Created At", "Expires At", "Revoked At", "Last used at"}) for _, p := range tokens { - r := table.Row{p.Name, p.ScopedEntity.String(), p.Description, p.CreatedAt.Format(time.RFC822)} + r := table.Row{p.ID, p.Name, p.ScopedEntity.String(), p.Description, p.CreatedAt.Format(time.RFC822)} if p.ExpiresAt != nil { r = append(r, p.ExpiresAt.Format(time.RFC822)) } else { diff --git a/app/cli/cmd/organization_apitoken_list.go b/app/cli/cmd/organization_apitoken_list.go index 9b6b7817b..ff63ecda9 100644 --- a/app/cli/cmd/organization_apitoken_list.go +++ b/app/cli/cmd/organization_apitoken_list.go @@ -1,5 +1,5 @@ // -// Copyright 2023 The Chainloop Authors. +// Copyright 2023-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/app/cli/cmd/organization_apitoken_revoke.go b/app/cli/cmd/organization_apitoken_revoke.go index b3df4af16..cb5d820c9 100644 --- a/app/cli/cmd/organization_apitoken_revoke.go +++ b/app/cli/cmd/organization_apitoken_revoke.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,13 +24,13 @@ import ( ) func newAPITokenRevokeCmd() *cobra.Command { - var name string + var id string cmd := &cobra.Command{ Use: "revoke", Short: "revoke API token", RunE: func(cmd *cobra.Command, args []string) error { - if err := action.NewAPITokenRevoke(actionOpts).Run(context.Background(), name); err != nil { + if err := action.NewAPITokenRevoke(actionOpts).Run(context.Background(), id); err != nil { return fmt.Errorf("revoking API token: %w", err) } @@ -39,8 +39,8 @@ func newAPITokenRevokeCmd() *cobra.Command { }, } - cmd.Flags().StringVar(&name, "name", "", "API token name") - err := cmd.MarkFlagRequired("name") + cmd.Flags().StringVar(&id, "id", "", "API token ID") + err := cmd.MarkFlagRequired("id") cobra.CheckErr(err) return cmd diff --git a/app/cli/internal/action/apitoken_revoke.go b/app/cli/internal/action/apitoken_revoke.go index b02a709bf..6c57fc9bc 100644 --- a/app/cli/internal/action/apitoken_revoke.go +++ b/app/cli/internal/action/apitoken_revoke.go @@ -30,9 +30,9 @@ func NewAPITokenRevoke(cfg *ActionsOpts) *APITokenRevoke { return &APITokenRevoke{cfg} } -func (action *APITokenRevoke) Run(ctx context.Context, name string) error { +func (action *APITokenRevoke) Run(ctx context.Context, id string) error { client := pb.NewAPITokenServiceClient(action.cfg.CPConnection) - if _, err := client.Revoke(ctx, &pb.APITokenServiceRevokeRequest{Name: name}); err != nil { + if _, err := client.Revoke(ctx, &pb.APITokenServiceRevokeRequest{Id: id}); err != nil { return fmt.Errorf("revoking API token: %w", err) } diff --git a/app/controlplane/api/controlplane/v1/api_token.pb.go b/app/controlplane/api/controlplane/v1/api_token.pb.go index b45fefd0e..6593da309 100644 --- a/app/controlplane/api/controlplane/v1/api_token.pb.go +++ b/app/controlplane/api/controlplane/v1/api_token.pb.go @@ -161,7 +161,7 @@ type APITokenServiceRevokeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } func (x *APITokenServiceRevokeRequest) Reset() { @@ -196,9 +196,9 @@ func (*APITokenServiceRevokeRequest) Descriptor() ([]byte, []int) { return file_controlplane_v1_api_token_proto_rawDescGZIP(), []int{2} } -func (x *APITokenServiceRevokeRequest) GetName() string { +func (x *APITokenServiceRevokeRequest) GetId() string { if x != nil { - return x.Name + return x.Id } return "" } @@ -434,57 +434,49 @@ var file_controlplane_v1_api_token_proto_rawDesc = []byte{ 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, - 0x6a, 0x77, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0xb8, - 0x01, 0x0a, 0x1c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, - 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, - 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, - 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, - 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, - 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1a, 0x41, 0x50, - 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x64, 0x22, 0x54, 0x0a, 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x35, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x6a, 0x77, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0x38, + 0x0a, 0x1c, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, + 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x41, 0x50, 0x49, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1a, 0x41, 0x50, 0x49, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, + 0x22, 0x54, 0x0a, 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x35, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, + 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/controlplane/api/controlplane/v1/api_token.proto b/app/controlplane/api/controlplane/v1/api_token.proto index 3eaa7e542..a09344ee8 100644 --- a/app/controlplane/api/controlplane/v1/api_token.proto +++ b/app/controlplane/api/controlplane/v1/api_token.proto @@ -49,14 +49,7 @@ message APITokenServiceCreateResponse { } message APITokenServiceRevokeRequest { - string name = 1 [(buf.validate.field) = { - // NOTE: validations can not be shared yet https://github.com/bufbuild/protovalidate/issues/51 - cel: { - message: "must contain only lowercase letters, numbers, and hyphens." - expression: "this.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')" - id: "name.dns-1123" - } - }]; + string id = 1 [(buf.validate.field).string.uuid = true]; } message APITokenServiceRevokeResponse {} diff --git a/app/controlplane/api/controlplane/v1/project.pb.go b/app/controlplane/api/controlplane/v1/project.pb.go index 0deb0ed60..8e0b2f3ab 100644 --- a/app/controlplane/api/controlplane/v1/project.pb.go +++ b/app/controlplane/api/controlplane/v1/project.pb.go @@ -25,7 +25,7 @@ import ( _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" @@ -91,326 +91,6 @@ func (ProjectMemberRole) EnumDescriptor() ([]byte, []int) { return file_controlplane_v1_project_proto_rawDescGZIP(), []int{0} } -type ProjectServiceAPITokenCreateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - ProjectName string `protobuf:"bytes,2,opt,name=project_name,json=projectName,proto3" json:"project_name,omitempty"` - Description *string `protobuf:"bytes,3,opt,name=description,proto3,oneof" json:"description,omitempty"` - ExpiresIn *durationpb.Duration `protobuf:"bytes,4,opt,name=expires_in,json=expiresIn,proto3,oneof" json:"expires_in,omitempty"` -} - -func (x *ProjectServiceAPITokenCreateRequest) Reset() { - *x = ProjectServiceAPITokenCreateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenCreateRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenCreateRequest) ProtoMessage() {} - -func (x *ProjectServiceAPITokenCreateRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenCreateRequest.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenCreateRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{0} -} - -func (x *ProjectServiceAPITokenCreateRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *ProjectServiceAPITokenCreateRequest) GetProjectName() string { - if x != nil { - return x.ProjectName - } - return "" -} - -func (x *ProjectServiceAPITokenCreateRequest) GetDescription() string { - if x != nil && x.Description != nil { - return *x.Description - } - return "" -} - -func (x *ProjectServiceAPITokenCreateRequest) GetExpiresIn() *durationpb.Duration { - if x != nil { - return x.ExpiresIn - } - return nil -} - -type ProjectServiceAPITokenCreateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Result *ProjectServiceAPITokenCreateResponse_APITokenFull `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` -} - -func (x *ProjectServiceAPITokenCreateResponse) Reset() { - *x = ProjectServiceAPITokenCreateResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenCreateResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenCreateResponse) ProtoMessage() {} - -func (x *ProjectServiceAPITokenCreateResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenCreateResponse.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenCreateResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{1} -} - -func (x *ProjectServiceAPITokenCreateResponse) GetResult() *ProjectServiceAPITokenCreateResponse_APITokenFull { - if x != nil { - return x.Result - } - return nil -} - -// ProjectServiceAPITokenRevokeRequest contains the information needed to revoke an API token for a project -type ProjectServiceAPITokenRevokeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The name of the API token to revoke - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // IdentityReference is used to specify the project by either its ID or name - ProjectReference *IdentityReference `protobuf:"bytes,2,opt,name=project_reference,json=projectReference,proto3" json:"project_reference,omitempty"` -} - -func (x *ProjectServiceAPITokenRevokeRequest) Reset() { - *x = ProjectServiceAPITokenRevokeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenRevokeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenRevokeRequest) ProtoMessage() {} - -func (x *ProjectServiceAPITokenRevokeRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenRevokeRequest.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenRevokeRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{2} -} - -func (x *ProjectServiceAPITokenRevokeRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *ProjectServiceAPITokenRevokeRequest) GetProjectReference() *IdentityReference { - if x != nil { - return x.ProjectReference - } - return nil -} - -// ProjectServiceAPITokenRevokeResponse is returned upon successful revocation of an API token -type ProjectServiceAPITokenRevokeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ProjectServiceAPITokenRevokeResponse) Reset() { - *x = ProjectServiceAPITokenRevokeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenRevokeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenRevokeResponse) ProtoMessage() {} - -func (x *ProjectServiceAPITokenRevokeResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenRevokeResponse.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenRevokeResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{3} -} - -// ProjectServiceAPITokenListRequest contains the information needed to list API tokens for a project -type ProjectServiceAPITokenListRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // IdentityReference is used to specify the project by either its ID or name - ProjectReference *IdentityReference `protobuf:"bytes,1,opt,name=project_reference,json=projectReference,proto3" json:"project_reference,omitempty"` - // Flag to include revoked tokens in the list - IncludeRevoked bool `protobuf:"varint,2,opt,name=include_revoked,json=includeRevoked,proto3" json:"include_revoked,omitempty"` -} - -func (x *ProjectServiceAPITokenListRequest) Reset() { - *x = ProjectServiceAPITokenListRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenListRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenListRequest) ProtoMessage() {} - -func (x *ProjectServiceAPITokenListRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenListRequest.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenListRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{4} -} - -func (x *ProjectServiceAPITokenListRequest) GetProjectReference() *IdentityReference { - if x != nil { - return x.ProjectReference - } - return nil -} - -func (x *ProjectServiceAPITokenListRequest) GetIncludeRevoked() bool { - if x != nil { - return x.IncludeRevoked - } - return false -} - -type ProjectServiceAPITokenListResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Result []*APITokenItem `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` -} - -func (x *ProjectServiceAPITokenListResponse) Reset() { - *x = ProjectServiceAPITokenListResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenListResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenListResponse) ProtoMessage() {} - -func (x *ProjectServiceAPITokenListResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenListResponse.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenListResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{5} -} - -func (x *ProjectServiceAPITokenListResponse) GetResult() []*APITokenItem { - if x != nil { - return x.Result - } - return nil -} - // ProjectServiceListMembersRequest contains the information needed to list members of a project type ProjectServiceListMembersRequest struct { state protoimpl.MessageState @@ -426,7 +106,7 @@ type ProjectServiceListMembersRequest struct { func (x *ProjectServiceListMembersRequest) Reset() { *x = ProjectServiceListMembersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[6] + mi := &file_controlplane_v1_project_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -439,7 +119,7 @@ func (x *ProjectServiceListMembersRequest) String() string { func (*ProjectServiceListMembersRequest) ProtoMessage() {} func (x *ProjectServiceListMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[6] + mi := &file_controlplane_v1_project_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -452,7 +132,7 @@ func (x *ProjectServiceListMembersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProjectServiceListMembersRequest.ProtoReflect.Descriptor instead. func (*ProjectServiceListMembersRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{6} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{0} } func (x *ProjectServiceListMembersRequest) GetProjectReference() *IdentityReference { @@ -484,7 +164,7 @@ type ProjectServiceListMembersResponse struct { func (x *ProjectServiceListMembersResponse) Reset() { *x = ProjectServiceListMembersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[7] + mi := &file_controlplane_v1_project_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -497,7 +177,7 @@ func (x *ProjectServiceListMembersResponse) String() string { func (*ProjectServiceListMembersResponse) ProtoMessage() {} func (x *ProjectServiceListMembersResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[7] + mi := &file_controlplane_v1_project_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -510,7 +190,7 @@ func (x *ProjectServiceListMembersResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ProjectServiceListMembersResponse.ProtoReflect.Descriptor instead. func (*ProjectServiceListMembersResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{7} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{1} } func (x *ProjectServiceListMembersResponse) GetMembers() []*ProjectMember { @@ -551,7 +231,7 @@ type ProjectMember struct { func (x *ProjectMember) Reset() { *x = ProjectMember{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[8] + mi := &file_controlplane_v1_project_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -564,7 +244,7 @@ func (x *ProjectMember) String() string { func (*ProjectMember) ProtoMessage() {} func (x *ProjectMember) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[8] + mi := &file_controlplane_v1_project_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -577,7 +257,7 @@ func (x *ProjectMember) ProtoReflect() protoreflect.Message { // Deprecated: Use ProjectMember.ProtoReflect.Descriptor instead. func (*ProjectMember) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{8} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{2} } func (m *ProjectMember) GetSubject() isProjectMember_Subject { @@ -657,7 +337,7 @@ type ProjectServiceAddMemberRequest struct { func (x *ProjectServiceAddMemberRequest) Reset() { *x = ProjectServiceAddMemberRequest{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[9] + mi := &file_controlplane_v1_project_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -670,7 +350,7 @@ func (x *ProjectServiceAddMemberRequest) String() string { func (*ProjectServiceAddMemberRequest) ProtoMessage() {} func (x *ProjectServiceAddMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[9] + mi := &file_controlplane_v1_project_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -683,7 +363,7 @@ func (x *ProjectServiceAddMemberRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProjectServiceAddMemberRequest.ProtoReflect.Descriptor instead. func (*ProjectServiceAddMemberRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{9} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{3} } func (x *ProjectServiceAddMemberRequest) GetProjectReference() *IdentityReference { @@ -717,7 +397,7 @@ type ProjectServiceAddMemberResponse struct { func (x *ProjectServiceAddMemberResponse) Reset() { *x = ProjectServiceAddMemberResponse{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[10] + mi := &file_controlplane_v1_project_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -730,7 +410,7 @@ func (x *ProjectServiceAddMemberResponse) String() string { func (*ProjectServiceAddMemberResponse) ProtoMessage() {} func (x *ProjectServiceAddMemberResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[10] + mi := &file_controlplane_v1_project_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -743,7 +423,7 @@ func (x *ProjectServiceAddMemberResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ProjectServiceAddMemberResponse.ProtoReflect.Descriptor instead. func (*ProjectServiceAddMemberResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{10} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{4} } type ProjectServiceRemoveMemberRequest struct { @@ -760,7 +440,7 @@ type ProjectServiceRemoveMemberRequest struct { func (x *ProjectServiceRemoveMemberRequest) Reset() { *x = ProjectServiceRemoveMemberRequest{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[11] + mi := &file_controlplane_v1_project_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -773,7 +453,7 @@ func (x *ProjectServiceRemoveMemberRequest) String() string { func (*ProjectServiceRemoveMemberRequest) ProtoMessage() {} func (x *ProjectServiceRemoveMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[11] + mi := &file_controlplane_v1_project_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -786,7 +466,7 @@ func (x *ProjectServiceRemoveMemberRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ProjectServiceRemoveMemberRequest.ProtoReflect.Descriptor instead. func (*ProjectServiceRemoveMemberRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{11} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{5} } func (x *ProjectServiceRemoveMemberRequest) GetProjectReference() *IdentityReference { @@ -813,7 +493,7 @@ type ProjectServiceRemoveMemberResponse struct { func (x *ProjectServiceRemoveMemberResponse) Reset() { *x = ProjectServiceRemoveMemberResponse{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[12] + mi := &file_controlplane_v1_project_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -826,7 +506,7 @@ func (x *ProjectServiceRemoveMemberResponse) String() string { func (*ProjectServiceRemoveMemberResponse) ProtoMessage() {} func (x *ProjectServiceRemoveMemberResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[12] + mi := &file_controlplane_v1_project_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -839,7 +519,7 @@ func (x *ProjectServiceRemoveMemberResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ProjectServiceRemoveMemberResponse.ProtoReflect.Descriptor instead. func (*ProjectServiceRemoveMemberResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{12} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{6} } // ProjectMembershipReference is used to reference a user or group in the context of project membership @@ -860,7 +540,7 @@ type ProjectMembershipReference struct { func (x *ProjectMembershipReference) Reset() { *x = ProjectMembershipReference{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[13] + mi := &file_controlplane_v1_project_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -873,7 +553,7 @@ func (x *ProjectMembershipReference) String() string { func (*ProjectMembershipReference) ProtoMessage() {} func (x *ProjectMembershipReference) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[13] + mi := &file_controlplane_v1_project_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -886,7 +566,7 @@ func (x *ProjectMembershipReference) ProtoReflect() protoreflect.Message { // Deprecated: Use ProjectMembershipReference.ProtoReflect.Descriptor instead. func (*ProjectMembershipReference) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{13} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{7} } func (m *ProjectMembershipReference) GetMembershipReference() isProjectMembershipReference_MembershipReference { @@ -946,7 +626,7 @@ type ProjectServiceUpdateMemberRoleRequest struct { func (x *ProjectServiceUpdateMemberRoleRequest) Reset() { *x = ProjectServiceUpdateMemberRoleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[14] + mi := &file_controlplane_v1_project_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -959,7 +639,7 @@ func (x *ProjectServiceUpdateMemberRoleRequest) String() string { func (*ProjectServiceUpdateMemberRoleRequest) ProtoMessage() {} func (x *ProjectServiceUpdateMemberRoleRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[14] + mi := &file_controlplane_v1_project_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -972,7 +652,7 @@ func (x *ProjectServiceUpdateMemberRoleRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ProjectServiceUpdateMemberRoleRequest.ProtoReflect.Descriptor instead. func (*ProjectServiceUpdateMemberRoleRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{14} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{8} } func (x *ProjectServiceUpdateMemberRoleRequest) GetProjectReference() *IdentityReference { @@ -1006,7 +686,7 @@ type ProjectServiceUpdateMemberRoleResponse struct { func (x *ProjectServiceUpdateMemberRoleResponse) Reset() { *x = ProjectServiceUpdateMemberRoleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[15] + mi := &file_controlplane_v1_project_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1019,7 +699,7 @@ func (x *ProjectServiceUpdateMemberRoleResponse) String() string { func (*ProjectServiceUpdateMemberRoleResponse) ProtoMessage() {} func (x *ProjectServiceUpdateMemberRoleResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[15] + mi := &file_controlplane_v1_project_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1032,7 +712,7 @@ func (x *ProjectServiceUpdateMemberRoleResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ProjectServiceUpdateMemberRoleResponse.ProtoReflect.Descriptor instead. func (*ProjectServiceUpdateMemberRoleResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{15} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{9} } type ProjectServiceListPendingInvitationsRequest struct { @@ -1049,7 +729,7 @@ type ProjectServiceListPendingInvitationsRequest struct { func (x *ProjectServiceListPendingInvitationsRequest) Reset() { *x = ProjectServiceListPendingInvitationsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[16] + mi := &file_controlplane_v1_project_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1062,7 +742,7 @@ func (x *ProjectServiceListPendingInvitationsRequest) String() string { func (*ProjectServiceListPendingInvitationsRequest) ProtoMessage() {} func (x *ProjectServiceListPendingInvitationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[16] + mi := &file_controlplane_v1_project_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1075,7 +755,7 @@ func (x *ProjectServiceListPendingInvitationsRequest) ProtoReflect() protoreflec // Deprecated: Use ProjectServiceListPendingInvitationsRequest.ProtoReflect.Descriptor instead. func (*ProjectServiceListPendingInvitationsRequest) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{16} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{10} } func (x *ProjectServiceListPendingInvitationsRequest) GetProjectReference() *IdentityReference { @@ -1107,7 +787,7 @@ type ProjectServiceListPendingInvitationsResponse struct { func (x *ProjectServiceListPendingInvitationsResponse) Reset() { *x = ProjectServiceListPendingInvitationsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[17] + mi := &file_controlplane_v1_project_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1120,7 +800,7 @@ func (x *ProjectServiceListPendingInvitationsResponse) String() string { func (*ProjectServiceListPendingInvitationsResponse) ProtoMessage() {} func (x *ProjectServiceListPendingInvitationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[17] + mi := &file_controlplane_v1_project_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1133,7 +813,7 @@ func (x *ProjectServiceListPendingInvitationsResponse) ProtoReflect() protorefle // Deprecated: Use ProjectServiceListPendingInvitationsResponse.ProtoReflect.Descriptor instead. func (*ProjectServiceListPendingInvitationsResponse) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{17} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{11} } func (x *ProjectServiceListPendingInvitationsResponse) GetInvitations() []*PendingProjectInvitation { @@ -1169,7 +849,7 @@ type PendingProjectInvitation struct { func (x *PendingProjectInvitation) Reset() { *x = PendingProjectInvitation{} if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[18] + mi := &file_controlplane_v1_project_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1182,7 +862,7 @@ func (x *PendingProjectInvitation) String() string { func (*PendingProjectInvitation) ProtoMessage() {} func (x *PendingProjectInvitation) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[18] + mi := &file_controlplane_v1_project_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1195,7 +875,7 @@ func (x *PendingProjectInvitation) ProtoReflect() protoreflect.Message { // Deprecated: Use PendingProjectInvitation.ProtoReflect.Descriptor instead. func (*PendingProjectInvitation) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{18} + return file_controlplane_v1_project_proto_rawDescGZIP(), []int{12} } func (x *PendingProjectInvitation) GetUserEmail() string { @@ -1226,61 +906,6 @@ func (x *PendingProjectInvitation) GetInvitationId() string { return "" } -type ProjectServiceAPITokenCreateResponse_APITokenFull struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Item *APITokenItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` - Jwt string `protobuf:"bytes,2,opt,name=jwt,proto3" json:"jwt,omitempty"` -} - -func (x *ProjectServiceAPITokenCreateResponse_APITokenFull) Reset() { - *x = ProjectServiceAPITokenCreateResponse_APITokenFull{} - if protoimpl.UnsafeEnabled { - mi := &file_controlplane_v1_project_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProjectServiceAPITokenCreateResponse_APITokenFull) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProjectServiceAPITokenCreateResponse_APITokenFull) ProtoMessage() {} - -func (x *ProjectServiceAPITokenCreateResponse_APITokenFull) ProtoReflect() protoreflect.Message { - mi := &file_controlplane_v1_project_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProjectServiceAPITokenCreateResponse_APITokenFull.ProtoReflect.Descriptor instead. -func (*ProjectServiceAPITokenCreateResponse_APITokenFull) Descriptor() ([]byte, []int) { - return file_controlplane_v1_project_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *ProjectServiceAPITokenCreateResponse_APITokenFull) GetItem() *APITokenItem { - if x != nil { - return x.Item - } - return nil -} - -func (x *ProjectServiceAPITokenCreateResponse_APITokenFull) GetJwt() string { - if x != nil { - return x.Jwt - } - return "" -} - var File_controlplane_v1_project_proto protoreflect.FileDescriptor var file_controlplane_v1_project_proto_rawDesc = []byte{ @@ -1301,294 +926,213 @@ var file_controlplane_v1_project_proto_rawDesc = []byte{ 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf3, 0x01, 0x0a, - 0x23, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, - 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x2a, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, - 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x49, 0x6e, - 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, - 0x69, 0x6e, 0x22, 0xd7, 0x01, 0x0a, 0x24, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x53, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x12, 0x31, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x77, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0x9b, 0x01, 0x0a, - 0x23, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, - 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc5, 0x01, 0x0a, + 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x26, 0x0a, 0x24, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xa5, 0x01, 0x0a, 0x21, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, - 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x22, 0x5b, 0x0a, 0x22, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x35, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xc5, 0x01, 0x0a, 0x20, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0xa8, 0x01, 0x0a, 0x21, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, - 0x49, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, - 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa5, 0x02, 0x0a, 0x0d, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x05, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x48, 0x00, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, 0x0a, 0x04, 0x72, 0x6f, 0x6c, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, - 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x22, 0xa1, 0x02, 0x0a, 0x1e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x5e, - 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0f, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x46, + 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0a, 0x70, 0x61, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x01, 0x0a, 0x21, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x12, 0x49, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x66, 0x66, 0x73, 0x65, + 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0xa5, 0x02, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x2b, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x48, 0x00, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x2e, + 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, - 0x42, 0x0e, 0xba, 0x48, 0x0b, 0xc8, 0x01, 0x01, 0x82, 0x01, 0x05, 0x10, 0x01, 0x22, 0x01, 0x00, - 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdc, 0x01, 0x0a, 0x21, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, - 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, - 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x24, 0x0a, 0x22, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xad, - 0x01, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x28, 0x0a, - 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x60, 0x01, 0x48, 0x00, 0x52, 0x09, 0x75, 0x73, - 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x4d, 0x0a, 0x0f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x42, 0x09, 0x0a, 0x07, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xa1, 0x02, 0x0a, 0x1e, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, + 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, + 0x01, 0x01, 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x12, 0x46, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x42, 0x0e, 0xba, 0x48, 0x0b, 0xc8, 0x01, 0x01, 0x82, 0x01, 0x05, + 0x10, 0x01, 0x22, 0x01, 0x00, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdc, + 0x01, 0x0a, 0x21, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x5e, 0x0a, + 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0f, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x24, 0x0a, + 0x22, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xad, 0x01, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x12, 0x28, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x60, 0x01, 0x48, + 0x00, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x4d, 0x0a, 0x0f, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x16, 0x0a, 0x14, 0x6d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x22, 0xa7, 0x02, 0x0a, 0x25, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, + 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, + 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x16, 0x0a, 0x14, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0xa7, - 0x02, 0x0a, 0x25, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x5e, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, - 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x45, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x07, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x22, 0x28, 0x0a, 0x26, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x2b, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, + 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, + 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x42, 0x06, 0xba, 0x48, + 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x22, 0x28, 0x0a, + 0x26, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x2b, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x12, 0x48, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x50, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, + 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xc6, 0x01, 0x0a, 0x2c, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x69, + 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x49, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xec, 0x01, 0x0a, 0x18, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x26, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x60, 0x01, 0x52, 0x09, 0x75, + 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x48, 0x00, 0x52, 0x09, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x42, 0x79, + 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, + 0x0a, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x5f, + 0x62, 0x79, 0x2a, 0x77, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x4a, 0x45, + 0x43, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, + 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, + 0x4f, 0x4c, 0x45, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x50, + 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, + 0x4c, 0x45, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x10, 0x02, 0x32, 0x8f, 0x05, 0x0a, 0x0e, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x74, + 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0a, 0x70, - 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xc6, 0x01, 0x0a, 0x2c, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x49, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xec, - 0x01, 0x0a, 0x18, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0a, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x60, 0x01, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, - 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x62, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x48, 0x00, - 0x52, 0x09, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x42, 0x79, 0x88, 0x01, 0x01, 0x12, 0x39, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x0d, - 0x0a, 0x0b, 0x5f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x2a, 0x77, 0x0a, - 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, - 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x45, - 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x52, 0x4f, 0x4a, 0x45, - 0x43, 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x41, - 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, - 0x54, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x56, 0x49, - 0x45, 0x57, 0x45, 0x52, 0x10, 0x02, 0x32, 0x86, 0x08, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x0e, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x34, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x0c, 0x41, 0x50, 0x49, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x7d, 0x0a, 0x0e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x76, - 0x6f, 0x6b, 0x65, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x74, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, - 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, + 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, + 0x6c, 0x65, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, + 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x83, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, + 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x4c, 0x5a, + 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, + 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1604,90 +1148,69 @@ func file_controlplane_v1_project_proto_rawDescGZIP() []byte { } var file_controlplane_v1_project_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_controlplane_v1_project_proto_msgTypes = make([]protoimpl.MessageInfo, 20) +var file_controlplane_v1_project_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_controlplane_v1_project_proto_goTypes = []interface{}{ - (ProjectMemberRole)(0), // 0: controlplane.v1.ProjectMemberRole - (*ProjectServiceAPITokenCreateRequest)(nil), // 1: controlplane.v1.ProjectServiceAPITokenCreateRequest - (*ProjectServiceAPITokenCreateResponse)(nil), // 2: controlplane.v1.ProjectServiceAPITokenCreateResponse - (*ProjectServiceAPITokenRevokeRequest)(nil), // 3: controlplane.v1.ProjectServiceAPITokenRevokeRequest - (*ProjectServiceAPITokenRevokeResponse)(nil), // 4: controlplane.v1.ProjectServiceAPITokenRevokeResponse - (*ProjectServiceAPITokenListRequest)(nil), // 5: controlplane.v1.ProjectServiceAPITokenListRequest - (*ProjectServiceAPITokenListResponse)(nil), // 6: controlplane.v1.ProjectServiceAPITokenListResponse - (*ProjectServiceListMembersRequest)(nil), // 7: controlplane.v1.ProjectServiceListMembersRequest - (*ProjectServiceListMembersResponse)(nil), // 8: controlplane.v1.ProjectServiceListMembersResponse - (*ProjectMember)(nil), // 9: controlplane.v1.ProjectMember - (*ProjectServiceAddMemberRequest)(nil), // 10: controlplane.v1.ProjectServiceAddMemberRequest - (*ProjectServiceAddMemberResponse)(nil), // 11: controlplane.v1.ProjectServiceAddMemberResponse - (*ProjectServiceRemoveMemberRequest)(nil), // 12: controlplane.v1.ProjectServiceRemoveMemberRequest - (*ProjectServiceRemoveMemberResponse)(nil), // 13: controlplane.v1.ProjectServiceRemoveMemberResponse - (*ProjectMembershipReference)(nil), // 14: controlplane.v1.ProjectMembershipReference - (*ProjectServiceUpdateMemberRoleRequest)(nil), // 15: controlplane.v1.ProjectServiceUpdateMemberRoleRequest - (*ProjectServiceUpdateMemberRoleResponse)(nil), // 16: controlplane.v1.ProjectServiceUpdateMemberRoleResponse - (*ProjectServiceListPendingInvitationsRequest)(nil), // 17: controlplane.v1.ProjectServiceListPendingInvitationsRequest - (*ProjectServiceListPendingInvitationsResponse)(nil), // 18: controlplane.v1.ProjectServiceListPendingInvitationsResponse - (*PendingProjectInvitation)(nil), // 19: controlplane.v1.PendingProjectInvitation - (*ProjectServiceAPITokenCreateResponse_APITokenFull)(nil), // 20: controlplane.v1.ProjectServiceAPITokenCreateResponse.APITokenFull - (*durationpb.Duration)(nil), // 21: google.protobuf.Duration - (*IdentityReference)(nil), // 22: controlplane.v1.IdentityReference - (*APITokenItem)(nil), // 23: controlplane.v1.APITokenItem - (*OffsetPaginationRequest)(nil), // 24: controlplane.v1.OffsetPaginationRequest - (*OffsetPaginationResponse)(nil), // 25: controlplane.v1.OffsetPaginationResponse - (*User)(nil), // 26: controlplane.v1.User - (*Group)(nil), // 27: controlplane.v1.Group - (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp + (ProjectMemberRole)(0), // 0: controlplane.v1.ProjectMemberRole + (*ProjectServiceListMembersRequest)(nil), // 1: controlplane.v1.ProjectServiceListMembersRequest + (*ProjectServiceListMembersResponse)(nil), // 2: controlplane.v1.ProjectServiceListMembersResponse + (*ProjectMember)(nil), // 3: controlplane.v1.ProjectMember + (*ProjectServiceAddMemberRequest)(nil), // 4: controlplane.v1.ProjectServiceAddMemberRequest + (*ProjectServiceAddMemberResponse)(nil), // 5: controlplane.v1.ProjectServiceAddMemberResponse + (*ProjectServiceRemoveMemberRequest)(nil), // 6: controlplane.v1.ProjectServiceRemoveMemberRequest + (*ProjectServiceRemoveMemberResponse)(nil), // 7: controlplane.v1.ProjectServiceRemoveMemberResponse + (*ProjectMembershipReference)(nil), // 8: controlplane.v1.ProjectMembershipReference + (*ProjectServiceUpdateMemberRoleRequest)(nil), // 9: controlplane.v1.ProjectServiceUpdateMemberRoleRequest + (*ProjectServiceUpdateMemberRoleResponse)(nil), // 10: controlplane.v1.ProjectServiceUpdateMemberRoleResponse + (*ProjectServiceListPendingInvitationsRequest)(nil), // 11: controlplane.v1.ProjectServiceListPendingInvitationsRequest + (*ProjectServiceListPendingInvitationsResponse)(nil), // 12: controlplane.v1.ProjectServiceListPendingInvitationsResponse + (*PendingProjectInvitation)(nil), // 13: controlplane.v1.PendingProjectInvitation + (*IdentityReference)(nil), // 14: controlplane.v1.IdentityReference + (*OffsetPaginationRequest)(nil), // 15: controlplane.v1.OffsetPaginationRequest + (*OffsetPaginationResponse)(nil), // 16: controlplane.v1.OffsetPaginationResponse + (*User)(nil), // 17: controlplane.v1.User + (*Group)(nil), // 18: controlplane.v1.Group + (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp } var file_controlplane_v1_project_proto_depIdxs = []int32{ - 21, // 0: controlplane.v1.ProjectServiceAPITokenCreateRequest.expires_in:type_name -> google.protobuf.Duration - 20, // 1: controlplane.v1.ProjectServiceAPITokenCreateResponse.result:type_name -> controlplane.v1.ProjectServiceAPITokenCreateResponse.APITokenFull - 22, // 2: controlplane.v1.ProjectServiceAPITokenRevokeRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 22, // 3: controlplane.v1.ProjectServiceAPITokenListRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 23, // 4: controlplane.v1.ProjectServiceAPITokenListResponse.result:type_name -> controlplane.v1.APITokenItem - 22, // 5: controlplane.v1.ProjectServiceListMembersRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 24, // 6: controlplane.v1.ProjectServiceListMembersRequest.pagination:type_name -> controlplane.v1.OffsetPaginationRequest - 9, // 7: controlplane.v1.ProjectServiceListMembersResponse.members:type_name -> controlplane.v1.ProjectMember - 25, // 8: controlplane.v1.ProjectServiceListMembersResponse.pagination:type_name -> controlplane.v1.OffsetPaginationResponse - 26, // 9: controlplane.v1.ProjectMember.user:type_name -> controlplane.v1.User - 27, // 10: controlplane.v1.ProjectMember.group:type_name -> controlplane.v1.Group - 0, // 11: controlplane.v1.ProjectMember.role:type_name -> controlplane.v1.ProjectMemberRole - 28, // 12: controlplane.v1.ProjectMember.created_at:type_name -> google.protobuf.Timestamp - 28, // 13: controlplane.v1.ProjectMember.updated_at:type_name -> google.protobuf.Timestamp - 22, // 14: controlplane.v1.ProjectServiceAddMemberRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 14, // 15: controlplane.v1.ProjectServiceAddMemberRequest.member_reference:type_name -> controlplane.v1.ProjectMembershipReference - 0, // 16: controlplane.v1.ProjectServiceAddMemberRequest.role:type_name -> controlplane.v1.ProjectMemberRole - 22, // 17: controlplane.v1.ProjectServiceRemoveMemberRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 14, // 18: controlplane.v1.ProjectServiceRemoveMemberRequest.member_reference:type_name -> controlplane.v1.ProjectMembershipReference - 22, // 19: controlplane.v1.ProjectMembershipReference.group_reference:type_name -> controlplane.v1.IdentityReference - 22, // 20: controlplane.v1.ProjectServiceUpdateMemberRoleRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 14, // 21: controlplane.v1.ProjectServiceUpdateMemberRoleRequest.member_reference:type_name -> controlplane.v1.ProjectMembershipReference - 0, // 22: controlplane.v1.ProjectServiceUpdateMemberRoleRequest.new_role:type_name -> controlplane.v1.ProjectMemberRole - 22, // 23: controlplane.v1.ProjectServiceListPendingInvitationsRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 24, // 24: controlplane.v1.ProjectServiceListPendingInvitationsRequest.pagination:type_name -> controlplane.v1.OffsetPaginationRequest - 19, // 25: controlplane.v1.ProjectServiceListPendingInvitationsResponse.invitations:type_name -> controlplane.v1.PendingProjectInvitation - 25, // 26: controlplane.v1.ProjectServiceListPendingInvitationsResponse.pagination:type_name -> controlplane.v1.OffsetPaginationResponse - 26, // 27: controlplane.v1.PendingProjectInvitation.invited_by:type_name -> controlplane.v1.User - 28, // 28: controlplane.v1.PendingProjectInvitation.created_at:type_name -> google.protobuf.Timestamp - 23, // 29: controlplane.v1.ProjectServiceAPITokenCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem - 1, // 30: controlplane.v1.ProjectService.APITokenCreate:input_type -> controlplane.v1.ProjectServiceAPITokenCreateRequest - 5, // 31: controlplane.v1.ProjectService.APITokenList:input_type -> controlplane.v1.ProjectServiceAPITokenListRequest - 3, // 32: controlplane.v1.ProjectService.APITokenRevoke:input_type -> controlplane.v1.ProjectServiceAPITokenRevokeRequest - 7, // 33: controlplane.v1.ProjectService.ListMembers:input_type -> controlplane.v1.ProjectServiceListMembersRequest - 10, // 34: controlplane.v1.ProjectService.AddMember:input_type -> controlplane.v1.ProjectServiceAddMemberRequest - 12, // 35: controlplane.v1.ProjectService.RemoveMember:input_type -> controlplane.v1.ProjectServiceRemoveMemberRequest - 15, // 36: controlplane.v1.ProjectService.UpdateMemberRole:input_type -> controlplane.v1.ProjectServiceUpdateMemberRoleRequest - 17, // 37: controlplane.v1.ProjectService.ListPendingInvitations:input_type -> controlplane.v1.ProjectServiceListPendingInvitationsRequest - 2, // 38: controlplane.v1.ProjectService.APITokenCreate:output_type -> controlplane.v1.ProjectServiceAPITokenCreateResponse - 6, // 39: controlplane.v1.ProjectService.APITokenList:output_type -> controlplane.v1.ProjectServiceAPITokenListResponse - 4, // 40: controlplane.v1.ProjectService.APITokenRevoke:output_type -> controlplane.v1.ProjectServiceAPITokenRevokeResponse - 8, // 41: controlplane.v1.ProjectService.ListMembers:output_type -> controlplane.v1.ProjectServiceListMembersResponse - 11, // 42: controlplane.v1.ProjectService.AddMember:output_type -> controlplane.v1.ProjectServiceAddMemberResponse - 13, // 43: controlplane.v1.ProjectService.RemoveMember:output_type -> controlplane.v1.ProjectServiceRemoveMemberResponse - 16, // 44: controlplane.v1.ProjectService.UpdateMemberRole:output_type -> controlplane.v1.ProjectServiceUpdateMemberRoleResponse - 18, // 45: controlplane.v1.ProjectService.ListPendingInvitations:output_type -> controlplane.v1.ProjectServiceListPendingInvitationsResponse - 38, // [38:46] is the sub-list for method output_type - 30, // [30:38] is the sub-list for method input_type - 30, // [30:30] is the sub-list for extension type_name - 30, // [30:30] is the sub-list for extension extendee - 0, // [0:30] is the sub-list for field type_name + 14, // 0: controlplane.v1.ProjectServiceListMembersRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 15, // 1: controlplane.v1.ProjectServiceListMembersRequest.pagination:type_name -> controlplane.v1.OffsetPaginationRequest + 3, // 2: controlplane.v1.ProjectServiceListMembersResponse.members:type_name -> controlplane.v1.ProjectMember + 16, // 3: controlplane.v1.ProjectServiceListMembersResponse.pagination:type_name -> controlplane.v1.OffsetPaginationResponse + 17, // 4: controlplane.v1.ProjectMember.user:type_name -> controlplane.v1.User + 18, // 5: controlplane.v1.ProjectMember.group:type_name -> controlplane.v1.Group + 0, // 6: controlplane.v1.ProjectMember.role:type_name -> controlplane.v1.ProjectMemberRole + 19, // 7: controlplane.v1.ProjectMember.created_at:type_name -> google.protobuf.Timestamp + 19, // 8: controlplane.v1.ProjectMember.updated_at:type_name -> google.protobuf.Timestamp + 14, // 9: controlplane.v1.ProjectServiceAddMemberRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 8, // 10: controlplane.v1.ProjectServiceAddMemberRequest.member_reference:type_name -> controlplane.v1.ProjectMembershipReference + 0, // 11: controlplane.v1.ProjectServiceAddMemberRequest.role:type_name -> controlplane.v1.ProjectMemberRole + 14, // 12: controlplane.v1.ProjectServiceRemoveMemberRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 8, // 13: controlplane.v1.ProjectServiceRemoveMemberRequest.member_reference:type_name -> controlplane.v1.ProjectMembershipReference + 14, // 14: controlplane.v1.ProjectMembershipReference.group_reference:type_name -> controlplane.v1.IdentityReference + 14, // 15: controlplane.v1.ProjectServiceUpdateMemberRoleRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 8, // 16: controlplane.v1.ProjectServiceUpdateMemberRoleRequest.member_reference:type_name -> controlplane.v1.ProjectMembershipReference + 0, // 17: controlplane.v1.ProjectServiceUpdateMemberRoleRequest.new_role:type_name -> controlplane.v1.ProjectMemberRole + 14, // 18: controlplane.v1.ProjectServiceListPendingInvitationsRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 15, // 19: controlplane.v1.ProjectServiceListPendingInvitationsRequest.pagination:type_name -> controlplane.v1.OffsetPaginationRequest + 13, // 20: controlplane.v1.ProjectServiceListPendingInvitationsResponse.invitations:type_name -> controlplane.v1.PendingProjectInvitation + 16, // 21: controlplane.v1.ProjectServiceListPendingInvitationsResponse.pagination:type_name -> controlplane.v1.OffsetPaginationResponse + 17, // 22: controlplane.v1.PendingProjectInvitation.invited_by:type_name -> controlplane.v1.User + 19, // 23: controlplane.v1.PendingProjectInvitation.created_at:type_name -> google.protobuf.Timestamp + 1, // 24: controlplane.v1.ProjectService.ListMembers:input_type -> controlplane.v1.ProjectServiceListMembersRequest + 4, // 25: controlplane.v1.ProjectService.AddMember:input_type -> controlplane.v1.ProjectServiceAddMemberRequest + 6, // 26: controlplane.v1.ProjectService.RemoveMember:input_type -> controlplane.v1.ProjectServiceRemoveMemberRequest + 9, // 27: controlplane.v1.ProjectService.UpdateMemberRole:input_type -> controlplane.v1.ProjectServiceUpdateMemberRoleRequest + 11, // 28: controlplane.v1.ProjectService.ListPendingInvitations:input_type -> controlplane.v1.ProjectServiceListPendingInvitationsRequest + 2, // 29: controlplane.v1.ProjectService.ListMembers:output_type -> controlplane.v1.ProjectServiceListMembersResponse + 5, // 30: controlplane.v1.ProjectService.AddMember:output_type -> controlplane.v1.ProjectServiceAddMemberResponse + 7, // 31: controlplane.v1.ProjectService.RemoveMember:output_type -> controlplane.v1.ProjectServiceRemoveMemberResponse + 10, // 32: controlplane.v1.ProjectService.UpdateMemberRole:output_type -> controlplane.v1.ProjectServiceUpdateMemberRoleResponse + 12, // 33: controlplane.v1.ProjectService.ListPendingInvitations:output_type -> controlplane.v1.ProjectServiceListPendingInvitationsResponse + 29, // [29:34] is the sub-list for method output_type + 24, // [24:29] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name } func init() { file_controlplane_v1_project_proto_init() } @@ -1701,78 +1224,6 @@ func file_controlplane_v1_project_proto_init() { file_controlplane_v1_shared_message_proto_init() if !protoimpl.UnsafeEnabled { file_controlplane_v1_project_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenCreateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controlplane_v1_project_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenCreateResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controlplane_v1_project_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenRevokeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controlplane_v1_project_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenRevokeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controlplane_v1_project_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenListRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controlplane_v1_project_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenListResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controlplane_v1_project_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceListMembersRequest); i { case 0: return &v.state @@ -1784,7 +1235,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceListMembersResponse); i { case 0: return &v.state @@ -1796,7 +1247,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectMember); i { case 0: return &v.state @@ -1808,7 +1259,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceAddMemberRequest); i { case 0: return &v.state @@ -1820,7 +1271,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceAddMemberResponse); i { case 0: return &v.state @@ -1832,7 +1283,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceRemoveMemberRequest); i { case 0: return &v.state @@ -1844,7 +1295,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceRemoveMemberResponse); i { case 0: return &v.state @@ -1856,7 +1307,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectMembershipReference); i { case 0: return &v.state @@ -1868,7 +1319,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceUpdateMemberRoleRequest); i { case 0: return &v.state @@ -1880,7 +1331,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceUpdateMemberRoleResponse); i { case 0: return &v.state @@ -1892,7 +1343,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceListPendingInvitationsRequest); i { case 0: return &v.state @@ -1904,7 +1355,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectServiceListPendingInvitationsResponse); i { case 0: return &v.state @@ -1916,7 +1367,7 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_controlplane_v1_project_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingProjectInvitation); i { case 0: return &v.state @@ -1928,36 +1379,23 @@ func file_controlplane_v1_project_proto_init() { return nil } } - file_controlplane_v1_project_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProjectServiceAPITokenCreateResponse_APITokenFull); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } - file_controlplane_v1_project_proto_msgTypes[0].OneofWrappers = []interface{}{} - file_controlplane_v1_project_proto_msgTypes[8].OneofWrappers = []interface{}{ + file_controlplane_v1_project_proto_msgTypes[2].OneofWrappers = []interface{}{ (*ProjectMember_User)(nil), (*ProjectMember_Group)(nil), } - file_controlplane_v1_project_proto_msgTypes[13].OneofWrappers = []interface{}{ + file_controlplane_v1_project_proto_msgTypes[7].OneofWrappers = []interface{}{ (*ProjectMembershipReference_UserEmail)(nil), (*ProjectMembershipReference_GroupReference)(nil), } - file_controlplane_v1_project_proto_msgTypes[18].OneofWrappers = []interface{}{} + file_controlplane_v1_project_proto_msgTypes[12].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controlplane_v1_project_proto_rawDesc, NumEnums: 1, - NumMessages: 20, + NumMessages: 13, NumExtensions: 0, NumServices: 1, }, diff --git a/app/controlplane/api/controlplane/v1/project.proto b/app/controlplane/api/controlplane/v1/project.proto index ddff21970..54d4708b2 100644 --- a/app/controlplane/api/controlplane/v1/project.proto +++ b/app/controlplane/api/controlplane/v1/project.proto @@ -28,11 +28,6 @@ import "google/protobuf/timestamp.proto"; option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1"; service ProjectService { - // Project level API tokens - // DEPRECATED: Use the API token service instead - rpc APITokenCreate(ProjectServiceAPITokenCreateRequest) returns (ProjectServiceAPITokenCreateResponse); - rpc APITokenList(ProjectServiceAPITokenListRequest) returns (ProjectServiceAPITokenListResponse); - rpc APITokenRevoke(ProjectServiceAPITokenRevokeRequest) returns (ProjectServiceAPITokenRevokeResponse); // Project membership management rpc ListMembers(ProjectServiceListMembersRequest) returns (ProjectServiceListMembersResponse); rpc AddMember(ProjectServiceAddMemberRequest) returns (ProjectServiceAddMemberResponse); @@ -41,45 +36,6 @@ service ProjectService { rpc ListPendingInvitations(ProjectServiceListPendingInvitationsRequest) returns (ProjectServiceListPendingInvitationsResponse) {} } -message ProjectServiceAPITokenCreateRequest { - string name = 1 [(buf.validate.field).string.min_len = 1]; - string project_name = 2 [(buf.validate.field).string.min_len = 1]; - optional string description = 3; - optional google.protobuf.Duration expires_in = 4; -} - -message ProjectServiceAPITokenCreateResponse { - APITokenFull result = 1; - - message APITokenFull { - APITokenItem item = 1; - string jwt = 2; - } -} - -// ProjectServiceAPITokenRevokeRequest contains the information needed to revoke an API token for a project -message ProjectServiceAPITokenRevokeRequest { - // The name of the API token to revoke - string name = 1 [(buf.validate.field).string.min_len = 1]; - // IdentityReference is used to specify the project by either its ID or name - IdentityReference project_reference = 2 [(buf.validate.field).required = true]; -} - -// ProjectServiceAPITokenRevokeResponse is returned upon successful revocation of an API token -message ProjectServiceAPITokenRevokeResponse {} - -// ProjectServiceAPITokenListRequest contains the information needed to list API tokens for a project -message ProjectServiceAPITokenListRequest { - // IdentityReference is used to specify the project by either its ID or name - IdentityReference project_reference = 1 [(buf.validate.field).required = true]; - // Flag to include revoked tokens in the list - bool include_revoked = 2; -} - -message ProjectServiceAPITokenListResponse { - repeated APITokenItem result = 1; -} - // ProjectServiceListMembersRequest contains the information needed to list members of a project message ProjectServiceListMembersRequest { // IdentityReference is used to specify the project by either its ID or name diff --git a/app/controlplane/api/controlplane/v1/project_grpc.pb.go b/app/controlplane/api/controlplane/v1/project_grpc.pb.go index 9453b6974..06f0ecee5 100644 --- a/app/controlplane/api/controlplane/v1/project_grpc.pb.go +++ b/app/controlplane/api/controlplane/v1/project_grpc.pb.go @@ -34,9 +34,6 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ProjectService_APITokenCreate_FullMethodName = "/controlplane.v1.ProjectService/APITokenCreate" - ProjectService_APITokenList_FullMethodName = "/controlplane.v1.ProjectService/APITokenList" - ProjectService_APITokenRevoke_FullMethodName = "/controlplane.v1.ProjectService/APITokenRevoke" ProjectService_ListMembers_FullMethodName = "/controlplane.v1.ProjectService/ListMembers" ProjectService_AddMember_FullMethodName = "/controlplane.v1.ProjectService/AddMember" ProjectService_RemoveMember_FullMethodName = "/controlplane.v1.ProjectService/RemoveMember" @@ -48,11 +45,6 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ProjectServiceClient interface { - // Project level API tokens - // DEPRECATED: Use the API token service instead - APITokenCreate(ctx context.Context, in *ProjectServiceAPITokenCreateRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenCreateResponse, error) - APITokenList(ctx context.Context, in *ProjectServiceAPITokenListRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenListResponse, error) - APITokenRevoke(ctx context.Context, in *ProjectServiceAPITokenRevokeRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenRevokeResponse, error) // Project membership management ListMembers(ctx context.Context, in *ProjectServiceListMembersRequest, opts ...grpc.CallOption) (*ProjectServiceListMembersResponse, error) AddMember(ctx context.Context, in *ProjectServiceAddMemberRequest, opts ...grpc.CallOption) (*ProjectServiceAddMemberResponse, error) @@ -69,33 +61,6 @@ func NewProjectServiceClient(cc grpc.ClientConnInterface) ProjectServiceClient { return &projectServiceClient{cc} } -func (c *projectServiceClient) APITokenCreate(ctx context.Context, in *ProjectServiceAPITokenCreateRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenCreateResponse, error) { - out := new(ProjectServiceAPITokenCreateResponse) - err := c.cc.Invoke(ctx, ProjectService_APITokenCreate_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *projectServiceClient) APITokenList(ctx context.Context, in *ProjectServiceAPITokenListRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenListResponse, error) { - out := new(ProjectServiceAPITokenListResponse) - err := c.cc.Invoke(ctx, ProjectService_APITokenList_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *projectServiceClient) APITokenRevoke(ctx context.Context, in *ProjectServiceAPITokenRevokeRequest, opts ...grpc.CallOption) (*ProjectServiceAPITokenRevokeResponse, error) { - out := new(ProjectServiceAPITokenRevokeResponse) - err := c.cc.Invoke(ctx, ProjectService_APITokenRevoke_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *projectServiceClient) ListMembers(ctx context.Context, in *ProjectServiceListMembersRequest, opts ...grpc.CallOption) (*ProjectServiceListMembersResponse, error) { out := new(ProjectServiceListMembersResponse) err := c.cc.Invoke(ctx, ProjectService_ListMembers_FullMethodName, in, out, opts...) @@ -145,11 +110,6 @@ func (c *projectServiceClient) ListPendingInvitations(ctx context.Context, in *P // All implementations must embed UnimplementedProjectServiceServer // for forward compatibility type ProjectServiceServer interface { - // Project level API tokens - // DEPRECATED: Use the API token service instead - APITokenCreate(context.Context, *ProjectServiceAPITokenCreateRequest) (*ProjectServiceAPITokenCreateResponse, error) - APITokenList(context.Context, *ProjectServiceAPITokenListRequest) (*ProjectServiceAPITokenListResponse, error) - APITokenRevoke(context.Context, *ProjectServiceAPITokenRevokeRequest) (*ProjectServiceAPITokenRevokeResponse, error) // Project membership management ListMembers(context.Context, *ProjectServiceListMembersRequest) (*ProjectServiceListMembersResponse, error) AddMember(context.Context, *ProjectServiceAddMemberRequest) (*ProjectServiceAddMemberResponse, error) @@ -163,15 +123,6 @@ type ProjectServiceServer interface { type UnimplementedProjectServiceServer struct { } -func (UnimplementedProjectServiceServer) APITokenCreate(context.Context, *ProjectServiceAPITokenCreateRequest) (*ProjectServiceAPITokenCreateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method APITokenCreate not implemented") -} -func (UnimplementedProjectServiceServer) APITokenList(context.Context, *ProjectServiceAPITokenListRequest) (*ProjectServiceAPITokenListResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method APITokenList not implemented") -} -func (UnimplementedProjectServiceServer) APITokenRevoke(context.Context, *ProjectServiceAPITokenRevokeRequest) (*ProjectServiceAPITokenRevokeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method APITokenRevoke not implemented") -} func (UnimplementedProjectServiceServer) ListMembers(context.Context, *ProjectServiceListMembersRequest) (*ProjectServiceListMembersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListMembers not implemented") } @@ -200,60 +151,6 @@ func RegisterProjectServiceServer(s grpc.ServiceRegistrar, srv ProjectServiceSer s.RegisterService(&ProjectService_ServiceDesc, srv) } -func _ProjectService_APITokenCreate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProjectServiceAPITokenCreateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ProjectServiceServer).APITokenCreate(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: ProjectService_APITokenCreate_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProjectServiceServer).APITokenCreate(ctx, req.(*ProjectServiceAPITokenCreateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ProjectService_APITokenList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProjectServiceAPITokenListRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ProjectServiceServer).APITokenList(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: ProjectService_APITokenList_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProjectServiceServer).APITokenList(ctx, req.(*ProjectServiceAPITokenListRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ProjectService_APITokenRevoke_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProjectServiceAPITokenRevokeRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ProjectServiceServer).APITokenRevoke(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: ProjectService_APITokenRevoke_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProjectServiceServer).APITokenRevoke(ctx, req.(*ProjectServiceAPITokenRevokeRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _ProjectService_ListMembers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ProjectServiceListMembersRequest) if err := dec(in); err != nil { @@ -351,18 +248,6 @@ var ProjectService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "controlplane.v1.ProjectService", HandlerType: (*ProjectServiceServer)(nil), Methods: []grpc.MethodDesc{ - { - MethodName: "APITokenCreate", - Handler: _ProjectService_APITokenCreate_Handler, - }, - { - MethodName: "APITokenList", - Handler: _ProjectService_APITokenList_Handler, - }, - { - MethodName: "APITokenRevoke", - Handler: _ProjectService_APITokenRevoke_Handler, - }, { MethodName: "ListMembers", Handler: _ProjectService_ListMembers_Handler, diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts index 24c8e995b..f1d6abaab 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts @@ -28,7 +28,7 @@ export interface APITokenServiceCreateResponse_APITokenFull { } export interface APITokenServiceRevokeRequest { - name: string; + id: string; } export interface APITokenServiceRevokeResponse { @@ -290,13 +290,13 @@ export const APITokenServiceCreateResponse_APITokenFull = { }; function createBaseAPITokenServiceRevokeRequest(): APITokenServiceRevokeRequest { - return { name: "" }; + return { id: "" }; } export const APITokenServiceRevokeRequest = { encode(message: APITokenServiceRevokeRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.name !== "") { - writer.uint32(10).string(message.name); + if (message.id !== "") { + writer.uint32(10).string(message.id); } return writer; }, @@ -313,7 +313,7 @@ export const APITokenServiceRevokeRequest = { break; } - message.name = reader.string(); + message.id = reader.string(); continue; } if ((tag & 7) === 4 || tag === 0) { @@ -325,12 +325,12 @@ export const APITokenServiceRevokeRequest = { }, fromJSON(object: any): APITokenServiceRevokeRequest { - return { name: isSet(object.name) ? String(object.name) : "" }; + return { id: isSet(object.id) ? String(object.id) : "" }; }, toJSON(message: APITokenServiceRevokeRequest): unknown { const obj: any = {}; - message.name !== undefined && (obj.name = message.name); + message.id !== undefined && (obj.id = message.id); return obj; }, @@ -340,7 +340,7 @@ export const APITokenServiceRevokeRequest = { fromPartial, I>>(object: I): APITokenServiceRevokeRequest { const message = createBaseAPITokenServiceRevokeRequest(); - message.name = object.name ?? ""; + message.id = object.id ?? ""; return message; }, }; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/project.ts b/app/controlplane/api/gen/frontend/controlplane/v1/project.ts index e6f207486..2e4341abb 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/project.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/project.ts @@ -2,11 +2,10 @@ import { grpc } from "@improbable-eng/grpc-web"; import { BrowserHeaders } from "browser-headers"; import _m0 from "protobufjs/minimal"; -import { Duration } from "../../google/protobuf/duration"; import { Timestamp } from "../../google/protobuf/timestamp"; import { Group } from "./group"; import { OffsetPaginationRequest, OffsetPaginationResponse } from "./pagination"; -import { APITokenItem, User } from "./response_messages"; +import { User } from "./response_messages"; import { IdentityReference } from "./shared_message"; export const protobufPackage = "controlplane.v1"; @@ -54,46 +53,6 @@ export function projectMemberRoleToJSON(object: ProjectMemberRole): string { } } -export interface ProjectServiceAPITokenCreateRequest { - name: string; - projectName: string; - description?: string | undefined; - expiresIn?: Duration | undefined; -} - -export interface ProjectServiceAPITokenCreateResponse { - result?: ProjectServiceAPITokenCreateResponse_APITokenFull; -} - -export interface ProjectServiceAPITokenCreateResponse_APITokenFull { - item?: APITokenItem; - jwt: string; -} - -/** ProjectServiceAPITokenRevokeRequest contains the information needed to revoke an API token for a project */ -export interface ProjectServiceAPITokenRevokeRequest { - /** The name of the API token to revoke */ - name: string; - /** IdentityReference is used to specify the project by either its ID or name */ - projectReference?: IdentityReference; -} - -/** ProjectServiceAPITokenRevokeResponse is returned upon successful revocation of an API token */ -export interface ProjectServiceAPITokenRevokeResponse { -} - -/** ProjectServiceAPITokenListRequest contains the information needed to list API tokens for a project */ -export interface ProjectServiceAPITokenListRequest { - /** IdentityReference is used to specify the project by either its ID or name */ - projectReference?: IdentityReference; - /** Flag to include revoked tokens in the list */ - includeRevoked: boolean; -} - -export interface ProjectServiceAPITokenListResponse { - result: APITokenItem[]; -} - /** ProjectServiceListMembersRequest contains the information needed to list members of a project */ export interface ProjectServiceListMembersRequest { /** IdentityReference is used to specify the project by either its ID or name */ @@ -206,534 +165,6 @@ export interface PendingProjectInvitation { invitationId: string; } -function createBaseProjectServiceAPITokenCreateRequest(): ProjectServiceAPITokenCreateRequest { - return { name: "", projectName: "", description: undefined, expiresIn: undefined }; -} - -export const ProjectServiceAPITokenCreateRequest = { - encode(message: ProjectServiceAPITokenCreateRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.name !== "") { - writer.uint32(10).string(message.name); - } - if (message.projectName !== "") { - writer.uint32(18).string(message.projectName); - } - if (message.description !== undefined) { - writer.uint32(26).string(message.description); - } - if (message.expiresIn !== undefined) { - Duration.encode(message.expiresIn, writer.uint32(34).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenCreateRequest { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenCreateRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.name = reader.string(); - continue; - case 2: - if (tag !== 18) { - break; - } - - message.projectName = reader.string(); - continue; - case 3: - if (tag !== 26) { - break; - } - - message.description = reader.string(); - continue; - case 4: - if (tag !== 34) { - break; - } - - message.expiresIn = Duration.decode(reader, reader.uint32()); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(object: any): ProjectServiceAPITokenCreateRequest { - return { - name: isSet(object.name) ? String(object.name) : "", - projectName: isSet(object.projectName) ? String(object.projectName) : "", - description: isSet(object.description) ? String(object.description) : undefined, - expiresIn: isSet(object.expiresIn) ? Duration.fromJSON(object.expiresIn) : undefined, - }; - }, - - toJSON(message: ProjectServiceAPITokenCreateRequest): unknown { - const obj: any = {}; - message.name !== undefined && (obj.name = message.name); - message.projectName !== undefined && (obj.projectName = message.projectName); - message.description !== undefined && (obj.description = message.description); - message.expiresIn !== undefined && - (obj.expiresIn = message.expiresIn ? Duration.toJSON(message.expiresIn) : undefined); - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenCreateRequest { - return ProjectServiceAPITokenCreateRequest.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - object: I, - ): ProjectServiceAPITokenCreateRequest { - const message = createBaseProjectServiceAPITokenCreateRequest(); - message.name = object.name ?? ""; - message.projectName = object.projectName ?? ""; - message.description = object.description ?? undefined; - message.expiresIn = (object.expiresIn !== undefined && object.expiresIn !== null) - ? Duration.fromPartial(object.expiresIn) - : undefined; - return message; - }, -}; - -function createBaseProjectServiceAPITokenCreateResponse(): ProjectServiceAPITokenCreateResponse { - return { result: undefined }; -} - -export const ProjectServiceAPITokenCreateResponse = { - encode(message: ProjectServiceAPITokenCreateResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.result !== undefined) { - ProjectServiceAPITokenCreateResponse_APITokenFull.encode(message.result, writer.uint32(10).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenCreateResponse { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenCreateResponse(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.result = ProjectServiceAPITokenCreateResponse_APITokenFull.decode(reader, reader.uint32()); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(object: any): ProjectServiceAPITokenCreateResponse { - return { - result: isSet(object.result) - ? ProjectServiceAPITokenCreateResponse_APITokenFull.fromJSON(object.result) - : undefined, - }; - }, - - toJSON(message: ProjectServiceAPITokenCreateResponse): unknown { - const obj: any = {}; - message.result !== undefined && (obj.result = message.result - ? ProjectServiceAPITokenCreateResponse_APITokenFull.toJSON(message.result) - : undefined); - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenCreateResponse { - return ProjectServiceAPITokenCreateResponse.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - object: I, - ): ProjectServiceAPITokenCreateResponse { - const message = createBaseProjectServiceAPITokenCreateResponse(); - message.result = (object.result !== undefined && object.result !== null) - ? ProjectServiceAPITokenCreateResponse_APITokenFull.fromPartial(object.result) - : undefined; - return message; - }, -}; - -function createBaseProjectServiceAPITokenCreateResponse_APITokenFull(): ProjectServiceAPITokenCreateResponse_APITokenFull { - return { item: undefined, jwt: "" }; -} - -export const ProjectServiceAPITokenCreateResponse_APITokenFull = { - encode( - message: ProjectServiceAPITokenCreateResponse_APITokenFull, - writer: _m0.Writer = _m0.Writer.create(), - ): _m0.Writer { - if (message.item !== undefined) { - APITokenItem.encode(message.item, writer.uint32(10).fork()).ldelim(); - } - if (message.jwt !== "") { - writer.uint32(18).string(message.jwt); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenCreateResponse_APITokenFull { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenCreateResponse_APITokenFull(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.item = APITokenItem.decode(reader, reader.uint32()); - continue; - case 2: - if (tag !== 18) { - break; - } - - message.jwt = reader.string(); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(object: any): ProjectServiceAPITokenCreateResponse_APITokenFull { - return { - item: isSet(object.item) ? APITokenItem.fromJSON(object.item) : undefined, - jwt: isSet(object.jwt) ? String(object.jwt) : "", - }; - }, - - toJSON(message: ProjectServiceAPITokenCreateResponse_APITokenFull): unknown { - const obj: any = {}; - message.item !== undefined && (obj.item = message.item ? APITokenItem.toJSON(message.item) : undefined); - message.jwt !== undefined && (obj.jwt = message.jwt); - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenCreateResponse_APITokenFull { - return ProjectServiceAPITokenCreateResponse_APITokenFull.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - object: I, - ): ProjectServiceAPITokenCreateResponse_APITokenFull { - const message = createBaseProjectServiceAPITokenCreateResponse_APITokenFull(); - message.item = (object.item !== undefined && object.item !== null) - ? APITokenItem.fromPartial(object.item) - : undefined; - message.jwt = object.jwt ?? ""; - return message; - }, -}; - -function createBaseProjectServiceAPITokenRevokeRequest(): ProjectServiceAPITokenRevokeRequest { - return { name: "", projectReference: undefined }; -} - -export const ProjectServiceAPITokenRevokeRequest = { - encode(message: ProjectServiceAPITokenRevokeRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.name !== "") { - writer.uint32(10).string(message.name); - } - if (message.projectReference !== undefined) { - IdentityReference.encode(message.projectReference, writer.uint32(18).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenRevokeRequest { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenRevokeRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.name = reader.string(); - continue; - case 2: - if (tag !== 18) { - break; - } - - message.projectReference = IdentityReference.decode(reader, reader.uint32()); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(object: any): ProjectServiceAPITokenRevokeRequest { - return { - name: isSet(object.name) ? String(object.name) : "", - projectReference: isSet(object.projectReference) - ? IdentityReference.fromJSON(object.projectReference) - : undefined, - }; - }, - - toJSON(message: ProjectServiceAPITokenRevokeRequest): unknown { - const obj: any = {}; - message.name !== undefined && (obj.name = message.name); - message.projectReference !== undefined && - (obj.projectReference = message.projectReference - ? IdentityReference.toJSON(message.projectReference) - : undefined); - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenRevokeRequest { - return ProjectServiceAPITokenRevokeRequest.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - object: I, - ): ProjectServiceAPITokenRevokeRequest { - const message = createBaseProjectServiceAPITokenRevokeRequest(); - message.name = object.name ?? ""; - message.projectReference = (object.projectReference !== undefined && object.projectReference !== null) - ? IdentityReference.fromPartial(object.projectReference) - : undefined; - return message; - }, -}; - -function createBaseProjectServiceAPITokenRevokeResponse(): ProjectServiceAPITokenRevokeResponse { - return {}; -} - -export const ProjectServiceAPITokenRevokeResponse = { - encode(_: ProjectServiceAPITokenRevokeResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenRevokeResponse { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenRevokeResponse(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(_: any): ProjectServiceAPITokenRevokeResponse { - return {}; - }, - - toJSON(_: ProjectServiceAPITokenRevokeResponse): unknown { - const obj: any = {}; - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenRevokeResponse { - return ProjectServiceAPITokenRevokeResponse.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - _: I, - ): ProjectServiceAPITokenRevokeResponse { - const message = createBaseProjectServiceAPITokenRevokeResponse(); - return message; - }, -}; - -function createBaseProjectServiceAPITokenListRequest(): ProjectServiceAPITokenListRequest { - return { projectReference: undefined, includeRevoked: false }; -} - -export const ProjectServiceAPITokenListRequest = { - encode(message: ProjectServiceAPITokenListRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.projectReference !== undefined) { - IdentityReference.encode(message.projectReference, writer.uint32(10).fork()).ldelim(); - } - if (message.includeRevoked === true) { - writer.uint32(16).bool(message.includeRevoked); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenListRequest { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenListRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.projectReference = IdentityReference.decode(reader, reader.uint32()); - continue; - case 2: - if (tag !== 16) { - break; - } - - message.includeRevoked = reader.bool(); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(object: any): ProjectServiceAPITokenListRequest { - return { - projectReference: isSet(object.projectReference) - ? IdentityReference.fromJSON(object.projectReference) - : undefined, - includeRevoked: isSet(object.includeRevoked) ? Boolean(object.includeRevoked) : false, - }; - }, - - toJSON(message: ProjectServiceAPITokenListRequest): unknown { - const obj: any = {}; - message.projectReference !== undefined && - (obj.projectReference = message.projectReference - ? IdentityReference.toJSON(message.projectReference) - : undefined); - message.includeRevoked !== undefined && (obj.includeRevoked = message.includeRevoked); - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenListRequest { - return ProjectServiceAPITokenListRequest.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - object: I, - ): ProjectServiceAPITokenListRequest { - const message = createBaseProjectServiceAPITokenListRequest(); - message.projectReference = (object.projectReference !== undefined && object.projectReference !== null) - ? IdentityReference.fromPartial(object.projectReference) - : undefined; - message.includeRevoked = object.includeRevoked ?? false; - return message; - }, -}; - -function createBaseProjectServiceAPITokenListResponse(): ProjectServiceAPITokenListResponse { - return { result: [] }; -} - -export const ProjectServiceAPITokenListResponse = { - encode(message: ProjectServiceAPITokenListResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - for (const v of message.result) { - APITokenItem.encode(v!, writer.uint32(10).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ProjectServiceAPITokenListResponse { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseProjectServiceAPITokenListResponse(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.result.push(APITokenItem.decode(reader, reader.uint32())); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - fromJSON(object: any): ProjectServiceAPITokenListResponse { - return { result: Array.isArray(object?.result) ? object.result.map((e: any) => APITokenItem.fromJSON(e)) : [] }; - }, - - toJSON(message: ProjectServiceAPITokenListResponse): unknown { - const obj: any = {}; - if (message.result) { - obj.result = message.result.map((e) => e ? APITokenItem.toJSON(e) : undefined); - } else { - obj.result = []; - } - return obj; - }, - - create, I>>( - base?: I, - ): ProjectServiceAPITokenListResponse { - return ProjectServiceAPITokenListResponse.fromPartial(base ?? {}); - }, - - fromPartial, I>>( - object: I, - ): ProjectServiceAPITokenListResponse { - const message = createBaseProjectServiceAPITokenListResponse(); - message.result = object.result?.map((e) => APITokenItem.fromPartial(e)) || []; - return message; - }, -}; - function createBaseProjectServiceListMembersRequest(): ProjectServiceListMembersRequest { return { projectReference: undefined, pagination: undefined }; } @@ -1782,22 +1213,6 @@ export const PendingProjectInvitation = { }; export interface ProjectService { - /** - * Project level API tokens - * DEPRECATED: Use the API token service instead - */ - APITokenCreate( - request: DeepPartial, - metadata?: grpc.Metadata, - ): Promise; - APITokenList( - request: DeepPartial, - metadata?: grpc.Metadata, - ): Promise; - APITokenRevoke( - request: DeepPartial, - metadata?: grpc.Metadata, - ): Promise; /** Project membership management */ ListMembers( request: DeepPartial, @@ -1826,9 +1241,6 @@ export class ProjectServiceClientImpl implements ProjectService { constructor(rpc: Rpc) { this.rpc = rpc; - this.APITokenCreate = this.APITokenCreate.bind(this); - this.APITokenList = this.APITokenList.bind(this); - this.APITokenRevoke = this.APITokenRevoke.bind(this); this.ListMembers = this.ListMembers.bind(this); this.AddMember = this.AddMember.bind(this); this.RemoveMember = this.RemoveMember.bind(this); @@ -1836,39 +1248,6 @@ export class ProjectServiceClientImpl implements ProjectService { this.ListPendingInvitations = this.ListPendingInvitations.bind(this); } - APITokenCreate( - request: DeepPartial, - metadata?: grpc.Metadata, - ): Promise { - return this.rpc.unary( - ProjectServiceAPITokenCreateDesc, - ProjectServiceAPITokenCreateRequest.fromPartial(request), - metadata, - ); - } - - APITokenList( - request: DeepPartial, - metadata?: grpc.Metadata, - ): Promise { - return this.rpc.unary( - ProjectServiceAPITokenListDesc, - ProjectServiceAPITokenListRequest.fromPartial(request), - metadata, - ); - } - - APITokenRevoke( - request: DeepPartial, - metadata?: grpc.Metadata, - ): Promise { - return this.rpc.unary( - ProjectServiceAPITokenRevokeDesc, - ProjectServiceAPITokenRevokeRequest.fromPartial(request), - metadata, - ); - } - ListMembers( request: DeepPartial, metadata?: grpc.Metadata, @@ -1923,75 +1302,6 @@ export class ProjectServiceClientImpl implements ProjectService { export const ProjectServiceDesc = { serviceName: "controlplane.v1.ProjectService" }; -export const ProjectServiceAPITokenCreateDesc: UnaryMethodDefinitionish = { - methodName: "APITokenCreate", - service: ProjectServiceDesc, - requestStream: false, - responseStream: false, - requestType: { - serializeBinary() { - return ProjectServiceAPITokenCreateRequest.encode(this).finish(); - }, - } as any, - responseType: { - deserializeBinary(data: Uint8Array) { - const value = ProjectServiceAPITokenCreateResponse.decode(data); - return { - ...value, - toObject() { - return value; - }, - }; - }, - } as any, -}; - -export const ProjectServiceAPITokenListDesc: UnaryMethodDefinitionish = { - methodName: "APITokenList", - service: ProjectServiceDesc, - requestStream: false, - responseStream: false, - requestType: { - serializeBinary() { - return ProjectServiceAPITokenListRequest.encode(this).finish(); - }, - } as any, - responseType: { - deserializeBinary(data: Uint8Array) { - const value = ProjectServiceAPITokenListResponse.decode(data); - return { - ...value, - toObject() { - return value; - }, - }; - }, - } as any, -}; - -export const ProjectServiceAPITokenRevokeDesc: UnaryMethodDefinitionish = { - methodName: "APITokenRevoke", - service: ProjectServiceDesc, - requestStream: false, - responseStream: false, - requestType: { - serializeBinary() { - return ProjectServiceAPITokenRevokeRequest.encode(this).finish(); - }, - } as any, - responseType: { - deserializeBinary(data: Uint8Array) { - const value = ProjectServiceAPITokenRevokeResponse.decode(data); - return { - ...value, - toObject() { - return value; - }, - }; - }, - } as any, -}; - export const ProjectServiceListMembersDesc: UnaryMethodDefinitionish = { methodName: "ListMembers", service: ProjectServiceDesc, diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.jsonschema.json index 862e7ead7..21307c1e9 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.jsonschema.json @@ -3,7 +3,8 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, "properties": { - "name": { + "id": { + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", "type": "string" } }, diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.schema.json index a4451b008..1c91a21f9 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceRevokeRequest.schema.json @@ -3,7 +3,8 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, "properties": { - "name": { + "id": { + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", "type": "string" } }, diff --git a/app/controlplane/cmd/wire_gen.go b/app/controlplane/cmd/wire_gen.go index 05efc269b..65076e3bf 100644 --- a/app/controlplane/cmd/wire_gen.go +++ b/app/controlplane/cmd/wire_gen.go @@ -231,7 +231,7 @@ func wireApp(bootstrap *conf.Bootstrap, readerWriter credentials.ReaderWriter, l signingService := service.NewSigningService(signingUseCase, v5...) prometheusService := service.NewPrometheusService(organizationUseCase, prometheusUseCase, v5...) groupService := service.NewGroupService(groupUseCase, v5...) - projectService := service.NewProjectService(apiTokenUseCase, v5...) + projectService := service.NewProjectService(v5...) federatedAuthentication := bootstrap.FederatedAuthentication validator, err := newProtoValidator() if err != nil { diff --git a/app/controlplane/internal/service/apitoken.go b/app/controlplane/internal/service/apitoken.go index 27eebf443..65ba275a7 100644 --- a/app/controlplane/internal/service/apitoken.go +++ b/app/controlplane/internal/service/apitoken.go @@ -1,5 +1,5 @@ // -// Copyright 2023 The Chainloop Authors. +// Copyright 2023-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -56,7 +56,7 @@ func (s *APITokenService) Create(ctx context.Context, req *pb.APITokenServiceCre var project *biz.Project if req.ProjectReference.IsSet() { // Make sure the provided project exists and the user has permission to create tokens in it - project, err = s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProjectReference(), authz.PolicyWorkflowContractCreate) + project, err = s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProjectReference(), authz.PolicyAPITokenCreate) if err != nil { return nil, err } @@ -107,11 +107,23 @@ func (s *APITokenService) Revoke(ctx context.Context, req *pb.APITokenServiceRev return nil, err } - t, err := s.APITokenUseCase.FindByNameInOrg(ctx, currentOrg.ID, req.Name) + t, err := s.APITokenUseCase.FindByIDInOrg(ctx, currentOrg.ID, req.GetId()) if err != nil { return nil, handleUseCaseErr(err, s.log) } + // 1 - Only admins can manage global contracts + if t.ProjectID == nil && rbacEnabled(ctx) { + return nil, errors.BadRequest("invalid", "you can not manage a global API token") + } + + // Make sure the user has permission to revoke the token in the project + if t.ProjectID != nil { + if err := s.authorizeResource(ctx, authz.PolicyAPITokenRevoke, authz.ResourceTypeProject, *t.ProjectID); err != nil { + return nil, err + } + } + if err := s.APITokenUseCase.Revoke(ctx, currentOrg.ID, t.ID.String()); err != nil { return nil, handleUseCaseErr(err, s.log) } diff --git a/app/controlplane/internal/service/project.go b/app/controlplane/internal/service/project.go index f2a24e488..0ac18fd78 100644 --- a/app/controlplane/internal/service/project.go +++ b/app/controlplane/internal/service/project.go @@ -18,7 +18,6 @@ package service import ( "context" "fmt" - "time" pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/authz" @@ -32,96 +31,12 @@ import ( type ProjectService struct { pb.UnimplementedProjectServiceServer *service - - // Use Cases - apiTokenUseCase *biz.APITokenUseCase } -func NewProjectService(apiTokenUseCase *biz.APITokenUseCase, opts ...NewOpt) *ProjectService { +func NewProjectService(opts ...NewOpt) *ProjectService { return &ProjectService{ - service: newService(opts...), - apiTokenUseCase: apiTokenUseCase, - } -} - -func (s *ProjectService) APITokenCreate(ctx context.Context, req *pb.ProjectServiceAPITokenCreateRequest) (*pb.ProjectServiceAPITokenCreateResponse, error) { - currentOrg, err := requireCurrentOrg(ctx) - if err != nil { - return nil, err - } - - // Make sure the provided project exists and the user has permission to create tokens in it - project, err := s.userHasPermissionOnProject(ctx, currentOrg.ID, &pb.IdentityReference{Name: &req.ProjectName}, authz.PolicyProjectAPITokenCreate) - if err != nil { - return nil, err - } - - var expiresIn *time.Duration - if req.ExpiresIn != nil { - expiresIn = new(time.Duration) - *expiresIn = req.ExpiresIn.AsDuration() - } - - token, err := s.apiTokenUseCase.Create(ctx, req.Name, req.Description, expiresIn, currentOrg.ID, biz.APITokenWithProject(project)) - if err != nil { - return nil, handleUseCaseErr(err, s.log) - } - - return &pb.ProjectServiceAPITokenCreateResponse{ - Result: &pb.ProjectServiceAPITokenCreateResponse_APITokenFull{ - Item: apiTokenBizToPb(token), - Jwt: token.JWT, - }, - }, nil -} - -func (s *ProjectService) APITokenList(ctx context.Context, req *pb.ProjectServiceAPITokenListRequest) (*pb.ProjectServiceAPITokenListResponse, error) { - currentOrg, err := requireCurrentOrg(ctx) - if err != nil { - return nil, err - } - - // Make sure the provided project exists and the user has permission to create tokens in it - project, err := s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProjectReference(), authz.PolicyProjectAPITokenList) - if err != nil { - return nil, err - } - - tokens, err := s.apiTokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenProjectFilter([]uuid.UUID{project.ID}), biz.WithApiTokenRevoked(req.IncludeRevoked)) - if err != nil { - return nil, handleUseCaseErr(err, s.log) - } - - result := make([]*pb.APITokenItem, 0, len(tokens)) - for _, p := range tokens { - result = append(result, apiTokenBizToPb(p)) + service: newService(opts...), } - - return &pb.ProjectServiceAPITokenListResponse{Result: result}, nil -} - -func (s *ProjectService) APITokenRevoke(ctx context.Context, req *pb.ProjectServiceAPITokenRevokeRequest) (*pb.ProjectServiceAPITokenRevokeResponse, error) { - currentOrg, err := requireCurrentOrg(ctx) - if err != nil { - return nil, err - } - - // Make sure the provided project exists and the user has permission to create tokens in it - project, err := s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProjectReference(), authz.PolicyProjectAPITokenRevoke) - if err != nil { - return nil, err - } - - t, err := s.apiTokenUseCase.FindByNameInOrg(ctx, currentOrg.ID, req.Name, biz.APITokenWithProject(project)) - if err != nil { - return nil, handleUseCaseErr(err, s.log) - } - - if err := s.apiTokenUseCase.Revoke(ctx, currentOrg.ID, t.ID.String()); err != nil { - return nil, handleUseCaseErr(err, s.log) - } - - return &pb.ProjectServiceAPITokenRevokeResponse{}, nil } // ListMembers lists the members of a project. diff --git a/app/controlplane/pkg/authz/authz.go b/app/controlplane/pkg/authz/authz.go index 1eb64343e..0fd91e9fa 100644 --- a/app/controlplane/pkg/authz/authz.go +++ b/app/controlplane/pkg/authz/authz.go @@ -50,7 +50,7 @@ const ( OrganizationMemberships = "organization_memberships" ResourceGroup = "group" ResourceGroupMembership = "group_membership" - ResourceProjectAPIToken = "project_api_token" + ResourceAPIToken = "api_token" ResourceProjectMembership = "project_membership" ResourceOrganizationInvitations = "organization_invitations" @@ -96,7 +96,7 @@ var ManagedResources = []string{ OrganizationMemberships, ResourceGroup, ResourceGroupMembership, - ResourceProjectAPIToken, + ResourceAPIToken, ResourceProjectMembership, ResourceOrganizationInvitations, } @@ -154,10 +154,10 @@ var ( PolicyGroupAddMemberships = &Policy{ResourceGroupMembership, ActionCreate} PolicyGroupRemoveMemberships = &Policy{ResourceGroupMembership, ActionDelete} PolicyGroupUpdateMemberships = &Policy{ResourceGroupMembership, ActionUpdate} - // Project API Token - PolicyProjectAPITokenList = &Policy{ResourceProjectAPIToken, ActionList} - PolicyProjectAPITokenCreate = &Policy{ResourceProjectAPIToken, ActionCreate} - PolicyProjectAPITokenRevoke = &Policy{ResourceProjectAPIToken, ActionDelete} + // API Token + PolicyAPITokenList = &Policy{ResourceAPIToken, ActionList} + PolicyAPITokenCreate = &Policy{ResourceAPIToken, ActionCreate} + PolicyAPITokenRevoke = &Policy{ResourceAPIToken, ActionDelete} // Project Memberships PolicyProjectListMemberships = &Policy{ResourceProjectMembership, ActionList} PolicyProjectAddMemberships = &Policy{ResourceProjectMembership, ActionCreate} @@ -257,10 +257,10 @@ var RolesMap = map[Role][]*Policy{ // Group Memberships PolicyGroupListMemberships, - // Project API Token - PolicyProjectAPITokenList, - PolicyProjectAPITokenCreate, - PolicyProjectAPITokenRevoke, + // Additional check for API tokens is done at the service level + PolicyAPITokenList, + PolicyAPITokenCreate, + PolicyAPITokenRevoke, // Project Memberships PolicyProjectListMemberships, @@ -307,9 +307,9 @@ var RolesMap = map[Role][]*Policy{ PolicyAttachedIntegrationDetach, // Project API Token - PolicyProjectAPITokenList, - PolicyProjectAPITokenCreate, - PolicyProjectAPITokenRevoke, + PolicyAPITokenList, + PolicyAPITokenCreate, + PolicyAPITokenRevoke, // Project Memberships PolicyProjectListMemberships, @@ -411,6 +411,11 @@ var ServerOperationsMap = map[string][]*Policy{ "/controlplane.v1.ProjectService/RemoveMember": {}, "/controlplane.v1.ProjectService/UpdateMemberRole": {}, "/controlplane.v1.ProjectService/ListPendingInvitations": {}, + + // API tokens RBAC are handled at the service level + "/controlplane.v1.APITokenService/List": {}, + "/controlplane.v1.APITokenService/Create": {}, + "/controlplane.v1.APITokenService/Revoke": {}, } // Implements https://pkg.go.dev/entgo.io/ent/schema/field#EnumValues diff --git a/app/controlplane/pkg/biz/apitoken.go b/app/controlplane/pkg/biz/apitoken.go index 5a5abd660..5459dcf67 100644 --- a/app/controlplane/pkg/biz/apitoken.go +++ b/app/controlplane/pkg/biz/apitoken.go @@ -62,7 +62,7 @@ type APITokenRepo interface { UpdateExpiration(ctx context.Context, ID uuid.UUID, expiresAt time.Time) error UpdateLastUsedAt(ctx context.Context, ID uuid.UUID, lastUsedAt time.Time) error FindByID(ctx context.Context, ID uuid.UUID) (*APIToken, error) - FindByNameInOrg(ctx context.Context, orgID uuid.UUID, name string, projectID *uuid.UUID) (*APIToken, error) + FindByIDInOrg(ctx context.Context, orgID uuid.UUID, id uuid.UUID) (*APIToken, error) } type APITokenUseCase struct { @@ -342,23 +342,18 @@ func (uc *APITokenUseCase) Revoke(ctx context.Context, orgID, id string) error { return nil } -func (uc *APITokenUseCase) FindByNameInOrg(ctx context.Context, orgID, name string, opts ...APITokenCreateOpt) (*APIToken, error) { - options := &apiTokenOptions{} - for _, opt := range opts { - opt(options) - } - +func (uc *APITokenUseCase) FindByIDInOrg(ctx context.Context, orgID, id string) (*APIToken, error) { orgUUID, err := uuid.Parse(orgID) if err != nil { return nil, NewErrInvalidUUID(err) } - var projectID *uuid.UUID - if options.project != nil { - projectID = ToPtr(options.project.ID) + tokenUUID, err := uuid.Parse(id) + if err != nil { + return nil, NewErrInvalidUUID(err) } - t, err := uc.apiTokenRepo.FindByNameInOrg(ctx, orgUUID, name, projectID) + t, err := uc.apiTokenRepo.FindByIDInOrg(ctx, orgUUID, tokenUUID) if err != nil { return nil, fmt.Errorf("finding token: %w", err) } diff --git a/app/controlplane/pkg/data/apitoken.go b/app/controlplane/pkg/data/apitoken.go index 6713f17a4..c47aa8e1d 100644 --- a/app/controlplane/pkg/data/apitoken.go +++ b/app/controlplane/pkg/data/apitoken.go @@ -71,16 +71,8 @@ func (r *APITokenRepo) FindByID(ctx context.Context, id uuid.UUID) (*biz.APIToke return entAPITokenToBiz(token), nil } -func (r *APITokenRepo) FindByNameInOrg(ctx context.Context, orgID uuid.UUID, name string, projectID *uuid.UUID) (*biz.APIToken, error) { - query := r.data.DB.APIToken.Query().Where(apitoken.NameEQ(name), apitoken.HasOrganizationWith(organization.ID(orgID)), apitoken.RevokedAtIsNil()) - - if projectID != nil { - query = query.Where(apitoken.ProjectIDEQ(*projectID)) - } else { - query = query.Where(apitoken.ProjectIDIsNil()) - } - - token, err := query.Only(ctx) +func (r *APITokenRepo) FindByIDInOrg(ctx context.Context, orgID uuid.UUID, id uuid.UUID) (*biz.APIToken, error) { + token, err := r.data.DB.APIToken.Query().Where(apitoken.ID(id), apitoken.HasOrganizationWith(organization.ID(orgID)), apitoken.RevokedAtIsNil()).WithProject().Only(ctx) if err != nil { if ent.IsNotFound(err) { return nil, biz.NewErrNotFound("API token") From 509f501bf7bd6d23407806b06154bedb4a22454e Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 21:59:19 +0200 Subject: [PATCH 19/24] add api token Signed-off-by: Miguel Martinez --- app/cli/cmd/organization_apitoken_list.go | 8 +- app/cli/documentation/cli-reference.mdx | 10 +- app/cli/internal/action/apitoken_list.go | 12 +- .../api/controlplane/v1/api_token.pb.go | 110 ++++++++++-------- .../api/controlplane/v1/api_token.proto | 3 + .../api/controlplane/v1/project.pb.go | 5 +- .../api/controlplane/v1/project.proto | 1 - .../gen/frontend/controlplane/v1/api_token.ts | 24 +++- ...APITokenServiceListRequest.jsonschema.json | 4 + ....v1.APITokenServiceListRequest.schema.json | 4 + app/controlplane/internal/service/apitoken.go | 15 ++- app/controlplane/pkg/authz/authz.go | 2 + .../pkg/biz/apitoken_integration_test.go | 13 +-- 13 files changed, 135 insertions(+), 76 deletions(-) diff --git a/app/cli/cmd/organization_apitoken_list.go b/app/cli/cmd/organization_apitoken_list.go index ff63ecda9..b695b3605 100644 --- a/app/cli/cmd/organization_apitoken_list.go +++ b/app/cli/cmd/organization_apitoken_list.go @@ -24,14 +24,17 @@ import ( ) func newAPITokenListCmd() *cobra.Command { - var includeRevoked bool + var ( + includeRevoked bool + project string + ) cmd := &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "List API tokens in this organization", RunE: func(cmd *cobra.Command, args []string) error { - res, err := action.NewAPITokenList(actionOpts).Run(context.Background(), includeRevoked) + res, err := action.NewAPITokenList(actionOpts).Run(context.Background(), includeRevoked, project) if err != nil { return fmt.Errorf("listing API tokens: %w", err) } @@ -41,5 +44,6 @@ func newAPITokenListCmd() *cobra.Command { } cmd.Flags().BoolVarP(&includeRevoked, "all", "a", false, "show all API tokens including revoked ones") + cmd.Flags().StringVarP(&project, "project", "p", "", "filter by project name") return cmd } diff --git a/app/cli/documentation/cli-reference.mdx b/app/cli/documentation/cli-reference.mdx index c9d05bb4d..5fa4132da 100755 --- a/app/cli/documentation/cli-reference.mdx +++ b/app/cli/documentation/cli-reference.mdx @@ -2044,6 +2044,7 @@ Options --expiration duration optional API token expiration, in hours i.e 1h, 24h, 178h (week), ... -h, --help help for create --name string token name +--project string project name used to scope the token, if not set the token will be created at the organization level ``` Options inherited from parent commands @@ -2108,8 +2109,9 @@ chainloop organization api-token list [flags] Options ``` --a, --all show all API tokens including revoked ones --h, --help help for list +-a, --all show all API tokens including revoked ones +-h, --help help for list +-p, --project string filter by project name ``` Options inherited from parent commands @@ -2139,8 +2141,8 @@ chainloop organization api-token revoke [flags] Options ``` --h, --help help for revoke ---name string API token name +-h, --help help for revoke +--id string API token ID ``` Options inherited from parent commands diff --git a/app/cli/internal/action/apitoken_list.go b/app/cli/internal/action/apitoken_list.go index 486df4fe2..848c70453 100644 --- a/app/cli/internal/action/apitoken_list.go +++ b/app/cli/internal/action/apitoken_list.go @@ -1,5 +1,5 @@ // -// Copyright 2024 The Chainloop Authors. +// Copyright 2024-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,9 +30,15 @@ func NewAPITokenList(cfg *ActionsOpts) *APITokenList { return &APITokenList{cfg} } -func (action *APITokenList) Run(ctx context.Context, includeRevoked bool) ([]*APITokenItem, error) { +func (action *APITokenList) Run(ctx context.Context, includeRevoked bool, project string) ([]*APITokenItem, error) { client := pb.NewAPITokenServiceClient(action.cfg.CPConnection) - resp, err := client.List(ctx, &pb.APITokenServiceListRequest{IncludeRevoked: includeRevoked}) + + req := &pb.APITokenServiceListRequest{IncludeRevoked: includeRevoked} + if project != "" { + req.Project = &pb.IdentityReference{Name: &project} + } + + resp, err := client.List(ctx, req) if err != nil { return nil, fmt.Errorf("listing API tokens: %w", err) } diff --git a/app/controlplane/api/controlplane/v1/api_token.pb.go b/app/controlplane/api/controlplane/v1/api_token.pb.go index 6593da309..ff4906652 100644 --- a/app/controlplane/api/controlplane/v1/api_token.pb.go +++ b/app/controlplane/api/controlplane/v1/api_token.pb.go @@ -247,6 +247,8 @@ type APITokenServiceListRequest struct { unknownFields protoimpl.UnknownFields IncludeRevoked bool `protobuf:"varint,1,opt,name=include_revoked,json=includeRevoked,proto3" json:"include_revoked,omitempty"` + // optional project reference to filter by + Project *IdentityReference `protobuf:"bytes,4,opt,name=project,proto3" json:"project,omitempty"` } func (x *APITokenServiceListRequest) Reset() { @@ -288,6 +290,13 @@ func (x *APITokenServiceListRequest) GetIncludeRevoked() bool { return false } +func (x *APITokenServiceListRequest) GetProject() *IdentityReference { + if x != nil { + return x.Project + } + return nil +} + type APITokenServiceListResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -440,43 +449,47 @@ var file_controlplane_v1_api_token_proto_rawDesc = []byte{ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1a, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, - 0x22, 0x54, 0x0a, 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x35, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, + 0x54, 0x0a, 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, + 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, + 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x4c, 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, + 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -508,19 +521,20 @@ var file_controlplane_v1_api_token_proto_depIdxs = []int32{ 7, // 0: controlplane.v1.APITokenServiceCreateRequest.project_reference:type_name -> controlplane.v1.IdentityReference 8, // 1: controlplane.v1.APITokenServiceCreateRequest.expires_in:type_name -> google.protobuf.Duration 6, // 2: controlplane.v1.APITokenServiceCreateResponse.result:type_name -> controlplane.v1.APITokenServiceCreateResponse.APITokenFull - 9, // 3: controlplane.v1.APITokenServiceListResponse.result:type_name -> controlplane.v1.APITokenItem - 9, // 4: controlplane.v1.APITokenServiceCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem - 0, // 5: controlplane.v1.APITokenService.Create:input_type -> controlplane.v1.APITokenServiceCreateRequest - 4, // 6: controlplane.v1.APITokenService.List:input_type -> controlplane.v1.APITokenServiceListRequest - 2, // 7: controlplane.v1.APITokenService.Revoke:input_type -> controlplane.v1.APITokenServiceRevokeRequest - 1, // 8: controlplane.v1.APITokenService.Create:output_type -> controlplane.v1.APITokenServiceCreateResponse - 5, // 9: controlplane.v1.APITokenService.List:output_type -> controlplane.v1.APITokenServiceListResponse - 3, // 10: controlplane.v1.APITokenService.Revoke:output_type -> controlplane.v1.APITokenServiceRevokeResponse - 8, // [8:11] is the sub-list for method output_type - 5, // [5:8] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 7, // 3: controlplane.v1.APITokenServiceListRequest.project:type_name -> controlplane.v1.IdentityReference + 9, // 4: controlplane.v1.APITokenServiceListResponse.result:type_name -> controlplane.v1.APITokenItem + 9, // 5: controlplane.v1.APITokenServiceCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem + 0, // 6: controlplane.v1.APITokenService.Create:input_type -> controlplane.v1.APITokenServiceCreateRequest + 4, // 7: controlplane.v1.APITokenService.List:input_type -> controlplane.v1.APITokenServiceListRequest + 2, // 8: controlplane.v1.APITokenService.Revoke:input_type -> controlplane.v1.APITokenServiceRevokeRequest + 1, // 9: controlplane.v1.APITokenService.Create:output_type -> controlplane.v1.APITokenServiceCreateResponse + 5, // 10: controlplane.v1.APITokenService.List:output_type -> controlplane.v1.APITokenServiceListResponse + 3, // 11: controlplane.v1.APITokenService.Revoke:output_type -> controlplane.v1.APITokenServiceRevokeResponse + 9, // [9:12] is the sub-list for method output_type + 6, // [6:9] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_controlplane_v1_api_token_proto_init() } diff --git a/app/controlplane/api/controlplane/v1/api_token.proto b/app/controlplane/api/controlplane/v1/api_token.proto index a09344ee8..9ec4fd60e 100644 --- a/app/controlplane/api/controlplane/v1/api_token.proto +++ b/app/controlplane/api/controlplane/v1/api_token.proto @@ -56,6 +56,9 @@ message APITokenServiceRevokeResponse {} message APITokenServiceListRequest { bool include_revoked = 1; + + // optional project reference to filter by + IdentityReference project = 4; } message APITokenServiceListResponse { diff --git a/app/controlplane/api/controlplane/v1/project.pb.go b/app/controlplane/api/controlplane/v1/project.pb.go index 8e0b2f3ab..618dfc62c 100644 --- a/app/controlplane/api/controlplane/v1/project.pb.go +++ b/app/controlplane/api/controlplane/v1/project.pb.go @@ -25,7 +25,6 @@ import ( _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - _ "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" @@ -922,9 +921,7 @@ var file_controlplane_v1_project_proto_rawDesc = []byte{ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, diff --git a/app/controlplane/api/controlplane/v1/project.proto b/app/controlplane/api/controlplane/v1/project.proto index 54d4708b2..b4248d2d9 100644 --- a/app/controlplane/api/controlplane/v1/project.proto +++ b/app/controlplane/api/controlplane/v1/project.proto @@ -22,7 +22,6 @@ import "controlplane/v1/group.proto"; import "controlplane/v1/pagination.proto"; import "controlplane/v1/response_messages.proto"; import "controlplane/v1/shared_message.proto"; -import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1"; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts index f1d6abaab..7540274a9 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts @@ -36,6 +36,8 @@ export interface APITokenServiceRevokeResponse { export interface APITokenServiceListRequest { includeRevoked: boolean; + /** optional project reference to filter by */ + project?: IdentityReference; } export interface APITokenServiceListResponse { @@ -390,7 +392,7 @@ export const APITokenServiceRevokeResponse = { }; function createBaseAPITokenServiceListRequest(): APITokenServiceListRequest { - return { includeRevoked: false }; + return { includeRevoked: false, project: undefined }; } export const APITokenServiceListRequest = { @@ -398,6 +400,9 @@ export const APITokenServiceListRequest = { if (message.includeRevoked === true) { writer.uint32(8).bool(message.includeRevoked); } + if (message.project !== undefined) { + IdentityReference.encode(message.project, writer.uint32(34).fork()).ldelim(); + } return writer; }, @@ -415,6 +420,13 @@ export const APITokenServiceListRequest = { message.includeRevoked = reader.bool(); continue; + case 4: + if (tag !== 34) { + break; + } + + message.project = IdentityReference.decode(reader, reader.uint32()); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -425,12 +437,17 @@ export const APITokenServiceListRequest = { }, fromJSON(object: any): APITokenServiceListRequest { - return { includeRevoked: isSet(object.includeRevoked) ? Boolean(object.includeRevoked) : false }; + return { + includeRevoked: isSet(object.includeRevoked) ? Boolean(object.includeRevoked) : false, + project: isSet(object.project) ? IdentityReference.fromJSON(object.project) : undefined, + }; }, toJSON(message: APITokenServiceListRequest): unknown { const obj: any = {}; message.includeRevoked !== undefined && (obj.includeRevoked = message.includeRevoked); + message.project !== undefined && + (obj.project = message.project ? IdentityReference.toJSON(message.project) : undefined); return obj; }, @@ -441,6 +458,9 @@ export const APITokenServiceListRequest = { fromPartial, I>>(object: I): APITokenServiceListRequest { const message = createBaseAPITokenServiceListRequest(); message.includeRevoked = object.includeRevoked ?? false; + message.project = (object.project !== undefined && object.project !== null) + ? IdentityReference.fromPartial(object.project) + : undefined; return message; }, }; diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json index 205bc414f..f8442440c 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json @@ -10,6 +10,10 @@ "properties": { "includeRevoked": { "type": "boolean" + }, + "project": { + "$ref": "controlplane.v1.IdentityReference.jsonschema.json", + "description": "optional project reference to filter by" } }, "title": "API Token Service List Request", diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json index 1747f0268..328ef93bc 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json @@ -10,6 +10,10 @@ "properties": { "include_revoked": { "type": "boolean" + }, + "project": { + "$ref": "controlplane.v1.IdentityReference.schema.json", + "description": "optional project reference to filter by" } }, "title": "API Token Service List Request", diff --git a/app/controlplane/internal/service/apitoken.go b/app/controlplane/internal/service/apitoken.go index 65ba275a7..c13e0e5fc 100644 --- a/app/controlplane/internal/service/apitoken.go +++ b/app/controlplane/internal/service/apitoken.go @@ -23,6 +23,7 @@ import ( "github.com/chainloop-dev/chainloop/app/controlplane/pkg/authz" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" errors "github.com/go-kratos/kratos/v2/errors" + "github.com/google/uuid" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -87,8 +88,20 @@ func (s *APITokenService) List(ctx context.Context, req *pb.APITokenServiceListR return nil, err } + // default to visible projects for the user + defaultProjectFilter := s.visibleProjects(ctx) + // or the user has provided a project filter + if req.Project.IsSet() { + project, err := s.userHasPermissionOnProject(ctx, currentOrg.ID, req.GetProject(), authz.PolicyAPITokenList) + if err != nil { + return nil, err + } + + defaultProjectFilter = []uuid.UUID{project.ID} + } + // Only expose system tokens - tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenRevoked(req.IncludeRevoked), biz.WithApiTokenProjectFilter(s.visibleProjects(ctx))) + tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenRevoked(req.IncludeRevoked), biz.WithApiTokenProjectFilter(defaultProjectFilter)) if err != nil { return nil, handleUseCaseErr(err, s.log) } diff --git a/app/controlplane/pkg/authz/authz.go b/app/controlplane/pkg/authz/authz.go index 0fd91e9fa..7c5b04b0b 100644 --- a/app/controlplane/pkg/authz/authz.go +++ b/app/controlplane/pkg/authz/authz.go @@ -278,6 +278,8 @@ var RolesMap = map[Role][]*Policy{ // workflow contracts PolicyWorkflowContractList, PolicyWorkflowContractRead, + // Project API Token + PolicyAPITokenList, }, // RoleProjectAdmin: represents a project administrator. It's the higher role in project resources, // and it's only considered when the org-level role is `RoleOrgMember` diff --git a/app/controlplane/pkg/biz/apitoken_integration_test.go b/app/controlplane/pkg/biz/apitoken_integration_test.go index 12605d830..2b1fdca34 100644 --- a/app/controlplane/pkg/biz/apitoken_integration_test.go +++ b/app/controlplane/pkg/biz/apitoken_integration_test.go @@ -280,20 +280,11 @@ func (s *apiTokenTestSuite) TestList() { s.Equal(s.t5.ID, tokens[1].ID) }) - s.Run("or just the system tokens", func() { - var err error - tokens, err := s.APIToken.List(ctx, s.org.ID) - s.NoError(err) - require.Len(s.T(), tokens, 2) - s.Equal(s.t1.ID, tokens[0].ID) - s.Equal(s.t2.ID, tokens[1].ID) - }) - s.Run("doesn't return revoked by default", func() { // revoke one token err := s.APIToken.Revoke(ctx, s.org.ID, s.t1.ID.String()) require.NoError(s.T(), err) - tokens, err := s.APIToken.List(ctx, s.org.ID, false) + tokens, err := s.APIToken.List(ctx, s.org.ID) s.NoError(err) require.Len(s.T(), tokens, 3) s.Equal(s.t2.ID, tokens[0].ID) @@ -301,7 +292,7 @@ func (s *apiTokenTestSuite) TestList() { s.Run("doesn't return revoked unless requested", func() { // revoke one token - tokens, err := s.APIToken.List(ctx, s.org.ID, true) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenRevoked(true)) s.NoError(err) require.Len(s.T(), tokens, 4) s.Equal(s.t1.ID, tokens[0].ID) From 13ac3ac63fcade052e7130c78fbc9c5aaf602644 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 22:26:49 +0200 Subject: [PATCH 20/24] add tests Signed-off-by: Miguel Martinez --- app/cli/cmd/organization_apitoken_list.go | 17 +- app/cli/internal/action/apitoken_list.go | 17 +- .../api/controlplane/v1/api_token.pb.go | 191 ++++++++++++------ .../api/controlplane/v1/api_token.proto | 9 + .../gen/frontend/controlplane/v1/api_token.ts | 56 ++++- .../frontend/google/protobuf/descriptor.ts | 16 +- ...APITokenServiceListRequest.jsonschema.json | 19 ++ ....v1.APITokenServiceListRequest.schema.json | 19 ++ app/controlplane/internal/service/apitoken.go | 13 +- app/controlplane/pkg/biz/apitoken.go | 27 +++ .../pkg/biz/apitoken_integration_test.go | 42 +++- app/controlplane/pkg/data/apitoken.go | 15 +- 12 files changed, 355 insertions(+), 86 deletions(-) diff --git a/app/cli/cmd/organization_apitoken_list.go b/app/cli/cmd/organization_apitoken_list.go index b695b3605..9f1f41479 100644 --- a/app/cli/cmd/organization_apitoken_list.go +++ b/app/cli/cmd/organization_apitoken_list.go @@ -18,6 +18,7 @@ package cmd import ( "context" "fmt" + "slices" "github.com/chainloop-dev/chainloop/app/cli/internal/action" "github.com/spf13/cobra" @@ -27,14 +28,27 @@ func newAPITokenListCmd() *cobra.Command { var ( includeRevoked bool project string + scope string ) + var availableScopes = []string{ + "project", + "global", + } + cmd := &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "List API tokens in this organization", + PreRunE: func(cmd *cobra.Command, args []string) error { + if scope != "" && !slices.Contains(availableScopes, scope) { + return fmt.Errorf("invalid scope %q, please chose one of: %v", scope, availableScopes) + } + + return nil + }, RunE: func(cmd *cobra.Command, args []string) error { - res, err := action.NewAPITokenList(actionOpts).Run(context.Background(), includeRevoked, project) + res, err := action.NewAPITokenList(actionOpts).Run(context.Background(), includeRevoked, project, scope) if err != nil { return fmt.Errorf("listing API tokens: %w", err) } @@ -45,5 +59,6 @@ func newAPITokenListCmd() *cobra.Command { cmd.Flags().BoolVarP(&includeRevoked, "all", "a", false, "show all API tokens including revoked ones") cmd.Flags().StringVarP(&project, "project", "p", "", "filter by project name") + cmd.Flags().StringVarP(&scope, "scope", "s", "", fmt.Sprintf("filter by scope, available scopes: %v", availableScopes)) return cmd } diff --git a/app/cli/internal/action/apitoken_list.go b/app/cli/internal/action/apitoken_list.go index 848c70453..489d53245 100644 --- a/app/cli/internal/action/apitoken_list.go +++ b/app/cli/internal/action/apitoken_list.go @@ -30,7 +30,7 @@ func NewAPITokenList(cfg *ActionsOpts) *APITokenList { return &APITokenList{cfg} } -func (action *APITokenList) Run(ctx context.Context, includeRevoked bool, project string) ([]*APITokenItem, error) { +func (action *APITokenList) Run(ctx context.Context, includeRevoked bool, project string, scope string) ([]*APITokenItem, error) { client := pb.NewAPITokenServiceClient(action.cfg.CPConnection) req := &pb.APITokenServiceListRequest{IncludeRevoked: includeRevoked} @@ -38,6 +38,10 @@ func (action *APITokenList) Run(ctx context.Context, includeRevoked bool, projec req.Project = &pb.IdentityReference{Name: &project} } + if scope != "" { + req.Scope = mapScope(scope) + } + resp, err := client.List(ctx, req) if err != nil { return nil, fmt.Errorf("listing API tokens: %w", err) @@ -50,3 +54,14 @@ func (action *APITokenList) Run(ctx context.Context, includeRevoked bool, projec return result, nil } + +func mapScope(scope string) pb.APITokenServiceListRequest_Scope { + switch scope { + case "project": + return pb.APITokenServiceListRequest_SCOPE_PROJECT + case "global": + return pb.APITokenServiceListRequest_SCOPE_GLOBAL + default: + return pb.APITokenServiceListRequest_SCOPE_UNSPECIFIED + } +} diff --git a/app/controlplane/api/controlplane/v1/api_token.pb.go b/app/controlplane/api/controlplane/v1/api_token.pb.go index ff4906652..bccee55dd 100644 --- a/app/controlplane/api/controlplane/v1/api_token.pb.go +++ b/app/controlplane/api/controlplane/v1/api_token.pb.go @@ -37,6 +37,55 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type APITokenServiceListRequest_Scope int32 + +const ( + APITokenServiceListRequest_SCOPE_UNSPECIFIED APITokenServiceListRequest_Scope = 0 + APITokenServiceListRequest_SCOPE_PROJECT APITokenServiceListRequest_Scope = 1 + APITokenServiceListRequest_SCOPE_GLOBAL APITokenServiceListRequest_Scope = 2 +) + +// Enum value maps for APITokenServiceListRequest_Scope. +var ( + APITokenServiceListRequest_Scope_name = map[int32]string{ + 0: "SCOPE_UNSPECIFIED", + 1: "SCOPE_PROJECT", + 2: "SCOPE_GLOBAL", + } + APITokenServiceListRequest_Scope_value = map[string]int32{ + "SCOPE_UNSPECIFIED": 0, + "SCOPE_PROJECT": 1, + "SCOPE_GLOBAL": 2, + } +) + +func (x APITokenServiceListRequest_Scope) Enum() *APITokenServiceListRequest_Scope { + p := new(APITokenServiceListRequest_Scope) + *p = x + return p +} + +func (x APITokenServiceListRequest_Scope) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (APITokenServiceListRequest_Scope) Descriptor() protoreflect.EnumDescriptor { + return file_controlplane_v1_api_token_proto_enumTypes[0].Descriptor() +} + +func (APITokenServiceListRequest_Scope) Type() protoreflect.EnumType { + return &file_controlplane_v1_api_token_proto_enumTypes[0] +} + +func (x APITokenServiceListRequest_Scope) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use APITokenServiceListRequest_Scope.Descriptor instead. +func (APITokenServiceListRequest_Scope) EnumDescriptor() ([]byte, []int) { + return file_controlplane_v1_api_token_proto_rawDescGZIP(), []int{4, 0} +} + type APITokenServiceCreateRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -249,6 +298,8 @@ type APITokenServiceListRequest struct { IncludeRevoked bool `protobuf:"varint,1,opt,name=include_revoked,json=includeRevoked,proto3" json:"include_revoked,omitempty"` // optional project reference to filter by Project *IdentityReference `protobuf:"bytes,4,opt,name=project,proto3" json:"project,omitempty"` + // filter by the scope of the token + Scope APITokenServiceListRequest_Scope `protobuf:"varint,2,opt,name=scope,proto3,enum=controlplane.v1.APITokenServiceListRequest_Scope" json:"scope,omitempty"` } func (x *APITokenServiceListRequest) Reset() { @@ -297,6 +348,13 @@ func (x *APITokenServiceListRequest) GetProject() *IdentityReference { return nil } +func (x *APITokenServiceListRequest) GetScope() APITokenServiceListRequest_Scope { + if x != nil { + return x.Scope + } + return APITokenServiceListRequest_SCOPE_UNSPECIFIED +} + type APITokenServiceListResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -449,7 +507,7 @@ var file_controlplane_v1_api_token_proto_rawDesc = []byte{ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x1a, 0x41, 0x50, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x91, 0x02, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, @@ -457,39 +515,48 @@ var file_controlplane_v1_api_token_proto_rawDesc = []byte{ 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, - 0x54, 0x0a, 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, - 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, - 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x47, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, - 0x5a, 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x43, 0x4f, 0x50, + 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, + 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x02, 0x22, 0x54, 0x0a, + 0x1b, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x32, 0xc6, 0x02, 0x0a, 0x0f, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x06, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x2d, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x50, 0x49, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, + 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -504,37 +571,40 @@ func file_controlplane_v1_api_token_proto_rawDescGZIP() []byte { return file_controlplane_v1_api_token_proto_rawDescData } +var file_controlplane_v1_api_token_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_controlplane_v1_api_token_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_controlplane_v1_api_token_proto_goTypes = []interface{}{ - (*APITokenServiceCreateRequest)(nil), // 0: controlplane.v1.APITokenServiceCreateRequest - (*APITokenServiceCreateResponse)(nil), // 1: controlplane.v1.APITokenServiceCreateResponse - (*APITokenServiceRevokeRequest)(nil), // 2: controlplane.v1.APITokenServiceRevokeRequest - (*APITokenServiceRevokeResponse)(nil), // 3: controlplane.v1.APITokenServiceRevokeResponse - (*APITokenServiceListRequest)(nil), // 4: controlplane.v1.APITokenServiceListRequest - (*APITokenServiceListResponse)(nil), // 5: controlplane.v1.APITokenServiceListResponse - (*APITokenServiceCreateResponse_APITokenFull)(nil), // 6: controlplane.v1.APITokenServiceCreateResponse.APITokenFull - (*IdentityReference)(nil), // 7: controlplane.v1.IdentityReference - (*durationpb.Duration)(nil), // 8: google.protobuf.Duration - (*APITokenItem)(nil), // 9: controlplane.v1.APITokenItem + (APITokenServiceListRequest_Scope)(0), // 0: controlplane.v1.APITokenServiceListRequest.Scope + (*APITokenServiceCreateRequest)(nil), // 1: controlplane.v1.APITokenServiceCreateRequest + (*APITokenServiceCreateResponse)(nil), // 2: controlplane.v1.APITokenServiceCreateResponse + (*APITokenServiceRevokeRequest)(nil), // 3: controlplane.v1.APITokenServiceRevokeRequest + (*APITokenServiceRevokeResponse)(nil), // 4: controlplane.v1.APITokenServiceRevokeResponse + (*APITokenServiceListRequest)(nil), // 5: controlplane.v1.APITokenServiceListRequest + (*APITokenServiceListResponse)(nil), // 6: controlplane.v1.APITokenServiceListResponse + (*APITokenServiceCreateResponse_APITokenFull)(nil), // 7: controlplane.v1.APITokenServiceCreateResponse.APITokenFull + (*IdentityReference)(nil), // 8: controlplane.v1.IdentityReference + (*durationpb.Duration)(nil), // 9: google.protobuf.Duration + (*APITokenItem)(nil), // 10: controlplane.v1.APITokenItem } var file_controlplane_v1_api_token_proto_depIdxs = []int32{ - 7, // 0: controlplane.v1.APITokenServiceCreateRequest.project_reference:type_name -> controlplane.v1.IdentityReference - 8, // 1: controlplane.v1.APITokenServiceCreateRequest.expires_in:type_name -> google.protobuf.Duration - 6, // 2: controlplane.v1.APITokenServiceCreateResponse.result:type_name -> controlplane.v1.APITokenServiceCreateResponse.APITokenFull - 7, // 3: controlplane.v1.APITokenServiceListRequest.project:type_name -> controlplane.v1.IdentityReference - 9, // 4: controlplane.v1.APITokenServiceListResponse.result:type_name -> controlplane.v1.APITokenItem - 9, // 5: controlplane.v1.APITokenServiceCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem - 0, // 6: controlplane.v1.APITokenService.Create:input_type -> controlplane.v1.APITokenServiceCreateRequest - 4, // 7: controlplane.v1.APITokenService.List:input_type -> controlplane.v1.APITokenServiceListRequest - 2, // 8: controlplane.v1.APITokenService.Revoke:input_type -> controlplane.v1.APITokenServiceRevokeRequest - 1, // 9: controlplane.v1.APITokenService.Create:output_type -> controlplane.v1.APITokenServiceCreateResponse - 5, // 10: controlplane.v1.APITokenService.List:output_type -> controlplane.v1.APITokenServiceListResponse - 3, // 11: controlplane.v1.APITokenService.Revoke:output_type -> controlplane.v1.APITokenServiceRevokeResponse - 9, // [9:12] is the sub-list for method output_type - 6, // [6:9] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 8, // 0: controlplane.v1.APITokenServiceCreateRequest.project_reference:type_name -> controlplane.v1.IdentityReference + 9, // 1: controlplane.v1.APITokenServiceCreateRequest.expires_in:type_name -> google.protobuf.Duration + 7, // 2: controlplane.v1.APITokenServiceCreateResponse.result:type_name -> controlplane.v1.APITokenServiceCreateResponse.APITokenFull + 8, // 3: controlplane.v1.APITokenServiceListRequest.project:type_name -> controlplane.v1.IdentityReference + 0, // 4: controlplane.v1.APITokenServiceListRequest.scope:type_name -> controlplane.v1.APITokenServiceListRequest.Scope + 10, // 5: controlplane.v1.APITokenServiceListResponse.result:type_name -> controlplane.v1.APITokenItem + 10, // 6: controlplane.v1.APITokenServiceCreateResponse.APITokenFull.item:type_name -> controlplane.v1.APITokenItem + 1, // 7: controlplane.v1.APITokenService.Create:input_type -> controlplane.v1.APITokenServiceCreateRequest + 5, // 8: controlplane.v1.APITokenService.List:input_type -> controlplane.v1.APITokenServiceListRequest + 3, // 9: controlplane.v1.APITokenService.Revoke:input_type -> controlplane.v1.APITokenServiceRevokeRequest + 2, // 10: controlplane.v1.APITokenService.Create:output_type -> controlplane.v1.APITokenServiceCreateResponse + 6, // 11: controlplane.v1.APITokenService.List:output_type -> controlplane.v1.APITokenServiceListResponse + 4, // 12: controlplane.v1.APITokenService.Revoke:output_type -> controlplane.v1.APITokenServiceRevokeResponse + 10, // [10:13] is the sub-list for method output_type + 7, // [7:10] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_controlplane_v1_api_token_proto_init() } @@ -636,13 +706,14 @@ func file_controlplane_v1_api_token_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controlplane_v1_api_token_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 7, NumExtensions: 0, NumServices: 1, }, GoTypes: file_controlplane_v1_api_token_proto_goTypes, DependencyIndexes: file_controlplane_v1_api_token_proto_depIdxs, + EnumInfos: file_controlplane_v1_api_token_proto_enumTypes, MessageInfos: file_controlplane_v1_api_token_proto_msgTypes, }.Build() File_controlplane_v1_api_token_proto = out.File diff --git a/app/controlplane/api/controlplane/v1/api_token.proto b/app/controlplane/api/controlplane/v1/api_token.proto index 9ec4fd60e..609162da0 100644 --- a/app/controlplane/api/controlplane/v1/api_token.proto +++ b/app/controlplane/api/controlplane/v1/api_token.proto @@ -59,6 +59,15 @@ message APITokenServiceListRequest { // optional project reference to filter by IdentityReference project = 4; + + enum Scope { + SCOPE_UNSPECIFIED = 0; + SCOPE_PROJECT = 1; + SCOPE_GLOBAL = 2; + } + + // filter by the scope of the token + Scope scope = 2; } message APITokenServiceListResponse { diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts index 7540274a9..0fdbca493 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts @@ -38,6 +38,47 @@ export interface APITokenServiceListRequest { includeRevoked: boolean; /** optional project reference to filter by */ project?: IdentityReference; + /** filter by the scope of the token */ + scope: APITokenServiceListRequest_Scope; +} + +export enum APITokenServiceListRequest_Scope { + SCOPE_UNSPECIFIED = 0, + SCOPE_PROJECT = 1, + SCOPE_GLOBAL = 2, + UNRECOGNIZED = -1, +} + +export function aPITokenServiceListRequest_ScopeFromJSON(object: any): APITokenServiceListRequest_Scope { + switch (object) { + case 0: + case "SCOPE_UNSPECIFIED": + return APITokenServiceListRequest_Scope.SCOPE_UNSPECIFIED; + case 1: + case "SCOPE_PROJECT": + return APITokenServiceListRequest_Scope.SCOPE_PROJECT; + case 2: + case "SCOPE_GLOBAL": + return APITokenServiceListRequest_Scope.SCOPE_GLOBAL; + case -1: + case "UNRECOGNIZED": + default: + return APITokenServiceListRequest_Scope.UNRECOGNIZED; + } +} + +export function aPITokenServiceListRequest_ScopeToJSON(object: APITokenServiceListRequest_Scope): string { + switch (object) { + case APITokenServiceListRequest_Scope.SCOPE_UNSPECIFIED: + return "SCOPE_UNSPECIFIED"; + case APITokenServiceListRequest_Scope.SCOPE_PROJECT: + return "SCOPE_PROJECT"; + case APITokenServiceListRequest_Scope.SCOPE_GLOBAL: + return "SCOPE_GLOBAL"; + case APITokenServiceListRequest_Scope.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } } export interface APITokenServiceListResponse { @@ -392,7 +433,7 @@ export const APITokenServiceRevokeResponse = { }; function createBaseAPITokenServiceListRequest(): APITokenServiceListRequest { - return { includeRevoked: false, project: undefined }; + return { includeRevoked: false, project: undefined, scope: 0 }; } export const APITokenServiceListRequest = { @@ -403,6 +444,9 @@ export const APITokenServiceListRequest = { if (message.project !== undefined) { IdentityReference.encode(message.project, writer.uint32(34).fork()).ldelim(); } + if (message.scope !== 0) { + writer.uint32(16).int32(message.scope); + } return writer; }, @@ -427,6 +471,13 @@ export const APITokenServiceListRequest = { message.project = IdentityReference.decode(reader, reader.uint32()); continue; + case 2: + if (tag !== 16) { + break; + } + + message.scope = reader.int32() as any; + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -440,6 +491,7 @@ export const APITokenServiceListRequest = { return { includeRevoked: isSet(object.includeRevoked) ? Boolean(object.includeRevoked) : false, project: isSet(object.project) ? IdentityReference.fromJSON(object.project) : undefined, + scope: isSet(object.scope) ? aPITokenServiceListRequest_ScopeFromJSON(object.scope) : 0, }; }, @@ -448,6 +500,7 @@ export const APITokenServiceListRequest = { message.includeRevoked !== undefined && (obj.includeRevoked = message.includeRevoked); message.project !== undefined && (obj.project = message.project ? IdentityReference.toJSON(message.project) : undefined); + message.scope !== undefined && (obj.scope = aPITokenServiceListRequest_ScopeToJSON(message.scope)); return obj; }, @@ -461,6 +514,7 @@ export const APITokenServiceListRequest = { message.project = (object.project !== undefined && object.project !== null) ? IdentityReference.fromPartial(object.project) : undefined; + message.scope = object.scope ?? 0; return message; }, }; diff --git a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts index 0d2d2fb32..d59b21da4 100644 --- a/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts +++ b/app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts @@ -30,7 +30,7 @@ export enum Edition { EDITION_2024 = 1001, /** * EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be - * used or relyed on outside of tests. + * used or relied on outside of tests. */ EDITION_1_TEST_ONLY = 1, EDITION_2_TEST_ONLY = 2, @@ -875,12 +875,13 @@ export interface MessageOptions { export interface FieldOptions { /** + * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific * options below. This option is only implemented to support use of * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of - * type "bytes" in the open source release -- sorry, we'll try to include - * other types in a future version! + * type "bytes" in the open source release. + * TODO: make ctype actually deprecated. */ ctype: FieldOptions_CType; /** @@ -1052,11 +1053,7 @@ export function fieldOptions_JSTypeToJSON(object: FieldOptions_JSType): string { } } -/** - * If set to RETENTION_SOURCE, the option will be omitted from the binary. - * Note: as of January 2023, support for this is in progress and does not yet - * have an effect (b/264593489). - */ +/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */ export enum FieldOptions_OptionRetention { RETENTION_UNKNOWN = 0, RETENTION_RUNTIME = 1, @@ -1099,8 +1096,7 @@ export function fieldOptions_OptionRetentionToJSON(object: FieldOptions_OptionRe /** * This indicates the types of entities that the field may apply to when used * as an option. If it is unset, then the field may be freely used as an - * option on any kind of entity. Note: as of January 2023, support for this is - * in progress and does not yet have an effect (b/264593489). + * option on any kind of entity. */ export enum FieldOptions_OptionTargetType { TARGET_TYPE_UNKNOWN = 0, diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json index f8442440c..984e5cd4b 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.jsonschema.json @@ -14,6 +14,25 @@ "project": { "$ref": "controlplane.v1.IdentityReference.jsonschema.json", "description": "optional project reference to filter by" + }, + "scope": { + "anyOf": [ + { + "enum": [ + "SCOPE_UNSPECIFIED", + "SCOPE_PROJECT", + "SCOPE_GLOBAL" + ], + "title": "Scope", + "type": "string" + }, + { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + } + ], + "description": "filter by the scope of the token" } }, "title": "API Token Service List Request", diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json index 328ef93bc..d6bfc4712 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.APITokenServiceListRequest.schema.json @@ -14,6 +14,25 @@ "project": { "$ref": "controlplane.v1.IdentityReference.schema.json", "description": "optional project reference to filter by" + }, + "scope": { + "anyOf": [ + { + "enum": [ + "SCOPE_UNSPECIFIED", + "SCOPE_PROJECT", + "SCOPE_GLOBAL" + ], + "title": "Scope", + "type": "string" + }, + { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + } + ], + "description": "filter by the scope of the token" } }, "title": "API Token Service List Request", diff --git a/app/controlplane/internal/service/apitoken.go b/app/controlplane/internal/service/apitoken.go index c13e0e5fc..2bf56c117 100644 --- a/app/controlplane/internal/service/apitoken.go +++ b/app/controlplane/internal/service/apitoken.go @@ -101,7 +101,7 @@ func (s *APITokenService) List(ctx context.Context, req *pb.APITokenServiceListR } // Only expose system tokens - tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenRevoked(req.IncludeRevoked), biz.WithApiTokenProjectFilter(defaultProjectFilter)) + tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenRevoked(req.IncludeRevoked), biz.WithApiTokenProjectFilter(defaultProjectFilter), biz.WithApiTokenScope(mapTokenScope(req.Scope))) if err != nil { return nil, handleUseCaseErr(err, s.log) } @@ -114,6 +114,17 @@ func (s *APITokenService) List(ctx context.Context, req *pb.APITokenServiceListR return &pb.APITokenServiceListResponse{Result: result}, nil } +func mapTokenScope(scope pb.APITokenServiceListRequest_Scope) biz.APITokenScope { + switch scope { + case pb.APITokenServiceListRequest_SCOPE_PROJECT: + return biz.APITokenScopeProject + case pb.APITokenServiceListRequest_SCOPE_GLOBAL: + return biz.APITokenScopeGlobal + } + + return "" +} + func (s *APITokenService) Revoke(ctx context.Context, req *pb.APITokenServiceRevokeRequest) (*pb.APITokenServiceRevokeResponse, error) { currentOrg, err := requireCurrentOrg(ctx) if err != nil { diff --git a/app/controlplane/pkg/biz/apitoken.go b/app/controlplane/pkg/biz/apitoken.go index 5459dcf67..0cc3be70c 100644 --- a/app/controlplane/pkg/biz/apitoken.go +++ b/app/controlplane/pkg/biz/apitoken.go @@ -18,6 +18,7 @@ package biz import ( "context" "fmt" + "slices" "time" "github.com/chainloop-dev/chainloop/app/controlplane/pkg/auditor/events" @@ -284,12 +285,32 @@ func WithApiTokenRevoked(includeRevoked bool) APITokenListOpt { } } +func WithApiTokenScope(scope APITokenScope) APITokenListOpt { + return func(opts *APITokenListFilters) { + opts.FilterByScope = scope + } +} + +type APITokenScope string + +const ( + APITokenScopeProject APITokenScope = "project" + APITokenScopeGlobal APITokenScope = "global" +) + +var availableAPITokenScopes = []APITokenScope{ + APITokenScopeProject, + APITokenScopeGlobal, +} + type APITokenListFilters struct { // FilterByProjects is used to filter the result by a project list // If it's empty, no filter will be applied FilterByProjects []uuid.UUID // IncludeRevoked is used to include revoked tokens in the result IncludeRevoked bool + // FilterByScope is used to filter the result by the scope of the token + FilterByScope APITokenScope } func (uc *APITokenUseCase) List(ctx context.Context, orgID string, opts ...APITokenListOpt) ([]*APIToken, error) { @@ -298,6 +319,10 @@ func (uc *APITokenUseCase) List(ctx context.Context, orgID string, opts ...APITo opt(filters) } + if filters.FilterByScope != "" && !slices.Contains(availableAPITokenScopes, filters.FilterByScope) { + return nil, NewErrValidationStr(fmt.Sprintf("invalid scope %q, please chose one of: %v", filters.FilterByScope, availableAPITokenScopes)) + } + orgUUID, err := uuid.Parse(orgID) if err != nil { return nil, NewErrInvalidUUID(err) @@ -401,6 +426,8 @@ func (suc *APITokenSyncerUseCase) SyncPolicies() error { } } + suc.base.logger.Info("policies synced") + return nil } diff --git a/app/controlplane/pkg/biz/apitoken_integration_test.go b/app/controlplane/pkg/biz/apitoken_integration_test.go index 2b1fdca34..558a7a2d8 100644 --- a/app/controlplane/pkg/biz/apitoken_integration_test.go +++ b/app/controlplane/pkg/biz/apitoken_integration_test.go @@ -255,15 +255,13 @@ func (s *apiTokenTestSuite) TestList() { }) s.Run("returns all tokens for that org both system and project scoped", func() { - var err error tokens, err := s.APIToken.List(ctx, s.org.ID) s.NoError(err) - require.Len(s.T(), tokens, 4) + require.Len(s.T(), tokens, 5) s.Equal(s.t1.ID, tokens[0].ID) s.Equal(s.t2.ID, tokens[1].ID) // It has a name set s.NotEmpty(tokens[1].Name) - s.Equal(s.t2.Name, tokens[1].Name) tokens, err = s.APIToken.List(ctx, s.org2.ID) s.NoError(err) @@ -272,7 +270,6 @@ func (s *apiTokenTestSuite) TestList() { }) s.Run("can return only for a specific project", func() { - var err error tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenProjectFilter([]uuid.UUID{s.p1.ID})) s.NoError(err) require.Len(s.T(), tokens, 2) @@ -280,21 +277,42 @@ func (s *apiTokenTestSuite) TestList() { s.Equal(s.t5.ID, tokens[1].ID) }) + s.Run("can return scoped to a project", func() { + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenScope(biz.APITokenScopeProject)) + s.NoError(err) + require.Len(s.T(), tokens, 3) + }) + + s.Run("can return scoped to a global", func() { + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenScope(biz.APITokenScopeGlobal)) + s.NoError(err) + s.Len(tokens, 2) + }) + + s.Run("they are org scoped", func() { + tokens, err := s.APIToken.List(ctx, s.org.ID) + s.NoError(err) + s.Len(tokens, 5) + + tokens, err = s.APIToken.List(ctx, s.org2.ID) + s.NoError(err) + s.Len(tokens, 1) + }) + s.Run("doesn't return revoked by default", func() { // revoke one token err := s.APIToken.Revoke(ctx, s.org.ID, s.t1.ID.String()) require.NoError(s.T(), err) tokens, err := s.APIToken.List(ctx, s.org.ID) s.NoError(err) - require.Len(s.T(), tokens, 3) + require.Len(s.T(), tokens, 4) s.Equal(s.t2.ID, tokens[0].ID) }) s.Run("doesn't return revoked unless requested", func() { - // revoke one token tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenRevoked(true)) s.NoError(err) - require.Len(s.T(), tokens, 4) + require.Len(s.T(), tokens, 5) s.Equal(s.t1.ID, tokens[0].ID) s.Equal(s.t2.ID, tokens[1].ID) }) @@ -327,9 +345,9 @@ func TestAPITokenUseCase(t *testing.T) { // Utility struct to hold the test suite type apiTokenTestSuite struct { testhelpers.UseCasesEachTestSuite - org, org2 *biz.Organization - t1, t2, t3, t4, t5 *biz.APIToken - p1, p2 *biz.Project + org, org2 *biz.Organization + t1, t2, t3, t4, t5, t6 *biz.APIToken + p1, p2 *biz.Project } func (s *apiTokenTestSuite) SetupTest() { @@ -364,6 +382,10 @@ func (s *apiTokenTestSuite) SetupTest() { require.NoError(s.T(), err) s.t5, err = s.APIToken.Create(ctx, randomName(), nil, nil, s.org.ID, biz.APITokenWithProject(s.p1)) require.NoError(s.T(), err) + + // Create 1 token for project 2 + s.t6, err = s.APIToken.Create(ctx, randomName(), nil, nil, s.org.ID, biz.APITokenWithProject(s.p2)) + require.NoError(s.T(), err) } func (s *apiTokenTestSuite) TestUpdateLastUsedAt() { diff --git a/app/controlplane/pkg/data/apitoken.go b/app/controlplane/pkg/data/apitoken.go index c47aa8e1d..57f060fa3 100644 --- a/app/controlplane/pkg/data/apitoken.go +++ b/app/controlplane/pkg/data/apitoken.go @@ -87,14 +87,25 @@ func (r *APITokenRepo) FindByIDInOrg(ctx context.Context, orgID uuid.UUID, id uu func (r *APITokenRepo) List(ctx context.Context, orgID *uuid.UUID, filters *biz.APITokenListFilters) ([]*biz.APIToken, error) { query := r.data.DB.APIToken.Query().WithProject().WithOrganization() - if orgID == nil { - return nil, fmt.Errorf("organizationID is required") + if filters == nil { + filters = &biz.APITokenListFilters{} + } + + if orgID != nil { + query = query.Where(apitoken.OrganizationIDEQ(*orgID)) } if len(filters.FilterByProjects) > 0 { query = query.Where(apitoken.ProjectIDIn(filters.FilterByProjects...)) } + switch filters.FilterByScope { + case biz.APITokenScopeProject: + query = query.Where(apitoken.ProjectIDNotNil()) + case biz.APITokenScopeGlobal: + query = query.Where(apitoken.ProjectIDIsNil()) + } + if !filters.IncludeRevoked { query = query.Where(apitoken.RevokedAtIsNil()) } From d3e42545e4210abdc310bcc000a8ef6686e0b307 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 22:32:36 +0200 Subject: [PATCH 21/24] add tests Signed-off-by: Miguel Martinez --- app/cli/cmd/organization_apitoken_list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/cli/cmd/organization_apitoken_list.go b/app/cli/cmd/organization_apitoken_list.go index 9f1f41479..46a79edce 100644 --- a/app/cli/cmd/organization_apitoken_list.go +++ b/app/cli/cmd/organization_apitoken_list.go @@ -40,7 +40,7 @@ func newAPITokenListCmd() *cobra.Command { Use: "list", Aliases: []string{"ls"}, Short: "List API tokens in this organization", - PreRunE: func(cmd *cobra.Command, args []string) error { + PreRunE: func(_ *cobra.Command, _ []string) error { if scope != "" && !slices.Contains(availableScopes, scope) { return fmt.Errorf("invalid scope %q, please chose one of: %v", scope, availableScopes) } From 6b61ee1b533ed6768666d6cb4e9b884d5005b78f Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 22:43:29 +0200 Subject: [PATCH 22/24] add tests Signed-off-by: Miguel Martinez --- .../usercontext/apitoken_middleware_test.go | 2 +- .../pkg/biz/mocks/APITokenRepo.go | 512 +++--------------- 2 files changed, 83 insertions(+), 431 deletions(-) diff --git a/app/controlplane/internal/usercontext/apitoken_middleware_test.go b/app/controlplane/internal/usercontext/apitoken_middleware_test.go index 0c7e2120b..8b8699bb8 100644 --- a/app/controlplane/internal/usercontext/apitoken_middleware_test.go +++ b/app/controlplane/internal/usercontext/apitoken_middleware_test.go @@ -97,7 +97,7 @@ func TestWithCurrentAPITokenAndOrgMiddleware(t *testing.T) { wantToken := &biz.APIToken{ID: uuid.New(), OrganizationID: wantOrgID} t.Run(tc.name, func(t *testing.T) { - apiTokenRepo := bizMocks.NewMockAPITokenRepo(t) + apiTokenRepo := bizMocks.NewAPITokenRepo(t) orgRepo := bizMocks.NewOrganizationRepo(t) apiTokenUC, err := biz.NewAPITokenUseCase(apiTokenRepo, &biz.APITokenJWTConfig{SymmetricHmacKey: "test"}, nil, nil, nil, nil) require.NoError(t, err) diff --git a/app/controlplane/pkg/biz/mocks/APITokenRepo.go b/app/controlplane/pkg/biz/mocks/APITokenRepo.go index 29c84e754..9803d4411 100644 --- a/app/controlplane/pkg/biz/mocks/APITokenRepo.go +++ b/app/controlplane/pkg/biz/mocks/APITokenRepo.go @@ -1,48 +1,27 @@ -// Code generated by mockery; DO NOT EDIT. -// github.com/vektra/mockery -// template: testify +// Code generated by mockery v2.53.4. DO NOT EDIT. package mocks import ( - "context" - "time" + context "context" - "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" - "github.com/google/uuid" - mock "github.com/stretchr/testify/mock" -) + biz "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz" -// NewMockAPITokenRepo creates a new instance of MockAPITokenRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockAPITokenRepo(t interface { - mock.TestingT - Cleanup(func()) -}) *MockAPITokenRepo { - mock := &MockAPITokenRepo{} - mock.Mock.Test(t) + mock "github.com/stretchr/testify/mock" - t.Cleanup(func() { mock.AssertExpectations(t) }) + time "time" - return mock -} + uuid "github.com/google/uuid" +) -// MockAPITokenRepo is an autogenerated mock type for the APITokenRepo type -type MockAPITokenRepo struct { +// APITokenRepo is an autogenerated mock type for the APITokenRepo type +type APITokenRepo struct { mock.Mock } -type MockAPITokenRepo_Expecter struct { - mock *mock.Mock -} - -func (_m *MockAPITokenRepo) EXPECT() *MockAPITokenRepo_Expecter { - return &MockAPITokenRepo_Expecter{mock: &_m.Mock} -} - -// Create provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) Create(ctx context.Context, name string, description *string, expiresAt *time.Time, organizationID uuid.UUID, projectID *uuid.UUID) (*biz.APIToken, error) { - ret := _mock.Called(ctx, name, description, expiresAt, organizationID, projectID) +// Create provides a mock function with given fields: ctx, name, description, expiresAt, organizationID, projectID +func (_m *APITokenRepo) Create(ctx context.Context, name string, description *string, expiresAt *time.Time, organizationID uuid.UUID, projectID *uuid.UUID) (*biz.APIToken, error) { + ret := _m.Called(ctx, name, description, expiresAt, organizationID, projectID) if len(ret) == 0 { panic("no return value specified for Create") @@ -50,91 +29,29 @@ func (_mock *MockAPITokenRepo) Create(ctx context.Context, name string, descript var r0 *biz.APIToken var r1 error - if returnFunc, ok := ret.Get(0).(func(context.Context, string, *string, *time.Time, uuid.UUID, *uuid.UUID) (*biz.APIToken, error)); ok { - return returnFunc(ctx, name, description, expiresAt, organizationID, projectID) + if rf, ok := ret.Get(0).(func(context.Context, string, *string, *time.Time, uuid.UUID, *uuid.UUID) (*biz.APIToken, error)); ok { + return rf(ctx, name, description, expiresAt, organizationID, projectID) } - if returnFunc, ok := ret.Get(0).(func(context.Context, string, *string, *time.Time, uuid.UUID, *uuid.UUID) *biz.APIToken); ok { - r0 = returnFunc(ctx, name, description, expiresAt, organizationID, projectID) + if rf, ok := ret.Get(0).(func(context.Context, string, *string, *time.Time, uuid.UUID, *uuid.UUID) *biz.APIToken); ok { + r0 = rf(ctx, name, description, expiresAt, organizationID, projectID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*biz.APIToken) } } - if returnFunc, ok := ret.Get(1).(func(context.Context, string, *string, *time.Time, uuid.UUID, *uuid.UUID) error); ok { - r1 = returnFunc(ctx, name, description, expiresAt, organizationID, projectID) + + if rf, ok := ret.Get(1).(func(context.Context, string, *string, *time.Time, uuid.UUID, *uuid.UUID) error); ok { + r1 = rf(ctx, name, description, expiresAt, organizationID, projectID) } else { r1 = ret.Error(1) } - return r0, r1 -} - -// MockAPITokenRepo_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' -type MockAPITokenRepo_Create_Call struct { - *mock.Call -} - -// Create is a helper method to define mock.On call -// - ctx context.Context -// - name string -// - description *string -// - expiresAt *time.Time -// - organizationID uuid.UUID -// - projectID *uuid.UUID -func (_e *MockAPITokenRepo_Expecter) Create(ctx interface{}, name interface{}, description interface{}, expiresAt interface{}, organizationID interface{}, projectID interface{}) *MockAPITokenRepo_Create_Call { - return &MockAPITokenRepo_Create_Call{Call: _e.mock.On("Create", ctx, name, description, expiresAt, organizationID, projectID)} -} - -func (_c *MockAPITokenRepo_Create_Call) Run(run func(ctx context.Context, name string, description *string, expiresAt *time.Time, organizationID uuid.UUID, projectID *uuid.UUID)) *MockAPITokenRepo_Create_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 string - if args[1] != nil { - arg1 = args[1].(string) - } - var arg2 *string - if args[2] != nil { - arg2 = args[2].(*string) - } - var arg3 *time.Time - if args[3] != nil { - arg3 = args[3].(*time.Time) - } - var arg4 uuid.UUID - if args[4] != nil { - arg4 = args[4].(uuid.UUID) - } - var arg5 *uuid.UUID - if args[5] != nil { - arg5 = args[5].(*uuid.UUID) - } - run( - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - ) - }) - return _c -} - -func (_c *MockAPITokenRepo_Create_Call) Return(aPIToken *biz.APIToken, err error) *MockAPITokenRepo_Create_Call { - _c.Call.Return(aPIToken, err) - return _c -} -func (_c *MockAPITokenRepo_Create_Call) RunAndReturn(run func(ctx context.Context, name string, description *string, expiresAt *time.Time, organizationID uuid.UUID, projectID *uuid.UUID) (*biz.APIToken, error)) *MockAPITokenRepo_Create_Call { - _c.Call.Return(run) - return _c + return r0, r1 } -// FindByID provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) FindByID(ctx context.Context, ID uuid.UUID) (*biz.APIToken, error) { - ret := _mock.Called(ctx, ID) +// FindByID provides a mock function with given fields: ctx, ID +func (_m *APITokenRepo) FindByID(ctx context.Context, ID uuid.UUID) (*biz.APIToken, error) { + ret := _m.Called(ctx, ID) if len(ret) == 0 { panic("no return value specified for FindByID") @@ -142,147 +59,59 @@ func (_mock *MockAPITokenRepo) FindByID(ctx context.Context, ID uuid.UUID) (*biz var r0 *biz.APIToken var r1 error - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID) (*biz.APIToken, error)); ok { - return returnFunc(ctx, ID) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (*biz.APIToken, error)); ok { + return rf(ctx, ID) } - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID) *biz.APIToken); ok { - r0 = returnFunc(ctx, ID) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) *biz.APIToken); ok { + r0 = rf(ctx, ID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*biz.APIToken) } } - if returnFunc, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { - r1 = returnFunc(ctx, ID) + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, ID) } else { r1 = ret.Error(1) } - return r0, r1 -} - -// MockAPITokenRepo_FindByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByID' -type MockAPITokenRepo_FindByID_Call struct { - *mock.Call -} - -// FindByID is a helper method to define mock.On call -// - ctx context.Context -// - ID uuid.UUID -func (_e *MockAPITokenRepo_Expecter) FindByID(ctx interface{}, ID interface{}) *MockAPITokenRepo_FindByID_Call { - return &MockAPITokenRepo_FindByID_Call{Call: _e.mock.On("FindByID", ctx, ID)} -} - -func (_c *MockAPITokenRepo_FindByID_Call) Run(run func(ctx context.Context, ID uuid.UUID)) *MockAPITokenRepo_FindByID_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 uuid.UUID - if args[1] != nil { - arg1 = args[1].(uuid.UUID) - } - run( - arg0, - arg1, - ) - }) - return _c -} - -func (_c *MockAPITokenRepo_FindByID_Call) Return(aPIToken *biz.APIToken, err error) *MockAPITokenRepo_FindByID_Call { - _c.Call.Return(aPIToken, err) - return _c -} -func (_c *MockAPITokenRepo_FindByID_Call) RunAndReturn(run func(ctx context.Context, ID uuid.UUID) (*biz.APIToken, error)) *MockAPITokenRepo_FindByID_Call { - _c.Call.Return(run) - return _c + return r0, r1 } -// FindByNameInOrg provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) FindByNameInOrg(ctx context.Context, orgID uuid.UUID, name string, projectID *uuid.UUID) (*biz.APIToken, error) { - ret := _mock.Called(ctx, orgID, name, projectID) +// FindByIDInOrg provides a mock function with given fields: ctx, orgID, id +func (_m *APITokenRepo) FindByIDInOrg(ctx context.Context, orgID uuid.UUID, id uuid.UUID) (*biz.APIToken, error) { + ret := _m.Called(ctx, orgID, id) if len(ret) == 0 { - panic("no return value specified for FindByNameInOrg") + panic("no return value specified for FindByIDInOrg") } var r0 *biz.APIToken var r1 error - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, *uuid.UUID) (*biz.APIToken, error)); ok { - return returnFunc(ctx, orgID, name, projectID) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, uuid.UUID) (*biz.APIToken, error)); ok { + return rf(ctx, orgID, id) } - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, string, *uuid.UUID) *biz.APIToken); ok { - r0 = returnFunc(ctx, orgID, name, projectID) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, uuid.UUID) *biz.APIToken); ok { + r0 = rf(ctx, orgID, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*biz.APIToken) } } - if returnFunc, ok := ret.Get(1).(func(context.Context, uuid.UUID, string, *uuid.UUID) error); ok { - r1 = returnFunc(ctx, orgID, name, projectID) + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID, uuid.UUID) error); ok { + r1 = rf(ctx, orgID, id) } else { r1 = ret.Error(1) } - return r0, r1 -} - -// MockAPITokenRepo_FindByNameInOrg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByNameInOrg' -type MockAPITokenRepo_FindByNameInOrg_Call struct { - *mock.Call -} - -// FindByNameInOrg is a helper method to define mock.On call -// - ctx context.Context -// - orgID uuid.UUID -// - name string -// - projectID *uuid.UUID -func (_e *MockAPITokenRepo_Expecter) FindByNameInOrg(ctx interface{}, orgID interface{}, name interface{}, projectID interface{}) *MockAPITokenRepo_FindByNameInOrg_Call { - return &MockAPITokenRepo_FindByNameInOrg_Call{Call: _e.mock.On("FindByNameInOrg", ctx, orgID, name, projectID)} -} - -func (_c *MockAPITokenRepo_FindByNameInOrg_Call) Run(run func(ctx context.Context, orgID uuid.UUID, name string, projectID *uuid.UUID)) *MockAPITokenRepo_FindByNameInOrg_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 uuid.UUID - if args[1] != nil { - arg1 = args[1].(uuid.UUID) - } - var arg2 string - if args[2] != nil { - arg2 = args[2].(string) - } - var arg3 *uuid.UUID - if args[3] != nil { - arg3 = args[3].(*uuid.UUID) - } - run( - arg0, - arg1, - arg2, - arg3, - ) - }) - return _c -} - -func (_c *MockAPITokenRepo_FindByNameInOrg_Call) Return(aPIToken *biz.APIToken, err error) *MockAPITokenRepo_FindByNameInOrg_Call { - _c.Call.Return(aPIToken, err) - return _c -} -func (_c *MockAPITokenRepo_FindByNameInOrg_Call) RunAndReturn(run func(ctx context.Context, orgID uuid.UUID, name string, projectID *uuid.UUID) (*biz.APIToken, error)) *MockAPITokenRepo_FindByNameInOrg_Call { - _c.Call.Return(run) - return _c + return r0, r1 } -// List provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) List(ctx context.Context, orgID *uuid.UUID, projectID *uuid.UUID, includeRevoked bool, showOnlySystemTokens bool) ([]*biz.APIToken, error) { - ret := _mock.Called(ctx, orgID, projectID, includeRevoked, showOnlySystemTokens) +// List provides a mock function with given fields: ctx, orgID, filters +func (_m *APITokenRepo) List(ctx context.Context, orgID *uuid.UUID, filters *biz.APITokenListFilters) ([]*biz.APIToken, error) { + ret := _m.Called(ctx, orgID, filters) if len(ret) == 0 { panic("no return value specified for List") @@ -290,267 +119,90 @@ func (_mock *MockAPITokenRepo) List(ctx context.Context, orgID *uuid.UUID, proje var r0 []*biz.APIToken var r1 error - if returnFunc, ok := ret.Get(0).(func(context.Context, *uuid.UUID, *uuid.UUID, bool, bool) ([]*biz.APIToken, error)); ok { - return returnFunc(ctx, orgID, projectID, includeRevoked, showOnlySystemTokens) + if rf, ok := ret.Get(0).(func(context.Context, *uuid.UUID, *biz.APITokenListFilters) ([]*biz.APIToken, error)); ok { + return rf(ctx, orgID, filters) } - if returnFunc, ok := ret.Get(0).(func(context.Context, *uuid.UUID, *uuid.UUID, bool, bool) []*biz.APIToken); ok { - r0 = returnFunc(ctx, orgID, projectID, includeRevoked, showOnlySystemTokens) + if rf, ok := ret.Get(0).(func(context.Context, *uuid.UUID, *biz.APITokenListFilters) []*biz.APIToken); ok { + r0 = rf(ctx, orgID, filters) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*biz.APIToken) } } - if returnFunc, ok := ret.Get(1).(func(context.Context, *uuid.UUID, *uuid.UUID, bool, bool) error); ok { - r1 = returnFunc(ctx, orgID, projectID, includeRevoked, showOnlySystemTokens) + + if rf, ok := ret.Get(1).(func(context.Context, *uuid.UUID, *biz.APITokenListFilters) error); ok { + r1 = rf(ctx, orgID, filters) } else { r1 = ret.Error(1) } - return r0, r1 -} - -// MockAPITokenRepo_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' -type MockAPITokenRepo_List_Call struct { - *mock.Call -} - -// List is a helper method to define mock.On call -// - ctx context.Context -// - orgID *uuid.UUID -// - projectID *uuid.UUID -// - includeRevoked bool -// - showOnlySystemTokens bool -func (_e *MockAPITokenRepo_Expecter) List(ctx interface{}, orgID interface{}, projectID interface{}, includeRevoked interface{}, showOnlySystemTokens interface{}) *MockAPITokenRepo_List_Call { - return &MockAPITokenRepo_List_Call{Call: _e.mock.On("List", ctx, orgID, projectID, includeRevoked, showOnlySystemTokens)} -} -func (_c *MockAPITokenRepo_List_Call) Run(run func(ctx context.Context, orgID *uuid.UUID, projectID *uuid.UUID, includeRevoked bool, showOnlySystemTokens bool)) *MockAPITokenRepo_List_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 *uuid.UUID - if args[1] != nil { - arg1 = args[1].(*uuid.UUID) - } - var arg2 *uuid.UUID - if args[2] != nil { - arg2 = args[2].(*uuid.UUID) - } - var arg3 bool - if args[3] != nil { - arg3 = args[3].(bool) - } - var arg4 bool - if args[4] != nil { - arg4 = args[4].(bool) - } - run( - arg0, - arg1, - arg2, - arg3, - arg4, - ) - }) - return _c -} - -func (_c *MockAPITokenRepo_List_Call) Return(aPITokens []*biz.APIToken, err error) *MockAPITokenRepo_List_Call { - _c.Call.Return(aPITokens, err) - return _c -} - -func (_c *MockAPITokenRepo_List_Call) RunAndReturn(run func(ctx context.Context, orgID *uuid.UUID, projectID *uuid.UUID, includeRevoked bool, showOnlySystemTokens bool) ([]*biz.APIToken, error)) *MockAPITokenRepo_List_Call { - _c.Call.Return(run) - return _c + return r0, r1 } -// Revoke provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) Revoke(ctx context.Context, orgID uuid.UUID, ID uuid.UUID) error { - ret := _mock.Called(ctx, orgID, ID) +// Revoke provides a mock function with given fields: ctx, orgID, ID +func (_m *APITokenRepo) Revoke(ctx context.Context, orgID uuid.UUID, ID uuid.UUID) error { + ret := _m.Called(ctx, orgID, ID) if len(ret) == 0 { panic("no return value specified for Revoke") } var r0 error - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, uuid.UUID) error); ok { - r0 = returnFunc(ctx, orgID, ID) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, uuid.UUID) error); ok { + r0 = rf(ctx, orgID, ID) } else { r0 = ret.Error(0) } - return r0 -} - -// MockAPITokenRepo_Revoke_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Revoke' -type MockAPITokenRepo_Revoke_Call struct { - *mock.Call -} - -// Revoke is a helper method to define mock.On call -// - ctx context.Context -// - orgID uuid.UUID -// - ID uuid.UUID -func (_e *MockAPITokenRepo_Expecter) Revoke(ctx interface{}, orgID interface{}, ID interface{}) *MockAPITokenRepo_Revoke_Call { - return &MockAPITokenRepo_Revoke_Call{Call: _e.mock.On("Revoke", ctx, orgID, ID)} -} - -func (_c *MockAPITokenRepo_Revoke_Call) Run(run func(ctx context.Context, orgID uuid.UUID, ID uuid.UUID)) *MockAPITokenRepo_Revoke_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 uuid.UUID - if args[1] != nil { - arg1 = args[1].(uuid.UUID) - } - var arg2 uuid.UUID - if args[2] != nil { - arg2 = args[2].(uuid.UUID) - } - run( - arg0, - arg1, - arg2, - ) - }) - return _c -} - -func (_c *MockAPITokenRepo_Revoke_Call) Return(err error) *MockAPITokenRepo_Revoke_Call { - _c.Call.Return(err) - return _c -} -func (_c *MockAPITokenRepo_Revoke_Call) RunAndReturn(run func(ctx context.Context, orgID uuid.UUID, ID uuid.UUID) error) *MockAPITokenRepo_Revoke_Call { - _c.Call.Return(run) - return _c + return r0 } -// UpdateExpiration provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) UpdateExpiration(ctx context.Context, ID uuid.UUID, expiresAt time.Time) error { - ret := _mock.Called(ctx, ID, expiresAt) +// UpdateExpiration provides a mock function with given fields: ctx, ID, expiresAt +func (_m *APITokenRepo) UpdateExpiration(ctx context.Context, ID uuid.UUID, expiresAt time.Time) error { + ret := _m.Called(ctx, ID, expiresAt) if len(ret) == 0 { panic("no return value specified for UpdateExpiration") } var r0 error - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, time.Time) error); ok { - r0 = returnFunc(ctx, ID, expiresAt) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, time.Time) error); ok { + r0 = rf(ctx, ID, expiresAt) } else { r0 = ret.Error(0) } - return r0 -} - -// MockAPITokenRepo_UpdateExpiration_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateExpiration' -type MockAPITokenRepo_UpdateExpiration_Call struct { - *mock.Call -} - -// UpdateExpiration is a helper method to define mock.On call -// - ctx context.Context -// - ID uuid.UUID -// - expiresAt time.Time -func (_e *MockAPITokenRepo_Expecter) UpdateExpiration(ctx interface{}, ID interface{}, expiresAt interface{}) *MockAPITokenRepo_UpdateExpiration_Call { - return &MockAPITokenRepo_UpdateExpiration_Call{Call: _e.mock.On("UpdateExpiration", ctx, ID, expiresAt)} -} - -func (_c *MockAPITokenRepo_UpdateExpiration_Call) Run(run func(ctx context.Context, ID uuid.UUID, expiresAt time.Time)) *MockAPITokenRepo_UpdateExpiration_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 uuid.UUID - if args[1] != nil { - arg1 = args[1].(uuid.UUID) - } - var arg2 time.Time - if args[2] != nil { - arg2 = args[2].(time.Time) - } - run( - arg0, - arg1, - arg2, - ) - }) - return _c -} -func (_c *MockAPITokenRepo_UpdateExpiration_Call) Return(err error) *MockAPITokenRepo_UpdateExpiration_Call { - _c.Call.Return(err) - return _c -} - -func (_c *MockAPITokenRepo_UpdateExpiration_Call) RunAndReturn(run func(ctx context.Context, ID uuid.UUID, expiresAt time.Time) error) *MockAPITokenRepo_UpdateExpiration_Call { - _c.Call.Return(run) - return _c + return r0 } -// UpdateLastUsedAt provides a mock function for the type MockAPITokenRepo -func (_mock *MockAPITokenRepo) UpdateLastUsedAt(ctx context.Context, ID uuid.UUID, lastUsedAt time.Time) error { - ret := _mock.Called(ctx, ID, lastUsedAt) +// UpdateLastUsedAt provides a mock function with given fields: ctx, ID, lastUsedAt +func (_m *APITokenRepo) UpdateLastUsedAt(ctx context.Context, ID uuid.UUID, lastUsedAt time.Time) error { + ret := _m.Called(ctx, ID, lastUsedAt) if len(ret) == 0 { panic("no return value specified for UpdateLastUsedAt") } var r0 error - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, time.Time) error); ok { - r0 = returnFunc(ctx, ID, lastUsedAt) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, time.Time) error); ok { + r0 = rf(ctx, ID, lastUsedAt) } else { r0 = ret.Error(0) } - return r0 -} - -// MockAPITokenRepo_UpdateLastUsedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateLastUsedAt' -type MockAPITokenRepo_UpdateLastUsedAt_Call struct { - *mock.Call -} -// UpdateLastUsedAt is a helper method to define mock.On call -// - ctx context.Context -// - ID uuid.UUID -// - lastUsedAt time.Time -func (_e *MockAPITokenRepo_Expecter) UpdateLastUsedAt(ctx interface{}, ID interface{}, lastUsedAt interface{}) *MockAPITokenRepo_UpdateLastUsedAt_Call { - return &MockAPITokenRepo_UpdateLastUsedAt_Call{Call: _e.mock.On("UpdateLastUsedAt", ctx, ID, lastUsedAt)} + return r0 } -func (_c *MockAPITokenRepo_UpdateLastUsedAt_Call) Run(run func(ctx context.Context, ID uuid.UUID, lastUsedAt time.Time)) *MockAPITokenRepo_UpdateLastUsedAt_Call { - _c.Call.Run(func(args mock.Arguments) { - var arg0 context.Context - if args[0] != nil { - arg0 = args[0].(context.Context) - } - var arg1 uuid.UUID - if args[1] != nil { - arg1 = args[1].(uuid.UUID) - } - var arg2 time.Time - if args[2] != nil { - arg2 = args[2].(time.Time) - } - run( - arg0, - arg1, - arg2, - ) - }) - return _c -} +// NewAPITokenRepo creates a new instance of APITokenRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAPITokenRepo(t interface { + mock.TestingT + Cleanup(func()) +}) *APITokenRepo { + mock := &APITokenRepo{} + mock.Mock.Test(t) -func (_c *MockAPITokenRepo_UpdateLastUsedAt_Call) Return(err error) *MockAPITokenRepo_UpdateLastUsedAt_Call { - _c.Call.Return(err) - return _c -} + t.Cleanup(func() { mock.AssertExpectations(t) }) -func (_c *MockAPITokenRepo_UpdateLastUsedAt_Call) RunAndReturn(run func(ctx context.Context, ID uuid.UUID, lastUsedAt time.Time) error) *MockAPITokenRepo_UpdateLastUsedAt_Call { - _c.Call.Return(run) - return _c + return mock } From 3ad55ab4d9ccb960579b1bf39f47034e8444321e Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 22:48:00 +0200 Subject: [PATCH 23/24] add tests Signed-off-by: Miguel Martinez --- app/controlplane/internal/service/apitoken.go | 2 +- app/controlplane/pkg/biz/apitoken.go | 6 +++--- app/controlplane/pkg/biz/apitoken_integration_test.go | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/controlplane/internal/service/apitoken.go b/app/controlplane/internal/service/apitoken.go index 2bf56c117..d7f98ecf4 100644 --- a/app/controlplane/internal/service/apitoken.go +++ b/app/controlplane/internal/service/apitoken.go @@ -101,7 +101,7 @@ func (s *APITokenService) List(ctx context.Context, req *pb.APITokenServiceListR } // Only expose system tokens - tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithApiTokenRevoked(req.IncludeRevoked), biz.WithApiTokenProjectFilter(defaultProjectFilter), biz.WithApiTokenScope(mapTokenScope(req.Scope))) + tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithAPITokenRevoked(req.IncludeRevoked), biz.WithAPITokenProjectFilter(defaultProjectFilter), biz.WithAPITokenScope(mapTokenScope(req.Scope))) if err != nil { return nil, handleUseCaseErr(err, s.log) } diff --git a/app/controlplane/pkg/biz/apitoken.go b/app/controlplane/pkg/biz/apitoken.go index 0cc3be70c..2a7d8cb8a 100644 --- a/app/controlplane/pkg/biz/apitoken.go +++ b/app/controlplane/pkg/biz/apitoken.go @@ -273,19 +273,19 @@ func (uc *APITokenUseCase) RegenerateJWT(ctx context.Context, tokenID uuid.UUID, type APITokenListOpt func(*APITokenListFilters) -func WithApiTokenProjectFilter(projectIDs []uuid.UUID) APITokenListOpt { +func WithAPITokenProjectFilter(projectIDs []uuid.UUID) APITokenListOpt { return func(opts *APITokenListFilters) { opts.FilterByProjects = projectIDs } } -func WithApiTokenRevoked(includeRevoked bool) APITokenListOpt { +func WithAPITokenRevoked(includeRevoked bool) APITokenListOpt { return func(opts *APITokenListFilters) { opts.IncludeRevoked = includeRevoked } } -func WithApiTokenScope(scope APITokenScope) APITokenListOpt { +func WithAPITokenScope(scope APITokenScope) APITokenListOpt { return func(opts *APITokenListFilters) { opts.FilterByScope = scope } diff --git a/app/controlplane/pkg/biz/apitoken_integration_test.go b/app/controlplane/pkg/biz/apitoken_integration_test.go index 558a7a2d8..0591bc6c2 100644 --- a/app/controlplane/pkg/biz/apitoken_integration_test.go +++ b/app/controlplane/pkg/biz/apitoken_integration_test.go @@ -201,7 +201,7 @@ func (s *apiTokenTestSuite) TestRevoke() { s.Run("token can be revoked once", func() { err := s.APIToken.Revoke(ctx, s.org.ID, s.t1.ID.String()) s.NoError(err) - tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenRevoked(true)) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithAPITokenRevoked(true)) s.NoError(err) s.Equal(s.t1.ID, tokens[0].ID) // It's revoked @@ -270,7 +270,7 @@ func (s *apiTokenTestSuite) TestList() { }) s.Run("can return only for a specific project", func() { - tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenProjectFilter([]uuid.UUID{s.p1.ID})) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithAPITokenProjectFilter([]uuid.UUID{s.p1.ID})) s.NoError(err) require.Len(s.T(), tokens, 2) s.Equal(s.t4.ID, tokens[0].ID) @@ -278,13 +278,13 @@ func (s *apiTokenTestSuite) TestList() { }) s.Run("can return scoped to a project", func() { - tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenScope(biz.APITokenScopeProject)) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithAPITokenScope(biz.APITokenScopeProject)) s.NoError(err) require.Len(s.T(), tokens, 3) }) s.Run("can return scoped to a global", func() { - tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenScope(biz.APITokenScopeGlobal)) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithAPITokenScope(biz.APITokenScopeGlobal)) s.NoError(err) s.Len(tokens, 2) }) @@ -310,7 +310,7 @@ func (s *apiTokenTestSuite) TestList() { }) s.Run("doesn't return revoked unless requested", func() { - tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithApiTokenRevoked(true)) + tokens, err := s.APIToken.List(ctx, s.org.ID, biz.WithAPITokenRevoked(true)) s.NoError(err) require.Len(s.T(), tokens, 5) s.Equal(s.t1.ID, tokens[0].ID) From 82bb03317e401f32daec7e6102e77d8db99fbff0 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Thu, 10 Jul 2025 22:52:18 +0200 Subject: [PATCH 24/24] add tests Signed-off-by: Miguel Martinez --- app/cli/documentation/cli-reference.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/cli/documentation/cli-reference.mdx b/app/cli/documentation/cli-reference.mdx index 5fa4132da..7ef836da1 100755 --- a/app/cli/documentation/cli-reference.mdx +++ b/app/cli/documentation/cli-reference.mdx @@ -2112,6 +2112,7 @@ Options -a, --all show all API tokens including revoked ones -h, --help help for list -p, --project string filter by project name +-s, --scope string filter by scope, available scopes: [project global] ``` Options inherited from parent commands