chore(api): initial definition of API for user schemas (user v3 and user schema v3 service) (#7372)

Adds the initial proto definition for a new user service (v3) based on user schema and it's corresponding user schema service (v3)
This commit is contained in:
Livio Spring 2024-02-15 11:22:48 +01:00 committed by GitHub
parent d5266ea51c
commit 104034c628
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 3821 additions and 118 deletions

View File

@ -5,4 +5,7 @@ managed:
plugins:
- plugin: buf.build/grpc-ecosystem/openapiv2
out: .artifacts/openapi
opt: allow_delete_body
opt:
- allow_delete_body
- remove_internal_comments=true
- preserve_rpc_order=true

View File

@ -290,14 +290,28 @@ module.exports = {
groupPathsBy: "tag",
},
},
user_schema: {
specPath: ".artifacts/openapi/zitadel/user/schema/v3alpha/user_schema_service.swagger.json",
outputDir: "docs/apis/resources/user_schema_service_v3",
sidebarOptions: {
groupPathsBy: "tag",
},
},
user_v3: {
specPath: ".artifacts/openapi/zitadel/user/v3alpha/user_service.swagger.json",
outputDir: "docs/apis/resources/user_service_v3",
sidebarOptions: {
groupPathsBy: "tag",
},
},
execution_v3: {
specPath: ".artifacts/openapi/zitadel/execution/v3alpha/execution_service.swagger.json",
outputDir: "docs/apis/resources/execution_service_v3",
sidebarOptions: {
groupPathsBy: "tag",
},
}
}
},
},
},
],
require.resolve("docusaurus-plugin-image-zoom"),

View File

@ -521,8 +521,36 @@ module.exports = {
link: {
type: "generated-index",
title: "Core Resources",
slug: "/apis/resources/",
description: "Resource based API definitions",
slug: "/apis/apis/",
description:
"ZITADEL provides multiple APIs to manage the system, instances and resources such as users, projects and more.\n" +
"\n" +
"There are multiple different versions and multiple services available:"+
"\n" +
"The resource based APIs are, as the name suggests, organized by resources such as users, session, settings and more.\n" +
"These services are the future of the ZITADEL APIS and the best way to start integrating ZITADEL.\n" +
"\n"+
"The service based APIs are organized by UseCase/Context, such as Auth API for authenticated users,"+
"Management API for organization managers, Admin API for instance managers and a System API for system managers.",
},
items: [
{
type: "category",
label: "Service Based (V1)",
collapsed: false,
link: {
type: "generated-index",
title: "Service Based APIs (V1)",
slug: "/apis/services/",
description:
"The service based APIs are organized by UseCase/Context, such as Auth API for authenticated users,"+
"Management API for organization managers, Admin API for instance managers and a System API for system managers.\n"+
"\n"+
"To improve the developer experience in managing the different resources, ZITADEL also offers Resource Based APIs (v2 and v3). "+
"Those APIs focus on the resources themselves. For example they offer a User Service, which will give you the possibility " +
"to search for users across multiple organizations.\n"+
"Note that the Resource Based APIs are not yet generally available. Please check the corresponding service" +
"for their state and functionality.",
},
items: [
{
@ -575,6 +603,30 @@ module.exports = {
},
items: require("./docs/apis/resources/system/sidebar.js"),
},
],
},
{
type: "category",
label: "Resource Based (V2)",
collapsed: false,
link: {
type: "generated-index",
title: "Resource Based APIs (V2)",
slug: "/apis/resources/",
description:
"The resource based APIs are, as the name suggest, organized by resources such as users, session, settings and more. "+
"Check the list below to get an overview of all available resources.\n"+
"\n"+
"While the service based APIs (V1) work great for use cases in a specific context such as a single organization, " +
"it's sometime difficult to know which API to use, particularly for resources across multiple organizations. "+
"For instance, SearchUsers on an Instance level or on an Organization level.\n"+
"This is exactly where the resource based APIs come in place, e.g. with the User Service, " +
"where you're able to search all users and can provide the context (organization) yourself if needed or just search the whole instance.\n"+
"\n"+
"Note that these APIs are not yet generally available and therefore breaking changes might still occur.\n"+
"Please check the corresponding service for more information on the state and availability.",
},
items: [
{
type: "category",
label: "User Lifecycle (Beta)",
@ -631,6 +683,61 @@ module.exports = {
},
items: require("./docs/apis/resources/settings_service/sidebar.js"),
},
]
},
{
type: "category",
label: "Resource Based (V3)",
collapsed: false,
link: {
type: "generated-index",
title: "Resource Based APIs (V3)",
slug: "/apis/resources_v3/",
description:
"The resource based APIs are, as the name suggests, organized by resources such as users, session, settings and more.\n"+
"\n"+
"While the service based APIs (V1) work great for use cases in a specific context such as a single organization, " +
"it's sometime difficult to know which API to use, particularly for resources across multiple organizations. "+
"For instance, SearchUsers on an Instance level or on an Organization level.\n"+
"This is exactly where the resource based APIs come in place, e.g. with the User Service, " +
"where you're able to search all users and can provide the context (organization) yourself if needed or just search the whole instance.\n"+
"\n"+
"Version 3 offers more customization than the V2 resource bases APIs. You can define your own user schema "+
"to be able to manage users based on these schemas and customize various behaviors, such as manipulating "+
"inbound API calls, call webhooks on different event and more with the execution service.\n"+
"\n"+
"Note that these APIs are not yet generally available and therefore breaking changes might still occur.\n"+
"Please check the corresponding service for more information on the state and availability.",
},
items: [
{
type: "category",
label: "User Schema Lifecycle (Alpha)",
link: {
type: "generated-index",
title: "User Schema Service API (Aplha)",
slug: "/apis/resources/user_schema_service",
description:
"This API is intended to manage data schemas for users in a ZITADEL instance.\n" +
"\n" +
"This project is in alpha state. It can AND will continue breaking until the service provides the same functionality as the v1 and v2 user services.",
},
items: require("./docs/apis/resources/user_schema_service_v3/sidebar.js"),
},
{
type: "category",
label: "User Lifecycle (Alpha)",
link: {
type: "generated-index",
title: "User Service API (Aplha)",
slug: "/apis/resources/user_service_v3",
description:
"This API is intended to manage users with your own data schema in a ZITADEL instance.\n"+
"\n"+
"This project is in alpha state. It can AND will continue breaking until the service provides the same functionality as the v1 and v2 user services."
},
items: require("./docs/apis/resources/user_service_v3/sidebar.js"),
},
{
type: "category",
label: "Execution Lifecycle (Alpha)",
@ -645,6 +752,8 @@ module.exports = {
},
items: require("./docs/apis/resources/execution_service_v3/sidebar.js"),
},
]
},
{
type: "category",
label: "Assets",

View File

@ -0,0 +1,168 @@
syntax = "proto3";
package zitadel.user.schema.v3alpha;
import "google/api/field_behavior.proto";
import "google/protobuf/struct.proto";
import "validate/validate.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "zitadel/object/v2beta/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/schema/v3alpha";
message UserSchema {
// ID is the read-only unique identifier of the schema.
string 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 schema.
zitadel.object.v2beta.Details details = 2;
// Type is a human readable text describing the schema.
string type = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"employees\""
}
];
// Current state of the schema.
State state = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"STATE_ACTIVE\""
}
];
// Revision is a read only version of the schema, each update increases the revision.
uint32 revision = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2\""
}
];
// JSON schema representation defining the user.
google.protobuf.Struct schema = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "{\"$schema\":\"https://example.com/user/employees\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"required\":true},\"description\":{\"type\":\"string\"}}}"
}
];
// Defines the possible types of authenticators.
// This allows creating different user types like human/machine without usage of actions to validate possible authenticators.
// Removal of an authenticator does not remove the authenticator on a user.
repeated AuthenticatorType possible_authenticators = 7 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"AUTHENTICATOR_TYPE_USERNAME\",\"AUTHENTICATOR_TYPE_PASSWORD\",\"AUTHENTICATOR_TYPE_WEBAUTHN\"]";
}
];
}
enum FieldName {
FIELD_NAME_UNSPECIFIED = 0;
FIELD_NAME_TYPE = 1;
FIELD_NAME_STATE = 2;
FIELD_NAME_REVISION = 3;
FIELD_NAME_CREATION_DATE = 4;
}
message SearchQuery {
oneof query {
option (validate.required) = true;
// Union the results of each sub query ('OR').
OrQuery or_query = 1;
// Limit the result to match all sub queries ('AND').
// Note that if you specify multiple queries, they will be implicitly used as andQueries.
// Use the andQuery in combination with orQuery and notQuery.
AndQuery and_query = 2;
// Exclude / Negate the result of the sub query ('NOT').
NotQuery not_query = 3;
// Limit the result to a specific schema type.
TypeQuery type_query = 5;
// Limit the result to a specific state of the schema.
StateQuery state_query = 6;
}
}
message OrQuery {
repeated SearchQuery queries = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[{\"idQuery\": {\"id\": \"163840776835432705\",\"method\": \"TEXT_QUERY_METHOD_EQUALS\"}},{\"idQuery\": {\"id\": \"163840776835943483\",\"method\": \"TEXT_QUERY_METHOD_EQUALS\"}}]"
}
];
}
message AndQuery {
repeated SearchQuery queries = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[{\"typeQuery\": {\"id\": \"employees\",\"method\": \"TEXT_QUERY_METHOD_STARTS_WITH\"}},{\"stateQuery\": {\"state\": \"STATE_ACTIVE\"}}]"
}
];
}
message NotQuery {
SearchQuery query = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "{\"stateQuery\": {\"state\": \"STATE_ACTIVE\"}}"
}
];
}
message IDQuery {
// Defines the ID of the user schema to query for.
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: "\"163840776835432705\"";
}
];
// Defines which text comparison method used for the id query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
message TypeQuery {
// Defines which type to query for.
string type = 1 [
(validate.rules).string = {max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
max_length: 200,
example: "\"employees\"";
}
];
// Defines which text comparison method used for the type query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
message StateQuery {
// Defines the state to query for.
State state = 1 [
(validate.rules).enum.defined_only = true,
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"STATE_ACTIVE\""
}
];
}
enum State {
STATE_UNSPECIFIED = 0;
STATE_ACTIVE = 1;
STATE_INACTIVE = 2;
}
enum AuthenticatorType {
AUTHENTICATOR_TYPE_UNSPECIFIED = 0;
AUTHENTICATOR_TYPE_USERNAME = 1;
AUTHENTICATOR_TYPE_PASSWORD = 2;
AUTHENTICATOR_TYPE_WEBAUTHN = 3;
AUTHENTICATOR_TYPE_TOTP = 4;
AUTHENTICATOR_TYPE_OTP_EMAIL = 5;
AUTHENTICATOR_TYPE_OTP_SMS = 6;
AUTHENTICATOR_TYPE_AUTHENTICATION_KEY = 7;
AUTHENTICATOR_TYPE_IDENTITY_PROVIDER = 8;
}

View File

@ -0,0 +1,452 @@
syntax = "proto3";
package zitadel.user.schema.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/object/v2beta/object.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/user/schema/v3alpha/user_schema.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/schema/v3alpha";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "User Schema Service";
version: "3.0-alpha";
description: "This API is intended to manage data schemas for users in a ZITADEL instance. This project is in alpha state. It can AND will continue breaking until the service provides the same functionality as the v1 and v2 user services.";
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";
produces: "application/json";
consumes: "application/grpc";
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 UserSchemaService {
// List user schemas
//
// List all matching user schemas. By default, we will return all user schema of your instance. Make sure to include a limit and sorting for pagination.
rpc ListUserSchemas (ListUserSchemasRequest) returns (ListUserSchemasResponse) {
option (google.api.http) = {
post: "/v3alpha/user_schemas/search"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "A list of all user schema matching the query";
};
};
responses: {
key: "400";
value: {
description: "invalid list query";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
// User schema by ID
//
// Returns the user schema identified by the requested ID.
rpc GetUserSchemaByID (GetUserSchemaByIDRequest) returns (GetUserSchemaByIDResponse) {
option (google.api.http) = {
get: "/v3alpha/user_schemas/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.read"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "Schema successfully retrieved";
}
};
};
}
// Create a user schema
//
// Create the first revision of a new user schema. The schema can then be used on users to store and validate their data.
rpc CreateUserSchema (CreateUserSchemaRequest) returns (CreateUserSchemaResponse) {
option (google.api.http) = {
post: "/v3alpha/user_schemas"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.write"
}
http_response: {
success_code: 201
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "201";
value: {
description: "Schema successfully created";
schema: {
json_schema: {
ref: "#/definitions/v3alphaCreateUserSchemaResponse";
}
}
};
};
};
}
// Update a user schema
//
// Update an existing user schema to a new revision. Users based on the current revision will not be affected until they are updated.
rpc UpdateUserSchema (UpdateUserSchemaRequest) returns (UpdateUserSchemaResponse) {
option (google.api.http) = {
put: "/v3alpha/user_schemas/{id}"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Schema successfully updated";
};
};
};
}
// Deactivate a user schema
//
// Deactivate an existing user schema and change it into a read-only state. Users based on this schema cannot be updated anymore, but are still able to authenticate.
rpc DeactivateUserSchema (DeactivateUserSchemaRequest) returns (DeactivateUserSchemaResponse) {
option (google.api.http) = {
post: "/v3alpha/user_schemas/{id}/deactivate"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Schema successfully deactivated";
};
};
};
}
// Reactivate a user schema
//
// Reactivate an previously deactivated user schema and change it into an active state again.
rpc ReactivateUserSchema (ReactivateUserSchemaRequest) returns (ReactivateUserSchemaResponse) {
option (google.api.http) = {
post: "/v3alpha/user_schemas/{id}/reactivate"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.write"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Schema successfully reactivated";
};
};
};
}
// Delete a user schema
//
// Delete an existing user schema. This operation is only allowed if there are no associated users to it.
rpc DeleteUserSchema (DeleteUserSchemaRequest) returns (DeleteUserSchemaResponse) {
option (google.api.http) = {
delete: "/v3alpha/user_schemas/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "userschema.delete"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200";
value: {
description: "Schema successfully deleted";
};
};
};
}
}
message ListUserSchemasRequest {
// list limitations and ordering.
zitadel.object.v2beta.ListQuery query = 1;
// the field the result is sorted.
zitadel.user.schema.v3alpha.FieldName sorting_column = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"FIELD_NAME_TYPE\"";
}
];
// Define the criteria to query for.
repeated zitadel.user.schema.v3alpha.SearchQuery queries = 3;
}
message ListUserSchemasResponse {
// Details provides information about the returned result including total amount found.
zitadel.object.v2beta.ListDetails details = 1;
// States by which field the results are sorted.
zitadel.user.schema.v3alpha.FieldName sorting_column = 2;
// The result contains the user schemas, which matched the queries.
repeated zitadel.user.schema.v3alpha.UserSchema result = 3;
}
message GetUserSchemaByIDRequest {
// unique identifier of the schema.
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 GetUserSchemaByIDResponse {
zitadel.user.schema.v3alpha.UserSchema schema = 1;
}
message CreateUserSchemaRequest {
// Type is a human readable word describing the schema.
string type = 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: "\"employees\"";
}
];
oneof data_type {
option (validate.required) = true;
// JSON schema representation defining the user.
google.protobuf.Struct schema = 2 [
(validate.rules).message = {required: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "{\"$schema\":\"https://example.com/user/employees\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"required\":true},\"description\":{\"type\":\"string\"}}}"
}
];
// (--In the future we will allow to use an external registry.--)
}
// Defines the possible types of authenticators.
repeated AuthenticatorType possible_authenticators = 3 [
(validate.rules).repeated = {unique: true, items: {enum: {defined_only: true}}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"AUTHENTICATOR_TYPE_USERNAME\",\"AUTHENTICATOR_TYPE_PASSWORD\",\"AUTHENTICATOR_TYPE_WEBAUTHN\"]";
}
];
}
message CreateUserSchemaResponse {
// ID is the read-only unique identifier of the schema.
string id = 1;
// Details provide some base information (such as the last change date) of the schema.
zitadel.object.v2beta.Details details = 2;
}
message UpdateUserSchemaRequest {
// unique identifier of the schema.
string id = 1;
// Type is a human readable word describing the schema.
optional string type = 2 [
(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: "\"employees\"";
}
];
oneof data_type {
// JSON schema representation defining the user.
google.protobuf.Struct schema = 3 [
(validate.rules).message = {required: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "{\"$schema\":\"https://example.com/user/employees\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"required\":true},\"description\":{\"type\":\"string\"}}}"
}
];
}
// Defines the possible types of authenticators.
//
// Removal of an authenticator does not remove the authenticator on a user.
repeated AuthenticatorType possible_authenticators = 4 [
(validate.rules).repeated = {unique: true, items: {enum: {defined_only: true}}},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"AUTHENTICATOR_TYPE_USERNAME\",\"AUTHENTICATOR_TYPE_PASSWORD\",\"AUTHENTICATOR_TYPE_WEBAUTHN\"]";
}
];
}
message UpdateUserSchemaResponse {
// Details provide some base information (such as the last change date) of the schema.
zitadel.object.v2beta.Details details = 1;
}
message DeactivateUserSchemaRequest {
// unique identifier of the schema.
string id = 1;
}
message DeactivateUserSchemaResponse {
// Details provide some base information (such as the last change date) of the schema.
zitadel.object.v2beta.Details details = 1;
}
message ReactivateUserSchemaRequest {
// unique identifier of the schema.
string id = 1;
}
message ReactivateUserSchemaResponse {
// Details provide some base information (such as the last change date) of the schema.
zitadel.object.v2beta.Details details = 1;
}
message DeleteUserSchemaRequest {
// unique identifier of the schema.
string id = 1;
}
message DeleteUserSchemaResponse {
// Details provide some base information (such as the last change date) of the schema.
zitadel.object.v2beta.Details details = 1;
}

View File

@ -0,0 +1,476 @@
syntax = "proto3";
package zitadel.user.v3alpha;
import "google/api/field_behavior.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/object/v2beta/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v3alpha";
message Authenticators {
// All of the user's usernames, which will be used for identification during authentication.
repeated Username usernames = 1;
// If the user has set a password, the time it was last changed will be returned.
Password password = 2;
// Meta information about the user's WebAuthN authenticators.
repeated WebAuthN web_auth_n = 3;
// A list of the user's time-based one-time-password (TOTP) authenticators,
// incl. the name for identification.
repeated TOTP totps = 4;
// A list of the user's one-time-password (OTP) SMS authenticators.
repeated OTPSMS otp_sms = 5;
// A list of the user's one-time-password (OTP) Email authenticators.
repeated OTPEmail otp_email = 6;
// A list of the user's authentication keys. They can be used to authenticate e.g. by JWT Profile.
repeated AuthenticationKey authentication_keys = 7;
// A list of the user's linked identity providers (IDPs).
repeated IdentityProvider identity_providers = 8;
}
message Username {
// unique identifier of the username.
string username_id = 1;
// The user's unique username. It is used for identification during authentication.
string username = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"gigi-giraffe\"";
}
];
// By default usernames must be unique across all organizations in an instance.
// This option allow to restrict the uniqueness to the user's own organization.
// As a result, this username can only be used if the authentication is limited
// to the corresponding organization.
//
// This can be useful if you provide multiple usernames for a single user, where one
// if specific to your organization, e.g.:
// - gigi-giraffe@zitadel.com (unique across organizations)
// - gigi-giraffe (unique only inside the ZITADEL organization)
bool is_organization_specific = 3;
}
message SetUsername {
// Set the user's username. This will be used for identification during authentication.
string username = 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: "\"gigi-giraffe\"";
}
];
// By default username must be unique across all organizations in an instance.
// This option allow to restrict the uniqueness to the user's own organization.
// As a result, this username can only be used if the authentication is limited
// to the corresponding organization.
//
// This can be useful if you provide multiple usernames for a single user, where one
// if specific to your organization, e.g.:
// - gigi-giraffe@zitadel.com (unique across organizations)
// - gigi-giraffe (unique only inside the ZITADEL organization)
bool is_organization_specific = 2;
}
message Password {
// States the time the password was last changed.
google.protobuf.Timestamp last_changed = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"2019-04-01T08:45:00.000000Z\"";
}
];
}
message WebAuthN {
// unique identifier of the WebAuthN authenticator.
string web_auth_n_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\""
}
];
// Name of the WebAuthN authenticator. This is used for easier identification.
string name = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"fido key\""
}
];
// State whether the WebAuthN registration has been completed.
bool is_verified = 3;
// States if the user has been verified during the registration. Authentication with this device
// will be considered as multi factor authentication (MFA) without the need to check a password
// (typically known as Passkeys).
// Without user verification it will be a second factor authentication (2FA), typically done
// after a password check.
//
// More on WebAuthN User Verification: https://www.w3.org/TR/webauthn/#user-verification
bool user_verified = 4;
}
message OTPSMS {
// unique identifier of the one-time-password (OTP) SMS authenticator.
string otp_sms_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\""
}
];
// The phone number used for the OTP SMS authenticator.
string phone = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"+41791234567\"";
}
];
// State whether the OTP SMS registration has been completed.
bool is_verified = 3;
}
message OTPEmail {
// unique identifier of the one-time-password (OTP) Email authenticator.
string otp_email_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\""
}
];
// The email address used for the OTP Email authenticator.
string address = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"mini@mouse.com\"";
}
];
// State whether the OTP Email registration has been completed.
bool is_verified = 3;
}
message TOTP {
// unique identifier of the time-based one-time-password (TOTP) authenticator.
string totp_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\""
}
];
// The name provided during registration. This is used for easier identification.
string name = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"Google Authenticator\""
}
];
// State whether the TOTP registration has been completed.
bool is_verified = 3;
}
message AuthenticationKey {
// ID is the read-only unique identifier of the authentication key.
string authentication_key_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
zitadel.object.v2beta.Details details = 2;
// the file type of the key
AuthNKeyType type = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"KEY_TYPE_JSON\"";
}
];
// After the expiration date, the key will no longer be usable for authentication.
google.protobuf.Timestamp expiration_date = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"3019-04-01T08:45:00.000000Z\"";
}
];
}
enum AuthNKeyType {
AUTHN_KEY_TYPE_UNSPECIFIED = 0;
AUTHN_KEY_TYPE_JSON = 1;
}
message IdentityProvider {
// IDP ID is the read-only unique identifier of the identity provider in ZITADEL.
string idp_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
// IDP name is the name of the identity provider in ZITADEL.
string idp_name = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"google\"";
}
];
// The user ID represents the ID provided by the identity provider.
// This ID is used to link the user in ZITADEL with the identity provider.
string user_id = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"as-12-df-89\"";
}
];
// The username represents the username provided by the identity provider.
string username = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"gigi.long-neck@gmail.com\"";
}
];
}
message SetAuthenticators {
repeated SetUsername usernames = 1;
SetPassword password = 2;
}
message SetPassword {
oneof type {
// Provide the plain text password. ZITADEL will take care to store it in a secure way (hash).
string password = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"Secr3tP4ssw0rd!\"";
min_length: 1,
max_length: 200;
}
];
// Encoded hash of a password in Modular Crypt Format:
// https://zitadel.com/docs/concepts/architecture/secrets#hashed-secrets.
string hash = 2 [
(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: "\"$2a$12$lJ08fqVr8bFJilRVnDT9QeULI7YW.nT3iwUv6dyg0aCrfm3UY8XR2\"";
}
];
}
// Provide if the user needs to change the password on the next use.
bool change_required = 3;
}
message SendPasswordResetEmail {
// Optionally set a url_template, which will be used in the password reset mail
// sent by ZITADEL to guide the user to your password change page.
// If no template is set, the default ZITADEL url will be used.
optional string url_template = 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: "\"https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
}
];
}
message SendPasswordResetSMS {}
message ReturnPasswordResetCode {}
enum WebAuthNAuthenticatorType {
WEB_AUTH_N_AUTHENTICATOR_UNSPECIFIED = 0;
WEB_AUTH_N_AUTHENTICATOR_PLATFORM = 1;
WEB_AUTH_N_AUTHENTICATOR_CROSS_PLATFORM = 2;
}
message AuthenticatorRegistrationCode {
// ID to the one time code generated by ZITADEL.
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: "\"e2a48d6a-362b-4db6-a1fb-34feab84dc62\"";
}
];
// one time code generated by ZITADEL.
string code = 2 [
(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: "\"SKJd342k\"";
}
];
}
message SendWebAuthNRegistrationLink {
// Optionally set a url_template, which will be used in the mail sent by ZITADEL
// to guide the user to your passkey registration page.
// If no template is set, the default ZITADEL url will be used.
optional string url_template = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"https://example.com/passkey/register?userID={{.UserID}}&orgID={{.OrgID}}&codeID={{.CodeID}}&code={{.Code}}\"";
}
];
}
message ReturnWebAuthNRegistrationCode {}
message RedirectURLs {
// URL to which the user will be redirected after a successful login.
string success_url = 1 [
(validate.rules).string = {min_len: 1, max_len: 200, uri_ref: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"https://custom.com/login/idp/success\"";
}
];
// URL to which the user will be redirected after a failed login.
string failure_url = 2 [
(validate.rules).string = {min_len: 1, max_len: 200, uri_ref: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"https://custom.com/login/idp/fail\"";
}
];
}
message LDAPCredentials {
// Username used to login through LDAP.
string username = 1 [
(validate.rules).string = {min_len: 1, max_len: 200, uri_ref: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"username\"";
}
];
// Password used to login through LDAP.
string password = 2 [
(validate.rules).string = {min_len: 1, max_len: 200, uri_ref: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"Password1!\"";
}
];
}
message IdentityProviderIntent {
// ID of the identity provider (IDP) intent.
string idp_intent_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"163840776835432705\"";
}
];
// Token of the identity provider (IDP) intent.
string idp_intent_token = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"SJKL3ioIDpo342ioqw98fjp3sdf32wahb=\"";
}
];
// If the user was already federated and linked to a ZITADEL user, it's id will be returned.
optional string user_id = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"163840776835432345\"";
}
];
}
message IDPInformation{
// ID of the identity provider.
string idp_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629026806489455\"";
}
];
// ID of the user provided by the identity provider.
string user_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
// Username of the user provided by the identity provider.
string user_name = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"user@external.com\"";
}
];
// Complete information returned by the identity provider.
google.protobuf.Struct raw_information = 4;
// additional access information returned by the identity provider.
oneof access{
// OAuth/OIDC access (and id_token) returned by the identity provider.
IDPOAuthAccessInformation oauth = 5;
// LDAP entity attributes returned by the identity provider
IDPLDAPAccessInformation ldap = 6;
// SAMLResponse returned by the identity provider
IDPSAMLAccessInformation saml = 7;
}
}
message IDPOAuthAccessInformation{
// The access_token returned by the identity provider.
string access_token = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"JWLKFSJlijorifjOJOIehjt8jOIEWJGh3tgiEN3WIUGH8Ehgiewhg\"";
}
];
// In case the provider returned an id_token.
optional string id_token = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\"";
}
];
}
message IDPLDAPAccessInformation{
// The attributes of the user returned by the identity provider.
google.protobuf.Struct attributes = 1;
}
message IDPSAMLAccessInformation{
// The SAML assertion returned by the identity provider.
bytes assertion = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"PEFzc2VydGlvbiB4bWxucz11cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIElEPV9mNjc5NDE5MjliZGY5MTcyOTMyMyBJc3N1ZUluc3RhbnQ9MjAyNC0wMi0wOFQxMzo1MTozNy45NDdaIFZlcnNpb249Mi4wPjxJc3N1ZXIgeG1sbnM9dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiBOYW1lUXVhbGlmaWVyPSBTUE5hbWVRdWFsaWZpZXI9IEZvcm1hdD11cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkgU1BQcm92aWRlZElEPT5odHRwczovL3NhbWwuZXhhbXBsZS5jb20vZW50aXR5aWRcPC9Jc3N1ZXJcPlw8U2lnbmF0dXJlXD5cPFNwYWNlXD5cPC9TcGFjZVw+XDxUYWdcPlw8L1RhZ1w+XDwvU2lnbmF0dXJlXD5cPFN1YmplY3QgeG1sbnM9dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbj48TmFtZUlEIE5hbWVRdWFsaWZpZXI9IFNQTmFtZVF1YWxpZmllcj0gRm9ybWF0PXVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyBTUFByb3ZpZGVkSUQ9PmphY2tzb25AZXhhbXBsZS5jb208L05hbWVJRD48U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlcj48U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPTIwMjQtMDItMDhUMTM6NTY6MzcuOTQ3WiBOb3RCZWZvcmU9MDAwMS0wMS0wMVQwMDowMDowMFogUmVjaXBpZW50PWh0dHBzOi8vZGVtby56aXRhZGVsLmNsb3VkL2lkcHMvMjUyODM0OTQ3NjU4NzA5NzYyL3NhbWwvYWNzIEluUmVzcG9uc2VUbz1pZC0yMGIxZGEyNWUzNzVhYWQyYmZmNjIxOGY2ZmUzMWRmMzYzNTRjMmI2IEFkZHJlc3M9PjwvU3ViamVjdENvbmZpcm1hdGlvbkRhdGE+PC9TdWJqZWN0Q29uZmlybWF0aW9uPjwvU3ViamVjdD48Q29uZGl0aW9ucyBOb3RCZWZvcmU9MjAyNC0wMi0wOFQxMzo0NjozNy45NDdaIE5vdE9uT3JBZnRlcj0yMDI0LTAyLTA4VDEzOjU2OjM3Ljk0N1o+PEF1ZGllbmNlUmVzdHJpY3Rpb24+PEF1ZGllbmNlPmh0dHBzOi8vZGVtby56aXRhZGVsLmNsb3VkL2lkcHMvMjUyODM0OTQ3NjU4NzA5NzYyL3NhbWwvbWV0YWRhdGFcPC9BdWRpZW5jZVw+XDwvQXVkaWVuY2VSZXN0cmljdGlvblw+XDwvQ29uZGl0aW9uc1w+XDxBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9MjAyNC0wMi0wOFQxMzo1MTozNy45NDdaIFNlc3Npb25JbmRleD1pZC0yMGIxZGEyNWUzNzVhYWQyYmZmNjIxOGY2ZmUzMWRmMzYzNTRjMmI2PjxBdXRobkNvbnRleHQ+PEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0PC9BdXRobkNvbnRleHRDbGFzc1JlZj48L0F1dGhuQ29udGV4dD48L0F1dGhuU3RhdGVtZW50PjxBdHRyaWJ1dGVTdGF0ZW1lbnQ+PEF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IE5hbWU9aWQgTmFtZUZvcm1hdD11cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVuc3BlY2lmaWVkPjxBdHRyaWJ1dGVWYWx1ZSB4bWxuczpfWE1MU2NoZW1hLWluc3RhbmNlPWh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIF9YTUxTY2hlbWEtaW5zdGFuY2U6dHlwZT14czpzdHJpbmc+MWRkYTlmYjQ5MWRjMDFiZDI0ZDI0MjNiYTJmMjJhZTU2MWY1NmRkZjIzNzZiMjlhMTFjODAyODFkMjEyMDFmOTwvQXR0cmlidXRlVmFsdWU+PC9BdHRyaWJ1dGU+PEF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IE5hbWU9ZW1haWwgTmFtZUZvcm1hdD11cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVuc3BlY2lmaWVkPjxBdHRyaWJ1dGVWYWx1ZSB4bWxuczpfWE1MU2NoZW1hLWluc3RhbmNlPWh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIF9YTUxTY2hlbWEtaW5zdGFuY2U6dHlwZT14czpzdHJpbmc+amFja3NvbkBleGFtcGxlLmNvbTwvQXR0cmlidXRlVmFsdWU+PC9BdHRyaWJ1dGU+PEF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IE5hbWU9Zmlyc3ROYW1lIE5hbWVGb3JtYXQ9dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1bnNwZWNpZmllZD48QXR0cmlidXRlVmFsdWUgeG1sbnM6X1hNTFNjaGVtYS1pbnN0YW5jZT1odHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSBfWE1MU2NoZW1hLWluc3RhbmNlOnR5cGU9eHM6c3RyaW5nPmphY2tzb248L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSBOYW1lPWxhc3ROYW1lIE5hbWVGb3JtYXQ9dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1bnNwZWNpZmllZD48QXR0cmlidXRlVmFsdWUgeG1sbnM6X1hNTFNjaGVtYS1pbnN0YW5jZT1odHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSBfWE1MU2NoZW1hLWluc3RhbmNlOnR5cGU9eHM6c3RyaW5nPmphY2tzb248L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjwvQXR0cmlidXRlU3RhdGVtZW50PjwvQXNzZXJ0aW9uPg==\""
}
];
}
message IDPAuthenticator {
// ID of the identity provider
string idp_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\"";
}
];
// ID of the user provided by the identity provider
string user_id = 2 [
(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: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
// Username of the user provided by the identity provider.
string user_name = 3 [
(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: "\"user@external.com\"";
}
];
}

View File

@ -0,0 +1,109 @@
syntax = "proto3";
package zitadel.user.v3alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v3alpha";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
message Contact {
// Email contact information of the user.
Email email = 1;
// Phone contact information of the user.
Phone phone = 2;
}
message Email {
// Email address of the user.
string address = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"mini@mouse.com\"";
}
];
// IsVerified states if the email address has been verified to belong to the user.
bool is_verified = 2;
}
message Phone {
// Phone number of the user.
string number = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"+41791234567\"";
}
];
// IsVerified states if the phone number has been verified to belong to the user.
bool is_verified = 2;
}
message SetContact {
optional SetEmail email = 1;
optional SetPhone phone = 2;
}
message SetEmail {
// Set the email address.
string address = 1 [
(validate.rules).string = {min_len: 1, max_len: 200, email: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"mini@mouse.com\"";
}
];
// if no verification is specified, an email is sent with the default url
oneof verification {
// Let ZITADEL send the link to the user via email.
SendEmailVerificationCode send_code = 2;
// Get the code back to provide it to the user in your preferred mechanism.
ReturnEmailVerificationCode return_code = 3;
// Set the email as already verified.
bool is_verified = 4 [(validate.rules).bool.const = true];
}
}
message SendEmailVerificationCode {
// Optionally set a url_template, which will be used in the verification mail sent by ZITADEL
// to guide the user to your verification page.
// If no template is set, the default ZITADEL url will be used.
optional string url_template = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"https://example.com/email/verify?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
}
];
}
message ReturnEmailVerificationCode {}
message SetPhone {
// Set the user's phone number.
string number = 1 [
(validate.rules).string = {min_len: 1, max_len: 20},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 20;
example: "\"+41791234567\"";
}
];
// if no verification is specified, a SMS is sent
oneof verification {
// Let ZITADEL send the link to the user via SMS.
SendPhoneVerificationCode send_code = 2;
// Get the code back to provide it to the user in your preferred mechanism.
ReturnPhoneVerificationCode return_code = 3;
// Set the phone as already verified.
bool is_verified = 4 [(validate.rules).bool.const = true];
}
}
message SendPhoneVerificationCode {}
message ReturnPhoneVerificationCode {}

View File

@ -0,0 +1,207 @@
syntax = "proto3";
package zitadel.user.v3alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v3alpha";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/user/v3alpha/user.proto";
import "zitadel/object/v2beta/object.proto";
message SearchQuery {
oneof query {
option (validate.required) = true;
// Union the results of each sub query ('OR').
OrQuery or_query = 1;
// Limit the result to match all sub queries ('AND').
// Note that if you specify multiple queries, they will be implicitly used as andQueries.
// Use the andQuery in combination with orQuery and notQuery.
AndQuery and_query = 2;
// Exclude / Negate the result of the sub query ('NOT').
NotQuery not_query = 3;
// Limit the result to a specific user ID.
UserIDQuery user_id_query = 4;
// Limit the result to a specific organization.
OrganizationIDQuery organization_id_query = 5;
// Limit the result to a specific username.
UsernameQuery username_query = 6;
// Limit the result to a specific contact email.
EmailQuery email_query = 7;
// Limit the result to a specific contact phone.
PhoneQuery phone_query = 8;
// Limit the result to a specific state of the user.
StateQuery state_query = 9;
// Limit the result to a specific schema ID.
SchemaIDQuery schema_ID_query = 10;
// Limit the result to a specific schema type.
SchemaTypeQuery schema_type_query = 11;
}
}
message OrQuery {
repeated SearchQuery queries = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[{\"userIdQuery\": {\"id\": \"163840776835432705\",\"method\": \"TEXT_QUERY_METHOD_EQUALS\"}},{\"userIdQuery\": {\"id\": \"163840776835943483\",\"method\": \"TEXT_QUERY_METHOD_EQUALS\"}}]"
}
];
}
message AndQuery {
repeated SearchQuery queries = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[{\"organizationIdQuery\": {\"id\": \"163840776835432705\",\"method\": \"TEXT_QUERY_METHOD_EQUALS\"}},{\"usernameQuery\": {\"username\": \"gigi\",\"method\": \"TEXT_QUERY_METHOD_EQUALS\"}}]"
}
];
}
message NotQuery {
SearchQuery query = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "{\"schemaIDQuery\": {\"id\": \"163840776835432705\"}}"
}
];
}
message UserIDQuery {
// Defines the ID of the user to query for.
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: "\"163840776835432705\"";
}
];
// Defines which text comparison method used for the id query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
message OrganizationIDQuery {
// Defines the ID of the organization to query for.
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: "\"163840776835432705\"";
}
];
// Defines which text comparison method used for the id query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
message UsernameQuery {
// Defines the username to query for.
string username = 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: "\"gigi-giraffe\"";
}
];
// Defines which text comparison method used for the username query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
// Defines that the username must only be unique in the organisation.
bool is_organization_specific = 3;
}
message EmailQuery {
// Defines the email of the user to query for.
string address = 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: "\"gigi@zitadel.com\"";
}
];
// Defines which text comparison method used for the email query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
message PhoneQuery {
// Defines the phone of the user to query for.
string number = 1 [
(validate.rules).string = {min_len: 1, max_len: 20},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 20;
example: "\"+41791234567\"";
}
];
// Defines which text comparison method used for the phone query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
message StateQuery {
// Defines the state to query for.
State state = 1 [
(validate.rules).enum.defined_only = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"STATE_ACTIVE\""
}
];
}
message SchemaIDQuery {
// Defines the ID of the schema to query for.
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: "\"163840776835432705\"";
}
];
}
message SchemaTypeQuery {
// Defines which type to query for.
string type = 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: "\"employees\"";
}
];
// Defines which text comparison method used for the type query.
zitadel.object.v2beta.TextQueryMethod method = 2 [
(validate.rules).enum.defined_only = true
];
}
enum FieldName {
FIELD_NAME_UNSPECIFIED = 0;
FIELD_NAME_ID = 1;
FIELD_NAME_CREATION_DATE = 2;
FIELD_NAME_CHANGE_DATE = 3;
FIELD_NAME_EMAIL = 4;
FIELD_NAME_PHONE = 5;
FIELD_NAME_STATE = 6;
FIELD_NAME_SCHEMA_ID = 7;
FIELD_NAME_SCHEMA_TYPE = 8;
}

View File

@ -0,0 +1,66 @@
syntax = "proto3";
package zitadel.user.v3alpha;
import "google/api/field_behavior.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/object/v2beta/object.proto";
import "zitadel/user/v3alpha/authenticator.proto";
import "zitadel/user/v3alpha/communication.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v3alpha";
message User {
// ID is the read-only unique identifier of the user.
string user_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 user.
zitadel.object.v2beta.Details details = 2;
// The user's authenticators. They are used to identify and authenticate the user
// during the authentication process.
Authenticators authenticators = 3;
// Contact information for the user. ZITADEL will use this in case of internal notifications.
Contact contact = 4;
// State of the user.
State state = 5;
// The schema the user and it's data is based on.
Schema schema = 6;
// The user's data based on the provided schema.
google.protobuf.Struct data = 7;
}
enum State {
USER_STATE_UNSPECIFIED = 0;
USER_STATE_ACTIVE = 1;
USER_STATE_INACTIVE = 2;
USER_STATE_DELETED = 3;
USER_STATE_LOCKED = 4;
}
message Schema {
// The unique identifier of the user schema.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629026806489455\""
}
];
// The human readable name of the user schema.
string type = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"employees\"";
}
];
// The revision the user's data is based on of the revision.
uint32 revision = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "7";
}
];
}

File diff suppressed because it is too large Load Diff