diff --git a/internal/admin/repository/eventsourcing/handler/iam_member.go b/internal/admin/repository/eventsourcing/handler/iam_member.go index aceef8b55..be26a3bce 100644 --- a/internal/admin/repository/eventsourcing/handler/iam_member.go +++ b/internal/admin/repository/eventsourcing/handler/iam_member.go @@ -2,8 +2,14 @@ package handler import ( "context" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1" + es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" + iam_view "github.com/caos/zitadel/internal/iam/repository/view" + org_model "github.com/caos/zitadel/internal/org/model" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" + org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/user/repository/view" view_model "github.com/caos/zitadel/internal/user/repository/view/model" @@ -11,8 +17,10 @@ import ( es_models "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/spooler" + iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" + iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" usr_model "github.com/caos/zitadel/internal/user/model" usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) @@ -84,7 +92,7 @@ func (m *IAMMember) Reduce(event *es_models.Event) (err error) { } func (m *IAMMember) processIAMMember(event *es_models.Event) (err error) { - member := new(iam_model.IAMMemberView) + member := new(iam_view_model.IAMMemberView) switch event.Type { case model.IAMMemberAdded: err = member.AppendEvent(event) @@ -146,17 +154,25 @@ func (m *IAMMember) processUser(event *es_models.Event) (err error) { } } -func (m *IAMMember) fillData(member *iam_model.IAMMemberView) (err error) { +func (m *IAMMember) fillData(member *iam_view_model.IAMMemberView) (err error) { user, err := m.getUserByID(member.UserID) if err != nil { return err } - m.fillUserData(member, user) - return nil + return m.fillUserData(member, user) } -func (m *IAMMember) fillUserData(member *iam_model.IAMMemberView, user *view_model.UserView) { +func (m *IAMMember) fillUserData(member *iam_view_model.IAMMemberView, user *view_model.UserView) error { + org, err := m.getOrgByID(context.Background(), user.ResourceOwner) + policy := org.OrgIamPolicy + if policy == nil { + policy, err = m.getDefaultOrgIAMPolicy(context.TODO()) + if err != nil { + return err + } + } member.UserName = user.UserName + member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) if user.HumanView != nil { member.FirstName = user.FirstName member.LastName = user.LastName @@ -166,7 +182,9 @@ func (m *IAMMember) fillUserData(member *iam_model.IAMMemberView, user *view_mod if user.MachineView != nil { member.DisplayName = user.MachineView.Name } + return nil } + func (m *IAMMember) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Ld9ow", "id", event.AggregateID).WithError(err).Warn("something went wrong in iammember handler") return spooler.HandleError(event, err, m.view.GetLatestIAMMemberFailedEvent, m.view.ProcessedIAMMemberFailedEvent, m.view.ProcessedIAMMemberSequence, m.errorCountUntilSkip) @@ -208,3 +226,53 @@ func (m *IAMMember) getUserEvents(userID string, sequence uint64) ([]*es_models. return m.es.FilterEvents(context.Background(), query) } + +func (u *IAMMember) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) { + query, err := org_view.OrgByIDQuery(orgID, 0) + if err != nil { + return nil, err + } + + esOrg := &org_es_model.Org{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: orgID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query) + if err != nil && !caos_errs.IsNotFound(err) { + return nil, err + } + if esOrg.Sequence == 0 { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-3nd7s", "Errors.Org.NotFound") + } + + return org_es_model.OrgToModel(esOrg), nil +} + +func (u *IAMMember) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) { + existingIAM, err := u.getIAMByID(ctx) + if err != nil { + return nil, err + } + if existingIAM.DefaultOrgIAMPolicy == nil { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-3Bf7s", "Errors.IAM.OrgIAMPolicy.NotExisting") + } + return existingIAM.DefaultOrgIAMPolicy, nil +} + +func (u *IAMMember) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { + query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) + if err != nil { + return nil, err + } + iam := &iam_es_model.IAM{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: domain.IAMID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query) + if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 { + return nil, err + } + return iam_es_model.IAMToModel(iam), nil +} diff --git a/internal/api/grpc/admin/iam_member.go b/internal/api/grpc/admin/iam_member.go index 9604ce90d..4cd5ce69f 100644 --- a/internal/api/grpc/admin/iam_member.go +++ b/internal/api/grpc/admin/iam_member.go @@ -12,6 +12,7 @@ import ( func (s *Server) ListIAMMemberRoles(ctx context.Context, req *admin_pb.ListIAMMemberRolesRequest) (*admin_pb.ListIAMMemberRolesResponse, error) { roles := s.iam.GetIAMMemberRoles() return &admin_pb.ListIAMMemberRolesResponse{ + Roles: roles, Details: object.ToListDetails(uint64(len(roles)), 0, time.Now()), }, nil } diff --git a/internal/api/grpc/auth/multi_factor.go b/internal/api/grpc/auth/multi_factor.go index bbf0b7aeb..6ceeaa2f8 100644 --- a/internal/api/grpc/auth/multi_factor.go +++ b/internal/api/grpc/auth/multi_factor.go @@ -67,7 +67,6 @@ func (s *Server) AddMyAuthFactorU2F(ctx context.Context, _ *auth_pb.AddMyAuthFac } return &auth_pb.AddMyAuthFactorU2FResponse{ Key: &user_pb.WebAuthNKey{ - Id: u2f.WebAuthNTokenID, PublicKey: u2f.CredentialCreationData, }, Details: object.AddToDetailsPb( @@ -91,7 +90,7 @@ func (s *Server) VerifyMyAuthFactorU2F(ctx context.Context, req *auth_pb.VerifyM func (s *Server) RemoveMyAuthFactorU2F(ctx context.Context, req *auth_pb.RemoveMyAuthFactorU2FRequest) (*auth_pb.RemoveMyAuthFactorU2FResponse, error) { ctxData := authz.GetCtxData(ctx) - objectDetails, err := s.command.HumanRemovePasswordless(ctx, ctxData.UserID, req.TokenId, ctxData.ResourceOwner) + objectDetails, err := s.command.HumanRemoveU2F(ctx, ctxData.UserID, req.TokenId, ctxData.ResourceOwner) if err != nil { return nil, err } diff --git a/internal/api/grpc/auth/phone.go b/internal/api/grpc/auth/phone.go index 0f4d28675..e78c15d11 100644 --- a/internal/api/grpc/auth/phone.go +++ b/internal/api/grpc/auth/phone.go @@ -41,14 +41,13 @@ func (s *Server) SetMyPhone(ctx context.Context, req *auth_pb.SetMyPhoneRequest) func (s *Server) VerifyMyPhone(ctx context.Context, req *auth_pb.VerifyMyPhoneRequest) (*auth_pb.VerifyMyPhoneResponse, error) { ctxData := authz.GetCtxData(ctx) - _, err := s.command.VerifyHumanPhone(ctx, ctxData.UserID, req.Code, ctxData.ResourceOwner) + objectDetails, err := s.command.VerifyHumanPhone(ctx, ctxData.UserID, req.Code, ctxData.ResourceOwner) if err != nil { return nil, err } - //TODO: response from business return &auth_pb.VerifyMyPhoneResponse{ - //Details: object.DomainToChangeDetailsPb(objectDetails), + Details: object.DomainToChangeDetailsPb(objectDetails), }, nil } diff --git a/internal/api/grpc/idp/converter.go b/internal/api/grpc/idp/converter.go index 24d99b8a1..dd38f27ed 100644 --- a/internal/api/grpc/idp/converter.go +++ b/internal/api/grpc/idp/converter.go @@ -245,7 +245,7 @@ func IDPProviderTypeModelFromPb(typ idp_pb.IDPOwnerType) iam_model.IDPProviderTy func IDPIDQueryToModel(query *idp_pb.IDPIDQuery) *iam_model.IDPConfigSearchQuery { return &iam_model.IDPConfigSearchQuery{ - Key: iam_model.IDPConfigSearchKeyIdpConfigID, //TODO: whats the difference between idpconfigid and aggregateid search key? + Key: iam_model.IDPConfigSearchKeyIdpConfigID, Method: domain.SearchMethodEquals, Value: query.Id, } diff --git a/internal/api/grpc/management/org.go b/internal/api/grpc/management/org.go index 2f26a74ad..2535a5444 100644 --- a/internal/api/grpc/management/org.go +++ b/internal/api/grpc/management/org.go @@ -139,7 +139,6 @@ func (s *Server) GenerateOrgDomainValidation(ctx context.Context, req *mgmt_pb.G return &mgmt_pb.GenerateOrgDomainValidationResponse{ Token: token, Url: url, - //TODO: remove details from proto }, nil } diff --git a/internal/api/grpc/management/project_application_converter.go b/internal/api/grpc/management/project_application_converter.go index d7b629dd5..e38ee5157 100644 --- a/internal/api/grpc/management/project_application_converter.go +++ b/internal/api/grpc/management/project_application_converter.go @@ -121,7 +121,7 @@ func AddAPIClientKeyRequestToDomain(key *mgmt_pb.AddAppKeyRequest) *domain.Appli func ListAPIClientKeysRequestToModel(req *mgmt_pb.ListAppKeysRequest) (*key_model.AuthNKeySearchRequest, error) { offset, limit, asc := object.ListQueryToModel(req.Query) - queries := make([]*key_model.AuthNKeySearchQuery, 2) + queries := make([]*key_model.AuthNKeySearchQuery, 0) queries = append(queries, &key_model.AuthNKeySearchQuery{ Key: key_model.AuthNKeyObjectID, Method: domain.SearchMethodEquals, diff --git a/internal/api/grpc/management/project_grant.go b/internal/api/grpc/management/project_grant.go index 4874e6570..554d90fbb 100644 --- a/internal/api/grpc/management/project_grant.go +++ b/internal/api/grpc/management/project_grant.go @@ -2,6 +2,7 @@ package management import ( "context" + "time" "github.com/caos/zitadel/internal/api/authz" member_grpc "github.com/caos/zitadel/internal/api/grpc/member" @@ -106,8 +107,8 @@ func (s *Server) RemoveProjectGrant(ctx context.Context, req *mgmt_pb.RemoveProj func (s *Server) ListProjectGrantMemberRoles(ctx context.Context, req *mgmt_pb.ListProjectGrantMemberRolesRequest) (*mgmt_pb.ListProjectGrantMemberRolesResponse, error) { roles := s.project.GetProjectGrantMemberRoles() return &mgmt_pb.ListProjectGrantMemberRolesResponse{ - Result: roles, - //TODO: metadata + Result: roles, + Details: object_grpc.ToListDetails(uint64(len(roles)), 0, time.Now()), }, nil } diff --git a/internal/api/grpc/management/user_grant.go b/internal/api/grpc/management/user_grant.go index 599ecb911..06dfbe830 100644 --- a/internal/api/grpc/management/user_grant.go +++ b/internal/api/grpc/management/user_grant.go @@ -100,7 +100,5 @@ func (s *Server) BulkRemoveUserGrant(ctx context.Context, req *mgmt_pb.BulkRemov if err != nil { return nil, err } - return &mgmt_pb.BulkRemoveUserGrantResponse{ - //TODO: Do we need details here? - }, nil + return &mgmt_pb.BulkRemoveUserGrantResponse{}, nil } diff --git a/internal/api/grpc/member/iam_member.go b/internal/api/grpc/member/iam_member.go index 8c91c8442..67f052741 100644 --- a/internal/api/grpc/member/iam_member.go +++ b/internal/api/grpc/member/iam_member.go @@ -17,13 +17,13 @@ func IAMMembersToPb(members []*iam_model.IAMMemberView) []*member_pb.Member { func IAMMemberToPb(m *iam_model.IAMMemberView) *member_pb.Member { return &member_pb.Member{ - UserId: m.UserID, - Roles: m.Roles, - // PreferredLoginName: //TODO: not implemented in be - Email: m.Email, - FirstName: m.FirstName, - LastName: m.LastName, - DisplayName: m.DisplayName, + UserId: m.UserID, + Roles: m.Roles, + PreferredLoginName: m.PreferredLoginName, + Email: m.Email, + FirstName: m.FirstName, + LastName: m.LastName, + DisplayName: m.DisplayName, Details: object.ToViewDetailsPb( m.Sequence, m.CreationDate, diff --git a/internal/api/grpc/member/org_member.go b/internal/api/grpc/member/org_member.go index b4e9787fc..3c613eaf5 100644 --- a/internal/api/grpc/member/org_member.go +++ b/internal/api/grpc/member/org_member.go @@ -17,13 +17,13 @@ func OrgMembersToPb(members []*org_model.OrgMemberView) []*member_pb.Member { func OrgMemberToPb(m *org_model.OrgMemberView) *member_pb.Member { return &member_pb.Member{ - UserId: m.UserID, - Roles: m.Roles, - // PreferredLoginName: //TODO: not implemented in be - Email: m.Email, - FirstName: m.FirstName, - LastName: m.LastName, - DisplayName: m.DisplayName, + UserId: m.UserID, + Roles: m.Roles, + PreferredLoginName: m.PreferredLoginName, + Email: m.Email, + FirstName: m.FirstName, + LastName: m.LastName, + DisplayName: m.DisplayName, Details: object.ToViewDetailsPb( m.Sequence, m.CreationDate, diff --git a/internal/api/grpc/member/project_grant_member.go b/internal/api/grpc/member/project_grant_member.go index d7f199a4c..3b8c52906 100644 --- a/internal/api/grpc/member/project_grant_member.go +++ b/internal/api/grpc/member/project_grant_member.go @@ -17,13 +17,13 @@ func ProjectGrantMembersToPb(members []*proj_model.ProjectGrantMemberView) []*me func ProjectGrantMemberToPb(m *proj_model.ProjectGrantMemberView) *member_pb.Member { return &member_pb.Member{ - UserId: m.UserID, - Roles: m.Roles, - // PreferredLoginName: //TODO: not implemented in be - Email: m.Email, - FirstName: m.FirstName, - LastName: m.LastName, - DisplayName: m.DisplayName, + UserId: m.UserID, + Roles: m.Roles, + PreferredLoginName: m.PreferredLoginName, + Email: m.Email, + FirstName: m.FirstName, + LastName: m.LastName, + DisplayName: m.DisplayName, Details: object.ToViewDetailsPb( m.Sequence, m.CreationDate, diff --git a/internal/api/grpc/member/project_member.go b/internal/api/grpc/member/project_member.go index 0e7f8bf41..b3206d872 100644 --- a/internal/api/grpc/member/project_member.go +++ b/internal/api/grpc/member/project_member.go @@ -17,13 +17,13 @@ func ProjectMembersToPb(members []*proj_model.ProjectMemberView) []*member_pb.Me func ProjectMemberToPb(m *proj_model.ProjectMemberView) *member_pb.Member { return &member_pb.Member{ - UserId: m.UserID, - Roles: m.Roles, - // PreferredLoginName: //TODO: not implemented in be - Email: m.Email, - FirstName: m.FirstName, - LastName: m.LastName, - DisplayName: m.DisplayName, + UserId: m.UserID, + Roles: m.Roles, + PreferredLoginName: m.PreferredLoginName, + Email: m.Email, + FirstName: m.FirstName, + LastName: m.LastName, + DisplayName: m.DisplayName, Details: object.ToViewDetailsPb( m.Sequence, m.CreationDate, diff --git a/internal/api/grpc/org/converter.go b/internal/api/grpc/org/converter.go index 4df44e1c1..79c4f0c6d 100644 --- a/internal/api/grpc/org/converter.go +++ b/internal/api/grpc/org/converter.go @@ -29,8 +29,11 @@ func OrgQueryToModel(query *org_pb.OrgQuery) (*org_model.OrgSearchQuery, error) Value: q.DomainQuery.Domain, }, nil case *org_pb.OrgQuery_NameQuery: - //TODO: implement name in backend - return nil, errors.ThrowUnimplemented(nil, "ADMIN-KGXnX", "name query not implemented") + return &org_model.OrgSearchQuery{ + Key: org_model.OrgSearchKeyOrgName, + Method: object.TextMethodToModel(q.NameQuery.Method), + Value: q.NameQuery.Name, + }, nil default: return nil, errors.ThrowInvalidArgument(nil, "ADMIN-vR9nC", "List.Query.Invalid") } diff --git a/internal/api/grpc/policy/multi_factor.go b/internal/api/grpc/policy/multi_factor.go index b1cda04c0..2ebf8bb05 100644 --- a/internal/api/grpc/policy/multi_factor.go +++ b/internal/api/grpc/policy/multi_factor.go @@ -7,7 +7,8 @@ import ( func MultiFactorTypeToDomain(multiFactorType policy_pb.MultiFactorType) domain.MultiFactorType { switch multiFactorType { - //TODO: gap between proto and backend + case policy_pb.MultiFactorType_MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION: + return domain.MultiFactorTypeU2FWithPIN default: return domain.MultiFactorTypeUnspecified } diff --git a/internal/api/grpc/user/converter.go b/internal/api/grpc/user/converter.go index 07b2d1055..d0020a86d 100644 --- a/internal/api/grpc/user/converter.go +++ b/internal/api/grpc/user/converter.go @@ -244,7 +244,6 @@ func WebAuthNTokenViewToPb(token *model.WebAuthNView) *user_pb.WebAuthNToken { func WebAuthNTokenToWebAuthNKeyPb(token *domain.WebAuthNToken) *user_pb.WebAuthNKey { return &user_pb.WebAuthNKey{ - Id: string(token.KeyID), //TODO: ask if it's the correct id? PublicKey: token.PublicKey, } } diff --git a/internal/command/user_human_email_model.go b/internal/command/user_human_email_model.go index 8c9ebbd1d..fe5402318 100644 --- a/internal/command/user_human_email_model.go +++ b/internal/command/user_human_email_model.go @@ -37,10 +37,14 @@ func (wm *HumanEmailWriteModel) Reduce() error { switch e := event.(type) { case *user.HumanAddedEvent: wm.Email = e.EmailAddress - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive case *user.HumanRegisteredEvent: wm.Email = e.EmailAddress + wm.UserState = domain.UserStateActive + case *user.HumanInitialCodeAddedEvent: wm.UserState = domain.UserStateInitial + case *user.HumanInitializedCheckSucceededEvent: + wm.UserState = domain.UserStateActive case *user.HumanEmailChangedEvent: wm.Email = e.EmailAddress wm.IsEmailVerified = false @@ -52,9 +56,6 @@ func (wm *HumanEmailWriteModel) Reduce() error { case *user.HumanEmailVerifiedEvent: wm.IsEmailVerified = true wm.Code = nil - if wm.UserState == domain.UserStateInitial { - wm.UserState = domain.UserStateActive - } case *user.UserRemovedEvent: wm.UserState = domain.UserStateDeleted } diff --git a/internal/command/user_human_email_test.go b/internal/command/user_human_email_test.go index e22517a8b..d8626009b 100644 --- a/internal/command/user_human_email_test.go +++ b/internal/command/user_human_email_test.go @@ -572,6 +572,12 @@ func TestCommandSide_CreateVerificationCodeHumanEmail(t *testing.T) { true, ), ), + eventFromEventPusher( + user.NewHumanInitialCodeAddedEvent(context.Background(), + &user.NewAggregate("user1", "org1").Aggregate, + nil, time.Hour*1, + ), + ), ), ), }, diff --git a/internal/command/user_human_init_model.go b/internal/command/user_human_init_model.go index 58e6963e7..b8fe2389c 100644 --- a/internal/command/user_human_init_model.go +++ b/internal/command/user_human_init_model.go @@ -37,10 +37,10 @@ func (wm *HumanInitCodeWriteModel) Reduce() error { switch e := event.(type) { case *user.HumanAddedEvent: wm.Email = e.EmailAddress - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive case *user.HumanRegisteredEvent: wm.Email = e.EmailAddress - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive case *user.HumanEmailChangedEvent: wm.Email = e.EmailAddress wm.IsEmailVerified = false @@ -54,8 +54,10 @@ func (wm *HumanInitCodeWriteModel) Reduce() error { wm.Code = e.Code wm.CodeCreationDate = e.CreationDate() wm.CodeExpiry = e.Expiry + wm.UserState = domain.UserStateInitial case *user.HumanInitializedCheckSucceededEvent: wm.Code = nil + wm.UserState = domain.UserStateActive case *user.UserRemovedEvent: wm.UserState = domain.UserStateDeleted } diff --git a/internal/command/user_human_init_test.go b/internal/command/user_human_init_test.go index 260c81e71..f0089fbf5 100644 --- a/internal/command/user_human_init_test.go +++ b/internal/command/user_human_init_test.go @@ -126,6 +126,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) { true, ), ), + eventFromEventPusher( + user.NewHumanInitialCodeAddedEvent(context.Background(), + &user.NewAggregate("user1", "org1").Aggregate, + nil, time.Hour*1, + ), + ), ), expectPush( []*repository.Event{ @@ -178,6 +184,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) { true, ), ), + eventFromEventPusher( + user.NewHumanInitialCodeAddedEvent(context.Background(), + &user.NewAggregate("user1", "org1").Aggregate, + nil, time.Hour*1, + ), + ), ), expectPush( []*repository.Event{ @@ -229,6 +241,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) { true, ), ), + eventFromEventPusher( + user.NewHumanInitialCodeAddedEvent(context.Background(), + &user.NewAggregate("user1", "org1").Aggregate, + nil, time.Hour*1, + ), + ), ), expectPush( []*repository.Event{ diff --git a/internal/command/user_human_model.go b/internal/command/user_human_model.go index b283c4c9a..051975480 100644 --- a/internal/command/user_human_model.go +++ b/internal/command/user_human_model.go @@ -54,6 +54,10 @@ func (wm *HumanWriteModel) Reduce() error { wm.reduceHumanAddedEvent(e) case *user.HumanRegisteredEvent: wm.reduceHumanRegisteredEvent(e) + case *user.HumanInitialCodeAddedEvent: + wm.UserState = domain.UserStateInitial + case *user.HumanInitializedCheckSucceededEvent: + wm.UserState = domain.UserStateActive case *user.UsernameChangedEvent: wm.UserName = e.UserName case *user.HumanProfileChangedEvent: @@ -128,7 +132,7 @@ func (wm *HumanWriteModel) reduceHumanAddedEvent(e *user.HumanAddedEvent) { wm.StreetAddress = e.StreetAddress wm.Secret = e.Secret wm.SecretChangeRequired = e.ChangeRequired - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive } func (wm *HumanWriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEvent) { @@ -148,7 +152,7 @@ func (wm *HumanWriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEve wm.StreetAddress = e.StreetAddress wm.Secret = e.Secret wm.SecretChangeRequired = e.ChangeRequired - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive } func (wm *HumanWriteModel) reduceHumanProfileChangedEvent(e *user.HumanProfileChangedEvent) { diff --git a/internal/command/user_human_password_model.go b/internal/command/user_human_password_model.go index 3e7cc3207..13489de54 100644 --- a/internal/command/user_human_password_model.go +++ b/internal/command/user_human_password_model.go @@ -37,11 +37,15 @@ func (wm *HumanPasswordWriteModel) Reduce() error { case *user.HumanAddedEvent: wm.Secret = e.Secret wm.SecretChangeRequired = e.ChangeRequired - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive case *user.HumanRegisteredEvent: wm.Secret = e.Secret wm.SecretChangeRequired = e.ChangeRequired wm.UserState = domain.UserStateActive + case *user.HumanInitialCodeAddedEvent: + wm.UserState = domain.UserStateInitial + case *user.HumanInitializedCheckSucceededEvent: + wm.UserState = domain.UserStateActive case *user.HumanPasswordChangedEvent: wm.Secret = e.Secret wm.SecretChangeRequired = e.ChangeRequired diff --git a/internal/command/user_human_password_test.go b/internal/command/user_human_password_test.go index c04bc794d..1526b626b 100644 --- a/internal/command/user_human_password_test.go +++ b/internal/command/user_human_password_test.go @@ -757,7 +757,7 @@ func TestCommandSide_RequestSetPassword(t *testing.T) { }, }, { - name: "phone already verified, precondition error", + name: "user initial, precondition error", fields: fields{ eventstore: eventstoreExpect( t, @@ -776,6 +776,12 @@ func TestCommandSide_RequestSetPassword(t *testing.T) { true, ), ), + eventFromEventPusher( + user.NewHumanInitialCodeAddedEvent(context.Background(), + &user.NewAggregate("user1", "org1").Aggregate, + nil, time.Hour*1, + ), + ), eventFromEventPusher( user.NewHumanPhoneChangedEvent(context.Background(), &user.NewAggregate("user1", "org1").Aggregate, diff --git a/internal/command/user_human_phone_model.go b/internal/command/user_human_phone_model.go index 29f1a28a3..3c65378f1 100644 --- a/internal/command/user_human_phone_model.go +++ b/internal/command/user_human_phone_model.go @@ -48,6 +48,10 @@ func (wm *HumanPhoneWriteModel) Reduce() error { wm.State = domain.PhoneStateActive } wm.UserState = domain.UserStateActive + case *user.HumanInitialCodeAddedEvent: + wm.UserState = domain.UserStateInitial + case *user.HumanInitializedCheckSucceededEvent: + wm.UserState = domain.UserStateActive case *user.HumanPhoneChangedEvent: wm.Phone = e.PhoneNumber wm.IsPhoneVerified = false diff --git a/internal/command/user_human_test.go b/internal/command/user_human_test.go index 63e9d52f8..109b79baf 100644 --- a/internal/command/user_human_test.go +++ b/internal/command/user_human_test.go @@ -474,7 +474,7 @@ func TestCommandSide_AddHuman(t *testing.T) { EmailAddress: "email@test.ch", IsEmailVerified: true, }, - State: domain.UserStateInitial, + State: domain.UserStateActive, }, }, }, @@ -1048,7 +1048,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { EmailAddress: "email@test.ch", IsEmailVerified: true, }, - State: domain.UserStateInitial, + State: domain.UserStateActive, }, }, }, diff --git a/internal/command/user_human_webauthn.go b/internal/command/user_human_webauthn.go index 5193599eb..68dc50e74 100644 --- a/internal/command/user_human_webauthn.go +++ b/internal/command/user_human_webauthn.go @@ -173,6 +173,7 @@ func (c *Commands) HumanVerifyU2FSetup(ctx context.Context, userID, resourceowne webAuthN.PublicKey, webAuthN.AAGUID, webAuthN.SignCount, + userAgentID, ), ) if err != nil { @@ -206,6 +207,7 @@ func (c *Commands) HumanHumanPasswordlessSetup(ctx context.Context, userID, reso webAuthN.PublicKey, webAuthN.AAGUID, webAuthN.SignCount, + userAgentID, ), ) if err != nil { @@ -436,7 +438,7 @@ func (c *Commands) removeHumanWebAuthN(ctx context.Context, userID, webAuthNID, return nil, err } if existingWebAuthN.State == domain.MFAStateUnspecified || existingWebAuthN.State == domain.MFAStateRemoved { - return nil, caos_errs.ThrowNotFound(nil, "COMMAND-2M9ds", "Errors.User.ExternalIDP.NotFound") + return nil, caos_errs.ThrowNotFound(nil, "COMMAND-DAfb2", "Errors.User.WebAuthN.NotFound") } userAgg := UserAggregateFromWriteModel(&existingWebAuthN.WriteModel) diff --git a/internal/command/user_human_webauthn_model.go b/internal/command/user_human_webauthn_model.go index 3a4b8fe26..46069e114 100644 --- a/internal/command/user_human_webauthn_model.go +++ b/internal/command/user_human_webauthn_model.go @@ -39,18 +39,50 @@ func (wm *HumanWebAuthNWriteModel) AppendEvents(events ...eventstore.EventReader if wm.WebauthNTokenID == e.WebAuthNTokenID { wm.WriteModel.AppendEvents(e) } + case *user.HumanPasswordlessAddedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(&e.HumanWebAuthNAddedEvent) + } + case *user.HumanU2FAddedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(&e.HumanWebAuthNAddedEvent) + } case *user.HumanWebAuthNVerifiedEvent: if wm.WebauthNTokenID == e.WebAuthNTokenID { wm.WriteModel.AppendEvents(e) } + case *user.HumanPasswordlessVerifiedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(e) + } + case *user.HumanU2FVerifiedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(e) + } case *user.HumanWebAuthNSignCountChangedEvent: if wm.WebauthNTokenID == e.WebAuthNTokenID { wm.WriteModel.AppendEvents(e) } + case *user.HumanPasswordlessSignCountChangedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(e) + } + case *user.HumanU2FSignCountChangedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(e) + } case *user.HumanWebAuthNRemovedEvent: if wm.WebauthNTokenID == e.WebAuthNTokenID { wm.WriteModel.AppendEvents(e) } + case *user.HumanPasswordlessRemovedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(e) + } + case *user.HumanU2FRemovedEvent: + if wm.WebauthNTokenID == e.WebAuthNTokenID { + wm.WriteModel.AppendEvents(e) + } case *user.UserRemovedEvent: wm.WriteModel.AppendEvents(e) } diff --git a/internal/command/user_model.go b/internal/command/user_model.go index 5fd06a9e8..66be37676 100644 --- a/internal/command/user_model.go +++ b/internal/command/user_model.go @@ -30,9 +30,11 @@ func (wm *UserWriteModel) Reduce() error { switch e := event.(type) { case *user.HumanAddedEvent: wm.UserName = e.UserName - wm.UserState = domain.UserStateInitial + wm.UserState = domain.UserStateActive case *user.HumanRegisteredEvent: wm.UserName = e.UserName + wm.UserState = domain.UserStateActive + case *user.HumanInitialCodeAddedEvent: wm.UserState = domain.UserStateInitial case *user.HumanInitializedCheckSucceededEvent: wm.UserState = domain.UserStateActive diff --git a/internal/iam/model/iam_member_view.go b/internal/iam/model/iam_member_view.go index 3f89ebe54..3eb7a177c 100644 --- a/internal/iam/model/iam_member_view.go +++ b/internal/iam/model/iam_member_view.go @@ -6,17 +6,18 @@ import ( ) type IAMMemberView struct { - UserID string - IAMID string - UserName string - Email string - FirstName string - LastName string - DisplayName string - Roles []string - CreationDate time.Time - ChangeDate time.Time - Sequence uint64 + UserID string + IAMID string + UserName string + Email string + FirstName string + LastName string + DisplayName string + PreferredLoginName string + Roles []string + CreationDate time.Time + ChangeDate time.Time + Sequence uint64 } type IAMMemberSearchRequest struct { diff --git a/internal/iam/repository/view/model/iam_member.go b/internal/iam/repository/view/model/iam_member.go index fd86f1883..384dd7bb7 100644 --- a/internal/iam/repository/view/model/iam_member.go +++ b/internal/iam/repository/view/model/iam_member.go @@ -23,15 +23,16 @@ const ( ) type IAMMemberView struct { - UserID string `json:"userId" gorm:"column:user_id;primary_key"` - IAMID string `json:"-" gorm:"column:iam_id"` - UserName string `json:"-" gorm:"column:user_name"` - Email string `json:"-" gorm:"column:email_address"` - FirstName string `json:"-" gorm:"column:first_name"` - LastName string `json:"-" gorm:"column:last_name"` - DisplayName string `json:"-" gorm:"column:display_name"` - Roles pq.StringArray `json:"roles" gorm:"column:roles"` - Sequence uint64 `json:"-" gorm:"column:sequence"` + UserID string `json:"userId" gorm:"column:user_id;primary_key"` + IAMID string `json:"-" gorm:"column:iam_id"` + UserName string `json:"-" gorm:"column:user_name"` + Email string `json:"-" gorm:"column:email_address"` + FirstName string `json:"-" gorm:"column:first_name"` + LastName string `json:"-" gorm:"column:last_name"` + DisplayName string `json:"-" gorm:"column:display_name"` + Roles pq.StringArray `json:"roles" gorm:"column:roles"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` CreationDate time.Time `json:"-" gorm:"column:creation_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"` @@ -55,17 +56,18 @@ func IAMMemberViewFromModel(member *model.IAMMemberView) *IAMMemberView { func IAMMemberToModel(member *IAMMemberView) *model.IAMMemberView { return &model.IAMMemberView{ - UserID: member.UserID, - IAMID: member.IAMID, - UserName: member.UserName, - Email: member.Email, - FirstName: member.FirstName, - LastName: member.LastName, - DisplayName: member.DisplayName, - Roles: member.Roles, - Sequence: member.Sequence, - CreationDate: member.CreationDate, - ChangeDate: member.ChangeDate, + UserID: member.UserID, + IAMID: member.IAMID, + UserName: member.UserName, + Email: member.Email, + FirstName: member.FirstName, + LastName: member.LastName, + DisplayName: member.DisplayName, + PreferredLoginName: member.PreferredLoginName, + Roles: member.Roles, + Sequence: member.Sequence, + CreationDate: member.CreationDate, + ChangeDate: member.ChangeDate, } } diff --git a/internal/management/repository/eventsourcing/handler/org_member.go b/internal/management/repository/eventsourcing/handler/org_member.go index bf0262dc3..be9a4c1e2 100644 --- a/internal/management/repository/eventsourcing/handler/org_member.go +++ b/internal/management/repository/eventsourcing/handler/org_member.go @@ -2,16 +2,23 @@ package handler import ( "context" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1" + es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" + iam_model "github.com/caos/zitadel/internal/iam/model" + iam_view "github.com/caos/zitadel/internal/iam/repository/view" + org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/logging" es_models "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" + org_model "github.com/caos/zitadel/internal/org/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" - org_model "github.com/caos/zitadel/internal/org/repository/view/model" + org_view_model "github.com/caos/zitadel/internal/org/repository/view/model" usr_model "github.com/caos/zitadel/internal/user/model" usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" @@ -84,7 +91,7 @@ func (m *OrgMember) Reduce(event *es_models.Event) (err error) { } func (m *OrgMember) processOrgMember(event *es_models.Event) (err error) { - member := new(org_model.OrgMemberView) + member := new(org_view_model.OrgMemberView) switch event.Type { case model.OrgMemberAdded: err = member.AppendEvent(event) @@ -146,17 +153,25 @@ func (m *OrgMember) processUser(event *es_models.Event) (err error) { } } -func (m *OrgMember) fillData(member *org_model.OrgMemberView) (err error) { +func (m *OrgMember) fillData(member *org_view_model.OrgMemberView) (err error) { user, err := m.getUserByID(member.UserID) if err != nil { return err } - m.fillUserData(member, user) - return nil + return m.fillUserData(member, user) } -func (m *OrgMember) fillUserData(member *org_model.OrgMemberView, user *usr_view_model.UserView) { +func (m *OrgMember) fillUserData(member *org_view_model.OrgMemberView, user *usr_view_model.UserView) error { + org, err := m.getOrgByID(context.Background(), user.ResourceOwner) + policy := org.OrgIamPolicy + if policy == nil { + policy, err = m.getDefaultOrgIAMPolicy(context.TODO()) + if err != nil { + return err + } + } member.UserName = user.UserName + member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) if user.HumanView != nil { member.FirstName = user.FirstName member.LastName = user.LastName @@ -166,7 +181,9 @@ func (m *OrgMember) fillUserData(member *org_model.OrgMemberView, user *usr_view if user.MachineView != nil { member.DisplayName = user.MachineView.Name } + return nil } + func (m *OrgMember) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-u73es", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgmember handler") return spooler.HandleError(event, err, m.view.GetLatestOrgMemberFailedEvent, m.view.ProcessedOrgMemberFailedEvent, m.view.ProcessedOrgMemberSequence, m.errorCountUntilSkip) @@ -208,3 +225,53 @@ func (u *OrgMember) getUserEvents(userID string, sequence uint64) ([]*es_models. return u.es.FilterEvents(context.Background(), query) } + +func (u *OrgMember) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) { + query, err := org_view.OrgByIDQuery(orgID, 0) + if err != nil { + return nil, err + } + + esOrg := &model.Org{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: orgID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query) + if err != nil && !caos_errs.IsNotFound(err) { + return nil, err + } + if esOrg.Sequence == 0 { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-kVLb2", "Errors.Org.NotFound") + } + + return model.OrgToModel(esOrg), nil +} + +func (u *OrgMember) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) { + existingIAM, err := u.getIAMByID(ctx) + if err != nil { + return nil, err + } + if existingIAM.DefaultOrgIAMPolicy == nil { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-2Fj8s", "Errors.IAM.OrgIAMPolicy.NotExisting") + } + return existingIAM.DefaultOrgIAMPolicy, nil +} + +func (u *OrgMember) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { + query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) + if err != nil { + return nil, err + } + iam := &iam_es_model.IAM{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: domain.IAMID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query) + if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 { + return nil, err + } + return iam_es_model.IAMToModel(iam), nil +} diff --git a/internal/management/repository/eventsourcing/handler/project_grant_member.go b/internal/management/repository/eventsourcing/handler/project_grant_member.go index 23bfc5c0a..31fa74f8e 100644 --- a/internal/management/repository/eventsourcing/handler/project_grant_member.go +++ b/internal/management/repository/eventsourcing/handler/project_grant_member.go @@ -2,8 +2,16 @@ package handler import ( "context" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1" + es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" + iam_model "github.com/caos/zitadel/internal/iam/model" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" + iam_view "github.com/caos/zitadel/internal/iam/repository/view" + org_model "github.com/caos/zitadel/internal/org/model" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" + org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/user/repository/view" usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" @@ -160,8 +168,17 @@ func (p *ProjectGrantMember) fillData(member *view_model.ProjectGrantMemberView) return nil } -func (p *ProjectGrantMember) fillUserData(member *view_model.ProjectGrantMemberView, user *usr_view_model.UserView) { +func (p *ProjectGrantMember) fillUserData(member *view_model.ProjectGrantMemberView, user *usr_view_model.UserView) error { + org, err := p.getOrgByID(context.Background(), user.ResourceOwner) + policy := org.OrgIamPolicy + if policy == nil { + policy, err = p.getDefaultOrgIAMPolicy(context.TODO()) + if err != nil { + return err + } + } member.UserName = user.UserName + member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) if user.HumanView != nil { member.FirstName = user.FirstName member.LastName = user.LastName @@ -171,6 +188,7 @@ func (p *ProjectGrantMember) fillUserData(member *view_model.ProjectGrantMemberV if user.MachineView != nil { member.DisplayName = user.MachineView.Name } + return nil } func (p *ProjectGrantMember) OnError(event *es_models.Event, err error) error { @@ -214,3 +232,53 @@ func (u *ProjectGrantMember) getUserEvents(userID string, sequence uint64) ([]*e return u.es.FilterEvents(context.Background(), query) } + +func (u *ProjectGrantMember) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) { + query, err := org_view.OrgByIDQuery(orgID, 0) + if err != nil { + return nil, err + } + + esOrg := &org_es_model.Org{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: orgID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query) + if err != nil && !caos_errs.IsNotFound(err) { + return nil, err + } + if esOrg.Sequence == 0 { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-3nd7s", "Errors.Org.NotFound") + } + + return org_es_model.OrgToModel(esOrg), nil +} + +func (u *ProjectGrantMember) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) { + existingIAM, err := u.getIAMByID(ctx) + if err != nil { + return nil, err + } + if existingIAM.DefaultOrgIAMPolicy == nil { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-3Bf7s", "Errors.IAM.OrgIAMPolicy.NotExisting") + } + return existingIAM.DefaultOrgIAMPolicy, nil +} + +func (u *ProjectGrantMember) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { + query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) + if err != nil { + return nil, err + } + iam := &iam_es_model.IAM{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: domain.IAMID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query) + if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 { + return nil, err + } + return iam_es_model.IAMToModel(iam), nil +} diff --git a/internal/management/repository/eventsourcing/handler/project_member.go b/internal/management/repository/eventsourcing/handler/project_member.go index 107781468..42025bd0b 100644 --- a/internal/management/repository/eventsourcing/handler/project_member.go +++ b/internal/management/repository/eventsourcing/handler/project_member.go @@ -2,8 +2,15 @@ package handler import ( "context" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1" + es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk" + iam_model "github.com/caos/zitadel/internal/iam/model" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" + iam_view "github.com/caos/zitadel/internal/iam/repository/view" + org_model "github.com/caos/zitadel/internal/org/model" + org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/logging" @@ -11,6 +18,7 @@ import ( es_models "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/spooler" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model" usr_model "github.com/caos/zitadel/internal/user/model" @@ -153,12 +161,20 @@ func (p *ProjectMember) fillData(member *view_model.ProjectMemberView) (err erro if err != nil { return err } - p.fillUserData(member, user) - return nil + return p.fillUserData(member, user) } -func (p *ProjectMember) fillUserData(member *view_model.ProjectMemberView, user *usr_view_model.UserView) { +func (p *ProjectMember) fillUserData(member *view_model.ProjectMemberView, user *usr_view_model.UserView) error { + org, err := p.getOrgByID(context.Background(), user.ResourceOwner) + policy := org.OrgIamPolicy + if policy == nil { + policy, err = p.getDefaultOrgIAMPolicy(context.TODO()) + if err != nil { + return err + } + } member.UserName = user.UserName + member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) if user.HumanView != nil { member.FirstName = user.FirstName member.LastName = user.LastName @@ -168,7 +184,9 @@ func (p *ProjectMember) fillUserData(member *view_model.ProjectMemberView, user if user.MachineView != nil { member.DisplayName = user.MachineView.Name } + return nil } + func (p *ProjectMember) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-u73es", "id", event.AggregateID).WithError(err).Warn("something went wrong in projectmember handler") return spooler.HandleError(event, err, p.view.GetLatestProjectMemberFailedEvent, p.view.ProcessedProjectMemberFailedEvent, p.view.ProcessedProjectMemberSequence, p.errorCountUntilSkip) @@ -210,3 +228,53 @@ func (u *ProjectMember) getUserEvents(userID string, sequence uint64) ([]*es_mod return u.es.FilterEvents(context.Background(), query) } + +func (u *ProjectMember) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) { + query, err := org_view.OrgByIDQuery(orgID, 0) + if err != nil { + return nil, err + } + + esOrg := &org_es_model.Org{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: orgID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, esOrg.AppendEvents, query) + if err != nil && !caos_errs.IsNotFound(err) { + return nil, err + } + if esOrg.Sequence == 0 { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-3N8fs", "Errors.Org.NotFound") + } + + return org_es_model.OrgToModel(esOrg), nil +} + +func (u *ProjectMember) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) { + existingIAM, err := u.getIAMByID(ctx) + if err != nil { + return nil, err + } + if existingIAM.DefaultOrgIAMPolicy == nil { + return nil, caos_errs.ThrowNotFound(nil, "EVENT-5M9sd", "Errors.IAM.OrgIAMPolicy.NotExisting") + } + return existingIAM.DefaultOrgIAMPolicy, nil +} + +func (u *ProjectMember) getIAMByID(ctx context.Context) (*iam_model.IAM, error) { + query, err := iam_view.IAMByIDQuery(domain.IAMID, 0) + if err != nil { + return nil, err + } + iam := &iam_es_model.IAM{ + ObjectRoot: es_models.ObjectRoot{ + AggregateID: domain.IAMID, + }, + } + err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query) + if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 { + return nil, err + } + return iam_es_model.IAMToModel(iam), nil +} diff --git a/internal/notification/providers/email/message.go b/internal/notification/providers/email/message.go index fdb81b164..fcd992835 100644 --- a/internal/notification/providers/email/message.go +++ b/internal/notification/providers/email/message.go @@ -32,9 +32,9 @@ func (msg *EmailMessage) GetContent() string { } //default mime-type is html - mime := "MIME-version: 1.0;" + lineBreak + "Content-KeyType: text/html; charset=\"UTF-8\";" + lineBreak + lineBreak + mime := "MIME-version: 1.0;" + lineBreak + "Content-Type: text/html; charset=\"UTF-8\";" + lineBreak + lineBreak if !isHTML(msg.Content) { - mime = "MIME-version: 1.0;" + lineBreak + "Content-KeyType: text/plain; charset=\"UTF-8\";" + lineBreak + lineBreak + mime = "MIME-version: 1.0;" + lineBreak + "Content-Type: text/plain; charset=\"UTF-8\";" + lineBreak + lineBreak } subject := "Subject: " + msg.Subject + lineBreak message += subject + mime + lineBreak + msg.Content diff --git a/internal/notification/repository/eventsourcing/handler/notify_user.go b/internal/notification/repository/eventsourcing/handler/notify_user.go index 20e406a29..82d2ab5fd 100644 --- a/internal/notification/repository/eventsourcing/handler/notify_user.go +++ b/internal/notification/repository/eventsourcing/handler/notify_user.go @@ -2,6 +2,7 @@ package handler import ( "context" + "github.com/caos/zitadel/internal/domain" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1" @@ -12,6 +13,7 @@ import ( org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/logging" + es_models "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/query" "github.com/caos/zitadel/internal/eventstore/v1/spooler" @@ -97,9 +99,13 @@ func (u *NotifyUser) ProcessUser(event *es_models.Event) (err error) { case es_model.UserAdded, es_model.UserRegistered, es_model.HumanRegistered, - es_model.HumanAdded: - user.AppendEvent(event) - u.fillLoginNames(user) + es_model.HumanAdded, + es_model.MachineAdded: + err := user.AppendEvent(event) + if err != nil { + return err + } + err = u.fillLoginNames(user) case es_model.UserProfileChanged, es_model.UserEmailChanged, es_model.UserEmailVerified, @@ -128,7 +134,7 @@ func (u *NotifyUser) ProcessUser(event *es_models.Event) (err error) { if err != nil { return err } - u.fillLoginNames(user) + err = u.fillLoginNames(user) case es_model.UserRemoved: return u.view.DeleteNotifyUser(event.AggregateID, event) default: diff --git a/internal/org/model/org_member_view.go b/internal/org/model/org_member_view.go index 32aa0b85f..27378e531 100644 --- a/internal/org/model/org_member_view.go +++ b/internal/org/model/org_member_view.go @@ -1,22 +1,24 @@ package model import ( - "github.com/caos/zitadel/internal/domain" "time" + + "github.com/caos/zitadel/internal/domain" ) type OrgMemberView struct { - UserID string - OrgID string - UserName string - Email string - FirstName string - LastName string - DisplayName string - Roles []string - CreationDate time.Time - ChangeDate time.Time - Sequence uint64 + UserID string + OrgID string + UserName string + Email string + FirstName string + LastName string + DisplayName string + PreferredLoginName string + Roles []string + CreationDate time.Time + ChangeDate time.Time + Sequence uint64 } type OrgMemberSearchRequest struct { diff --git a/internal/org/repository/view/model/org_member.go b/internal/org/repository/view/model/org_member.go index b26fc0600..5167464bd 100644 --- a/internal/org/repository/view/model/org_member.go +++ b/internal/org/repository/view/model/org_member.go @@ -23,15 +23,16 @@ const ( ) type OrgMemberView struct { - UserID string `json:"userId" gorm:"column:user_id;primary_key"` - OrgID string `json:"-" gorm:"column:org_id;primary_key"` - UserName string `json:"-" gorm:"column:user_name"` - Email string `json:"-" gorm:"column:email_address"` - FirstName string `json:"-" gorm:"column:first_name"` - LastName string `json:"-" gorm:"column:last_name"` - DisplayName string `json:"-" gorm:"column:display_name"` - Roles pq.StringArray `json:"roles" gorm:"column:roles"` - Sequence uint64 `json:"-" gorm:"column:sequence"` + UserID string `json:"userId" gorm:"column:user_id;primary_key"` + OrgID string `json:"-" gorm:"column:org_id;primary_key"` + UserName string `json:"-" gorm:"column:user_name"` + Email string `json:"-" gorm:"column:email_address"` + FirstName string `json:"-" gorm:"column:first_name"` + LastName string `json:"-" gorm:"column:last_name"` + DisplayName string `json:"-" gorm:"column:display_name"` + Roles pq.StringArray `json:"roles" gorm:"column:roles"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` CreationDate time.Time `json:"-" gorm:"column:creation_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"` @@ -39,17 +40,18 @@ type OrgMemberView struct { func OrgMemberToModel(member *OrgMemberView) *model.OrgMemberView { return &model.OrgMemberView{ - UserID: member.UserID, - OrgID: member.OrgID, - UserName: member.UserName, - Email: member.Email, - FirstName: member.FirstName, - LastName: member.LastName, - DisplayName: member.DisplayName, - Roles: member.Roles, - Sequence: member.Sequence, - CreationDate: member.CreationDate, - ChangeDate: member.ChangeDate, + UserID: member.UserID, + OrgID: member.OrgID, + UserName: member.UserName, + Email: member.Email, + FirstName: member.FirstName, + LastName: member.LastName, + DisplayName: member.DisplayName, + PreferredLoginName: member.PreferredLoginName, + Roles: member.Roles, + Sequence: member.Sequence, + CreationDate: member.CreationDate, + ChangeDate: member.ChangeDate, } } diff --git a/internal/project/model/project_grant_member_view.go b/internal/project/model/project_grant_member_view.go index 4108b76f3..b51c5720c 100644 --- a/internal/project/model/project_grant_member_view.go +++ b/internal/project/model/project_grant_member_view.go @@ -6,18 +6,19 @@ import ( ) type ProjectGrantMemberView struct { - UserID string - GrantID string - ProjectID string - UserName string - Email string - FirstName string - LastName string - DisplayName string - Roles []string - CreationDate time.Time - ChangeDate time.Time - Sequence uint64 + UserID string + GrantID string + ProjectID string + UserName string + Email string + FirstName string + LastName string + DisplayName string + PreferredLoginName string + Roles []string + CreationDate time.Time + ChangeDate time.Time + Sequence uint64 } type ProjectGrantMemberSearchRequest struct { diff --git a/internal/project/model/project_member_view.go b/internal/project/model/project_member_view.go index f07fcfe2a..bade990c6 100644 --- a/internal/project/model/project_member_view.go +++ b/internal/project/model/project_member_view.go @@ -6,17 +6,18 @@ import ( ) type ProjectMemberView struct { - UserID string - ProjectID string - UserName string - Email string - FirstName string - LastName string - DisplayName string - Roles []string - CreationDate time.Time - ChangeDate time.Time - Sequence uint64 + UserID string + ProjectID string + UserName string + Email string + FirstName string + LastName string + DisplayName string + PreferredLoginName string + Roles []string + CreationDate time.Time + ChangeDate time.Time + Sequence uint64 } type ProjectMemberSearchRequest struct { diff --git a/internal/project/repository/view/model/project_grant_member.go b/internal/project/repository/view/model/project_grant_member.go index 2614b0dfb..72d653661 100644 --- a/internal/project/repository/view/model/project_grant_member.go +++ b/internal/project/repository/view/model/project_grant_member.go @@ -5,11 +5,12 @@ import ( "time" "github.com/caos/logging" + "github.com/lib/pq" + caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/project/model" es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" - "github.com/lib/pq" ) const ( @@ -23,16 +24,17 @@ const ( ) type ProjectGrantMemberView struct { - UserID string `json:"userId" gorm:"column:user_id;primary_key"` - GrantID string `json:"grantId" gorm:"column:grant_id;primary_key"` - ProjectID string `json:"-" gorm:"column:project_id"` - UserName string `json:"-" gorm:"column:user_name"` - Email string `json:"-" gorm:"column:email_address"` - FirstName string `json:"-" gorm:"column:first_name"` - LastName string `json:"-" gorm:"column:last_name"` - DisplayName string `json:"-" gorm:"column:display_name"` - Roles pq.StringArray `json:"roles" gorm:"column:roles"` - Sequence uint64 `json:"-" gorm:"column:sequence"` + UserID string `json:"userId" gorm:"column:user_id;primary_key"` + GrantID string `json:"grantId" gorm:"column:grant_id;primary_key"` + ProjectID string `json:"-" gorm:"column:project_id"` + UserName string `json:"-" gorm:"column:user_name"` + Email string `json:"-" gorm:"column:email_address"` + FirstName string `json:"-" gorm:"column:first_name"` + LastName string `json:"-" gorm:"column:last_name"` + DisplayName string `json:"-" gorm:"column:display_name"` + Roles pq.StringArray `json:"roles" gorm:"column:roles"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` CreationDate time.Time `json:"-" gorm:"column:creation_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"` @@ -40,18 +42,19 @@ type ProjectGrantMemberView struct { func ProjectGrantMemberToModel(member *ProjectGrantMemberView) *model.ProjectGrantMemberView { return &model.ProjectGrantMemberView{ - UserID: member.UserID, - GrantID: member.GrantID, - ProjectID: member.ProjectID, - UserName: member.UserName, - Email: member.Email, - FirstName: member.FirstName, - LastName: member.LastName, - DisplayName: member.DisplayName, - Roles: member.Roles, - Sequence: member.Sequence, - CreationDate: member.CreationDate, - ChangeDate: member.ChangeDate, + UserID: member.UserID, + GrantID: member.GrantID, + ProjectID: member.ProjectID, + UserName: member.UserName, + Email: member.Email, + FirstName: member.FirstName, + LastName: member.LastName, + DisplayName: member.DisplayName, + PreferredLoginName: member.PreferredLoginName, + Roles: member.Roles, + Sequence: member.Sequence, + CreationDate: member.CreationDate, + ChangeDate: member.ChangeDate, } } diff --git a/internal/project/repository/view/model/project_member.go b/internal/project/repository/view/model/project_member.go index bd90fe0f3..5c24695f0 100644 --- a/internal/project/repository/view/model/project_member.go +++ b/internal/project/repository/view/model/project_member.go @@ -22,15 +22,16 @@ const ( ) type ProjectMemberView struct { - UserID string `json:"userId" gorm:"column:user_id;primary_key"` - ProjectID string `json:"-" gorm:"column:project_id;primary_key"` - UserName string `json:"-" gorm:"column:user_name"` - Email string `json:"-" gorm:"column:email_address"` - FirstName string `json:"-" gorm:"column:first_name"` - LastName string `json:"-" gorm:"column:last_name"` - DisplayName string `json:"-" gorm:"column:display_name"` - Roles pq.StringArray `json:"roles" gorm:"column:roles"` - Sequence uint64 `json:"-" gorm:"column:sequence"` + UserID string `json:"userId" gorm:"column:user_id;primary_key"` + ProjectID string `json:"-" gorm:"column:project_id;primary_key"` + UserName string `json:"-" gorm:"column:user_name"` + Email string `json:"-" gorm:"column:email_address"` + FirstName string `json:"-" gorm:"column:first_name"` + LastName string `json:"-" gorm:"column:last_name"` + DisplayName string `json:"-" gorm:"column:display_name"` + Roles pq.StringArray `json:"roles" gorm:"column:roles"` + Sequence uint64 `json:"-" gorm:"column:sequence"` + PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"` CreationDate time.Time `json:"-" gorm:"column:creation_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"` diff --git a/internal/repository/user/human_mfa_passwordless.go b/internal/repository/user/human_mfa_passwordless.go index 02356efb8..acb27c540 100644 --- a/internal/repository/user/human_mfa_passwordless.go +++ b/internal/repository/user/human_mfa_passwordless.go @@ -64,6 +64,7 @@ func NewHumanPasswordlessVerifiedEvent( publicKey, aaguid []byte, signCount uint32, + userAgentID string, ) *HumanPasswordlessVerifiedEvent { return &HumanPasswordlessVerifiedEvent{ HumanWebAuthNVerifiedEvent: *NewHumanWebAuthNVerifiedEvent( @@ -79,6 +80,7 @@ func NewHumanPasswordlessVerifiedEvent( publicKey, aaguid, signCount, + userAgentID, ), } } diff --git a/internal/repository/user/human_mfa_u2f.go b/internal/repository/user/human_mfa_u2f.go index bca2ec773..975f326bc 100644 --- a/internal/repository/user/human_mfa_u2f.go +++ b/internal/repository/user/human_mfa_u2f.go @@ -64,6 +64,7 @@ func NewHumanU2FVerifiedEvent( publicKey, aaguid []byte, signCount uint32, + userAgentID string, ) *HumanU2FVerifiedEvent { return &HumanU2FVerifiedEvent{ HumanWebAuthNVerifiedEvent: *NewHumanWebAuthNVerifiedEvent( @@ -79,6 +80,7 @@ func NewHumanU2FVerifiedEvent( publicKey, aaguid, signCount, + userAgentID, ), } } diff --git a/internal/repository/user/human_mfa_web_auth_n.go b/internal/repository/user/human_mfa_web_auth_n.go index 0af90d8c0..8c0f13458 100644 --- a/internal/repository/user/human_mfa_web_auth_n.go +++ b/internal/repository/user/human_mfa_web_auth_n.go @@ -2,6 +2,7 @@ package user import ( "encoding/json" + "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore" @@ -56,6 +57,7 @@ type HumanWebAuthNVerifiedEvent struct { AAGUID []byte `json:"aaguid"` SignCount uint32 `json:"signCount"` WebAuthNTokenName string `json:"webAuthNTokenName"` + UserAgentID string `json:"userAgentID,omitempty"` } func (e *HumanWebAuthNVerifiedEvent) Data() interface{} { @@ -75,6 +77,7 @@ func NewHumanWebAuthNVerifiedEvent( publicKey, aaguid []byte, signCount uint32, + userAgentID string, ) *HumanWebAuthNVerifiedEvent { return &HumanWebAuthNVerifiedEvent{ BaseEvent: *base, @@ -85,6 +88,7 @@ func NewHumanWebAuthNVerifiedEvent( AAGUID: aaguid, SignCount: signCount, WebAuthNTokenName: webAuthNTokenName, + UserAgentID: userAgentID, } } diff --git a/internal/repository/user/machine.go b/internal/repository/user/machine.go index 3b23304d5..389c693b9 100644 --- a/internal/repository/user/machine.go +++ b/internal/repository/user/machine.go @@ -69,8 +69,6 @@ func MachineAddedEventMapper(event *repository.Event) (eventstore.EventReader, e type MachineChangedEvent struct { eventstore.BaseEvent `json:"-"` - UserName string `json:"userName"` - Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` } diff --git a/internal/user/repository/view/model/notify_user.go b/internal/user/repository/view/model/notify_user.go index 31060f88f..f4b15f8cf 100644 --- a/internal/user/repository/view/model/notify_user.go +++ b/internal/user/repository/view/model/notify_user.go @@ -2,16 +2,18 @@ package model import ( "encoding/json" - iam_model "github.com/caos/zitadel/internal/iam/model" "time" + iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/logging" + "github.com/lib/pq" + caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v1/models" org_model "github.com/caos/zitadel/internal/org/model" "github.com/caos/zitadel/internal/user/model" es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" - "github.com/lib/pq" ) const ( @@ -117,7 +119,8 @@ func (u *NotifyUser) AppendEvent(event *models.Event) (err error) { case es_model.UserAdded, es_model.UserRegistered, es_model.HumanRegistered, - es_model.HumanAdded: + es_model.HumanAdded, + es_model.MachineAdded: u.CreationDate = event.CreationDate u.setRootData(event) err = u.setData(event) @@ -130,7 +133,8 @@ func (u *NotifyUser) AppendEvent(event *models.Event) (err error) { es_model.UserPhoneChanged, es_model.HumanProfileChanged, es_model.HumanEmailChanged, - es_model.HumanPhoneChanged: + es_model.HumanPhoneChanged, + es_model.UserUserNameChanged: err = u.setData(event) case es_model.UserEmailVerified, es_model.HumanEmailVerified: diff --git a/migrations/cockroach/V1.37__members.sql b/migrations/cockroach/V1.37__members.sql new file mode 100644 index 000000000..94f58be84 --- /dev/null +++ b/migrations/cockroach/V1.37__members.sql @@ -0,0 +1,5 @@ +ALTER TABLE management.org_members ADD COLUMN preferred_login_name TEXT; +ALTER TABLE management.project_members ADD COLUMN preferred_login_name TEXT; +ALTER TABLE management.project_grant_members ADD COLUMN preferred_login_name TEXT; + +ALTER TABLE adminapi.iam_members ADD COLUMN preferred_login_name TEXT; diff --git a/pkg/grpc/app/application.go b/pkg/grpc/app/application.go index 7d35bddaf..272100ad0 100644 --- a/pkg/grpc/app/application.go +++ b/pkg/grpc/app/application.go @@ -11,16 +11,24 @@ func (a *App) Localizers() []middleware.Localizer { switch configType := a.Config.(type) { case *App_OidcConfig: - if !configType.OidcConfig.NoneCompliant { - return nil - } - localizers := make([]middleware.Localizer, len(configType.OidcConfig.ComplianceProblems)) - for i, problem := range configType.OidcConfig.ComplianceProblems { - localizers[i] = problem - } - return localizers + return configType.ComplianceLocalizers() } return nil } +func (o *App_OidcConfig) ComplianceLocalizers() []middleware.Localizer { + if o.OidcConfig == nil { + return nil + } + + if !o.OidcConfig.NoneCompliant { + return nil + } + localizers := make([]middleware.Localizer, len(o.OidcConfig.ComplianceProblems)) + for i, problem := range o.OidcConfig.ComplianceProblems { + localizers[i] = problem + } + return localizers +} + type AppConfig = isApp_Config diff --git a/pkg/grpc/management/app.go b/pkg/grpc/management/app.go index ad77e0e71..6b5f85113 100644 --- a/pkg/grpc/management/app.go +++ b/pkg/grpc/management/app.go @@ -1,6 +1,28 @@ package management -import "github.com/caos/zitadel/internal/api/grpc/server/middleware" +import ( + "github.com/caos/zitadel/internal/api/grpc/server/middleware" +) + +func (a *ListAppsResponse) Localizers() []middleware.Localizer { + if a == nil { + return nil + } + + localizers := make([]middleware.Localizer, 0) + for _, a := range a.Result { + localizers = append(localizers, a.Localizers()...) + } + return localizers +} + +func (a *GetAppByIDResponse) Localizers() []middleware.Localizer { + if a == nil || (a != nil && a.App == nil) { + return nil + } + + return a.App.Localizers() +} func (a *AddOIDCAppResponse) Localizers() []middleware.Localizer { if a == nil { diff --git a/proto/zitadel/auth.proto b/proto/zitadel/auth.proto index 98395c00d..3fa4d35c4 100644 --- a/proto/zitadel/auth.proto +++ b/proto/zitadel/auth.proto @@ -515,7 +515,9 @@ message VerifyMyPhoneRequest { string code = 1 [(validate.rules).string = {min_len: 1, max_len: 200}]; } -message VerifyMyPhoneResponse {} +message VerifyMyPhoneResponse { + zitadel.v1.ObjectDetails details = 1; +} message ResendMyPhoneVerificationRequest {} diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto index 446d15761..03fd28e37 100644 --- a/proto/zitadel/management.proto +++ b/proto/zitadel/management.proto @@ -388,7 +388,7 @@ service ManagementService { rpc RemoveHumanAuthFactorU2F(RemoveHumanAuthFactorU2FRequest) returns (RemoveHumanAuthFactorU2FResponse) { option (google.api.http) = { - delete: "/users/{user_id}/auth_factors/u2f" + delete: "/users/{user_id}/auth_factors/u2f/{token_id}" }; option (zitadel.v1.auth_option) = { @@ -408,7 +408,7 @@ service ManagementService { rpc RemoveHumanPasswordless(RemoveHumanPasswordlessRequest) returns (RemoveHumanPasswordlessResponse) { option (google.api.http) = { - delete: "/users/{user_id}/passwordless" + delete: "/users/{user_id}/passwordless/{token_id}" }; option (zitadel.v1.auth_option) = { @@ -429,8 +429,7 @@ service ManagementService { rpc GetMachineKeyByIDs(GetMachineKeyByIDsRequest) returns (GetMachineKeyByIDsResponse) { option (google.api.http) = { - post: "/users/{user_id}/keys/{key_id}" - body: "*" + get: "/users/{user_id}/keys/{key_id}" }; option (zitadel.v1.auth_option) = { @@ -2206,9 +2205,8 @@ message GenerateOrgDomainValidationRequest { } message GenerateOrgDomainValidationResponse { - zitadel.v1.ObjectDetails details = 1; - string token = 2; - string url = 3; + string token = 1; + string url = 2; } message ValidateOrgDomainRequest { diff --git a/proto/zitadel/user.proto b/proto/zitadel/user.proto index 398d744c1..0b90d33c2 100644 --- a/proto/zitadel/user.proto +++ b/proto/zitadel/user.proto @@ -172,8 +172,7 @@ message AuthFactorU2F { } message WebAuthNKey { - string id = 1; - bytes public_key = 2; + bytes public_key = 1; } message WebAuthNVerification {