feat(v3alpha): write actions (#8225)

# Which Problems Are Solved

The current v3alpha actions APIs don't exactly adhere to the [new
resources API
design](https://zitadel.com/docs/apis/v3#standard-resources).

# How the Problems Are Solved

- **Breaking**: The current v3alpha actions APIs are removed. This is
breaking.
- **Resource Namespace**: New v3alpha actions APIs for targets and
executions are added under the namespace /resources.
- **Feature Flag**: New v3alpha actions APIs still have to be activated
using the actions feature flag
- **Reduced Executions Overhead**: Executions are managed similar to
settings according to the new API design: an empty list of targets
basically makes an execution a Noop. So a single method, SetExecution is
enough to cover all use cases. Noop executions are not returned in
future search requests.
- **Compatibility**: The executions created with previous v3alpha APIs
are still available to be managed with the new executions API.

# Additional Changes

- Removed integration tests which test executions but rely on readable
targets. They are added again with #8169

# Additional Context

Closes #8168
This commit is contained in:
Elio Bischof
2024-07-31 14:42:12 +02:00
committed by GitHub
parent a1d24353db
commit cc3ec1e2a7
50 changed files with 2822 additions and 5570 deletions

View File

@@ -1,612 +0,0 @@
syntax = "proto3";
package zitadel.action.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/action/v3alpha/target.proto";
import "zitadel/action/v3alpha/execution.proto";
import "zitadel/action/v3alpha/query.proto";
import "zitadel/object/v2/object.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha;action";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Action Service";
version: "3.0-preview";
description: "This API is intended to manage custom executions (previously known as actions) in a ZITADEL instance. This project is in preview state. It can AND will continue breaking until the services provide the same functionality as the current actions.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
consumes: "application/grpc";
produces: "application/json";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$CUSTOM-DOMAIN";
base_path: "/";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
service ActionService {
// Create a target
//
// Create a new target, which can be used in executions.
rpc CreateTarget (CreateTargetRequest) returns (CreateTargetResponse) {
option (google.api.http) = {
post: "/v3alpha/targets"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.target.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "201";
value: {
description: "Target successfully created";
schema: {
json_schema: {
ref: "#/definitions/v3alphaCreateTargetResponse";
}
}
};
};
};
}
// Update a target
//
// Update an existing target.
rpc UpdateTarget (UpdateTargetRequest) returns (UpdateTargetResponse) {
option (google.api.http) = {
put: "/v3alpha/targets/{target_id}"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.target.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully updated";
};
};
};
}
// Delete a target
//
// Delete an existing target. This will remove it from any configured execution as well.
rpc DeleteTarget (DeleteTargetRequest) returns (DeleteTargetResponse) {
option (google.api.http) = {
delete: "/v3alpha/targets/{target_id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.target.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully deleted";
};
};
};
}
// List targets
//
// List all matching targets. By default, we will return all targets of your instance.
// Make sure to include a limit and sorting for pagination.
rpc ListTargets (ListTargetsRequest) returns (ListTargetsResponse) {
option (google.api.http) = {
post: "/v3alpha/targets/search"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.target.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all targets matching the query";
};
};
responses: {
key: "400";
value: {
description: "invalid list query";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
// Target by ID
//
// Returns the target identified by the requested ID.
rpc GetTargetByID (GetTargetByIDRequest) returns (GetTargetByIDResponse) {
option (google.api.http) = {
get: "/v3alpha/targets/{target_id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.target.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Target successfully retrieved";
}
};
};
}
// Set an execution
//
// Set an execution to call a previously defined target or include the targets of a previously defined execution.
rpc SetExecution (SetExecutionRequest) returns (SetExecutionResponse) {
option (google.api.http) = {
put: "/v3alpha/executions"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Execution successfully set";
};
};
};
}
// Delete an execution
//
// Delete an existing execution.
rpc DeleteExecution (DeleteExecutionRequest) returns (DeleteExecutionResponse) {
option (google.api.http) = {
delete: "/v3alpha/executions"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Execution successfully deleted";
};
};
};
}
// List executions
//
// List all matching executions. By default, we will return all executions of your instance.
// Make sure to include a limit and sorting for pagination.
rpc ListExecutions (ListExecutionsRequest) returns (ListExecutionsResponse) {
option (google.api.http) = {
post: "/v3alpha/executions/search"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all executions matching the query";
};
};
responses: {
key: "400";
value: {
description: "invalid list query";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
// List all available functions
//
// List all available functions which can be used as condition for executions.
rpc ListExecutionFunctions (ListExecutionFunctionsRequest) returns (ListExecutionFunctionsResponse) {
option (google.api.http) = {
get: "/v3alpha/executions/functions"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all functions successfully";
};
};
};
}
// List all available methods
//
// List all available methods which can be used as condition for executions.
rpc ListExecutionMethods (ListExecutionMethodsRequest) returns (ListExecutionMethodsResponse) {
option (google.api.http) = {
get: "/v3alpha/executions/methods"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all methods successfully";
};
};
};
}
// List all available service
//
// List all available services which can be used as condition for executions.
rpc ListExecutionServices (ListExecutionServicesRequest) returns (ListExecutionServicesResponse) {
option (google.api.http) = {
get: "/v3alpha/executions/services"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "execution.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all services successfully";
};
};
};
}
}
message CreateTargetRequest {
// Unique name of the target.
string name = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"ip_allow_list\"";
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
option (validate.required) = true;
SetRESTWebhook rest_webhook = 2;
SetRESTCall rest_call = 3;
SetRESTAsync rest_async = 4;
}
// Timeout defines the duration until ZITADEL cancels the execution.
google.protobuf.Duration timeout = 5 [
(validate.rules).duration = {gt: {seconds: 0}, required: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
string endpoint = 6 [
(validate.rules).string = {min_len: 1, max_len: 1000, uri: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 1000,
example: "\"https://example.com/hooks/ip_check\"";
}
];
}
message CreateTargetResponse {
// ID is the read-only unique identifier of the target.
string id = 1;
// Details provide some base information (such as the last change date) of the target.
zitadel.object.v2.Details details = 2;
}
message UpdateTargetRequest {
// unique identifier of the target.
string target_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
// Optionally change the unique name of the target.
optional string name = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"ip_allow_list\"";
}
];
// Optionally change the target type and how the response of the target is treated,
// or its target URL.
oneof target_type {
SetRESTWebhook rest_webhook = 3;
SetRESTCall rest_call = 4;
SetRESTAsync rest_async = 5;
}
// Optionally change the timeout, which defines the duration until ZITADEL cancels the execution.
optional google.protobuf.Duration timeout = 6 [
(validate.rules).duration = {gt: {seconds: 0}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
optional string endpoint = 7 [
(validate.rules).string = {max_len: 1000, uri: true},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 1000,
example: "\"https://example.com/hooks/ip_check\"";
}
];
}
message UpdateTargetResponse {
// Details provide some base information (such as the last change date) of the target.
zitadel.object.v2.Details details = 1;
}
message DeleteTargetRequest {
// unique identifier of the target.
string target_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message DeleteTargetResponse {
// Details provide some base information (such as the last change date) of the target.
zitadel.object.v2.Details details = 1;
}
message ListTargetsRequest {
// list limitations and ordering.
zitadel.object.v2.ListQuery query = 1;
// the field the result is sorted.
zitadel.action.v3alpha.TargetFieldName sorting_column = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"FIELD_NAME_SCHEMA_TYPE\""
}
];
// Define the criteria to query for.
repeated zitadel.action.v3alpha.TargetSearchQuery queries = 3;
}
message ListTargetsResponse {
// Details provides information about the returned result including total amount found.
zitadel.object.v2.ListDetails details = 1;
// States by which field the results are sorted.
zitadel.action.v3alpha.TargetFieldName sorting_column = 2;
// The result contains the user schemas, which matched the queries.
repeated zitadel.action.v3alpha.Target result = 3;
}
message GetTargetByIDRequest {
// unique identifier of the target.
string target_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message GetTargetByIDResponse {
zitadel.action.v3alpha.Target target = 1;
}
message SetExecutionRequest {
// Defines the condition type and content of the condition for execution.
Condition condition = 1;
// Ordered list of targets/includes called during the execution.
repeated zitadel.action.v3alpha.ExecutionTargetType targets = 2;
}
message SetExecutionResponse {
// Details provide some base information (such as the last change date) of the execution.
zitadel.object.v2.Details details = 2;
}
message DeleteExecutionRequest {
// Unique identifier of the execution.
Condition condition = 1;
}
message DeleteExecutionResponse {
// Details provide some base information (such as the last change date) of the execution.
zitadel.object.v2.Details details = 1;
}
message ListExecutionsRequest {
// list limitations and ordering.
zitadel.object.v2.ListQuery query = 1;
// Define the criteria to query for.
repeated zitadel.action.v3alpha.SearchQuery queries = 2;
}
message ListExecutionsResponse {
// Details provides information about the returned result including total amount found.
zitadel.object.v2.ListDetails details = 1;
// The result contains the executions, which matched the queries.
repeated zitadel.action.v3alpha.Execution result = 2;
}
message ListExecutionFunctionsRequest{}
message ListExecutionFunctionsResponse{
// All available methods
repeated string functions = 1;
}
message ListExecutionMethodsRequest{}
message ListExecutionMethodsResponse{
// All available methods
repeated string methods = 1;
}
message ListExecutionServicesRequest{}
message ListExecutionServicesResponse{
// All available methods
repeated string services = 1;
}

View File

@@ -1,110 +0,0 @@
syntax = "proto3";
package zitadel.action.v3alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha;action";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/object/v2/object.proto";
import "zitadel/action/v3alpha/execution.proto";
message SearchQuery {
oneof query {
option (validate.required) = true;
InConditionsQuery in_conditions_query = 1;
ExecutionTypeQuery execution_type_query = 2;
TargetQuery target_query = 3;
IncludeQuery include_query = 4;
}
}
message InConditionsQuery {
// Defines the conditions to query for.
repeated Condition conditions = 1;
}
message ExecutionTypeQuery {
// Defines the type to query for.
ExecutionType execution_type = 1;
}
message TargetQuery {
// Defines the id to query for.
string target_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the id of the targets to include"
example: "\"69629023906488334\"";
}
];
}
message IncludeQuery {
// Defines the include to query for.
Condition include = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the id of the include"
example: "\"request.zitadel.session.v2.SessionService\"";
}
];
}
message TargetSearchQuery {
oneof query {
option (validate.required) = true;
TargetNameQuery target_name_query = 1;
InTargetIDsQuery in_target_ids_query = 2;
}
}
message TargetNameQuery {
// Defines the name of the target to query for.
string target_name = 1 [
(validate.rules).string = {max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 200;
example: "\"ip_allow_list\"";
}
];
// Defines which text comparison method used for the name query.
zitadel.object.v2.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "defines which text equality method is used";
}
];
}
message InTargetIDsQuery {
// Defines the ids to query for.
repeated string target_ids = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "the ids of the targets to include"
example: "[\"69629023906488334\",\"69622366012355662\"]";
}
];
}
enum ExecutionType {
EXECUTION_TYPE_UNSPECIFIED = 0;
EXECUTION_TYPE_REQUEST = 1;
EXECUTION_TYPE_RESPONSE = 2;
EXECUTION_TYPE_EVENT = 3;
EXECUTION_TYPE_FUNCTION = 4;
}
enum TargetFieldName {
FIELD_NAME_UNSPECIFIED = 0;
FIELD_NAME_ID = 1;
FIELD_NAME_CREATION_DATE = 2;
FIELD_NAME_CHANGE_DATE = 3;
FIELD_NAME_NAME = 4;
FIELD_NAME_TARGET_TYPE = 5;
FIELD_NAME_URL = 6;
FIELD_NAME_TIMEOUT = 7;
FIELD_NAME_ASYNC = 8;
FIELD_NAME_INTERRUPT_ON_ERROR = 9;
}

View File

@@ -0,0 +1,22 @@
syntax = "proto3";
package zitadel.object.v3alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/object/v3alpha;object";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
enum OwnerType {
OWNER_TYPE_UNSPECIFIED = 0;
OWNER_TYPE_SYSTEM = 1;
OWNER_TYPE_INSTANCE = 2;
OWNER_TYPE_ORG = 3;
}
message Owner {
OwnerType type = 1;
string id = 2;
}

View File

@@ -0,0 +1,361 @@
syntax = "proto3";
package zitadel.resources.action.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/resources/action/v3alpha/target.proto";
import "zitadel/resources/action/v3alpha/execution.proto";
import "zitadel/resources/object/v3alpha/object.proto";
import "zitadel/settings/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Action Service";
version: "3.0-alpha";
description: "This API is intended to manage custom executions (previously known as actions) in a ZITADEL instance. It will continue breaking as long as it is in alpha state.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
consumes: "application/grpc";
produces: "application/json";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$ZITADEL_DOMAIN";
base_path: "/resources/v3alpha/actions";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
service ZITADELActions {
// Create a target
//
// Create a new target, which can be used in executions.
rpc CreateTarget (CreateTargetRequest) returns (CreateTargetResponse) {
option (google.api.http) = {
post: "/targets"
body: "target"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "201";
value: {
description: "Target successfully created";
schema: {
json_schema: {
ref: "#/definitions/CreateTargetResponse";
}
}
};
};
};
}
// Patch a target
//
// Patch an existing target.
rpc PatchTarget (PatchTargetRequest) returns (PatchTargetResponse) {
option (google.api.http) = {
patch: "/targets/{id}"
body: "target"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully updated or left unchanged";
};
};
};
}
// Delete a target
//
// Delete an existing target. This will remove it from any configured execution as well.
rpc DeleteTarget (DeleteTargetRequest) returns (DeleteTargetResponse) {
option (google.api.http) = {
delete: "/targets/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.target.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Target successfully deleted";
};
};
};
}
// Sets an execution to call a target or include the targets of another execution.
//
// Setting an empty list of targets will remove all targets from the execution, making it a noop.
rpc SetExecution (SetExecutionRequest) returns (SetExecutionResponse) {
option (google.api.http) = {
put: "/executions"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "action.execution.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Execution successfully updated or left unchanged";
schema: {
json_schema: {
ref: "#/definitions/SetExecutionResponse";
}
}
};
};
};
}
// List all available functions
//
// List all available functions which can be used as condition for executions.
rpc ListExecutionFunctions (ListExecutionFunctionsRequest) returns (ListExecutionFunctionsResponse) {
option (google.api.http) = {
get: "/executions/functions"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all functions successfully";
};
};
};
}
// List all available methods
//
// List all available methods which can be used as condition for executions.
rpc ListExecutionMethods (ListExecutionMethodsRequest) returns (ListExecutionMethodsResponse) {
option (google.api.http) = {
get: "/executions/methods"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all methods successfully";
};
};
};
}
// List all available service
//
// List all available services which can be used as condition for executions.
rpc ListExecutionServices (ListExecutionServicesRequest) returns (ListExecutionServicesResponse) {
option (google.api.http) = {
get: "/executions/services"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "List all services successfully";
};
};
};
}
}
message CreateTargetRequest {
Target target = 1;
}
message CreateTargetResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message PatchTargetRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
PatchTarget target = 2;
}
message PatchTargetResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message DeleteTargetRequest {
string id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1,
max_length: 200,
example: "\"69629026806489455\"";
}
];
}
message DeleteTargetResponse {
zitadel.resources.object.v3alpha.Details details = 1;
}
message SetExecutionRequest {
Condition condition = 1;
Execution execution = 2;
}
message SetExecutionResponse {
zitadel.settings.object.v3alpha.Details details = 1;
}
message ListExecutionFunctionsRequest{}
message ListExecutionFunctionsResponse{
// All available methods
repeated string functions = 1;
}
message ListExecutionMethodsRequest{}
message ListExecutionMethodsResponse{
// All available methods
repeated string methods = 1;
}
message ListExecutionServicesRequest{}
message ListExecutionServicesResponse{
// All available methods
repeated string services = 1;
}

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
package zitadel.action.v3alpha;
package zitadel.resources.action.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
@@ -8,21 +8,22 @@ import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/object/v2/object.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha;action";
import "zitadel/resources/object/v3alpha/object.proto";
import "google/protobuf/timestamp.proto";
import "zitadel/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
message Execution {
Condition Condition = 1;
// Details provide some base information (such as the last change date) of the target.
zitadel.object.v2.Details details = 2;
// List of ordered list of targets/includes called during the execution.
repeated ExecutionTargetType targets = 3;
// Ordered list of targets/includes called during the execution.
repeated ExecutionTargetType targets = 1;
}
message ExecutionTargetType {
oneof type {
option (validate.required) = true;
// Unique identifier of existing target to call.
string target = 1;
// Unique identifier of existing execution to include targets of.
@@ -47,8 +48,9 @@ message Condition {
}
message RequestExecution {
// Condition for the request execution, only one possible.
// Condition for the request execution. Only one is possible.
oneof condition{
option (validate.required) = true;
// GRPC-method as condition.
string method = 1 [
(validate.rules).string = {min_len: 1, max_len: 1000},
@@ -67,14 +69,15 @@ message RequestExecution {
example: "\"zitadel.session.v2.SessionService\"";
}
];
// All calls to any available service and endpoint as condition.
bool all = 3;
// All calls to any available services and methods as condition.
bool all = 3 [(validate.rules).bool = {const: true}];
}
}
message ResponseExecution {
// Condition for the response execution, only one possible.
// Condition for the response execution. Only one is possible.
oneof condition{
option (validate.required) = true;
// GRPC-method as condition.
string method = 1 [
(validate.rules).string = {min_len: 1, max_len: 1000},
@@ -93,8 +96,8 @@ message ResponseExecution {
example: "\"zitadel.session.v2.SessionService\"";
}
];
// All calls to any available service and endpoint as condition.
bool all = 3;
// All calls to any available services and methods as condition.
bool all = 3 [(validate.rules).bool = {const: true}];
}
}
@@ -103,9 +106,10 @@ message FunctionExecution {
string name = 1 [(validate.rules).string = {min_len: 1, max_len: 1000}];
}
message EventExecution{
// Condition for the event execution, only one possible.
message EventExecution {
// Condition for the event execution. Only one is possible.
oneof condition{
option (validate.required) = true;
// Event name as condition.
string event = 1 [
(validate.rules).string = {min_len: 1, max_len: 1000},
@@ -125,7 +129,6 @@ message EventExecution{
}
];
// all events as condition.
bool all = 3;
bool all = 3 [(validate.rules).bool = {const: true}];
}
}

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
package zitadel.action.v3alpha;
package zitadel.resources.action.v3alpha;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
@@ -8,10 +8,61 @@ import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/object/v2/object.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v3alpha;action";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/action/v3alpha;action";
message Target {
string name = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\"";
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
option (validate.required) = true;
SetRESTWebhook rest_webhook = 2;
SetRESTCall rest_call = 3;
SetRESTAsync rest_async = 4;
}
// Timeout defines the duration until ZITADEL cancels the execution.
google.protobuf.Duration timeout = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
string endpoint = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\"";
}
];
}
message PatchTarget {
optional string name = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\"";
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
SetRESTWebhook rest_webhook = 2;
SetRESTCall rest_call = 3;
SetRESTAsync rest_async = 4;
}
// Timeout defines the duration until ZITADEL cancels the execution.
optional google.protobuf.Duration timeout = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
optional string endpoint = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\"";
}
];
}
// Wait for response but response body is ignored, status is checked, call is sent as post.
message SetRESTWebhook {
@@ -27,39 +78,3 @@ message SetRESTCall {
// Call is executed in parallel to others, ZITADEL does not wait until the call is finished. The state is ignored, call is sent as post.
message SetRESTAsync {}
message Target {
// ID is the read-only unique identifier of the target.
string target_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629012906488334\"";
}
];
// Details provide some base information (such as the last change date) of the target.
zitadel.object.v2.Details details = 2;
// Unique name of the target.
string name = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ip_allow_list\"";
}
];
// Defines the target type and how the response of the target is treated.
oneof target_type {
SetRESTWebhook rest_webhook = 4;
SetRESTCall rest_call = 5;
SetRESTAsync rest_async = 6;
}
// Timeout defines the duration until ZITADEL cancels the execution.
google.protobuf.Duration timeout = 7 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"10s\"";
}
];
string endpoint = 8 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://example.com/hooks/ip_check\"";
}
];
}

View File

@@ -0,0 +1,43 @@
syntax = "proto3";
package zitadel.resources.object.v3alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/resources/object/v3alpha;object";
import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/object/v3alpha/object.proto";
message Details {
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629012906488334\"";
}
];
//sequence represents the order of events. It's always counting
//
// on read: the sequence of the last event reduced by the projection
//
// on manipulation: the timestamp of the event(s) added by the manipulation
uint64 sequence = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2\"";
}
];
//change_date is the timestamp when the object was changed
//
// on read: the timestamp of the last event reduced by the projection
//
// on manipulation: the timestamp of the event(s) added by the manipulation
google.protobuf.Timestamp change_date = 3;
//resource_owner represents the context an object belongs to
zitadel.object.v3alpha.Owner owner = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
}

View File

@@ -0,0 +1,38 @@
syntax = "proto3";
package zitadel.settings.object.v3alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/settings/object/v3alpha;object";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "google/protobuf/duration.proto";
import "zitadel/object/v3alpha/object.proto";
message Details {
//sequence represents the order of events. It's always counting
//
// on read: the sequence of the last event reduced by the projection
//
// on manipulation: the timestamp of the event(s) added by the manipulation
uint64 sequence = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2\"";
}
];
//change_date is the timestamp when the object was changed
//
// on read: the timestamp of the last event reduced by the projection
//
// on manipulation: the timestamp of the event(s) added by the manipulation
google.protobuf.Timestamp change_date = 2;
//resource_owner represents the context an object belongs to
zitadel.object.v3alpha.Owner owner = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
}