mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 17:57:33 +00:00
feat: user v2alpha email API (#5708)
* 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 c89e90ae35
.
* 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
* 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
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
@@ -2801,7 +2801,7 @@ service AdminService {
|
||||
|
||||
rpc ResetCustomPasswordResetMessageTextToDefault(ResetCustomPasswordResetMessageTextToDefaultRequest) returns (ResetCustomPasswordResetMessageTextToDefaultResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/text/message/verifyemail/{language}"
|
||||
delete: "/text/message/passwordreset/{language}"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
|
@@ -5588,7 +5588,7 @@ service ManagementService {
|
||||
|
||||
rpc ResetCustomPasswordResetMessageTextToDefault(ResetCustomPasswordResetMessageTextToDefaultRequest) returns (ResetCustomPasswordResetMessageTextToDefaultResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/text/message/verifyemail/{language}"
|
||||
delete: "/text/message/passwordreset/{language}"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
|
40
proto/zitadel/object/v2alpha/object.proto
Normal file
40
proto/zitadel/object/v2alpha/object.proto
Normal file
@@ -0,0 +1,40 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.object.v2alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/object/v2alpha;object";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
message OrgContext {
|
||||
oneof ctx {
|
||||
string org_id = 1;
|
||||
string org_domain = 2;
|
||||
}
|
||||
}
|
||||
|
||||
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 is the organization or instance_id an object belongs to
|
||||
string resource_owner = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"69629023906488334\"";
|
||||
}
|
||||
];
|
||||
}
|
27
proto/zitadel/user/v2alpha/email.proto
Normal file
27
proto/zitadel/user/v2alpha/email.proto
Normal file
@@ -0,0 +1,27 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package zitadel.user.v2alpha;
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha;user";
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
|
||||
message SendEmailVerificationCode {
|
||||
optional string url_template = 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: "\"https://example.com/email/verify?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
|
||||
description: "\"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.\""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message ReturnEmailVerificationCode {}
|
||||
|
@@ -3,39 +3,32 @@ syntax = "proto3";
|
||||
package zitadel.user.v2alpha;
|
||||
|
||||
import "zitadel/options.proto";
|
||||
import "zitadel/user/v2alpha/user.proto";
|
||||
import "zitadel/object/v2alpha/object.proto";
|
||||
import "zitadel/user/v2alpha/email.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/field_behavior.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "validate/validate.proto";
|
||||
|
||||
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha;user";
|
||||
|
||||
service UserService {
|
||||
|
||||
// TestGet simply demonstrates how the context (org, instance) could be handled in a GET request //
|
||||
//
|
||||
// this request is subject to change and currently used for demonstration only
|
||||
rpc TestGet (TestGetRequest) returns (TestGetResponse) {
|
||||
rpc SetEmail (SetEmailRequest) returns (SetEmailResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v2alpha/users/test"
|
||||
};
|
||||
}
|
||||
|
||||
// TestPOST simply demonstrates how the context (org, instance) could be handled in a POST request
|
||||
//
|
||||
// this request is subject to change and currently used for demonstration only
|
||||
rpc TestPost (TestPostRequest) returns (TestPostResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v2alpha/users/test"
|
||||
post: "/v2alpha/users/{user_id}/email"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "authenticated"
|
||||
};
|
||||
}
|
||||
|
||||
// TestAuth demonstrates how the context (org, instance) could be handled in combination of the authorized context
|
||||
//
|
||||
// this request is subject to change and currently used for demonstration only
|
||||
rpc TestAuth (TestAuthRequest) returns (TestAuthResponse) {
|
||||
rpc VerifyEmail (VerifyEmailRequest) returns (VerifyEmailResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v2alpha/users/test_auth"
|
||||
post: "/v2alpha/users/{user_id}/email/_verify"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
@@ -44,35 +37,61 @@ service UserService {
|
||||
}
|
||||
}
|
||||
|
||||
message TestGetRequest{
|
||||
Context ctx = 1;
|
||||
}
|
||||
|
||||
message TestGetResponse{
|
||||
string ctx = 1;
|
||||
}
|
||||
|
||||
message TestPostRequest{
|
||||
Context ctx = 1;
|
||||
}
|
||||
|
||||
message TestPostResponse{
|
||||
string ctx = 1;
|
||||
}
|
||||
|
||||
message TestAuthRequest{
|
||||
Context ctx = 1;
|
||||
}
|
||||
|
||||
message TestAuthResponse{
|
||||
User user = 1;
|
||||
Context ctx = 2;
|
||||
}
|
||||
|
||||
message Context {
|
||||
oneof ctx {
|
||||
bool instance = 1;
|
||||
string org_id = 2;
|
||||
string org_domain = 3;
|
||||
message SetEmailRequest{
|
||||
string user_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\"";
|
||||
}
|
||||
];
|
||||
string email = 2 [
|
||||
(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 = 3;
|
||||
ReturnEmailVerificationCode return_code = 4;
|
||||
bool is_verified = 5 [(validate.rules).bool.const = true];
|
||||
}
|
||||
}
|
||||
|
||||
message SetEmailResponse{
|
||||
zitadel.object.v2alpha.Details details = 1;
|
||||
// in case the verification was set to return_code, the code will be returned
|
||||
optional string verification_code = 2;
|
||||
}
|
||||
|
||||
message VerifyEmailRequest{
|
||||
string user_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\"";
|
||||
}
|
||||
];
|
||||
string verification_code = 2 [
|
||||
(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: "\"SKJd342k\"";
|
||||
description: "\"the verification code generated during the set email request\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message VerifyEmailResponse{
|
||||
zitadel.object.v2alpha.Details details = 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user