feat: fixes (#228)

* feat: user login names

* fix: user login names

* fix: generate login name
This commit is contained in:
Fabi
2020-06-17 07:25:04 +02:00
committed by GitHub
parent f2cdae9ea3
commit 6fa62ccd0a
31 changed files with 7131 additions and 4888 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -145,7 +145,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserAddress"
"$ref": "#/definitions/v1UserAddressView"
}
}
},
@@ -185,7 +185,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserEmail"
"$ref": "#/definitions/v1UserEmailView"
}
}
},
@@ -387,7 +387,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserPhone"
"$ref": "#/definitions/v1UserPhoneView"
}
}
},
@@ -480,7 +480,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserProfile"
"$ref": "#/definitions/v1UserProfileView"
}
}
},
@@ -872,6 +872,41 @@
}
}
},
"v1UserAddressView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"country": {
"type": "string"
},
"locality": {
"type": "string"
},
"postal_code": {
"type": "string"
},
"region": {
"type": "string"
},
"street_address": {
"type": "string"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
}
}
},
"v1UserEmail": {
"type": "object",
"properties": {
@@ -899,6 +934,33 @@
}
}
},
"v1UserEmailView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"email": {
"type": "string"
},
"isEmailVerified": {
"type": "boolean",
"format": "boolean"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
}
}
},
"v1UserGrantSearchKey": {
"type": "string",
"enum": [
@@ -1021,6 +1083,33 @@
}
}
},
"v1UserPhoneView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"phone": {
"type": "string"
},
"is_phone_verified": {
"type": "boolean",
"format": "boolean"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
}
}
},
"v1UserProfile": {
"type": "object",
"properties": {
@@ -1062,6 +1151,56 @@
}
}
},
"v1UserProfileView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"user_name": {
"type": "string"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"nick_name": {
"type": "string"
},
"display_name": {
"type": "string"
},
"preferred_language": {
"type": "string"
},
"gender": {
"$ref": "#/definitions/v1Gender"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
},
"login_names": {
"type": "array",
"items": {
"type": "string"
}
},
"preferred_login_name": {
"type": "string"
}
}
},
"v1UserSessionState": {
"type": "string",
"enum": [

View File

@@ -8,36 +8,36 @@ import (
"github.com/caos/zitadel/internal/errors"
)
func (s *Server) GetMyUserProfile(ctx context.Context, _ *empty.Empty) (*UserProfile, error) {
func (s *Server) GetMyUserProfile(ctx context.Context, _ *empty.Empty) (*UserProfileView, error) {
profile, err := s.repo.MyProfile(ctx)
if err != nil {
return nil, err
}
return profileFromModel(profile), nil
return profileViewFromModel(profile), nil
}
func (s *Server) GetMyUserEmail(ctx context.Context, _ *empty.Empty) (*UserEmail, error) {
func (s *Server) GetMyUserEmail(ctx context.Context, _ *empty.Empty) (*UserEmailView, error) {
email, err := s.repo.MyEmail(ctx)
if err != nil {
return nil, err
}
return emailFromModel(email), nil
return emailViewFromModel(email), nil
}
func (s *Server) GetMyUserPhone(ctx context.Context, _ *empty.Empty) (*UserPhone, error) {
func (s *Server) GetMyUserPhone(ctx context.Context, _ *empty.Empty) (*UserPhoneView, error) {
phone, err := s.repo.MyPhone(ctx)
if err != nil {
return nil, err
}
return phoneFromModel(phone), nil
return phoneViewFromModel(phone), nil
}
func (s *Server) GetMyUserAddress(ctx context.Context, _ *empty.Empty) (*UserAddress, error) {
func (s *Server) GetMyUserAddress(ctx context.Context, _ *empty.Empty) (*UserAddressView, error) {
address, err := s.repo.MyAddress(ctx)
if err != nil {
return nil, err
}
return addressFromModel(address), nil
return addressViewFromModel(address), nil
}
func (s *Server) GetMyMfas(ctx context.Context, _ *empty.Empty) (*MultiFactors, error) {

View File

@@ -33,6 +33,30 @@ func profileFromModel(profile *usr_model.Profile) *UserProfile {
}
}
func profileViewFromModel(profile *usr_model.Profile) *UserProfileView {
creationDate, err := ptypes.TimestampProto(profile.CreationDate)
logging.Log("GRPC-s9iKs").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(profile.ChangeDate)
logging.Log("GRPC-9sujE").OnError(err).Debug("unable to parse timestamp")
return &UserProfileView{
Id: profile.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: profile.Sequence,
UserName: profile.UserName,
FirstName: profile.FirstName,
LastName: profile.LastName,
DisplayName: profile.DisplayName,
NickName: profile.NickName,
PreferredLanguage: profile.PreferredLanguage.String(),
Gender: genderFromModel(profile.Gender),
LoginNames: profile.LoginNames,
PreferredLoginName: profile.PreferredLoginName,
}
}
func updateProfileToModel(ctx context.Context, u *UpdateUserProfileRequest) *usr_model.Profile {
preferredLanguage, err := language.Parse(u.PreferredLanguage)
logging.Log("GRPC-lk73L").OnError(err).Debug("language malformed")
@@ -65,6 +89,23 @@ func emailFromModel(email *usr_model.Email) *UserEmail {
}
}
func emailViewFromModel(email *usr_model.Email) *UserEmailView {
creationDate, err := ptypes.TimestampProto(email.CreationDate)
logging.Log("GRPC-LSp8s").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(email.ChangeDate)
logging.Log("GRPC-6szJe").OnError(err).Debug("unable to parse timestamp")
return &UserEmailView{
Id: email.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: email.Sequence,
Email: email.EmailAddress,
IsEmailVerified: email.IsEmailVerified,
}
}
func updateEmailToModel(ctx context.Context, e *UpdateUserEmailRequest) *usr_model.Email {
return &usr_model.Email{
ObjectRoot: models.ObjectRoot{AggregateID: auth.GetCtxData(ctx).UserID},
@@ -89,6 +130,23 @@ func phoneFromModel(phone *usr_model.Phone) *UserPhone {
}
}
func phoneViewFromModel(phone *usr_model.Phone) *UserPhoneView {
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
logging.Log("GRPC-s5zJS").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(phone.ChangeDate)
logging.Log("GRPC-s9kLe").OnError(err).Debug("unable to parse timestamp")
return &UserPhoneView{
Id: phone.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: phone.Sequence,
Phone: phone.PhoneNumber,
IsPhoneVerified: phone.IsPhoneVerified,
}
}
func updatePhoneToModel(ctx context.Context, e *UpdateUserPhoneRequest) *usr_model.Phone {
return &usr_model.Phone{
ObjectRoot: models.ObjectRoot{AggregateID: auth.GetCtxData(ctx).UserID},
@@ -116,6 +174,26 @@ func addressFromModel(address *usr_model.Address) *UserAddress {
}
}
func addressViewFromModel(address *usr_model.Address) *UserAddressView {
creationDate, err := ptypes.TimestampProto(address.CreationDate)
logging.Log("GRPC-sk4fS").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(address.ChangeDate)
logging.Log("GRPC-9siEs").OnError(err).Debug("unable to parse timestamp")
return &UserAddressView{
Id: address.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: address.Sequence,
Country: address.Country,
StreetAddress: address.StreetAddress,
Region: address.Region,
PostalCode: address.PostalCode,
Locality: address.Locality,
}
}
func updateAddressToModel(ctx context.Context, address *UpdateUserAddressRequest) *usr_model.Address {
return &usr_model.Address{
ObjectRoot: models.ObjectRoot{AggregateID: auth.GetCtxData(ctx).UserID},

View File

@@ -46,18 +46,12 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc
for _, scope := range scopes {
switch scope {
case scopeOpenID:
userInfo.Subject = user.AggregateID
userInfo.Subject = user.ID
case scopeEmail:
if user.Email == nil {
continue
}
userInfo.Email = user.EmailAddress
userInfo.Email = user.Email
userInfo.EmailVerified = user.IsEmailVerified
case scopeProfile:
if user.Profile == nil {
continue
}
userInfo.Name = user.FirstName + " " + user.LastName
userInfo.Name = user.DisplayName
userInfo.FamilyName = user.LastName
userInfo.GivenName = user.FirstName
userInfo.Nickname = user.NickName
@@ -65,15 +59,9 @@ func (o *OPStorage) GetUserinfoFromScopes(ctx context.Context, userID string, sc
userInfo.UpdatedAt = user.ChangeDate
userInfo.Gender = oidc.Gender(getGender(user.Gender))
case scopePhone:
if user.Phone == nil {
continue
}
userInfo.PhoneNumber = user.PhoneNumber
userInfo.PhoneNumber = user.Phone
userInfo.PhoneNumberVerified = user.IsPhoneVerified
case scopeAddress:
if user.Address == nil {
continue
}
userInfo.Address.StreetAddress = user.StreetAddress
userInfo.Address.Locality = user.Locality
userInfo.Address.Region = user.Region

View File

@@ -62,7 +62,7 @@ service AuthService {
}
//User
rpc GetMyUserProfile(google.protobuf.Empty) returns (UserProfile) {
rpc GetMyUserProfile(google.protobuf.Empty) returns (UserProfileView) {
option (google.api.http) = {
get: "/users/me/profile"
};
@@ -83,7 +83,7 @@ service AuthService {
};
}
rpc GetMyUserEmail(google.protobuf.Empty) returns (UserEmail) {
rpc GetMyUserEmail(google.protobuf.Empty) returns (UserEmailView) {
option (google.api.http) = {
get: "/users/me/email"
};
@@ -126,7 +126,7 @@ service AuthService {
};
}
rpc GetMyUserPhone(google.protobuf.Empty) returns (UserPhone) {
rpc GetMyUserPhone(google.protobuf.Empty) returns (UserPhoneView) {
option (google.api.http) = {
get: "/users/me/phone"
};
@@ -169,7 +169,7 @@ service AuthService {
};
}
rpc GetMyUserAddress(google.protobuf.Empty) returns (UserAddress) {
rpc GetMyUserAddress(google.protobuf.Empty) returns (UserAddressView) {
option (google.api.http) = {
get: "/users/me/address"
};
@@ -326,6 +326,8 @@ message User {
string street_address = 23;
bool password_change_required = 24;
uint64 sequence = 25;
repeated string login_names = 26;
string preferred_login_name = 27;
}
enum UserState {
@@ -359,6 +361,22 @@ message UserProfile {
google.protobuf.Timestamp change_date = 11;
}
message UserProfileView {
string id = 1;
string user_name = 2;
string first_name = 3;
string last_name = 4;
string nick_name = 5;
string display_name = 6;
string preferred_language = 7;
Gender gender = 8;
uint64 sequence = 9;
google.protobuf.Timestamp creation_date = 10;
google.protobuf.Timestamp change_date = 11;
repeated string login_names = 12;
string preferred_login_name = 13;
}
message UpdateUserProfileRequest {
string first_name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
string last_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
@@ -377,6 +395,15 @@ message UserEmail {
google.protobuf.Timestamp change_date = 6;
}
message UserEmailView {
string id = 1;
string email = 2;
bool isEmailVerified = 3;
uint64 sequence = 4;
google.protobuf.Timestamp creation_date = 5;
google.protobuf.Timestamp change_date = 6;
}
message VerifyMyUserEmailRequest {
string code = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
}
@@ -399,6 +426,15 @@ message UserPhone {
google.protobuf.Timestamp change_date = 6;
}
message UserPhoneView {
string id = 1;
string phone = 2;
bool is_phone_verified = 3;
uint64 sequence = 4;
google.protobuf.Timestamp creation_date = 5;
google.protobuf.Timestamp change_date = 6;
}
message UpdateUserPhoneRequest {
string phone = 1 [(validate.rules).string = {min_len: 1, max_len: 20}];
}
@@ -419,6 +455,18 @@ message UserAddress {
google.protobuf.Timestamp change_date = 9;
}
message UserAddressView {
string id = 1;
string country = 2;
string locality = 3;
string postal_code = 4;
string region = 5;
string street_address = 6;
uint64 sequence = 7;
google.protobuf.Timestamp creation_date = 8;
google.protobuf.Timestamp change_date = 9;
}
message UpdateUserAddressRequest {
string country = 1 [(validate.rules).string = {max_len: 200}];
string locality = 2 [(validate.rules).string = {max_len: 200}];

View File

@@ -3,7 +3,6 @@ package grpc
import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/golang/protobuf/ptypes/empty"
)
@@ -38,9 +37,6 @@ func (s *Server) UpdateApplication(ctx context.Context, in *ApplicationUpdate) (
return appFromModel(app), nil
}
func (s *Server) DeactivateApplication(ctx context.Context, in *ApplicationID) (*Application, error) {
if s.IsZitadel(ctx, in.ProjectId) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSped", "Zitadel Project Applications should not be deactivated")
}
app, err := s.project.DeactivateApplication(ctx, in.ProjectId, in.Id)
if err != nil {
return nil, err
@@ -56,17 +52,11 @@ func (s *Server) ReactivateApplication(ctx context.Context, in *ApplicationID) (
}
func (s *Server) RemoveApplication(ctx context.Context, in *ApplicationID) (*empty.Empty, error) {
if s.IsZitadel(ctx, in.ProjectId) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpee", "Zitadel Project Applications should not be removed")
}
err := s.project.RemoveApplication(ctx, in.ProjectId, in.Id)
return &empty.Empty{}, err
}
func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfigUpdate) (*OIDCConfig, error) {
if s.IsZitadel(ctx, in.ProjectId) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpee", "Zitadel Project Applications OIdc Config should not be changed")
}
config, err := s.project.ChangeOIDCConfig(ctx, oidcConfigUpdateToModel(in))
if err != nil {
return nil, err
@@ -75,9 +65,6 @@ func (s *Server) UpdateApplicationOIDCConfig(ctx context.Context, in *OIDCConfig
}
func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *ApplicationID) (*ClientSecret, error) {
if s.IsZitadel(ctx, in.ProjectId) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-Lps4d", "Zitadel Project Applications OIdc Config should not be changed")
}
config, err := s.project.ChangeOIDConfigSecret(ctx, in.ProjectId, in.Id)
if err != nil {
return nil, err

View File

@@ -0,0 +1,14 @@
package grpc
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetIam(ctx context.Context, _ *empty.Empty) (*Iam, error) {
iam, err := s.iam.IamByID(ctx, s.systemDefaults.IamID)
if err != nil {
return nil, err
}
return iamFromModel(iam), nil
}

View File

@@ -0,0 +1,14 @@
package grpc
import (
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func iamFromModel(iam *iam_model.Iam) *Iam {
return &Iam{
IamProjectId: iam.IamProjectID,
GlobalOrgId: iam.GlobalOrgID,
SetUpDone: iam.SetUpDone,
SetUpStarted: iam.SetUpStarted,
}
}

View File

@@ -15,6 +15,11 @@ import (
var ManagementService_AuthMethods = utils_auth.MethodMapping{
"/caos.zitadel.management.api.v1.ManagementService/GetIam": utils_auth.Option{
Permission: "authenticated",
CheckParam: "",
},
"/caos.zitadel.management.api.v1.ManagementService/GetUserByID": utils_auth.Option{
Permission: "user.read",
CheckParam: "",

File diff suppressed because it is too large Load Diff

View File

@@ -56,6 +56,15 @@ func request_ManagementService_Validate_0(ctx context.Context, marshaler runtime
}
func request_ManagementService_GetIam_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq empty.Empty
var metadata runtime.ServerMetadata
msg, err := client.GetIam(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func request_ManagementService_GetUserByID_0(ctx context.Context, marshaler runtime.Marshaler, client ManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq UserID
var metadata runtime.ServerMetadata
@@ -3760,6 +3769,26 @@ func RegisterManagementServiceHandlerClient(ctx context.Context, mux *runtime.Se
})
mux.Handle("GET", pattern_ManagementService_GetIam_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_ManagementService_GetIam_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_ManagementService_GetIam_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_ManagementService_GetUserByID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -5950,6 +5979,8 @@ var (
pattern_ManagementService_Validate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"validate"}, ""))
pattern_ManagementService_GetIam_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"iam"}, ""))
pattern_ManagementService_GetUserByID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"users", "id"}, ""))
pattern_ManagementService_GetUserByEmailGlobal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 2}, []string{"global", "users", "email"}, ""))
@@ -6176,6 +6207,8 @@ var (
forward_ManagementService_Validate_0 = runtime.ForwardResponseMessage
forward_ManagementService_GetIam_0 = runtime.ForwardResponseMessage
forward_ManagementService_GetUserByID_0 = runtime.ForwardResponseMessage
forward_ManagementService_GetUserByEmailGlobal_0 = runtime.ForwardResponseMessage

View File

@@ -209,6 +209,23 @@
]
}
},
"/iam": {
"get": {
"summary": "IAM",
"operationId": "GetIam",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1Iam"
}
}
},
"tags": [
"ManagementService"
]
}
},
"/orgs/me/domains": {
"post": {
"operationId": "AddMyOrgDomain",
@@ -2663,7 +2680,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1User"
"$ref": "#/definitions/v1UserView"
}
}
},
@@ -2904,7 +2921,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserAddress"
"$ref": "#/definitions/v1UserAddressView"
}
}
},
@@ -3003,7 +3020,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserEmail"
"$ref": "#/definitions/v1UserEmailView"
}
}
},
@@ -3115,7 +3132,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserPhone"
"$ref": "#/definitions/v1UserPhoneView"
}
}
},
@@ -3202,7 +3219,7 @@
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1UserProfile"
"$ref": "#/definitions/v1UserProfileView"
}
}
},
@@ -3959,6 +3976,25 @@
}
}
},
"v1Iam": {
"type": "object",
"properties": {
"global_org_id": {
"type": "string"
},
"iam_project_id": {
"type": "string"
},
"set_up_done": {
"type": "boolean",
"format": "boolean"
},
"set_up_started": {
"type": "boolean",
"format": "boolean"
}
}
},
"v1MFAState": {
"type": "string",
"enum": [
@@ -5960,6 +5996,41 @@
}
}
},
"v1UserAddressView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"country": {
"type": "string"
},
"locality": {
"type": "string"
},
"postal_code": {
"type": "string"
},
"region": {
"type": "string"
},
"street_address": {
"type": "string"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
}
}
},
"v1UserEmail": {
"type": "object",
"properties": {
@@ -5987,6 +6058,33 @@
}
}
},
"v1UserEmailView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"email": {
"type": "string"
},
"is_email_verified": {
"type": "boolean",
"format": "boolean"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
}
}
},
"v1UserGrant": {
"type": "object",
"properties": {
@@ -6242,6 +6340,33 @@
}
}
},
"v1UserPhoneView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"phone": {
"type": "string"
},
"is_phone_verified": {
"type": "boolean",
"format": "boolean"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
}
}
},
"v1UserProfile": {
"type": "object",
"properties": {
@@ -6283,6 +6408,56 @@
}
}
},
"v1UserProfileView": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"nick_name": {
"type": "string"
},
"display_name": {
"type": "string"
},
"preferred_language": {
"type": "string"
},
"gender": {
"$ref": "#/definitions/v1Gender"
},
"user_name": {
"type": "string"
},
"sequence": {
"type": "string",
"format": "uint64"
},
"creation_date": {
"type": "string",
"format": "date-time"
},
"change_date": {
"type": "string",
"format": "date-time"
},
"login_names": {
"type": "array",
"items": {
"type": "string"
}
},
"preferred_login_name": {
"type": "string"
}
}
},
"v1UserSearchKey": {
"type": "string",
"enum": [
@@ -6454,6 +6629,15 @@
},
"resource_owner": {
"type": "string"
},
"login_names": {
"type": "array",
"items": {
"type": "string"
}
},
"preferred_login_name": {
"type": "string"
}
}
}

View File

@@ -6,7 +6,6 @@ import (
"github.com/caos/zitadel/internal/api"
"github.com/caos/zitadel/internal/api/auth"
grpc_util "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/errors"
"github.com/golang/protobuf/ptypes/empty"
)
@@ -18,9 +17,6 @@ func (s *Server) CreateProject(ctx context.Context, in *ProjectCreateRequest) (*
return projectFromModel(project), nil
}
func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (*Project, error) {
if s.IsZitadel(ctx, in.Id) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-SFH8d", "Zitadel Project should not be updated")
}
project, err := s.project.UpdateProject(ctx, projectUpdateToModel(in))
if err != nil {
return nil, err
@@ -28,9 +24,6 @@ func (s *Server) UpdateProject(ctx context.Context, in *ProjectUpdateRequest) (*
return projectFromModel(project), nil
}
func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project, error) {
if s.IsZitadel(ctx, in.Id) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-PS9cs", "Zitadel Project should not be deactivated")
}
project, err := s.project.DeactivateProject(ctx, in.Id)
if err != nil {
return nil, err
@@ -38,9 +31,6 @@ func (s *Server) DeactivateProject(ctx context.Context, in *ProjectID) (*Project
return projectFromModel(project), nil
}
func (s *Server) ReactivateProject(ctx context.Context, in *ProjectID) (*Project, error) {
if s.IsZitadel(ctx, in.Id) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LSpe2", "Zitadel Project should not be reactivated")
}
project, err := s.project.ReactivateProject(ctx, in.Id)
if err != nil {
return nil, err
@@ -85,9 +75,6 @@ func (s *Server) GetGrantedProjectByID(ctx context.Context, in *ProjectGrantID)
}
func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*ProjectRole, error) {
if s.IsZitadel(ctx, in.Id) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-PS9cs", "Zitadel Project should not get new role")
}
role, err := s.project.AddProjectRole(ctx, projectRoleAddToModel(in))
if err != nil {
return nil, err
@@ -95,9 +82,6 @@ func (s *Server) AddProjectRole(ctx context.Context, in *ProjectRoleAdd) (*Proje
return projectRoleFromModel(role), nil
}
func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) (*ProjectRole, error) {
if s.IsZitadel(ctx, in.Id) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-LASj8", "Zitadel Project should not change roles")
}
role, err := s.project.ChangeProjectRole(ctx, projectRoleChangeToModel(in))
if err != nil {
return nil, err
@@ -106,9 +90,6 @@ func (s *Server) ChangeProjectRole(ctx context.Context, in *ProjectRoleChange) (
}
func (s *Server) RemoveProjectRole(ctx context.Context, in *ProjectRoleRemove) (*empty.Empty, error) {
if s.IsZitadel(ctx, in.Id) {
return nil, errors.ThrowInvalidArgument(nil, "GRPC-Psn7s", "do not remove roles from Zitadel Project")
}
err := s.project.RemoveProjectRole(ctx, in.Id, in.Key)
return &empty.Empty{}, err
}
@@ -131,14 +112,3 @@ func (s *Server) ProjectChanges(ctx context.Context, changesRequest *ChangeReque
}
return projectChangesToResponse(response, changesRequest.GetSequenceOffset(), changesRequest.GetLimit()), nil
}
func (s *Server) IsZitadel(ctx context.Context, projectID string) bool {
iam, err := s.iam.IamByID(ctx, s.systemDefaults.IamID)
if err != nil {
return false
}
if iam.IamProjectID == projectID {
return true
}
return false
}

View File

@@ -9,12 +9,12 @@ import (
"github.com/golang/protobuf/ptypes/empty"
)
func (s *Server) GetUserByID(ctx context.Context, id *UserID) (*User, error) {
func (s *Server) GetUserByID(ctx context.Context, id *UserID) (*UserView, error) {
user, err := s.user.UserByID(ctx, id.Id)
if err != nil {
return nil, err
}
return userFromModel(user), nil
return userViewFromModel(user), nil
}
func (s *Server) GetUserByEmailGlobal(ctx context.Context, email *UserEmailID) (*UserView, error) {
@@ -96,12 +96,12 @@ func (s *Server) DeleteUser(ctx context.Context, in *UserID) (*empty.Empty, erro
return nil, errors.ThrowUnimplemented(nil, "GRPC-as4fg", "Not implemented")
}
func (s *Server) GetUserProfile(ctx context.Context, in *UserID) (*UserProfile, error) {
func (s *Server) GetUserProfile(ctx context.Context, in *UserID) (*UserProfileView, error) {
profile, err := s.user.ProfileByID(ctx, in.Id)
if err != nil {
return nil, err
}
return profileFromModel(profile), nil
return profileViewFromModel(profile), nil
}
func (s *Server) UpdateUserProfile(ctx context.Context, request *UpdateUserProfileRequest) (*UserProfile, error) {
@@ -112,12 +112,12 @@ func (s *Server) UpdateUserProfile(ctx context.Context, request *UpdateUserProfi
return profileFromModel(profile), nil
}
func (s *Server) GetUserEmail(ctx context.Context, in *UserID) (*UserEmail, error) {
func (s *Server) GetUserEmail(ctx context.Context, in *UserID) (*UserEmailView, error) {
email, err := s.user.EmailByID(ctx, in.Id)
if err != nil {
return nil, err
}
return emailFromModel(email), nil
return emailViewFromModel(email), nil
}
func (s *Server) ChangeUserEmail(ctx context.Context, request *UpdateUserEmailRequest) (*UserEmail, error) {
@@ -133,12 +133,12 @@ func (s *Server) ResendEmailVerificationMail(ctx context.Context, in *UserID) (*
return &empty.Empty{}, err
}
func (s *Server) GetUserPhone(ctx context.Context, in *UserID) (*UserPhone, error) {
func (s *Server) GetUserPhone(ctx context.Context, in *UserID) (*UserPhoneView, error) {
phone, err := s.user.PhoneByID(ctx, in.Id)
if err != nil {
return nil, err
}
return phoneFromModel(phone), nil
return phoneViewFromModel(phone), nil
}
func (s *Server) ChangeUserPhone(ctx context.Context, request *UpdateUserPhoneRequest) (*UserPhone, error) {
@@ -154,12 +154,12 @@ func (s *Server) ResendPhoneVerificationCode(ctx context.Context, in *UserID) (*
return &empty.Empty{}, err
}
func (s *Server) GetUserAddress(ctx context.Context, in *UserID) (*UserAddress, error) {
func (s *Server) GetUserAddress(ctx context.Context, in *UserID) (*UserAddressView, error) {
address, err := s.user.AddressByID(ctx, in.Id)
if err != nil {
return nil, err
}
return addressFromModel(address), nil
return addressViewFromModel(address), nil
}
func (s *Server) UpdateUserAddress(ctx context.Context, request *UpdateUserAddressRequest) (*UserAddress, error) {

View File

@@ -160,6 +160,30 @@ func profileFromModel(profile *usr_model.Profile) *UserProfile {
}
}
func profileViewFromModel(profile *usr_model.Profile) *UserProfileView {
creationDate, err := ptypes.TimestampProto(profile.CreationDate)
logging.Log("GRPC-sk8sk").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(profile.ChangeDate)
logging.Log("GRPC-s30Ks'").OnError(err).Debug("unable to parse timestamp")
return &UserProfileView{
Id: profile.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: profile.Sequence,
UserName: profile.UserName,
FirstName: profile.FirstName,
LastName: profile.LastName,
DisplayName: profile.DisplayName,
NickName: profile.NickName,
PreferredLanguage: profile.PreferredLanguage.String(),
Gender: genderFromModel(profile.Gender),
LoginNames: profile.LoginNames,
PreferredLoginName: profile.PreferredLoginName,
}
}
func updateProfileToModel(u *UpdateUserProfileRequest) *usr_model.Profile {
preferredLanguage, err := language.Parse(u.PreferredLanguage)
logging.Log("GRPC-d8k2s").OnError(err).Debug("language malformed")
@@ -192,6 +216,23 @@ func emailFromModel(email *usr_model.Email) *UserEmail {
}
}
func emailViewFromModel(email *usr_model.Email) *UserEmailView {
creationDate, err := ptypes.TimestampProto(email.CreationDate)
logging.Log("GRPC-sKefs").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(email.ChangeDate)
logging.Log("GRPC-0isjD").OnError(err).Debug("unable to parse timestamp")
return &UserEmailView{
Id: email.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: email.Sequence,
Email: email.EmailAddress,
IsEmailVerified: email.IsEmailVerified,
}
}
func updateEmailToModel(e *UpdateUserEmailRequest) *usr_model.Email {
return &usr_model.Email{
ObjectRoot: models.ObjectRoot{AggregateID: e.Id},
@@ -217,6 +258,22 @@ func phoneFromModel(phone *usr_model.Phone) *UserPhone {
}
}
func phoneViewFromModel(phone *usr_model.Phone) *UserPhoneView {
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
logging.Log("GRPC-6gSj").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(phone.ChangeDate)
logging.Log("GRPC-lKs8f").OnError(err).Debug("unable to parse timestamp")
return &UserPhoneView{
Id: phone.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: phone.Sequence,
Phone: phone.PhoneNumber,
IsPhoneVerified: phone.IsPhoneVerified,
}
}
func updatePhoneToModel(e *UpdateUserPhoneRequest) *usr_model.Phone {
return &usr_model.Phone{
ObjectRoot: models.ObjectRoot{AggregateID: e.Id},
@@ -245,6 +302,26 @@ func addressFromModel(address *usr_model.Address) *UserAddress {
}
}
func addressViewFromModel(address *usr_model.Address) *UserAddressView {
creationDate, err := ptypes.TimestampProto(address.CreationDate)
logging.Log("GRPC-67stC").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(address.ChangeDate)
logging.Log("GRPC-0jSfs").OnError(err).Debug("unable to parse timestamp")
return &UserAddressView{
Id: address.AggregateID,
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: address.Sequence,
Country: address.Country,
StreetAddress: address.StreetAddress,
Region: address.Region,
PostalCode: address.PostalCode,
Locality: address.Locality,
}
}
func updateAddressToModel(address *UpdateUserAddressRequest) *usr_model.Address {
return &usr_model.Address{
ObjectRoot: models.ObjectRoot{AggregateID: address.Id},
@@ -287,27 +364,29 @@ func userViewFromModel(user *usr_model.UserView) *UserView {
logging.Log("GRPC-dl9ws").OnError(err).Debug("unable to parse timestamp")
return &UserView{
Id: user.ID,
State: userStateFromModel(user.State),
CreationDate: creationDate,
ChangeDate: changeDate,
LastLogin: lastLogin,
PasswordChanged: passwordChanged,
Sequence: user.Sequence,
ResourceOwner: user.ResourceOwner,
UserName: user.UserName,
FirstName: user.FirstName,
LastName: user.LastName,
NickName: user.NickName,
Email: user.Email,
IsEmailVerified: user.IsEmailVerified,
Phone: user.Phone,
IsPhoneVerified: user.IsPhoneVerified,
Country: user.Country,
Locality: user.Locality,
Region: user.Region,
PostalCode: user.PostalCode,
StreetAddress: user.StreetAddress,
Id: user.ID,
State: userStateFromModel(user.State),
CreationDate: creationDate,
ChangeDate: changeDate,
LastLogin: lastLogin,
PasswordChanged: passwordChanged,
Sequence: user.Sequence,
ResourceOwner: user.ResourceOwner,
UserName: user.UserName,
FirstName: user.FirstName,
LastName: user.LastName,
NickName: user.NickName,
Email: user.Email,
IsEmailVerified: user.IsEmailVerified,
Phone: user.Phone,
IsPhoneVerified: user.IsPhoneVerified,
Country: user.Country,
Locality: user.Locality,
Region: user.Region,
PostalCode: user.PostalCode,
StreetAddress: user.StreetAddress,
LoginNames: user.LoginNames,
PreferredLoginName: user.PreferredLoginName,
}
}

View File

@@ -51,8 +51,19 @@ service ManagementService {
};
}
//IAM
rpc GetIam(google.protobuf.Empty) returns (Iam) {
option (google.api.http) = {
get: "/iam"
};
option (caos.zitadel.utils.v1.auth_option) = {
permission: "authenticated"
};
}
//USER
rpc GetUserByID(UserID) returns (User) {
rpc GetUserByID(UserID) returns (UserView) {
option (google.api.http) = {
get: "/users/{id}"
};
@@ -199,7 +210,7 @@ service ManagementService {
}
//USER_PROFILE
rpc GetUserProfile(UserID) returns (UserProfile) {
rpc GetUserProfile(UserID) returns (UserProfileView) {
option (google.api.http) = {
get: "/users/{id}/profile"
};
@@ -221,7 +232,7 @@ service ManagementService {
}
//USER_EMAIL
rpc GetUserEmail(UserID) returns (UserEmail) {
rpc GetUserEmail(UserID) returns (UserEmailView) {
option (google.api.http) = {
get: "/users/{id}/email"
};
@@ -254,7 +265,7 @@ service ManagementService {
}
//USER_PHONE
rpc GetUserPhone(UserID) returns (UserPhone) {
rpc GetUserPhone(UserID) returns (UserPhoneView) {
option (google.api.http) = {
get: "/users/{id}/phone"
};
@@ -287,7 +298,7 @@ service ManagementService {
}
//USER_ADDRESS
rpc GetUserAddress(UserID) returns (UserAddress) {
rpc GetUserAddress(UserID) returns (UserAddressView) {
option (google.api.http) = {
get: "/users/{id}/address"
};
@@ -1266,6 +1277,13 @@ service ManagementService {
}
}
message Iam {
string global_org_id = 1;
string iam_project_id = 2;
bool set_up_done = 3;
bool set_up_started = 4;
}
message ChangeRequest {
string id = 1;
string sec_id = 2;
@@ -1399,6 +1417,8 @@ message UserView {
string street_address = 22;
uint64 sequence = 23;
string resource_owner = 24;
repeated string login_names = 25;
string preferred_login_name = 27;
}
message UserSearchRequest {
@@ -1456,6 +1476,22 @@ message UserProfile {
google.protobuf.Timestamp change_date = 11;
}
message UserProfileView {
string id = 1;
string first_name = 2;
string last_name = 3;
string nick_name = 4;
string display_name = 5;
string preferred_language = 6;
Gender gender = 7;
string user_name = 8;
uint64 sequence = 9;
google.protobuf.Timestamp creation_date = 10;
google.protobuf.Timestamp change_date = 11;
repeated string login_names = 12;
string preferred_login_name = 27;
}
message UpdateUserProfileRequest {
string id = 1;
string first_name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
@@ -1475,6 +1511,15 @@ message UserEmail {
google.protobuf.Timestamp change_date = 6;
}
message UserEmailView {
string id = 1;
string email = 2;
bool is_email_verified = 3;
uint64 sequence = 4;
google.protobuf.Timestamp creation_date = 5;
google.protobuf.Timestamp change_date = 6;
}
message UpdateUserEmailRequest {
string id = 1;
string email = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
@@ -1490,6 +1535,15 @@ message UserPhone {
google.protobuf.Timestamp change_date = 7;
}
message UserPhoneView {
string id = 1;
string phone = 2;
bool is_phone_verified = 3;
uint64 sequence = 5;
google.protobuf.Timestamp creation_date = 6;
google.protobuf.Timestamp change_date = 7;
}
message UpdateUserPhoneRequest {
string id = 1;
string phone = 2 [(validate.rules).string = {min_len: 1, max_len: 20}];
@@ -1508,6 +1562,18 @@ message UserAddress {
google.protobuf.Timestamp change_date = 9;
}
message UserAddressView {
string id = 1;
string country = 2;
string locality = 3;
string postal_code = 4;
string region = 5;
string street_address = 6;
uint64 sequence = 7;
google.protobuf.Timestamp creation_date = 8;
google.protobuf.Timestamp change_date = 9;
}
message UpdateUserAddressRequest {
string id = 1;
string country = 2 [(validate.rules).string = {max_len: 200}];