diff --git a/app/controlplane/api/controlplane/v1/organization.pb.go b/app/controlplane/api/controlplane/v1/organization.pb.go index 6522e4c56..1af61fee6 100644 --- a/app/controlplane/api/controlplane/v1/organization.pb.go +++ b/app/controlplane/api/controlplane/v1/organization.pb.go @@ -471,6 +471,8 @@ type OrganizationServiceUpdateRequest struct { UpdatePoliciesAllowedHostnames bool `protobuf:"varint,4,opt,name=update_policies_allowed_hostnames,json=updatePoliciesAllowedHostnames,proto3" json:"update_policies_allowed_hostnames,omitempty"` // prevent workflows and projects from being created implicitly during attestation init PreventImplicitWorkflowCreation *bool `protobuf:"varint,5,opt,name=prevent_implicit_workflow_creation,json=preventImplicitWorkflowCreation,proto3,oneof" json:"prevent_implicit_workflow_creation,omitempty"` + // restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles) + RestrictContractCreationToOrgAdmins *bool `protobuf:"varint,6,opt,name=restrict_contract_creation_to_org_admins,json=restrictContractCreationToOrgAdmins,proto3,oneof" json:"restrict_contract_creation_to_org_admins,omitempty"` } func (x *OrganizationServiceUpdateRequest) Reset() { @@ -540,6 +542,13 @@ func (x *OrganizationServiceUpdateRequest) GetPreventImplicitWorkflowCreation() return false } +func (x *OrganizationServiceUpdateRequest) GetRestrictContractCreationToOrgAdmins() bool { + if x != nil && x.RestrictContractCreationToOrgAdmins != nil { + return *x.RestrictContractCreationToOrgAdmins + } + return false +} + type OrganizationServiceUpdateResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -752,7 +761,7 @@ var file_controlplane_v1_organization_proto_rawDesc = []byte{ 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 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, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x22, 0x9f, 0x03, 0x0a, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0xa8, 0x04, 0x0a, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 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, @@ -774,78 +783,86 @@ var file_controlplane_v1_organization_proto_rawDesc = []byte{ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x1f, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6d, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, - 0x01, 0x42, 0x1c, 0x0a, 0x1a, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x25, 0x0a, 0x23, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, - 0x69, 0x63, 0x69, 0x74, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x21, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 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, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3f, 0x0a, - 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 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, 0x22, 0x23, - 0x0a, 0x21, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0x95, 0x06, 0x0a, 0x13, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x06, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 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, 0x4f, 0x72, 0x67, 0x61, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x06, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 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, 0x4f, 0x72, 0x67, 0x61, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, - 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x01, 0x12, 0x5a, 0x0a, 0x28, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x5f, 0x6f, 0x72, 0x67, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x23, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x6f, 0x4f, 0x72, 0x67, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x42, 0x1c, 0x0a, + 0x1a, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x5f, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x25, 0x0a, 0x23, 0x5f, + 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, + 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x2b, 0x0a, 0x29, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x6f, 0x5f, 0x6f, 0x72, 0x67, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x73, 0x22, + 0x55, 0x0a, 0x21, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, + 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, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3f, 0x0a, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 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, 0x4f, 0x72, 0x67, - 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, - 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x73, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, + 0x65, 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, 0x22, 0x23, 0x0a, 0x21, 0x4f, 0x72, 0x67, 0x61, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x95, 0x06, 0x0a, + 0x13, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x10, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x12, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x10, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x12, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 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, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x68, 0x69, 0x70, 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, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x3a, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, + 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 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/organization.proto b/app/controlplane/api/controlplane/v1/organization.proto index 59533dc21..cb5f2a989 100644 --- a/app/controlplane/api/controlplane/v1/organization.proto +++ b/app/controlplane/api/controlplane/v1/organization.proto @@ -96,6 +96,9 @@ message OrganizationServiceUpdateRequest { // prevent workflows and projects from being created implicitly during attestation init optional bool prevent_implicit_workflow_creation = 5; + + // restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles) + optional bool restrict_contract_creation_to_org_admins = 6; } message OrganizationServiceUpdateResponse { diff --git a/app/controlplane/api/controlplane/v1/response_messages.pb.go b/app/controlplane/api/controlplane/v1/response_messages.pb.go index db3b528f7..5cf5cb783 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.pb.go +++ b/app/controlplane/api/controlplane/v1/response_messages.pb.go @@ -1928,6 +1928,8 @@ type OrgItem struct { PolicyAllowedHostnames []string `protobuf:"bytes,5,rep,name=policy_allowed_hostnames,json=policyAllowedHostnames,proto3" json:"policy_allowed_hostnames,omitempty"` // prevent workflows and projects from being created implicitly during attestation init PreventImplicitWorkflowCreation bool `protobuf:"varint,7,opt,name=prevent_implicit_workflow_creation,json=preventImplicitWorkflowCreation,proto3" json:"prevent_implicit_workflow_creation,omitempty"` + // restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles) + RestrictContractCreationToOrgAdmins bool `protobuf:"varint,8,opt,name=restrict_contract_creation_to_org_admins,json=restrictContractCreationToOrgAdmins,proto3" json:"restrict_contract_creation_to_org_admins,omitempty"` } func (x *OrgItem) Reset() { @@ -2011,6 +2013,13 @@ func (x *OrgItem) GetPreventImplicitWorkflowCreation() bool { return false } +func (x *OrgItem) GetRestrictContractCreationToOrgAdmins() bool { + if x != nil { + return x.RestrictContractCreationToOrgAdmins + } + return false +} + type CASBackendItem struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3008,7 +3017,7 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 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, 0xe7, 0x04, + 0x68, 0x69, 0x70, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0xbe, 0x05, 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, @@ -3036,165 +3045,170 @@ var file_controlplane_v1_response_messages_proto_rawDesc = []byte{ 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6d, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 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, 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, 0x05, 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, 0x12, 0x2e, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0d, 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, 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, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 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, 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, 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, + 0x12, 0x55, 0x0a, 0x28, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x6f, 0x5f, 0x6f, 0x72, 0x67, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x23, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x4f, 0x72, + 0x67, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x73, 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, 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, + 0x05, 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, 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, 0xa1, 0x01, 0x0a, 0x16, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x24, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, - 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 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, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x56, - 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x01, 0x12, 0x2f, 0x0a, 0x2b, 0x50, - 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, - 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x5f, - 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x02, 0x2a, 0xd4, 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, 0x12, 0x23, - 0x0a, 0x1f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, - 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, - 0x52, 0x10, 0x05, 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, + 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, 0x12, + 0x2e, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, + 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0d, 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, 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, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 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, 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, 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, + 0xa1, 0x01, 0x0a, 0x16, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x24, 0x50, 0x4f, + 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, + 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 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, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, + 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, + 0x10, 0x01, 0x12, 0x2f, 0x0a, 0x2b, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x56, 0x49, 0x4f, + 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x5f, 0x57, + 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x5f, 0x56, 0x49, 0x4f, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x53, 0x10, 0x02, 0x2a, 0xd4, 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, 0x12, 0x23, 0x0a, 0x1f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x53, + 0x48, 0x49, 0x50, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x5f, 0x43, 0x4f, 0x4e, + 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x10, 0x05, 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 ( diff --git a/app/controlplane/api/controlplane/v1/response_messages.proto b/app/controlplane/api/controlplane/v1/response_messages.proto index 8dcee28d1..cb12e2ce8 100644 --- a/app/controlplane/api/controlplane/v1/response_messages.proto +++ b/app/controlplane/api/controlplane/v1/response_messages.proto @@ -281,6 +281,8 @@ message OrgItem { repeated string policy_allowed_hostnames = 5; // prevent workflows and projects from being created implicitly during attestation init bool prevent_implicit_workflow_creation = 7; + // restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles) + bool restrict_contract_creation_to_org_admins = 8; enum PolicyViolationBlockingStrategy { POLICY_VIOLATION_BLOCKING_STRATEGY_UNSPECIFIED = 0; diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/organization.ts b/app/controlplane/api/gen/frontend/controlplane/v1/organization.ts index aecd08468..dc018ca11 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/organization.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/organization.ts @@ -77,7 +77,11 @@ export interface OrganizationServiceUpdateRequest { */ updatePoliciesAllowedHostnames: boolean; /** prevent workflows and projects from being created implicitly during attestation init */ - preventImplicitWorkflowCreation?: boolean | undefined; + preventImplicitWorkflowCreation?: + | boolean + | undefined; + /** restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles) */ + restrictContractCreationToOrgAdmins?: boolean | undefined; } export interface OrganizationServiceUpdateResponse { @@ -666,6 +670,7 @@ function createBaseOrganizationServiceUpdateRequest(): OrganizationServiceUpdate policiesAllowedHostnames: [], updatePoliciesAllowedHostnames: false, preventImplicitWorkflowCreation: undefined, + restrictContractCreationToOrgAdmins: undefined, }; } @@ -686,6 +691,9 @@ export const OrganizationServiceUpdateRequest = { if (message.preventImplicitWorkflowCreation !== undefined) { writer.uint32(40).bool(message.preventImplicitWorkflowCreation); } + if (message.restrictContractCreationToOrgAdmins !== undefined) { + writer.uint32(48).bool(message.restrictContractCreationToOrgAdmins); + } return writer; }, @@ -731,6 +739,13 @@ export const OrganizationServiceUpdateRequest = { message.preventImplicitWorkflowCreation = reader.bool(); continue; + case 6: + if (tag !== 48) { + break; + } + + message.restrictContractCreationToOrgAdmins = reader.bool(); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -753,6 +768,9 @@ export const OrganizationServiceUpdateRequest = { preventImplicitWorkflowCreation: isSet(object.preventImplicitWorkflowCreation) ? Boolean(object.preventImplicitWorkflowCreation) : undefined, + restrictContractCreationToOrgAdmins: isSet(object.restrictContractCreationToOrgAdmins) + ? Boolean(object.restrictContractCreationToOrgAdmins) + : undefined, }; }, @@ -769,6 +787,8 @@ export const OrganizationServiceUpdateRequest = { (obj.updatePoliciesAllowedHostnames = message.updatePoliciesAllowedHostnames); message.preventImplicitWorkflowCreation !== undefined && (obj.preventImplicitWorkflowCreation = message.preventImplicitWorkflowCreation); + message.restrictContractCreationToOrgAdmins !== undefined && + (obj.restrictContractCreationToOrgAdmins = message.restrictContractCreationToOrgAdmins); return obj; }, @@ -787,6 +807,7 @@ export const OrganizationServiceUpdateRequest = { message.policiesAllowedHostnames = object.policiesAllowedHostnames?.map((e) => e) || []; message.updatePoliciesAllowedHostnames = object.updatePoliciesAllowedHostnames ?? false; message.preventImplicitWorkflowCreation = object.preventImplicitWorkflowCreation ?? undefined; + message.restrictContractCreationToOrgAdmins = object.restrictContractCreationToOrgAdmins ?? undefined; return message; }, }; 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 d46979db4..7fe2b2932 100644 --- a/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts +++ b/app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts @@ -608,6 +608,8 @@ export interface OrgItem { policyAllowedHostnames: string[]; /** prevent workflows and projects from being created implicitly during attestation init */ preventImplicitWorkflowCreation: boolean; + /** restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles) */ + restrictContractCreationToOrgAdmins: boolean; } export enum OrgItem_PolicyViolationBlockingStrategy { @@ -3756,6 +3758,7 @@ function createBaseOrgItem(): OrgItem { defaultPolicyViolationStrategy: 0, policyAllowedHostnames: [], preventImplicitWorkflowCreation: false, + restrictContractCreationToOrgAdmins: false, }; } @@ -3782,6 +3785,9 @@ export const OrgItem = { if (message.preventImplicitWorkflowCreation === true) { writer.uint32(56).bool(message.preventImplicitWorkflowCreation); } + if (message.restrictContractCreationToOrgAdmins === true) { + writer.uint32(64).bool(message.restrictContractCreationToOrgAdmins); + } return writer; }, @@ -3841,6 +3847,13 @@ export const OrgItem = { message.preventImplicitWorkflowCreation = reader.bool(); continue; + case 8: + if (tag !== 64) { + break; + } + + message.restrictContractCreationToOrgAdmins = reader.bool(); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -3865,6 +3878,9 @@ export const OrgItem = { preventImplicitWorkflowCreation: isSet(object.preventImplicitWorkflowCreation) ? Boolean(object.preventImplicitWorkflowCreation) : false, + restrictContractCreationToOrgAdmins: isSet(object.restrictContractCreationToOrgAdmins) + ? Boolean(object.restrictContractCreationToOrgAdmins) + : false, }; }, @@ -3885,6 +3901,8 @@ export const OrgItem = { } message.preventImplicitWorkflowCreation !== undefined && (obj.preventImplicitWorkflowCreation = message.preventImplicitWorkflowCreation); + message.restrictContractCreationToOrgAdmins !== undefined && + (obj.restrictContractCreationToOrgAdmins = message.restrictContractCreationToOrgAdmins); return obj; }, @@ -3901,6 +3919,7 @@ export const OrgItem = { message.defaultPolicyViolationStrategy = object.defaultPolicyViolationStrategy ?? 0; message.policyAllowedHostnames = object.policyAllowedHostnames?.map((e) => e) || []; message.preventImplicitWorkflowCreation = object.preventImplicitWorkflowCreation ?? false; + message.restrictContractCreationToOrgAdmins = object.restrictContractCreationToOrgAdmins ?? false; return message; }, }; diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.jsonschema.json index 0a179c3b7..9383bebdd 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.jsonschema.json @@ -34,6 +34,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "^(restrict_contract_creation_to_org_admins)$": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "^(updated_at)$": { "$ref": "google.protobuf.Timestamp.jsonschema.json" } @@ -76,6 +80,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "restrictContractCreationToOrgAdmins": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "updatedAt": { "$ref": "google.protobuf.Timestamp.jsonschema.json" } diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.schema.json index ec7cd08c4..b3d35850c 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrgItem.schema.json @@ -34,6 +34,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "^(restrictContractCreationToOrgAdmins)$": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "^(updatedAt)$": { "$ref": "google.protobuf.Timestamp.schema.json" } @@ -76,6 +80,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "restrict_contract_creation_to_org_admins": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "updated_at": { "$ref": "google.protobuf.Timestamp.schema.json" } diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.jsonschema.json index feebca398..c80f03e8e 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.jsonschema.json @@ -18,6 +18,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "^(restrict_contract_creation_to_org_admins)$": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "^(update_policies_allowed_hostnames)$": { "description": "flag that allows us to detect if the value is explicitly set\n since repeated fields can not be optional", "type": "boolean" @@ -43,6 +47,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "restrictContractCreationToOrgAdmins": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "updatePoliciesAllowedHostnames": { "description": "flag that allows us to detect if the value is explicitly set\n since repeated fields can not be optional", "type": "boolean" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.schema.json index 346b7f3a9..9d85dd0a6 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.OrganizationServiceUpdateRequest.schema.json @@ -18,6 +18,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "^(restrictContractCreationToOrgAdmins)$": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "^(updatePoliciesAllowedHostnames)$": { "description": "flag that allows us to detect if the value is explicitly set\n since repeated fields can not be optional", "type": "boolean" @@ -43,6 +47,10 @@ "description": "prevent workflows and projects from being created implicitly during attestation init", "type": "boolean" }, + "restrict_contract_creation_to_org_admins": { + "description": "restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)", + "type": "boolean" + }, "update_policies_allowed_hostnames": { "description": "flag that allows us to detect if the value is explicitly set\n since repeated fields can not be optional", "type": "boolean" diff --git a/app/controlplane/cmd/wire_gen.go b/app/controlplane/cmd/wire_gen.go index 436700e5e..66d55b8ef 100644 --- a/app/controlplane/cmd/wire_gen.go +++ b/app/controlplane/cmd/wire_gen.go @@ -202,10 +202,11 @@ func wireApp(bootstrap *conf.Bootstrap, readerWriter credentials.ReaderWriter, l ProjectUC: projectUseCase, ProjectVersionUC: projectVersionUseCase, SigningUseCase: signingUseCase, + UserUC: userUseCase, Opts: v5, } attestationService := service.NewAttestationService(newAttestationServiceOpts) - workflowContractService := service.NewWorkflowSchemaService(workflowContractUseCase, v5...) + workflowContractService := service.NewWorkflowSchemaService(workflowContractUseCase, organizationUseCase, userUseCase, v5...) contextService := service.NewContextService(casBackendUseCase, userUseCase, v5...) casCredentialsService := service.NewCASCredentialsService(casCredentialsUseCase, casMappingUseCase, casBackendUseCase, authzUseCase, v5...) orgMetricsService := service.NewOrgMetricsService(orgMetricsUseCase, v5...) diff --git a/app/controlplane/internal/service/attestation.go b/app/controlplane/internal/service/attestation.go index 222bc4b30..224c8fa76 100644 --- a/app/controlplane/internal/service/attestation.go +++ b/app/controlplane/internal/service/attestation.go @@ -59,6 +59,7 @@ type AttestationService struct { projectVersionUseCase *biz.ProjectVersionUseCase projectUseCase *biz.ProjectUseCase signingUseCase *biz.SigningUseCase + userUseCase *biz.UserUseCase } type NewAttestationServiceOpts struct { @@ -78,6 +79,7 @@ type NewAttestationServiceOpts struct { ProjectUC *biz.ProjectUseCase ProjectVersionUC *biz.ProjectVersionUseCase SigningUseCase *biz.SigningUseCase + UserUC *biz.UserUseCase Opts []NewOpt } @@ -100,6 +102,7 @@ func NewAttestationService(opts *NewAttestationServiceOpts) *AttestationService projectUseCase: opts.ProjectUC, projectVersionUseCase: opts.ProjectVersionUC, signingUseCase: opts.SigningUseCase, + userUseCase: opts.UserUC, } } @@ -748,14 +751,21 @@ func (s *AttestationService) FindOrCreateWorkflow(ctx context.Context, req *cpAP return &cpAPI.FindOrCreateWorkflowResponse{Result: bizWorkflowToPb(wf)}, nil } + // Get organization + org, err := s.orgUseCase.FindByID(ctx, apiToken.OrgID) + if err != nil { + return nil, handleUseCaseErr(err, s.log) + } + // the workflow does not exist, let's create it alongside its project and contract createOpts := &biz.WorkflowCreateOpts{ - OrgID: apiToken.OrgID, - Name: req.GetWorkflowName(), - Project: req.GetProjectName(), - ContractName: req.GetContractName(), - ContractBytes: req.GetContractBytes(), - ImplicitCreation: true, // Mark as implicit creation from attestation init + OrgID: apiToken.OrgID, + Name: req.GetWorkflowName(), + Project: req.GetProjectName(), + ContractName: req.GetContractName(), + ContractBytes: req.GetContractBytes(), + ImplicitCreation: true, // Mark as implicit creation from attestation init + OrgRestrictContractCreationToAdmins: org.RestrictContractCreationToOrgAdmins, } // set project owner if RBAC is enabled @@ -766,6 +776,14 @@ func (s *AttestationService) FindOrCreateWorkflow(ctx context.Context, req *cpAP return nil, handleUseCaseErr(err, s.log) } createOpts.Owner = &userID + + // Check if user is an org admin + membership, err := s.userUseCase.MembershipInOrg(ctx, user.ID, org.Name) + + if err == nil && membership != nil { + isAdmin := membership.Role.IsAdmin() + createOpts.UserIsOrgAdmin = isAdmin + } } wf, err := s.workflowUseCase.Create(ctx, createOpts) diff --git a/app/controlplane/internal/service/context.go b/app/controlplane/internal/service/context.go index 3764f9d02..a9dd6aac5 100644 --- a/app/controlplane/internal/service/context.go +++ b/app/controlplane/internal/service/context.go @@ -118,10 +118,11 @@ func (s *ContextService) Current(ctx context.Context, _ *pb.ContextServiceCurren func bizOrgToPb(m *biz.Organization) *pb.OrgItem { return &pb.OrgItem{Id: m.ID, Name: m.Name, CreatedAt: timestamppb.New(*m.CreatedAt), - UpdatedAt: timestamppb.New(*m.UpdatedAt), - DefaultPolicyViolationStrategy: bizPolicyViolationBlockingStrategyToPb(m.BlockOnPolicyViolation), - PolicyAllowedHostnames: m.PoliciesAllowedHostnames, - PreventImplicitWorkflowCreation: m.PreventImplicitWorkflowCreation, + UpdatedAt: timestamppb.New(*m.UpdatedAt), + DefaultPolicyViolationStrategy: bizPolicyViolationBlockingStrategyToPb(m.BlockOnPolicyViolation), + PolicyAllowedHostnames: m.PoliciesAllowedHostnames, + PreventImplicitWorkflowCreation: m.PreventImplicitWorkflowCreation, + RestrictContractCreationToOrgAdmins: m.RestrictContractCreationToOrgAdmins, } } diff --git a/app/controlplane/internal/service/organization.go b/app/controlplane/internal/service/organization.go index 6a6f62f03..1268c1bfd 100644 --- a/app/controlplane/internal/service/organization.go +++ b/app/controlplane/internal/service/organization.go @@ -89,7 +89,7 @@ func (s *OrganizationService) Update(ctx context.Context, req *pb.OrganizationSe } } - org, err := s.orgUC.Update(ctx, currentUser.ID, req.Name, req.BlockOnPolicyViolation, policiesAllowedHostnames, req.PreventImplicitWorkflowCreation) + org, err := s.orgUC.Update(ctx, currentUser.ID, req.Name, req.BlockOnPolicyViolation, policiesAllowedHostnames, req.PreventImplicitWorkflowCreation, req.RestrictContractCreationToOrgAdmins) if err != nil { return nil, handleUseCaseErr(err, s.log) } diff --git a/app/controlplane/internal/service/workflowcontract.go b/app/controlplane/internal/service/workflowcontract.go index 701c4a4a4..7230118e1 100644 --- a/app/controlplane/internal/service/workflowcontract.go +++ b/app/controlplane/internal/service/workflowcontract.go @@ -34,12 +34,16 @@ type WorkflowContractService struct { *service contractUseCase *biz.WorkflowContractUseCase + orgUseCase *biz.OrganizationUseCase + userUC *biz.UserUseCase } -func NewWorkflowSchemaService(uc *biz.WorkflowContractUseCase, opts ...NewOpt) *WorkflowContractService { +func NewWorkflowSchemaService(uc *biz.WorkflowContractUseCase, orgUC *biz.OrganizationUseCase, userUC *biz.UserUseCase, opts ...NewOpt) *WorkflowContractService { return &WorkflowContractService{ service: newService(opts...), contractUseCase: uc, + orgUseCase: orgUC, + userUC: userUC, } } @@ -109,6 +113,29 @@ func (s *WorkflowContractService) Create(ctx context.Context, req *pb.WorkflowCo return nil, errors.BadRequest("invalid", "project is required") } + // Check organization settings for contract creation restriction + org, err := s.orgUseCase.FindByID(ctx, currentOrg.ID) + if err != nil { + return nil, handleUseCaseErr(err, s.log) + } + + // If setting is enabled, only org admins can create contracts (org-level or project-level) + if org.RestrictContractCreationToOrgAdmins { + currentUser, err := requireCurrentUser(ctx) + if err != nil { + return nil, err + } + + membership, err := s.userUC.MembershipInOrg(ctx, currentUser.ID, currentOrg.Name) + if err != nil { + return nil, handleUseCaseErr(err, s.log) + } + + if !membership.Role.IsAdmin() { + return nil, errors.Forbidden("forbidden", "only organization admins can create contracts") + } + } + // 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() { diff --git a/app/controlplane/pkg/biz/mocks/OrganizationRepo.go b/app/controlplane/pkg/biz/mocks/OrganizationRepo.go index 14d50f9df..56e67e83b 100644 --- a/app/controlplane/pkg/biz/mocks/OrganizationRepo.go +++ b/app/controlplane/pkg/biz/mocks/OrganizationRepo.go @@ -301,8 +301,8 @@ func (_c *OrganizationRepo_FindByName_Call) RunAndReturn(run func(ctx context.Co } // Update provides a mock function for the type OrganizationRepo -func (_mock *OrganizationRepo) Update(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool) (*biz.Organization, error) { - ret := _mock.Called(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation) +func (_mock *OrganizationRepo) Update(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool, preventProjectScopedContracts *bool) (*biz.Organization, error) { + ret := _mock.Called(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation, preventProjectScopedContracts) if len(ret) == 0 { panic("no return value specified for Update") @@ -310,18 +310,18 @@ func (_mock *OrganizationRepo) Update(ctx context.Context, id uuid.UUID, blockOn var r0 *biz.Organization var r1 error - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, *bool, []string, *bool) (*biz.Organization, error)); ok { - return returnFunc(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation) + if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, *bool, []string, *bool, *bool) (*biz.Organization, error)); ok { + return returnFunc(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation, preventProjectScopedContracts) } - if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, *bool, []string, *bool) *biz.Organization); ok { - r0 = returnFunc(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation) + if returnFunc, ok := ret.Get(0).(func(context.Context, uuid.UUID, *bool, []string, *bool, *bool) *biz.Organization); ok { + r0 = returnFunc(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation, preventProjectScopedContracts) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*biz.Organization) } } - if returnFunc, ok := ret.Get(1).(func(context.Context, uuid.UUID, *bool, []string, *bool) error); ok { - r1 = returnFunc(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation) + if returnFunc, ok := ret.Get(1).(func(context.Context, uuid.UUID, *bool, []string, *bool, *bool) error); ok { + r1 = returnFunc(ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation, preventProjectScopedContracts) } else { r1 = ret.Error(1) } @@ -339,11 +339,12 @@ type OrganizationRepo_Update_Call struct { // - blockOnPolicyViolation *bool // - policiesAllowedHostnames []string // - preventImplicitWorkflowCreation *bool -func (_e *OrganizationRepo_Expecter) Update(ctx interface{}, id interface{}, blockOnPolicyViolation interface{}, policiesAllowedHostnames interface{}, preventImplicitWorkflowCreation interface{}) *OrganizationRepo_Update_Call { - return &OrganizationRepo_Update_Call{Call: _e.mock.On("Update", ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation)} +// - preventProjectScopedContracts *bool +func (_e *OrganizationRepo_Expecter) Update(ctx interface{}, id interface{}, blockOnPolicyViolation interface{}, policiesAllowedHostnames interface{}, preventImplicitWorkflowCreation interface{}, preventProjectScopedContracts interface{}) *OrganizationRepo_Update_Call { + return &OrganizationRepo_Update_Call{Call: _e.mock.On("Update", ctx, id, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation, preventProjectScopedContracts)} } -func (_c *OrganizationRepo_Update_Call) Run(run func(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool)) *OrganizationRepo_Update_Call { +func (_c *OrganizationRepo_Update_Call) Run(run func(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool, preventProjectScopedContracts *bool)) *OrganizationRepo_Update_Call { _c.Call.Run(func(args mock.Arguments) { var arg0 context.Context if args[0] != nil { @@ -365,12 +366,17 @@ func (_c *OrganizationRepo_Update_Call) Run(run func(ctx context.Context, id uui if args[4] != nil { arg4 = args[4].(*bool) } + var arg5 *bool + if args[5] != nil { + arg5 = args[5].(*bool) + } run( arg0, arg1, arg2, arg3, arg4, + arg5, ) }) return _c @@ -381,7 +387,7 @@ func (_c *OrganizationRepo_Update_Call) Return(organization *biz.Organization, e return _c } -func (_c *OrganizationRepo_Update_Call) RunAndReturn(run func(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool) (*biz.Organization, error)) *OrganizationRepo_Update_Call { +func (_c *OrganizationRepo_Update_Call) RunAndReturn(run func(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool, preventProjectScopedContracts *bool) (*biz.Organization, error)) *OrganizationRepo_Update_Call { _c.Call.Return(run) return _c } diff --git a/app/controlplane/pkg/biz/organization.go b/app/controlplane/pkg/biz/organization.go index 1787b14cf..3a4bc1ab3 100644 --- a/app/controlplane/pkg/biz/organization.go +++ b/app/controlplane/pkg/biz/organization.go @@ -41,13 +41,15 @@ type Organization struct { PoliciesAllowedHostnames []string // PreventImplicitWorkflowCreation prevents workflows and projects from being created implicitly during attestation init PreventImplicitWorkflowCreation bool + // RestrictContractCreationToOrgAdmins restricts contract creation (org-level and project-level) to only organization admins + RestrictContractCreationToOrgAdmins bool } type OrganizationRepo interface { FindByID(ctx context.Context, orgID uuid.UUID) (*Organization, error) FindByName(ctx context.Context, name string) (*Organization, error) Create(ctx context.Context, name string) (*Organization, error) - Update(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool) (*Organization, error) + Update(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool, restrictContractCreationToOrgAdmins *bool) (*Organization, error) Delete(ctx context.Context, ID uuid.UUID) error } @@ -187,7 +189,7 @@ func (uc *OrganizationUseCase) doCreate(ctx context.Context, name string, opts . return org, nil } -func (uc *OrganizationUseCase) Update(ctx context.Context, userID, orgName string, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool) (*Organization, error) { +func (uc *OrganizationUseCase) Update(ctx context.Context, userID, orgName string, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool, restrictContractCreationToOrgAdmins *bool) (*Organization, error) { userUUID, err := uuid.Parse(userID) if err != nil { return nil, NewErrInvalidUUID(err) @@ -207,7 +209,7 @@ func (uc *OrganizationUseCase) Update(ctx context.Context, userID, orgName strin } // Perform the update - org, err := uc.orgRepo.Update(ctx, orgUUID, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation) + org, err := uc.orgRepo.Update(ctx, orgUUID, blockOnPolicyViolation, policiesAllowedHostnames, preventImplicitWorkflowCreation, restrictContractCreationToOrgAdmins) if err != nil { return nil, fmt.Errorf("failed to update organization: %w", err) } else if org == nil { diff --git a/app/controlplane/pkg/biz/organization_integration_test.go b/app/controlplane/pkg/biz/organization_integration_test.go index 2337df5b3..801a86fb2 100644 --- a/app/controlplane/pkg/biz/organization_integration_test.go +++ b/app/controlplane/pkg/biz/organization_integration_test.go @@ -118,7 +118,7 @@ func (s *OrgIntegrationTestSuite) TestUpdate() { s.Run("org non existent", func() { // org not found - _, err := s.Organization.Update(ctx, s.user.ID, uuid.NewString(), nil, nil, nil) + _, err := s.Organization.Update(ctx, s.user.ID, uuid.NewString(), nil, nil, nil, nil) s.Error(err) s.True(biz.IsNotFound(err)) }) @@ -126,35 +126,35 @@ func (s *OrgIntegrationTestSuite) TestUpdate() { s.Run("org not accessible to user", func() { org2, err := s.Organization.CreateWithRandomName(ctx) require.NoError(s.T(), err) - _, err = s.Organization.Update(ctx, s.user.ID, org2.Name, nil, nil, nil) + _, err = s.Organization.Update(ctx, s.user.ID, org2.Name, nil, nil, nil, nil) s.Error(err) s.True(biz.IsNotFound(err)) }) s.Run("valid block on policy violation update", func() { - got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, toPtrBool(true), nil, nil) + got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, toPtrBool(true), nil, nil, nil) s.NoError(err) s.True(got.BlockOnPolicyViolation) }) s.Run("valid policy allowed hostnames update", func() { - got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, []string{"foo.com", "bar.com"}, nil) + got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, []string{"foo.com", "bar.com"}, nil, nil) s.NoError(err) s.Equal([]string{"foo.com", "bar.com"}, got.PoliciesAllowedHostnames) }) s.Run("clear policy allowed hostnames", func() { - got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, []string{}, nil) + got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, []string{}, nil, nil) s.NoError(err) s.Equal([]string{}, got.PoliciesAllowedHostnames) }) s.Run("but not passing a value doesn't clear the hostnames value", func() { - got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, []string{"foo.com", "bar.com"}, nil) + got, err := s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, []string{"foo.com", "bar.com"}, nil, nil) s.NoError(err) s.Equal([]string{"foo.com", "bar.com"}, got.PoliciesAllowedHostnames) - got, err = s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, nil, nil) + got, err = s.Organization.Update(ctx, s.user.ID, s.org.Name, nil, nil, nil, nil) s.NoError(err) s.Equal([]string{"foo.com", "bar.com"}, got.PoliciesAllowedHostnames) }) diff --git a/app/controlplane/pkg/biz/workflow.go b/app/controlplane/pkg/biz/workflow.go index 60d53b8dc..c11d2a257 100644 --- a/app/controlplane/pkg/biz/workflow.go +++ b/app/controlplane/pkg/biz/workflow.go @@ -81,6 +81,10 @@ type WorkflowCreateOpts struct { Owner *uuid.UUID // ImplicitCreation indicates whether this workflow is being created implicitly via attestation init ImplicitCreation bool + // UserIsOrgAdmin indicates whether the current user is an organization admin + UserIsOrgAdmin bool + // OrgRestrictContractCreationToAdmins is the organization's setting for restricting contract creation + OrgRestrictContractCreationToAdmins bool } type WorkflowUpdateOpts struct { diff --git a/app/controlplane/pkg/biz/workflow_integration_test.go b/app/controlplane/pkg/biz/workflow_integration_test.go index c58aa648a..5bc303f00 100644 --- a/app/controlplane/pkg/biz/workflow_integration_test.go +++ b/app/controlplane/pkg/biz/workflow_integration_test.go @@ -187,7 +187,7 @@ func (s *workflowIntegrationTestSuite) TestCreate() { // Enable implicit workflow creation prevention for testing orgID, _ := uuid.Parse(s.org.ID) - _, err = s.Repos.OrganizationRepo.Update(ctx, orgID, nil, nil, toPtrBool(true)) + _, err = s.Repos.OrganizationRepo.Update(ctx, orgID, nil, nil, toPtrBool(true), nil) s.Require().NoError(err) for _, tc := range testCases { diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20251212115308.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20251212115308.sql new file mode 100644 index 000000000..6e6edc616 --- /dev/null +++ b/app/controlplane/pkg/data/ent/migrate/migrations/20251212115308.sql @@ -0,0 +1,2 @@ +-- Modify "organizations" table +ALTER TABLE "organizations" ADD COLUMN "restrict_contract_creation_to_org_admins" boolean NOT NULL DEFAULT false; diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index 527c94030..77f8d42e6 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:2JyaUYFWieGKl87rW890mAXAE3XJrL4K4/C51Nl3qOk= +h1:QYIHH5zsR/0t1wr7+F9jSRgXWFVAaYgSGomoG82EARI= 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -120,3 +120,4 @@ h1:2JyaUYFWieGKl87rW890mAXAE3XJrL4K4/C51Nl3qOk= 20251107233855.sql h1:fNK+hRlqzlM4qxKR7SPMEtbrYSAJfau6bKm1jecRDpE= 20251111162946.sql h1:oNke93PdAreUH6F5AD5FE6uI6riJpE4KPb77LXTeuRU= 20251114174059.sql h1:f/wB/OlhZxIc9AVCxTNu4dFmPd1T3sCY0nS8Zb9ZS9Q= +20251212115308.sql h1:CmwHDA9X91++2dnThzk57++5sBDAGw2IQnHzO3/bRlk= diff --git a/app/controlplane/pkg/data/ent/migrate/schema.go b/app/controlplane/pkg/data/ent/migrate/schema.go index 1a564b7dc..d949d1c79 100644 --- a/app/controlplane/pkg/data/ent/migrate/schema.go +++ b/app/controlplane/pkg/data/ent/migrate/schema.go @@ -423,6 +423,7 @@ var ( {Name: "block_on_policy_violation", Type: field.TypeBool, Default: false}, {Name: "policies_allowed_hostnames", Type: field.TypeJSON, Nullable: true}, {Name: "prevent_implicit_workflow_creation", Type: field.TypeBool, Default: false}, + {Name: "restrict_contract_creation_to_org_admins", Type: field.TypeBool, Default: false}, } // OrganizationsTable holds the schema information for the "organizations" table. OrganizationsTable = &schema.Table{ diff --git a/app/controlplane/pkg/data/ent/mutation.go b/app/controlplane/pkg/data/ent/mutation.go index dd2fe0581..d4c0c8a00 100644 --- a/app/controlplane/pkg/data/ent/mutation.go +++ b/app/controlplane/pkg/data/ent/mutation.go @@ -8696,45 +8696,46 @@ func (m *OrgInvitationMutation) ResetEdge(name string) error { // OrganizationMutation represents an operation that mutates the Organization nodes in the graph. type OrganizationMutation struct { config - op Op - typ string - id *uuid.UUID - name *string - created_at *time.Time - updated_at *time.Time - deleted_at *time.Time - block_on_policy_violation *bool - policies_allowed_hostnames *[]string - appendpolicies_allowed_hostnames []string - prevent_implicit_workflow_creation *bool - clearedFields map[string]struct{} - memberships map[uuid.UUID]struct{} - removedmemberships map[uuid.UUID]struct{} - clearedmemberships bool - workflow_contracts map[uuid.UUID]struct{} - removedworkflow_contracts map[uuid.UUID]struct{} - clearedworkflow_contracts bool - workflows map[uuid.UUID]struct{} - removedworkflows map[uuid.UUID]struct{} - clearedworkflows bool - cas_backends map[uuid.UUID]struct{} - removedcas_backends map[uuid.UUID]struct{} - clearedcas_backends bool - integrations map[uuid.UUID]struct{} - removedintegrations map[uuid.UUID]struct{} - clearedintegrations bool - api_tokens map[uuid.UUID]struct{} - removedapi_tokens map[uuid.UUID]struct{} - clearedapi_tokens bool - projects map[uuid.UUID]struct{} - removedprojects map[uuid.UUID]struct{} - clearedprojects bool - groups map[uuid.UUID]struct{} - removedgroups map[uuid.UUID]struct{} - clearedgroups bool - done bool - oldValue func(context.Context) (*Organization, error) - predicates []predicate.Organization + op Op + typ string + id *uuid.UUID + name *string + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + block_on_policy_violation *bool + policies_allowed_hostnames *[]string + appendpolicies_allowed_hostnames []string + prevent_implicit_workflow_creation *bool + restrict_contract_creation_to_org_admins *bool + clearedFields map[string]struct{} + memberships map[uuid.UUID]struct{} + removedmemberships map[uuid.UUID]struct{} + clearedmemberships bool + workflow_contracts map[uuid.UUID]struct{} + removedworkflow_contracts map[uuid.UUID]struct{} + clearedworkflow_contracts bool + workflows map[uuid.UUID]struct{} + removedworkflows map[uuid.UUID]struct{} + clearedworkflows bool + cas_backends map[uuid.UUID]struct{} + removedcas_backends map[uuid.UUID]struct{} + clearedcas_backends bool + integrations map[uuid.UUID]struct{} + removedintegrations map[uuid.UUID]struct{} + clearedintegrations bool + api_tokens map[uuid.UUID]struct{} + removedapi_tokens map[uuid.UUID]struct{} + clearedapi_tokens bool + projects map[uuid.UUID]struct{} + removedprojects map[uuid.UUID]struct{} + clearedprojects bool + groups map[uuid.UUID]struct{} + removedgroups map[uuid.UUID]struct{} + clearedgroups bool + done bool + oldValue func(context.Context) (*Organization, error) + predicates []predicate.Organization } var _ ent.Mutation = (*OrganizationMutation)(nil) @@ -9135,6 +9136,42 @@ func (m *OrganizationMutation) ResetPreventImplicitWorkflowCreation() { m.prevent_implicit_workflow_creation = nil } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (m *OrganizationMutation) SetRestrictContractCreationToOrgAdmins(b bool) { + m.restrict_contract_creation_to_org_admins = &b +} + +// RestrictContractCreationToOrgAdmins returns the value of the "restrict_contract_creation_to_org_admins" field in the mutation. +func (m *OrganizationMutation) RestrictContractCreationToOrgAdmins() (r bool, exists bool) { + v := m.restrict_contract_creation_to_org_admins + if v == nil { + return + } + return *v, true +} + +// OldRestrictContractCreationToOrgAdmins returns the old "restrict_contract_creation_to_org_admins" field's value of the Organization entity. +// If the Organization 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 *OrganizationMutation) OldRestrictContractCreationToOrgAdmins(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldRestrictContractCreationToOrgAdmins is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldRestrictContractCreationToOrgAdmins requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldRestrictContractCreationToOrgAdmins: %w", err) + } + return oldValue.RestrictContractCreationToOrgAdmins, nil +} + +// ResetRestrictContractCreationToOrgAdmins resets all changes to the "restrict_contract_creation_to_org_admins" field. +func (m *OrganizationMutation) ResetRestrictContractCreationToOrgAdmins() { + m.restrict_contract_creation_to_org_admins = nil +} + // AddMembershipIDs adds the "memberships" edge to the Membership entity by ids. func (m *OrganizationMutation) AddMembershipIDs(ids ...uuid.UUID) { if m.memberships == nil { @@ -9601,7 +9638,7 @@ func (m *OrganizationMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *OrganizationMutation) Fields() []string { - fields := make([]string, 0, 7) + fields := make([]string, 0, 8) if m.name != nil { fields = append(fields, organization.FieldName) } @@ -9623,6 +9660,9 @@ func (m *OrganizationMutation) Fields() []string { if m.prevent_implicit_workflow_creation != nil { fields = append(fields, organization.FieldPreventImplicitWorkflowCreation) } + if m.restrict_contract_creation_to_org_admins != nil { + fields = append(fields, organization.FieldRestrictContractCreationToOrgAdmins) + } return fields } @@ -9645,6 +9685,8 @@ func (m *OrganizationMutation) Field(name string) (ent.Value, bool) { return m.PoliciesAllowedHostnames() case organization.FieldPreventImplicitWorkflowCreation: return m.PreventImplicitWorkflowCreation() + case organization.FieldRestrictContractCreationToOrgAdmins: + return m.RestrictContractCreationToOrgAdmins() } return nil, false } @@ -9668,6 +9710,8 @@ func (m *OrganizationMutation) OldField(ctx context.Context, name string) (ent.V return m.OldPoliciesAllowedHostnames(ctx) case organization.FieldPreventImplicitWorkflowCreation: return m.OldPreventImplicitWorkflowCreation(ctx) + case organization.FieldRestrictContractCreationToOrgAdmins: + return m.OldRestrictContractCreationToOrgAdmins(ctx) } return nil, fmt.Errorf("unknown Organization field %s", name) } @@ -9726,6 +9770,13 @@ func (m *OrganizationMutation) SetField(name string, value ent.Value) error { } m.SetPreventImplicitWorkflowCreation(v) return nil + case organization.FieldRestrictContractCreationToOrgAdmins: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetRestrictContractCreationToOrgAdmins(v) + return nil } return fmt.Errorf("unknown Organization field %s", name) } @@ -9811,6 +9862,9 @@ func (m *OrganizationMutation) ResetField(name string) error { case organization.FieldPreventImplicitWorkflowCreation: m.ResetPreventImplicitWorkflowCreation() return nil + case organization.FieldRestrictContractCreationToOrgAdmins: + m.ResetRestrictContractCreationToOrgAdmins() + return nil } return fmt.Errorf("unknown Organization field %s", name) } diff --git a/app/controlplane/pkg/data/ent/organization.go b/app/controlplane/pkg/data/ent/organization.go index 2e17f6bfe..5a2b9fb55 100644 --- a/app/controlplane/pkg/data/ent/organization.go +++ b/app/controlplane/pkg/data/ent/organization.go @@ -33,6 +33,8 @@ type Organization struct { PoliciesAllowedHostnames []string `json:"policies_allowed_hostnames,omitempty"` // PreventImplicitWorkflowCreation holds the value of the "prevent_implicit_workflow_creation" field. PreventImplicitWorkflowCreation bool `json:"prevent_implicit_workflow_creation,omitempty"` + // RestrictContractCreationToOrgAdmins holds the value of the "restrict_contract_creation_to_org_admins" field. + RestrictContractCreationToOrgAdmins bool `json:"restrict_contract_creation_to_org_admins,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the OrganizationQuery when eager-loading is set. Edges OrganizationEdges `json:"edges"` @@ -141,7 +143,7 @@ func (*Organization) scanValues(columns []string) ([]any, error) { switch columns[i] { case organization.FieldPoliciesAllowedHostnames: values[i] = new([]byte) - case organization.FieldBlockOnPolicyViolation, organization.FieldPreventImplicitWorkflowCreation: + case organization.FieldBlockOnPolicyViolation, organization.FieldPreventImplicitWorkflowCreation, organization.FieldRestrictContractCreationToOrgAdmins: values[i] = new(sql.NullBool) case organization.FieldName: values[i] = new(sql.NullString) @@ -214,6 +216,12 @@ func (o *Organization) assignValues(columns []string, values []any) error { } else if value.Valid { o.PreventImplicitWorkflowCreation = value.Bool } + case organization.FieldRestrictContractCreationToOrgAdmins: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field restrict_contract_creation_to_org_admins", values[i]) + } else if value.Valid { + o.RestrictContractCreationToOrgAdmins = value.Bool + } default: o.selectValues.Set(columns[i], values[i]) } @@ -310,6 +318,9 @@ func (o *Organization) String() string { builder.WriteString(", ") builder.WriteString("prevent_implicit_workflow_creation=") builder.WriteString(fmt.Sprintf("%v", o.PreventImplicitWorkflowCreation)) + builder.WriteString(", ") + builder.WriteString("restrict_contract_creation_to_org_admins=") + builder.WriteString(fmt.Sprintf("%v", o.RestrictContractCreationToOrgAdmins)) builder.WriteByte(')') return builder.String() } diff --git a/app/controlplane/pkg/data/ent/organization/organization.go b/app/controlplane/pkg/data/ent/organization/organization.go index f948fc628..603667a7a 100644 --- a/app/controlplane/pkg/data/ent/organization/organization.go +++ b/app/controlplane/pkg/data/ent/organization/organization.go @@ -29,6 +29,8 @@ const ( FieldPoliciesAllowedHostnames = "policies_allowed_hostnames" // FieldPreventImplicitWorkflowCreation holds the string denoting the prevent_implicit_workflow_creation field in the database. FieldPreventImplicitWorkflowCreation = "prevent_implicit_workflow_creation" + // FieldRestrictContractCreationToOrgAdmins holds the string denoting the restrict_contract_creation_to_org_admins field in the database. + FieldRestrictContractCreationToOrgAdmins = "restrict_contract_creation_to_org_admins" // EdgeMemberships holds the string denoting the memberships edge name in mutations. EdgeMemberships = "memberships" // EdgeWorkflowContracts holds the string denoting the workflow_contracts edge name in mutations. @@ -115,6 +117,7 @@ var Columns = []string{ FieldBlockOnPolicyViolation, FieldPoliciesAllowedHostnames, FieldPreventImplicitWorkflowCreation, + FieldRestrictContractCreationToOrgAdmins, } // ValidColumn reports if the column name is valid (part of the table columns). @@ -136,6 +139,8 @@ var ( DefaultBlockOnPolicyViolation bool // DefaultPreventImplicitWorkflowCreation holds the default value on creation for the "prevent_implicit_workflow_creation" field. DefaultPreventImplicitWorkflowCreation bool + // DefaultRestrictContractCreationToOrgAdmins holds the default value on creation for the "restrict_contract_creation_to_org_admins" field. + DefaultRestrictContractCreationToOrgAdmins bool // DefaultID holds the default value on creation for the "id" field. DefaultID func() uuid.UUID ) @@ -178,6 +183,11 @@ func ByPreventImplicitWorkflowCreation(opts ...sql.OrderTermOption) OrderOption return sql.OrderByField(FieldPreventImplicitWorkflowCreation, opts...).ToFunc() } +// ByRestrictContractCreationToOrgAdmins orders the results by the restrict_contract_creation_to_org_admins field. +func ByRestrictContractCreationToOrgAdmins(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldRestrictContractCreationToOrgAdmins, opts...).ToFunc() +} + // ByMembershipsCount orders the results by memberships count. func ByMembershipsCount(opts ...sql.OrderTermOption) OrderOption { return func(s *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/organization/where.go b/app/controlplane/pkg/data/ent/organization/where.go index 566974961..022a28f8e 100644 --- a/app/controlplane/pkg/data/ent/organization/where.go +++ b/app/controlplane/pkg/data/ent/organization/where.go @@ -86,6 +86,11 @@ func PreventImplicitWorkflowCreation(v bool) predicate.Organization { return predicate.Organization(sql.FieldEQ(FieldPreventImplicitWorkflowCreation, v)) } +// RestrictContractCreationToOrgAdmins applies equality check predicate on the "restrict_contract_creation_to_org_admins" field. It's identical to RestrictContractCreationToOrgAdminsEQ. +func RestrictContractCreationToOrgAdmins(v bool) predicate.Organization { + return predicate.Organization(sql.FieldEQ(FieldRestrictContractCreationToOrgAdmins, v)) +} + // NameEQ applies the EQ predicate on the "name" field. func NameEQ(v string) predicate.Organization { return predicate.Organization(sql.FieldEQ(FieldName, v)) @@ -311,6 +316,16 @@ func PreventImplicitWorkflowCreationNEQ(v bool) predicate.Organization { return predicate.Organization(sql.FieldNEQ(FieldPreventImplicitWorkflowCreation, v)) } +// RestrictContractCreationToOrgAdminsEQ applies the EQ predicate on the "restrict_contract_creation_to_org_admins" field. +func RestrictContractCreationToOrgAdminsEQ(v bool) predicate.Organization { + return predicate.Organization(sql.FieldEQ(FieldRestrictContractCreationToOrgAdmins, v)) +} + +// RestrictContractCreationToOrgAdminsNEQ applies the NEQ predicate on the "restrict_contract_creation_to_org_admins" field. +func RestrictContractCreationToOrgAdminsNEQ(v bool) predicate.Organization { + return predicate.Organization(sql.FieldNEQ(FieldRestrictContractCreationToOrgAdmins, v)) +} + // HasMemberships applies the HasEdge predicate on the "memberships" edge. func HasMemberships() predicate.Organization { return predicate.Organization(func(s *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/organization_create.go b/app/controlplane/pkg/data/ent/organization_create.go index db0c7283c..a12b0133d 100644 --- a/app/controlplane/pkg/data/ent/organization_create.go +++ b/app/controlplane/pkg/data/ent/organization_create.go @@ -114,6 +114,20 @@ func (oc *OrganizationCreate) SetNillablePreventImplicitWorkflowCreation(b *bool return oc } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (oc *OrganizationCreate) SetRestrictContractCreationToOrgAdmins(b bool) *OrganizationCreate { + oc.mutation.SetRestrictContractCreationToOrgAdmins(b) + return oc +} + +// SetNillableRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field if the given value is not nil. +func (oc *OrganizationCreate) SetNillableRestrictContractCreationToOrgAdmins(b *bool) *OrganizationCreate { + if b != nil { + oc.SetRestrictContractCreationToOrgAdmins(*b) + } + return oc +} + // SetID sets the "id" field. func (oc *OrganizationCreate) SetID(u uuid.UUID) *OrganizationCreate { oc.mutation.SetID(u) @@ -299,6 +313,10 @@ func (oc *OrganizationCreate) defaults() { v := organization.DefaultPreventImplicitWorkflowCreation oc.mutation.SetPreventImplicitWorkflowCreation(v) } + if _, ok := oc.mutation.RestrictContractCreationToOrgAdmins(); !ok { + v := organization.DefaultRestrictContractCreationToOrgAdmins + oc.mutation.SetRestrictContractCreationToOrgAdmins(v) + } if _, ok := oc.mutation.ID(); !ok { v := organization.DefaultID() oc.mutation.SetID(v) @@ -322,6 +340,9 @@ func (oc *OrganizationCreate) check() error { if _, ok := oc.mutation.PreventImplicitWorkflowCreation(); !ok { return &ValidationError{Name: "prevent_implicit_workflow_creation", err: errors.New(`ent: missing required field "Organization.prevent_implicit_workflow_creation"`)} } + if _, ok := oc.mutation.RestrictContractCreationToOrgAdmins(); !ok { + return &ValidationError{Name: "restrict_contract_creation_to_org_admins", err: errors.New(`ent: missing required field "Organization.restrict_contract_creation_to_org_admins"`)} + } return nil } @@ -386,6 +407,10 @@ func (oc *OrganizationCreate) createSpec() (*Organization, *sqlgraph.CreateSpec) _spec.SetField(organization.FieldPreventImplicitWorkflowCreation, field.TypeBool, value) _node.PreventImplicitWorkflowCreation = value } + if value, ok := oc.mutation.RestrictContractCreationToOrgAdmins(); ok { + _spec.SetField(organization.FieldRestrictContractCreationToOrgAdmins, field.TypeBool, value) + _node.RestrictContractCreationToOrgAdmins = value + } if nodes := oc.mutation.MembershipsIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -650,6 +675,18 @@ func (u *OrganizationUpsert) UpdatePreventImplicitWorkflowCreation() *Organizati return u } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (u *OrganizationUpsert) SetRestrictContractCreationToOrgAdmins(v bool) *OrganizationUpsert { + u.Set(organization.FieldRestrictContractCreationToOrgAdmins, v) + return u +} + +// UpdateRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field to the value that was provided on create. +func (u *OrganizationUpsert) UpdateRestrictContractCreationToOrgAdmins() *OrganizationUpsert { + u.SetExcluded(organization.FieldRestrictContractCreationToOrgAdmins) + 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: // @@ -799,6 +836,20 @@ func (u *OrganizationUpsertOne) UpdatePreventImplicitWorkflowCreation() *Organiz }) } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (u *OrganizationUpsertOne) SetRestrictContractCreationToOrgAdmins(v bool) *OrganizationUpsertOne { + return u.Update(func(s *OrganizationUpsert) { + s.SetRestrictContractCreationToOrgAdmins(v) + }) +} + +// UpdateRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field to the value that was provided on create. +func (u *OrganizationUpsertOne) UpdateRestrictContractCreationToOrgAdmins() *OrganizationUpsertOne { + return u.Update(func(s *OrganizationUpsert) { + s.UpdateRestrictContractCreationToOrgAdmins() + }) +} + // Exec executes the query. func (u *OrganizationUpsertOne) Exec(ctx context.Context) error { if len(u.create.conflict) == 0 { @@ -1115,6 +1166,20 @@ func (u *OrganizationUpsertBulk) UpdatePreventImplicitWorkflowCreation() *Organi }) } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (u *OrganizationUpsertBulk) SetRestrictContractCreationToOrgAdmins(v bool) *OrganizationUpsertBulk { + return u.Update(func(s *OrganizationUpsert) { + s.SetRestrictContractCreationToOrgAdmins(v) + }) +} + +// UpdateRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field to the value that was provided on create. +func (u *OrganizationUpsertBulk) UpdateRestrictContractCreationToOrgAdmins() *OrganizationUpsertBulk { + return u.Update(func(s *OrganizationUpsert) { + s.UpdateRestrictContractCreationToOrgAdmins() + }) +} + // Exec executes the query. func (u *OrganizationUpsertBulk) Exec(ctx context.Context) error { if u.create.err != nil { diff --git a/app/controlplane/pkg/data/ent/organization_update.go b/app/controlplane/pkg/data/ent/organization_update.go index a6ae9efab..32ae1214c 100644 --- a/app/controlplane/pkg/data/ent/organization_update.go +++ b/app/controlplane/pkg/data/ent/organization_update.go @@ -133,6 +133,20 @@ func (ou *OrganizationUpdate) SetNillablePreventImplicitWorkflowCreation(b *bool return ou } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (ou *OrganizationUpdate) SetRestrictContractCreationToOrgAdmins(b bool) *OrganizationUpdate { + ou.mutation.SetRestrictContractCreationToOrgAdmins(b) + return ou +} + +// SetNillableRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field if the given value is not nil. +func (ou *OrganizationUpdate) SetNillableRestrictContractCreationToOrgAdmins(b *bool) *OrganizationUpdate { + if b != nil { + ou.SetRestrictContractCreationToOrgAdmins(*b) + } + return ou +} + // AddMembershipIDs adds the "memberships" edge to the Membership entity by IDs. func (ou *OrganizationUpdate) AddMembershipIDs(ids ...uuid.UUID) *OrganizationUpdate { ou.mutation.AddMembershipIDs(ids...) @@ -497,6 +511,9 @@ func (ou *OrganizationUpdate) sqlSave(ctx context.Context) (n int, err error) { if value, ok := ou.mutation.PreventImplicitWorkflowCreation(); ok { _spec.SetField(organization.FieldPreventImplicitWorkflowCreation, field.TypeBool, value) } + if value, ok := ou.mutation.RestrictContractCreationToOrgAdmins(); ok { + _spec.SetField(organization.FieldRestrictContractCreationToOrgAdmins, field.TypeBool, value) + } if ou.mutation.MembershipsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -973,6 +990,20 @@ func (ouo *OrganizationUpdateOne) SetNillablePreventImplicitWorkflowCreation(b * return ouo } +// SetRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field. +func (ouo *OrganizationUpdateOne) SetRestrictContractCreationToOrgAdmins(b bool) *OrganizationUpdateOne { + ouo.mutation.SetRestrictContractCreationToOrgAdmins(b) + return ouo +} + +// SetNillableRestrictContractCreationToOrgAdmins sets the "restrict_contract_creation_to_org_admins" field if the given value is not nil. +func (ouo *OrganizationUpdateOne) SetNillableRestrictContractCreationToOrgAdmins(b *bool) *OrganizationUpdateOne { + if b != nil { + ouo.SetRestrictContractCreationToOrgAdmins(*b) + } + return ouo +} + // AddMembershipIDs adds the "memberships" edge to the Membership entity by IDs. func (ouo *OrganizationUpdateOne) AddMembershipIDs(ids ...uuid.UUID) *OrganizationUpdateOne { ouo.mutation.AddMembershipIDs(ids...) @@ -1367,6 +1398,9 @@ func (ouo *OrganizationUpdateOne) sqlSave(ctx context.Context) (_node *Organizat if value, ok := ouo.mutation.PreventImplicitWorkflowCreation(); ok { _spec.SetField(organization.FieldPreventImplicitWorkflowCreation, field.TypeBool, value) } + if value, ok := ouo.mutation.RestrictContractCreationToOrgAdmins(); ok { + _spec.SetField(organization.FieldRestrictContractCreationToOrgAdmins, field.TypeBool, value) + } if ouo.mutation.MembershipsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, diff --git a/app/controlplane/pkg/data/ent/runtime.go b/app/controlplane/pkg/data/ent/runtime.go index b5548739f..d0cae38ce 100644 --- a/app/controlplane/pkg/data/ent/runtime.go +++ b/app/controlplane/pkg/data/ent/runtime.go @@ -209,6 +209,10 @@ func init() { organizationDescPreventImplicitWorkflowCreation := organizationFields[7].Descriptor() // organization.DefaultPreventImplicitWorkflowCreation holds the default value on creation for the prevent_implicit_workflow_creation field. organization.DefaultPreventImplicitWorkflowCreation = organizationDescPreventImplicitWorkflowCreation.Default.(bool) + // organizationDescRestrictContractCreationToOrgAdmins is the schema descriptor for restrict_contract_creation_to_org_admins field. + organizationDescRestrictContractCreationToOrgAdmins := organizationFields[8].Descriptor() + // organization.DefaultRestrictContractCreationToOrgAdmins holds the default value on creation for the restrict_contract_creation_to_org_admins field. + organization.DefaultRestrictContractCreationToOrgAdmins = organizationDescRestrictContractCreationToOrgAdmins.Default.(bool) // organizationDescID is the schema descriptor for id field. organizationDescID := organizationFields[0].Descriptor() // organization.DefaultID holds the default value on creation for the id field. diff --git a/app/controlplane/pkg/data/ent/schema/organization.go b/app/controlplane/pkg/data/ent/schema/organization.go index b422f9988..0c2367a4e 100644 --- a/app/controlplane/pkg/data/ent/schema/organization.go +++ b/app/controlplane/pkg/data/ent/schema/organization.go @@ -53,6 +53,8 @@ func (Organization) Fields() []ent.Field { field.Strings("policies_allowed_hostnames").Optional(), // prevent workflows and projects from being created implicitly during attestation init field.Bool("prevent_implicit_workflow_creation").Default(false), + // restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins + field.Bool("restrict_contract_creation_to_org_admins").Default(false), } } diff --git a/app/controlplane/pkg/data/organization.go b/app/controlplane/pkg/data/organization.go index 75b921352..6c349d1d6 100644 --- a/app/controlplane/pkg/data/organization.go +++ b/app/controlplane/pkg/data/organization.go @@ -77,11 +77,12 @@ func (r *OrganizationRepo) FindByName(ctx context.Context, name string) (*biz.Or return entOrgToBizOrg(org), nil } -func (r *OrganizationRepo) Update(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool) (*biz.Organization, error) { +func (r *OrganizationRepo) Update(ctx context.Context, id uuid.UUID, blockOnPolicyViolation *bool, policiesAllowedHostnames []string, preventImplicitWorkflowCreation *bool, restrictContractCreationToOrgAdmins *bool) (*biz.Organization, error) { opts := r.data.DB.Organization.UpdateOneID(id). Where(organization.DeletedAtIsNil()). SetNillableBlockOnPolicyViolation(blockOnPolicyViolation). SetNillablePreventImplicitWorkflowCreation(preventImplicitWorkflowCreation). + SetNillableRestrictContractCreationToOrgAdmins(restrictContractCreationToOrgAdmins). SetUpdatedAt(time.Now()) if policiesAllowedHostnames != nil { @@ -108,10 +109,11 @@ func (r *OrganizationRepo) Delete(ctx context.Context, id uuid.UUID) error { func entOrgToBizOrg(eu *ent.Organization) *biz.Organization { return &biz.Organization{ Name: eu.Name, ID: eu.ID.String(), - CreatedAt: toTimePtr(eu.CreatedAt), - UpdatedAt: toTimePtr(eu.UpdatedAt), - BlockOnPolicyViolation: eu.BlockOnPolicyViolation, - PoliciesAllowedHostnames: eu.PoliciesAllowedHostnames, - PreventImplicitWorkflowCreation: eu.PreventImplicitWorkflowCreation, + CreatedAt: toTimePtr(eu.CreatedAt), + UpdatedAt: toTimePtr(eu.UpdatedAt), + BlockOnPolicyViolation: eu.BlockOnPolicyViolation, + PoliciesAllowedHostnames: eu.PoliciesAllowedHostnames, + PreventImplicitWorkflowCreation: eu.PreventImplicitWorkflowCreation, + RestrictContractCreationToOrgAdmins: eu.RestrictContractCreationToOrgAdmins, } } diff --git a/app/controlplane/pkg/data/workflow.go b/app/controlplane/pkg/data/workflow.go index 91c371d68..548c5f643 100644 --- a/app/controlplane/pkg/data/workflow.go +++ b/app/controlplane/pkg/data/workflow.go @@ -118,6 +118,11 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts) contract, err := contractInOrg(ctx, r.data.DB, orgUUID, nil, &defaultContractName) if err != nil { if ent.IsNotFound(err) { + // Check if contract creation is restricted to org admins + if opts.OrgRestrictContractCreationToAdmins && !opts.UserIsOrgAdmin { + return biz.NewErrUnauthorizedStr("only organization admins can create contracts") + } + // Create a new contract associated with the workflow contract, _, err = r.contractRepo.addCreateToTx(ctx, tx, &biz.ContractCreateOpts{ OrgID: orgUUID,