mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-09 07:35:13 +00:00
feat(api): add user creation to user service (#5745)
* chore(proto): update versions * change protoc plugin * some cleanups * define api for setting emails in new api * implement user.SetEmail * move SetEmail buisiness logic into command * resuse newCryptoCode * command: add ChangeEmail unit tests Not complete, was not able to mock the generator. * Revert "resuse newCryptoCode" This reverts commit c89e90ae35ae924a3f706a0a7394f933910c2e65. * undo change to crypto code generators * command: use a generator so we can test properly * command: reorganise ChangeEmail improve test coverage * implement VerifyEmail including unit tests * add URL template tests * begin user creation * change protos * implement metadata and move context * merge commands * proto: change context to object * remove old auth option * remove old auth option * fix linting errors run gci on modified files * add permission checks and fix some errors * comments * comments * update email requests * rename proto requests * cleanup and docs * simplify * simplify * fix setup * remove unused proto messages / fields --------- Co-authored-by: adlerhurst <[email protected]> Co-authored-by: Tim Möhlmann <[email protected]>
This commit is contained in:
co-authored by
adlerhurst
Tim Möhlmann
parent
19f2f83b61
commit
e4a4b7cfbe
@@ -6,11 +6,11 @@ option go_package = "github.com/zitadel/zitadel/pkg/grpc/object/v2alpha;object";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
message OrgContext {
|
||||
oneof ctx {
|
||||
message Organisation {
|
||||
oneof org {
|
||||
string org_id = 1;
|
||||
string org_domain = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,23 @@ import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
message SetHumanEmail {
|
||||
string email = 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 {
|
||||
SendEmailVerificationCode send_code = 2;
|
||||
ReturnEmailVerificationCode return_code = 3;
|
||||
bool is_verified = 4 [(validate.rules).bool.const = true];
|
||||
}
|
||||
}
|
||||
|
||||
message SendEmailVerificationCode {
|
||||
optional string url_template = 1 [
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.user.v2alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha;user";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
message SetUserPassword {
|
||||
oneof type {
|
||||
Password password = 1;
|
||||
HashedPassword hashed_password = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message Password {
|
||||
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;
|
||||
}
|
||||
];
|
||||
bool change_required = 2;
|
||||
}
|
||||
|
||||
message HashedPassword {
|
||||
string hash = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"$2a$12$lJ08fqVr8bFJilRVnDT9QeULI7YW.nT3iwUv6dyg0aCrfm3UY8XR2\"";
|
||||
description: "\"hashed password\"";
|
||||
min_length: 1,
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
string algorithm = 2 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200, const: "bcrypt"},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"bcrypt\"";
|
||||
description: "\"algorithm used for the hash. currently only bcrypt is supported\"";
|
||||
min_length: 1,
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
bool change_required = 3;
|
||||
}
|
||||
@@ -4,6 +4,87 @@ package zitadel.user.v2alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha;user";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
message User {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
enum Gender {
|
||||
GENDER_UNSPECIFIED = 0;
|
||||
GENDER_FEMALE = 1;
|
||||
GENDER_MALE = 2;
|
||||
GENDER_DIVERSE = 3;
|
||||
}
|
||||
|
||||
message SetHumanProfile {
|
||||
string first_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: "\"Minnie\"";
|
||||
}
|
||||
];
|
||||
string last_name = 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: "\"Mouse\"";
|
||||
}
|
||||
];
|
||||
optional string nick_name = 3 [
|
||||
(validate.rules).string = {max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
max_length: 200;
|
||||
example: "\"Mini\"";
|
||||
}
|
||||
];
|
||||
optional string display_name = 4 [
|
||||
(validate.rules).string = {max_len: 200},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
max_length: 200;
|
||||
example: "\"Minnie Mouse\"";
|
||||
}
|
||||
];
|
||||
optional string preferred_language = 5 [
|
||||
(validate.rules).string = {max_len: 10},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
max_length: 10;
|
||||
example: "\"en\"";
|
||||
}
|
||||
];
|
||||
optional zitadel.user.v2alpha.Gender gender = 6 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"GENDER_FEMALE\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
message SetMetadataEntry {
|
||||
string key = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"my-key\"";
|
||||
min_length: 1,
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
bytes value = 2 [
|
||||
(validate.rules).bytes = {min_len: 1, max_len: 500000},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "The value has to be base64 encoded.";
|
||||
example: "\"VGhpcyBpcyBteSB0ZXN0IHZhbHVl\"";
|
||||
min_length: 1,
|
||||
max_length: 500000;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ package zitadel.user.v2alpha;
|
||||
import "zitadel/options.proto";
|
||||
import "zitadel/object/v2alpha/object.proto";
|
||||
import "zitadel/user/v2alpha/email.proto";
|
||||
import "zitadel/user/v2alpha/password.proto";
|
||||
import "zitadel/user/v2alpha/user.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
@@ -12,8 +14,91 @@ import "validate/validate.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha;user";
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "User Service";
|
||||
version: "2.0-alpha";
|
||||
description: "This API is intended to manage users in a ZITADEL instance. This project is in alpha state. It can AND will continue breaking until the services provide the same functionality as the current login.";
|
||||
contact:{
|
||||
name: "ZITADEL"
|
||||
url: "https://zitadel.com"
|
||||
email: "[email protected]"
|
||||
}
|
||||
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: "/";
|
||||
|
||||
external_docs: {
|
||||
description: "Detailed information about ZITADEL",
|
||||
url: "https://zitadel.com/docs"
|
||||
}
|
||||
|
||||
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 UserService {
|
||||
|
||||
// Create a new human user
|
||||
rpc AddHumanUser (AddHumanUserRequest) returns (AddHumanUserResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v2alpha/users/human"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "user.write"
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
summary: "Create a user (Human)";
|
||||
description: "Create/import a new user with the type human. The newly created user will get a verification email if either the email address is not marked as verified and you did not request the verification to be returned."
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "OK";
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Change the email of a user
|
||||
rpc SetEmail (SetEmailRequest) returns (SetEmailResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v2alpha/users/{user_id}/email"
|
||||
@@ -23,8 +108,20 @@ service UserService {
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "authenticated"
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
summary: "Change the user email";
|
||||
description: "Change the email address of a user. If the state is set to not verified, a verification code will be generated, which can be either returned or sent to the user by email."
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "OK";
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Verify the email with the provided code
|
||||
rpc VerifyEmail (VerifyEmailRequest) returns (VerifyEmailResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v2alpha/users/{user_id}/email/_verify"
|
||||
@@ -34,9 +131,61 @@ service UserService {
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "authenticated"
|
||||
};
|
||||
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
summary: "Verify the email";
|
||||
description: "Verify the email with the generated code."
|
||||
responses: {
|
||||
key: "200"
|
||||
value: {
|
||||
description: "OK";
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message AddHumanUserRequest{
|
||||
// optionally set your own id unique for the user
|
||||
optional string user_id = 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: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
|
||||
}
|
||||
];
|
||||
// optionally set a unique username, if none is provided the email will be used
|
||||
optional string username = 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: "\"minnie-mouse\"";
|
||||
}
|
||||
];
|
||||
zitadel.object.v2alpha.Organisation organisation = 3;
|
||||
SetHumanProfile profile = 4 [
|
||||
(validate.rules).message.required = true,
|
||||
(google.api.field_behavior) = REQUIRED
|
||||
];
|
||||
SetHumanEmail email = 5 [
|
||||
(validate.rules).message.required = true,
|
||||
(google.api.field_behavior) = REQUIRED
|
||||
];
|
||||
repeated SetMetadataEntry metadata = 6;
|
||||
oneof password_type {
|
||||
Password password = 7;
|
||||
HashedPassword hashed_password = 8;
|
||||
}
|
||||
}
|
||||
|
||||
message AddHumanUserResponse {
|
||||
string user_id = 1;
|
||||
zitadel.object.v2alpha.Details details = 2;
|
||||
optional string email_code = 3;
|
||||
}
|
||||
|
||||
message SetEmailRequest{
|
||||
string user_id = 1 [
|
||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||
|
||||
Reference in New Issue
Block a user