fix: backend bugs (#1449)

* i18n of compliance problems

* fix: return iam member roles

* remove u2f/passwordless

* u2f/passwordless

* fix rest path GetMachineKeyByIDs

* fix rest path GetMachineKeyByIDs

* fix email mime-type

* fix: member preferred login name

* machine users in notify

* fix api key query

* fix: todos grpc api

* fix: handle user init state

* fix: tests

Co-authored-by: fabi <fabienne.gerschwiler@gmail.com>
This commit is contained in:
Livio Amstutz 2021-03-22 14:40:25 +01:00 committed by GitHub
parent 6b1f7ba333
commit bd1a3bb6d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 639 additions and 224 deletions

View File

@ -2,8 +2,14 @@ package handler
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" "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" "github.com/caos/zitadel/internal/user/repository/view"
view_model "github.com/caos/zitadel/internal/user/repository/view/model" 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" 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/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler" "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" "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_model "github.com/caos/zitadel/internal/user/model"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/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) { func (m *IAMMember) processIAMMember(event *es_models.Event) (err error) {
member := new(iam_model.IAMMemberView) member := new(iam_view_model.IAMMemberView)
switch event.Type { switch event.Type {
case model.IAMMemberAdded: case model.IAMMemberAdded:
err = member.AppendEvent(event) 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) user, err := m.getUserByID(member.UserID)
if err != nil { if err != nil {
return err return err
} }
m.fillUserData(member, user) return m.fillUserData(member, user)
return nil
} }
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.UserName = user.UserName
member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
if user.HumanView != nil { if user.HumanView != nil {
member.FirstName = user.FirstName member.FirstName = user.FirstName
member.LastName = user.LastName member.LastName = user.LastName
@ -166,7 +182,9 @@ func (m *IAMMember) fillUserData(member *iam_model.IAMMemberView, user *view_mod
if user.MachineView != nil { if user.MachineView != nil {
member.DisplayName = user.MachineView.Name member.DisplayName = user.MachineView.Name
} }
return nil
} }
func (m *IAMMember) OnError(event *es_models.Event, err error) error { 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") 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) 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) 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
}

View File

@ -12,6 +12,7 @@ import (
func (s *Server) ListIAMMemberRoles(ctx context.Context, req *admin_pb.ListIAMMemberRolesRequest) (*admin_pb.ListIAMMemberRolesResponse, error) { func (s *Server) ListIAMMemberRoles(ctx context.Context, req *admin_pb.ListIAMMemberRolesRequest) (*admin_pb.ListIAMMemberRolesResponse, error) {
roles := s.iam.GetIAMMemberRoles() roles := s.iam.GetIAMMemberRoles()
return &admin_pb.ListIAMMemberRolesResponse{ return &admin_pb.ListIAMMemberRolesResponse{
Roles: roles,
Details: object.ToListDetails(uint64(len(roles)), 0, time.Now()), Details: object.ToListDetails(uint64(len(roles)), 0, time.Now()),
}, nil }, nil
} }

View File

@ -67,7 +67,6 @@ func (s *Server) AddMyAuthFactorU2F(ctx context.Context, _ *auth_pb.AddMyAuthFac
} }
return &auth_pb.AddMyAuthFactorU2FResponse{ return &auth_pb.AddMyAuthFactorU2FResponse{
Key: &user_pb.WebAuthNKey{ Key: &user_pb.WebAuthNKey{
Id: u2f.WebAuthNTokenID,
PublicKey: u2f.CredentialCreationData, PublicKey: u2f.CredentialCreationData,
}, },
Details: object.AddToDetailsPb( 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) { func (s *Server) RemoveMyAuthFactorU2F(ctx context.Context, req *auth_pb.RemoveMyAuthFactorU2FRequest) (*auth_pb.RemoveMyAuthFactorU2FResponse, error) {
ctxData := authz.GetCtxData(ctx) 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 { if err != nil {
return nil, err return nil, err
} }

View File

@ -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) { func (s *Server) VerifyMyPhone(ctx context.Context, req *auth_pb.VerifyMyPhoneRequest) (*auth_pb.VerifyMyPhoneResponse, error) {
ctxData := authz.GetCtxData(ctx) 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 { if err != nil {
return nil, err return nil, err
} }
//TODO: response from business
return &auth_pb.VerifyMyPhoneResponse{ return &auth_pb.VerifyMyPhoneResponse{
//Details: object.DomainToChangeDetailsPb(objectDetails), Details: object.DomainToChangeDetailsPb(objectDetails),
}, nil }, nil
} }

View File

@ -245,7 +245,7 @@ func IDPProviderTypeModelFromPb(typ idp_pb.IDPOwnerType) iam_model.IDPProviderTy
func IDPIDQueryToModel(query *idp_pb.IDPIDQuery) *iam_model.IDPConfigSearchQuery { func IDPIDQueryToModel(query *idp_pb.IDPIDQuery) *iam_model.IDPConfigSearchQuery {
return &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, Method: domain.SearchMethodEquals,
Value: query.Id, Value: query.Id,
} }

View File

@ -139,7 +139,6 @@ func (s *Server) GenerateOrgDomainValidation(ctx context.Context, req *mgmt_pb.G
return &mgmt_pb.GenerateOrgDomainValidationResponse{ return &mgmt_pb.GenerateOrgDomainValidationResponse{
Token: token, Token: token,
Url: url, Url: url,
//TODO: remove details from proto
}, nil }, nil
} }

View File

@ -121,7 +121,7 @@ func AddAPIClientKeyRequestToDomain(key *mgmt_pb.AddAppKeyRequest) *domain.Appli
func ListAPIClientKeysRequestToModel(req *mgmt_pb.ListAppKeysRequest) (*key_model.AuthNKeySearchRequest, error) { func ListAPIClientKeysRequestToModel(req *mgmt_pb.ListAppKeysRequest) (*key_model.AuthNKeySearchRequest, error) {
offset, limit, asc := object.ListQueryToModel(req.Query) 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{ queries = append(queries, &key_model.AuthNKeySearchQuery{
Key: key_model.AuthNKeyObjectID, Key: key_model.AuthNKeyObjectID,
Method: domain.SearchMethodEquals, Method: domain.SearchMethodEquals,

View File

@ -2,6 +2,7 @@ package management
import ( import (
"context" "context"
"time"
"github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/api/authz"
member_grpc "github.com/caos/zitadel/internal/api/grpc/member" member_grpc "github.com/caos/zitadel/internal/api/grpc/member"
@ -107,7 +108,7 @@ func (s *Server) ListProjectGrantMemberRoles(ctx context.Context, req *mgmt_pb.L
roles := s.project.GetProjectGrantMemberRoles() roles := s.project.GetProjectGrantMemberRoles()
return &mgmt_pb.ListProjectGrantMemberRolesResponse{ return &mgmt_pb.ListProjectGrantMemberRolesResponse{
Result: roles, Result: roles,
//TODO: metadata Details: object_grpc.ToListDetails(uint64(len(roles)), 0, time.Now()),
}, nil }, nil
} }

View File

@ -100,7 +100,5 @@ func (s *Server) BulkRemoveUserGrant(ctx context.Context, req *mgmt_pb.BulkRemov
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &mgmt_pb.BulkRemoveUserGrantResponse{ return &mgmt_pb.BulkRemoveUserGrantResponse{}, nil
//TODO: Do we need details here?
}, nil
} }

View File

@ -19,7 +19,7 @@ func IAMMemberToPb(m *iam_model.IAMMemberView) *member_pb.Member {
return &member_pb.Member{ return &member_pb.Member{
UserId: m.UserID, UserId: m.UserID,
Roles: m.Roles, Roles: m.Roles,
// PreferredLoginName: //TODO: not implemented in be PreferredLoginName: m.PreferredLoginName,
Email: m.Email, Email: m.Email,
FirstName: m.FirstName, FirstName: m.FirstName,
LastName: m.LastName, LastName: m.LastName,

View File

@ -19,7 +19,7 @@ func OrgMemberToPb(m *org_model.OrgMemberView) *member_pb.Member {
return &member_pb.Member{ return &member_pb.Member{
UserId: m.UserID, UserId: m.UserID,
Roles: m.Roles, Roles: m.Roles,
// PreferredLoginName: //TODO: not implemented in be PreferredLoginName: m.PreferredLoginName,
Email: m.Email, Email: m.Email,
FirstName: m.FirstName, FirstName: m.FirstName,
LastName: m.LastName, LastName: m.LastName,

View File

@ -19,7 +19,7 @@ func ProjectGrantMemberToPb(m *proj_model.ProjectGrantMemberView) *member_pb.Mem
return &member_pb.Member{ return &member_pb.Member{
UserId: m.UserID, UserId: m.UserID,
Roles: m.Roles, Roles: m.Roles,
// PreferredLoginName: //TODO: not implemented in be PreferredLoginName: m.PreferredLoginName,
Email: m.Email, Email: m.Email,
FirstName: m.FirstName, FirstName: m.FirstName,
LastName: m.LastName, LastName: m.LastName,

View File

@ -19,7 +19,7 @@ func ProjectMemberToPb(m *proj_model.ProjectMemberView) *member_pb.Member {
return &member_pb.Member{ return &member_pb.Member{
UserId: m.UserID, UserId: m.UserID,
Roles: m.Roles, Roles: m.Roles,
// PreferredLoginName: //TODO: not implemented in be PreferredLoginName: m.PreferredLoginName,
Email: m.Email, Email: m.Email,
FirstName: m.FirstName, FirstName: m.FirstName,
LastName: m.LastName, LastName: m.LastName,

View File

@ -29,8 +29,11 @@ func OrgQueryToModel(query *org_pb.OrgQuery) (*org_model.OrgSearchQuery, error)
Value: q.DomainQuery.Domain, Value: q.DomainQuery.Domain,
}, nil }, nil
case *org_pb.OrgQuery_NameQuery: case *org_pb.OrgQuery_NameQuery:
//TODO: implement name in backend return &org_model.OrgSearchQuery{
return nil, errors.ThrowUnimplemented(nil, "ADMIN-KGXnX", "name query not implemented") Key: org_model.OrgSearchKeyOrgName,
Method: object.TextMethodToModel(q.NameQuery.Method),
Value: q.NameQuery.Name,
}, nil
default: default:
return nil, errors.ThrowInvalidArgument(nil, "ADMIN-vR9nC", "List.Query.Invalid") return nil, errors.ThrowInvalidArgument(nil, "ADMIN-vR9nC", "List.Query.Invalid")
} }

View File

@ -7,7 +7,8 @@ import (
func MultiFactorTypeToDomain(multiFactorType policy_pb.MultiFactorType) domain.MultiFactorType { func MultiFactorTypeToDomain(multiFactorType policy_pb.MultiFactorType) domain.MultiFactorType {
switch multiFactorType { switch multiFactorType {
//TODO: gap between proto and backend case policy_pb.MultiFactorType_MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION:
return domain.MultiFactorTypeU2FWithPIN
default: default:
return domain.MultiFactorTypeUnspecified return domain.MultiFactorTypeUnspecified
} }

View File

@ -244,7 +244,6 @@ func WebAuthNTokenViewToPb(token *model.WebAuthNView) *user_pb.WebAuthNToken {
func WebAuthNTokenToWebAuthNKeyPb(token *domain.WebAuthNToken) *user_pb.WebAuthNKey { func WebAuthNTokenToWebAuthNKeyPb(token *domain.WebAuthNToken) *user_pb.WebAuthNKey {
return &user_pb.WebAuthNKey{ return &user_pb.WebAuthNKey{
Id: string(token.KeyID), //TODO: ask if it's the correct id?
PublicKey: token.PublicKey, PublicKey: token.PublicKey,
} }
} }

View File

@ -37,10 +37,14 @@ func (wm *HumanEmailWriteModel) Reduce() error {
switch e := event.(type) { switch e := event.(type) {
case *user.HumanAddedEvent: case *user.HumanAddedEvent:
wm.Email = e.EmailAddress wm.Email = e.EmailAddress
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
case *user.HumanRegisteredEvent: case *user.HumanRegisteredEvent:
wm.Email = e.EmailAddress wm.Email = e.EmailAddress
wm.UserState = domain.UserStateActive
case *user.HumanInitialCodeAddedEvent:
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateInitial
case *user.HumanInitializedCheckSucceededEvent:
wm.UserState = domain.UserStateActive
case *user.HumanEmailChangedEvent: case *user.HumanEmailChangedEvent:
wm.Email = e.EmailAddress wm.Email = e.EmailAddress
wm.IsEmailVerified = false wm.IsEmailVerified = false
@ -52,9 +56,6 @@ func (wm *HumanEmailWriteModel) Reduce() error {
case *user.HumanEmailVerifiedEvent: case *user.HumanEmailVerifiedEvent:
wm.IsEmailVerified = true wm.IsEmailVerified = true
wm.Code = nil wm.Code = nil
if wm.UserState == domain.UserStateInitial {
wm.UserState = domain.UserStateActive
}
case *user.UserRemovedEvent: case *user.UserRemovedEvent:
wm.UserState = domain.UserStateDeleted wm.UserState = domain.UserStateDeleted
} }

View File

@ -572,6 +572,12 @@ func TestCommandSide_CreateVerificationCodeHumanEmail(t *testing.T) {
true, true,
), ),
), ),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
nil, time.Hour*1,
),
),
), ),
), ),
}, },

View File

@ -37,10 +37,10 @@ func (wm *HumanInitCodeWriteModel) Reduce() error {
switch e := event.(type) { switch e := event.(type) {
case *user.HumanAddedEvent: case *user.HumanAddedEvent:
wm.Email = e.EmailAddress wm.Email = e.EmailAddress
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
case *user.HumanRegisteredEvent: case *user.HumanRegisteredEvent:
wm.Email = e.EmailAddress wm.Email = e.EmailAddress
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
case *user.HumanEmailChangedEvent: case *user.HumanEmailChangedEvent:
wm.Email = e.EmailAddress wm.Email = e.EmailAddress
wm.IsEmailVerified = false wm.IsEmailVerified = false
@ -54,8 +54,10 @@ func (wm *HumanInitCodeWriteModel) Reduce() error {
wm.Code = e.Code wm.Code = e.Code
wm.CodeCreationDate = e.CreationDate() wm.CodeCreationDate = e.CreationDate()
wm.CodeExpiry = e.Expiry wm.CodeExpiry = e.Expiry
wm.UserState = domain.UserStateInitial
case *user.HumanInitializedCheckSucceededEvent: case *user.HumanInitializedCheckSucceededEvent:
wm.Code = nil wm.Code = nil
wm.UserState = domain.UserStateActive
case *user.UserRemovedEvent: case *user.UserRemovedEvent:
wm.UserState = domain.UserStateDeleted wm.UserState = domain.UserStateDeleted
} }

View File

@ -126,6 +126,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
true, true,
), ),
), ),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
nil, time.Hour*1,
),
),
), ),
expectPush( expectPush(
[]*repository.Event{ []*repository.Event{
@ -178,6 +184,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
true, true,
), ),
), ),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
nil, time.Hour*1,
),
),
), ),
expectPush( expectPush(
[]*repository.Event{ []*repository.Event{
@ -229,6 +241,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
true, true,
), ),
), ),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
nil, time.Hour*1,
),
),
), ),
expectPush( expectPush(
[]*repository.Event{ []*repository.Event{

View File

@ -54,6 +54,10 @@ func (wm *HumanWriteModel) Reduce() error {
wm.reduceHumanAddedEvent(e) wm.reduceHumanAddedEvent(e)
case *user.HumanRegisteredEvent: case *user.HumanRegisteredEvent:
wm.reduceHumanRegisteredEvent(e) wm.reduceHumanRegisteredEvent(e)
case *user.HumanInitialCodeAddedEvent:
wm.UserState = domain.UserStateInitial
case *user.HumanInitializedCheckSucceededEvent:
wm.UserState = domain.UserStateActive
case *user.UsernameChangedEvent: case *user.UsernameChangedEvent:
wm.UserName = e.UserName wm.UserName = e.UserName
case *user.HumanProfileChangedEvent: case *user.HumanProfileChangedEvent:
@ -128,7 +132,7 @@ func (wm *HumanWriteModel) reduceHumanAddedEvent(e *user.HumanAddedEvent) {
wm.StreetAddress = e.StreetAddress wm.StreetAddress = e.StreetAddress
wm.Secret = e.Secret wm.Secret = e.Secret
wm.SecretChangeRequired = e.ChangeRequired wm.SecretChangeRequired = e.ChangeRequired
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
} }
func (wm *HumanWriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEvent) { func (wm *HumanWriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEvent) {
@ -148,7 +152,7 @@ func (wm *HumanWriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEve
wm.StreetAddress = e.StreetAddress wm.StreetAddress = e.StreetAddress
wm.Secret = e.Secret wm.Secret = e.Secret
wm.SecretChangeRequired = e.ChangeRequired wm.SecretChangeRequired = e.ChangeRequired
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
} }
func (wm *HumanWriteModel) reduceHumanProfileChangedEvent(e *user.HumanProfileChangedEvent) { func (wm *HumanWriteModel) reduceHumanProfileChangedEvent(e *user.HumanProfileChangedEvent) {

View File

@ -37,11 +37,15 @@ func (wm *HumanPasswordWriteModel) Reduce() error {
case *user.HumanAddedEvent: case *user.HumanAddedEvent:
wm.Secret = e.Secret wm.Secret = e.Secret
wm.SecretChangeRequired = e.ChangeRequired wm.SecretChangeRequired = e.ChangeRequired
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
case *user.HumanRegisteredEvent: case *user.HumanRegisteredEvent:
wm.Secret = e.Secret wm.Secret = e.Secret
wm.SecretChangeRequired = e.ChangeRequired wm.SecretChangeRequired = e.ChangeRequired
wm.UserState = domain.UserStateActive wm.UserState = domain.UserStateActive
case *user.HumanInitialCodeAddedEvent:
wm.UserState = domain.UserStateInitial
case *user.HumanInitializedCheckSucceededEvent:
wm.UserState = domain.UserStateActive
case *user.HumanPasswordChangedEvent: case *user.HumanPasswordChangedEvent:
wm.Secret = e.Secret wm.Secret = e.Secret
wm.SecretChangeRequired = e.ChangeRequired wm.SecretChangeRequired = e.ChangeRequired

View File

@ -757,7 +757,7 @@ func TestCommandSide_RequestSetPassword(t *testing.T) {
}, },
}, },
{ {
name: "phone already verified, precondition error", name: "user initial, precondition error",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -776,6 +776,12 @@ func TestCommandSide_RequestSetPassword(t *testing.T) {
true, true,
), ),
), ),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
nil, time.Hour*1,
),
),
eventFromEventPusher( eventFromEventPusher(
user.NewHumanPhoneChangedEvent(context.Background(), user.NewHumanPhoneChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate, &user.NewAggregate("user1", "org1").Aggregate,

View File

@ -48,6 +48,10 @@ func (wm *HumanPhoneWriteModel) Reduce() error {
wm.State = domain.PhoneStateActive wm.State = domain.PhoneStateActive
} }
wm.UserState = domain.UserStateActive wm.UserState = domain.UserStateActive
case *user.HumanInitialCodeAddedEvent:
wm.UserState = domain.UserStateInitial
case *user.HumanInitializedCheckSucceededEvent:
wm.UserState = domain.UserStateActive
case *user.HumanPhoneChangedEvent: case *user.HumanPhoneChangedEvent:
wm.Phone = e.PhoneNumber wm.Phone = e.PhoneNumber
wm.IsPhoneVerified = false wm.IsPhoneVerified = false

View File

@ -474,7 +474,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
IsEmailVerified: true, IsEmailVerified: true,
}, },
State: domain.UserStateInitial, State: domain.UserStateActive,
}, },
}, },
}, },
@ -1048,7 +1048,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
EmailAddress: "email@test.ch", EmailAddress: "email@test.ch",
IsEmailVerified: true, IsEmailVerified: true,
}, },
State: domain.UserStateInitial, State: domain.UserStateActive,
}, },
}, },
}, },

View File

@ -173,6 +173,7 @@ func (c *Commands) HumanVerifyU2FSetup(ctx context.Context, userID, resourceowne
webAuthN.PublicKey, webAuthN.PublicKey,
webAuthN.AAGUID, webAuthN.AAGUID,
webAuthN.SignCount, webAuthN.SignCount,
userAgentID,
), ),
) )
if err != nil { if err != nil {
@ -206,6 +207,7 @@ func (c *Commands) HumanHumanPasswordlessSetup(ctx context.Context, userID, reso
webAuthN.PublicKey, webAuthN.PublicKey,
webAuthN.AAGUID, webAuthN.AAGUID,
webAuthN.SignCount, webAuthN.SignCount,
userAgentID,
), ),
) )
if err != nil { if err != nil {
@ -436,7 +438,7 @@ func (c *Commands) removeHumanWebAuthN(ctx context.Context, userID, webAuthNID,
return nil, err return nil, err
} }
if existingWebAuthN.State == domain.MFAStateUnspecified || existingWebAuthN.State == domain.MFAStateRemoved { 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) userAgg := UserAggregateFromWriteModel(&existingWebAuthN.WriteModel)

View File

@ -39,18 +39,50 @@ func (wm *HumanWebAuthNWriteModel) AppendEvents(events ...eventstore.EventReader
if wm.WebauthNTokenID == e.WebAuthNTokenID { if wm.WebauthNTokenID == e.WebAuthNTokenID {
wm.WriteModel.AppendEvents(e) 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: case *user.HumanWebAuthNVerifiedEvent:
if wm.WebauthNTokenID == e.WebAuthNTokenID { if wm.WebauthNTokenID == e.WebAuthNTokenID {
wm.WriteModel.AppendEvents(e) 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: case *user.HumanWebAuthNSignCountChangedEvent:
if wm.WebauthNTokenID == e.WebAuthNTokenID { if wm.WebauthNTokenID == e.WebAuthNTokenID {
wm.WriteModel.AppendEvents(e) 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: case *user.HumanWebAuthNRemovedEvent:
if wm.WebauthNTokenID == e.WebAuthNTokenID { if wm.WebauthNTokenID == e.WebAuthNTokenID {
wm.WriteModel.AppendEvents(e) 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: case *user.UserRemovedEvent:
wm.WriteModel.AppendEvents(e) wm.WriteModel.AppendEvents(e)
} }

View File

@ -30,9 +30,11 @@ func (wm *UserWriteModel) Reduce() error {
switch e := event.(type) { switch e := event.(type) {
case *user.HumanAddedEvent: case *user.HumanAddedEvent:
wm.UserName = e.UserName wm.UserName = e.UserName
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateActive
case *user.HumanRegisteredEvent: case *user.HumanRegisteredEvent:
wm.UserName = e.UserName wm.UserName = e.UserName
wm.UserState = domain.UserStateActive
case *user.HumanInitialCodeAddedEvent:
wm.UserState = domain.UserStateInitial wm.UserState = domain.UserStateInitial
case *user.HumanInitializedCheckSucceededEvent: case *user.HumanInitializedCheckSucceededEvent:
wm.UserState = domain.UserStateActive wm.UserState = domain.UserStateActive

View File

@ -13,6 +13,7 @@ type IAMMemberView struct {
FirstName string FirstName string
LastName string LastName string
DisplayName string DisplayName string
PreferredLoginName string
Roles []string Roles []string
CreationDate time.Time CreationDate time.Time
ChangeDate time.Time ChangeDate time.Time

View File

@ -32,6 +32,7 @@ type IAMMemberView struct {
DisplayName string `json:"-" gorm:"column:display_name"` DisplayName string `json:"-" gorm:"column:display_name"`
Roles pq.StringArray `json:"roles" gorm:"column:roles"` Roles pq.StringArray `json:"roles" gorm:"column:roles"`
Sequence uint64 `json:"-" gorm:"column:sequence"` Sequence uint64 `json:"-" gorm:"column:sequence"`
PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"` CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"`
@ -62,6 +63,7 @@ func IAMMemberToModel(member *IAMMemberView) *model.IAMMemberView {
FirstName: member.FirstName, FirstName: member.FirstName,
LastName: member.LastName, LastName: member.LastName,
DisplayName: member.DisplayName, DisplayName: member.DisplayName,
PreferredLoginName: member.PreferredLoginName,
Roles: member.Roles, Roles: member.Roles,
Sequence: member.Sequence, Sequence: member.Sequence,
CreationDate: member.CreationDate, CreationDate: member.CreationDate,

View File

@ -2,16 +2,23 @@ package handler
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" "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/zitadel/internal/user/repository/view"
"github.com/caos/logging" "github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models" 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/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler" "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" "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_model "github.com/caos/zitadel/internal/user/model"
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/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" 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) { func (m *OrgMember) processOrgMember(event *es_models.Event) (err error) {
member := new(org_model.OrgMemberView) member := new(org_view_model.OrgMemberView)
switch event.Type { switch event.Type {
case model.OrgMemberAdded: case model.OrgMemberAdded:
err = member.AppendEvent(event) 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) user, err := m.getUserByID(member.UserID)
if err != nil { if err != nil {
return err return err
} }
m.fillUserData(member, user) return m.fillUserData(member, user)
return nil
} }
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.UserName = user.UserName
member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
if user.HumanView != nil { if user.HumanView != nil {
member.FirstName = user.FirstName member.FirstName = user.FirstName
member.LastName = user.LastName member.LastName = user.LastName
@ -166,7 +181,9 @@ func (m *OrgMember) fillUserData(member *org_model.OrgMemberView, user *usr_view
if user.MachineView != nil { if user.MachineView != nil {
member.DisplayName = user.MachineView.Name member.DisplayName = user.MachineView.Name
} }
return nil
} }
func (m *OrgMember) OnError(event *es_models.Event, err error) error { 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") 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) 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) 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
}

View File

@ -2,8 +2,16 @@ package handler
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" "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" "github.com/caos/zitadel/internal/user/repository/view"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" 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 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.UserName = user.UserName
member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
if user.HumanView != nil { if user.HumanView != nil {
member.FirstName = user.FirstName member.FirstName = user.FirstName
member.LastName = user.LastName member.LastName = user.LastName
@ -171,6 +188,7 @@ func (p *ProjectGrantMember) fillUserData(member *view_model.ProjectGrantMemberV
if user.MachineView != nil { if user.MachineView != nil {
member.DisplayName = user.MachineView.Name member.DisplayName = user.MachineView.Name
} }
return nil
} }
func (p *ProjectGrantMember) OnError(event *es_models.Event, err error) error { 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) 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
}

View File

@ -2,8 +2,15 @@ package handler
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" "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/zitadel/internal/user/repository/view"
"github.com/caos/logging" "github.com/caos/logging"
@ -11,6 +18,7 @@ import (
es_models "github.com/caos/zitadel/internal/eventstore/v1/models" 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/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler" "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" proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/project/repository/view/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model"
usr_model "github.com/caos/zitadel/internal/user/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 { if err != nil {
return err return err
} }
p.fillUserData(member, user) return p.fillUserData(member, user)
return nil
} }
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.UserName = user.UserName
member.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
if user.HumanView != nil { if user.HumanView != nil {
member.FirstName = user.FirstName member.FirstName = user.FirstName
member.LastName = user.LastName member.LastName = user.LastName
@ -168,7 +184,9 @@ func (p *ProjectMember) fillUserData(member *view_model.ProjectMemberView, user
if user.MachineView != nil { if user.MachineView != nil {
member.DisplayName = user.MachineView.Name member.DisplayName = user.MachineView.Name
} }
return nil
} }
func (p *ProjectMember) OnError(event *es_models.Event, err error) error { 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") 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) 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) 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
}

View File

@ -32,9 +32,9 @@ func (msg *EmailMessage) GetContent() string {
} }
//default mime-type is html //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) { 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 subject := "Subject: " + msg.Subject + lineBreak
message += subject + mime + lineBreak + msg.Content message += subject + mime + lineBreak + msg.Content

View File

@ -2,6 +2,7 @@ package handler
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1" "github.com/caos/zitadel/internal/eventstore/v1"
@ -12,6 +13,7 @@ import (
org_view "github.com/caos/zitadel/internal/org/repository/view" org_view "github.com/caos/zitadel/internal/org/repository/view"
"github.com/caos/logging" "github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models" 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/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler" "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, case es_model.UserAdded,
es_model.UserRegistered, es_model.UserRegistered,
es_model.HumanRegistered, es_model.HumanRegistered,
es_model.HumanAdded: es_model.HumanAdded,
user.AppendEvent(event) es_model.MachineAdded:
u.fillLoginNames(user) err := user.AppendEvent(event)
if err != nil {
return err
}
err = u.fillLoginNames(user)
case es_model.UserProfileChanged, case es_model.UserProfileChanged,
es_model.UserEmailChanged, es_model.UserEmailChanged,
es_model.UserEmailVerified, es_model.UserEmailVerified,
@ -128,7 +134,7 @@ func (u *NotifyUser) ProcessUser(event *es_models.Event) (err error) {
if err != nil { if err != nil {
return err return err
} }
u.fillLoginNames(user) err = u.fillLoginNames(user)
case es_model.UserRemoved: case es_model.UserRemoved:
return u.view.DeleteNotifyUser(event.AggregateID, event) return u.view.DeleteNotifyUser(event.AggregateID, event)
default: default:

View File

@ -1,8 +1,9 @@
package model package model
import ( import (
"github.com/caos/zitadel/internal/domain"
"time" "time"
"github.com/caos/zitadel/internal/domain"
) )
type OrgMemberView struct { type OrgMemberView struct {
@ -13,6 +14,7 @@ type OrgMemberView struct {
FirstName string FirstName string
LastName string LastName string
DisplayName string DisplayName string
PreferredLoginName string
Roles []string Roles []string
CreationDate time.Time CreationDate time.Time
ChangeDate time.Time ChangeDate time.Time

View File

@ -32,6 +32,7 @@ type OrgMemberView struct {
DisplayName string `json:"-" gorm:"column:display_name"` DisplayName string `json:"-" gorm:"column:display_name"`
Roles pq.StringArray `json:"roles" gorm:"column:roles"` Roles pq.StringArray `json:"roles" gorm:"column:roles"`
Sequence uint64 `json:"-" gorm:"column:sequence"` Sequence uint64 `json:"-" gorm:"column:sequence"`
PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"` CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"`
@ -46,6 +47,7 @@ func OrgMemberToModel(member *OrgMemberView) *model.OrgMemberView {
FirstName: member.FirstName, FirstName: member.FirstName,
LastName: member.LastName, LastName: member.LastName,
DisplayName: member.DisplayName, DisplayName: member.DisplayName,
PreferredLoginName: member.PreferredLoginName,
Roles: member.Roles, Roles: member.Roles,
Sequence: member.Sequence, Sequence: member.Sequence,
CreationDate: member.CreationDate, CreationDate: member.CreationDate,

View File

@ -14,6 +14,7 @@ type ProjectGrantMemberView struct {
FirstName string FirstName string
LastName string LastName string
DisplayName string DisplayName string
PreferredLoginName string
Roles []string Roles []string
CreationDate time.Time CreationDate time.Time
ChangeDate time.Time ChangeDate time.Time

View File

@ -13,6 +13,7 @@ type ProjectMemberView struct {
FirstName string FirstName string
LastName string LastName string
DisplayName string DisplayName string
PreferredLoginName string
Roles []string Roles []string
CreationDate time.Time CreationDate time.Time
ChangeDate time.Time ChangeDate time.Time

View File

@ -5,11 +5,12 @@ import (
"time" "time"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/lib/pq"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/model"
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
"github.com/lib/pq"
) )
const ( const (
@ -33,6 +34,7 @@ type ProjectGrantMemberView struct {
DisplayName string `json:"-" gorm:"column:display_name"` DisplayName string `json:"-" gorm:"column:display_name"`
Roles pq.StringArray `json:"roles" gorm:"column:roles"` Roles pq.StringArray `json:"roles" gorm:"column:roles"`
Sequence uint64 `json:"-" gorm:"column:sequence"` Sequence uint64 `json:"-" gorm:"column:sequence"`
PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"` CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"`
@ -48,6 +50,7 @@ func ProjectGrantMemberToModel(member *ProjectGrantMemberView) *model.ProjectGra
FirstName: member.FirstName, FirstName: member.FirstName,
LastName: member.LastName, LastName: member.LastName,
DisplayName: member.DisplayName, DisplayName: member.DisplayName,
PreferredLoginName: member.PreferredLoginName,
Roles: member.Roles, Roles: member.Roles,
Sequence: member.Sequence, Sequence: member.Sequence,
CreationDate: member.CreationDate, CreationDate: member.CreationDate,

View File

@ -31,6 +31,7 @@ type ProjectMemberView struct {
DisplayName string `json:"-" gorm:"column:display_name"` DisplayName string `json:"-" gorm:"column:display_name"`
Roles pq.StringArray `json:"roles" gorm:"column:roles"` Roles pq.StringArray `json:"roles" gorm:"column:roles"`
Sequence uint64 `json:"-" gorm:"column:sequence"` Sequence uint64 `json:"-" gorm:"column:sequence"`
PreferredLoginName string `json:"-" gorm:"column:preferred_login_name"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"` CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"` ChangeDate time.Time `json:"-" gorm:"column:change_date"`

View File

@ -64,6 +64,7 @@ func NewHumanPasswordlessVerifiedEvent(
publicKey, publicKey,
aaguid []byte, aaguid []byte,
signCount uint32, signCount uint32,
userAgentID string,
) *HumanPasswordlessVerifiedEvent { ) *HumanPasswordlessVerifiedEvent {
return &HumanPasswordlessVerifiedEvent{ return &HumanPasswordlessVerifiedEvent{
HumanWebAuthNVerifiedEvent: *NewHumanWebAuthNVerifiedEvent( HumanWebAuthNVerifiedEvent: *NewHumanWebAuthNVerifiedEvent(
@ -79,6 +80,7 @@ func NewHumanPasswordlessVerifiedEvent(
publicKey, publicKey,
aaguid, aaguid,
signCount, signCount,
userAgentID,
), ),
} }
} }

View File

@ -64,6 +64,7 @@ func NewHumanU2FVerifiedEvent(
publicKey, publicKey,
aaguid []byte, aaguid []byte,
signCount uint32, signCount uint32,
userAgentID string,
) *HumanU2FVerifiedEvent { ) *HumanU2FVerifiedEvent {
return &HumanU2FVerifiedEvent{ return &HumanU2FVerifiedEvent{
HumanWebAuthNVerifiedEvent: *NewHumanWebAuthNVerifiedEvent( HumanWebAuthNVerifiedEvent: *NewHumanWebAuthNVerifiedEvent(
@ -79,6 +80,7 @@ func NewHumanU2FVerifiedEvent(
publicKey, publicKey,
aaguid, aaguid,
signCount, signCount,
userAgentID,
), ),
} }
} }

View File

@ -2,6 +2,7 @@ package user
import ( import (
"encoding/json" "encoding/json"
"github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore"
@ -56,6 +57,7 @@ type HumanWebAuthNVerifiedEvent struct {
AAGUID []byte `json:"aaguid"` AAGUID []byte `json:"aaguid"`
SignCount uint32 `json:"signCount"` SignCount uint32 `json:"signCount"`
WebAuthNTokenName string `json:"webAuthNTokenName"` WebAuthNTokenName string `json:"webAuthNTokenName"`
UserAgentID string `json:"userAgentID,omitempty"`
} }
func (e *HumanWebAuthNVerifiedEvent) Data() interface{} { func (e *HumanWebAuthNVerifiedEvent) Data() interface{} {
@ -75,6 +77,7 @@ func NewHumanWebAuthNVerifiedEvent(
publicKey, publicKey,
aaguid []byte, aaguid []byte,
signCount uint32, signCount uint32,
userAgentID string,
) *HumanWebAuthNVerifiedEvent { ) *HumanWebAuthNVerifiedEvent {
return &HumanWebAuthNVerifiedEvent{ return &HumanWebAuthNVerifiedEvent{
BaseEvent: *base, BaseEvent: *base,
@ -85,6 +88,7 @@ func NewHumanWebAuthNVerifiedEvent(
AAGUID: aaguid, AAGUID: aaguid,
SignCount: signCount, SignCount: signCount,
WebAuthNTokenName: webAuthNTokenName, WebAuthNTokenName: webAuthNTokenName,
UserAgentID: userAgentID,
} }
} }

View File

@ -69,8 +69,6 @@ func MachineAddedEventMapper(event *repository.Event) (eventstore.EventReader, e
type MachineChangedEvent struct { type MachineChangedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"`
Name *string `json:"name,omitempty"` Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"` Description *string `json:"description,omitempty"`
} }

View File

@ -2,16 +2,18 @@ package model
import ( import (
"encoding/json" "encoding/json"
iam_model "github.com/caos/zitadel/internal/iam/model"
"time" "time"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/lib/pq"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models" "github.com/caos/zitadel/internal/eventstore/v1/models"
org_model "github.com/caos/zitadel/internal/org/model" org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/model"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
"github.com/lib/pq"
) )
const ( const (
@ -117,7 +119,8 @@ func (u *NotifyUser) AppendEvent(event *models.Event) (err error) {
case es_model.UserAdded, case es_model.UserAdded,
es_model.UserRegistered, es_model.UserRegistered,
es_model.HumanRegistered, es_model.HumanRegistered,
es_model.HumanAdded: es_model.HumanAdded,
es_model.MachineAdded:
u.CreationDate = event.CreationDate u.CreationDate = event.CreationDate
u.setRootData(event) u.setRootData(event)
err = u.setData(event) err = u.setData(event)
@ -130,7 +133,8 @@ func (u *NotifyUser) AppendEvent(event *models.Event) (err error) {
es_model.UserPhoneChanged, es_model.UserPhoneChanged,
es_model.HumanProfileChanged, es_model.HumanProfileChanged,
es_model.HumanEmailChanged, es_model.HumanEmailChanged,
es_model.HumanPhoneChanged: es_model.HumanPhoneChanged,
es_model.UserUserNameChanged:
err = u.setData(event) err = u.setData(event)
case es_model.UserEmailVerified, case es_model.UserEmailVerified,
es_model.HumanEmailVerified: es_model.HumanEmailVerified:

View File

@ -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;

View File

@ -11,16 +11,24 @@ func (a *App) Localizers() []middleware.Localizer {
switch configType := a.Config.(type) { switch configType := a.Config.(type) {
case *App_OidcConfig: case *App_OidcConfig:
if !configType.OidcConfig.NoneCompliant { return configType.ComplianceLocalizers()
return nil
}
localizers := make([]middleware.Localizer, len(configType.OidcConfig.ComplianceProblems))
for i, problem := range configType.OidcConfig.ComplianceProblems {
localizers[i] = problem
}
return localizers
} }
return nil 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 type AppConfig = isApp_Config

View File

@ -1,6 +1,28 @@
package management 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 { func (a *AddOIDCAppResponse) Localizers() []middleware.Localizer {
if a == nil { if a == nil {

View File

@ -515,7 +515,9 @@ message VerifyMyPhoneRequest {
string code = 1 [(validate.rules).string = {min_len: 1, max_len: 200}]; string code = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
} }
message VerifyMyPhoneResponse {} message VerifyMyPhoneResponse {
zitadel.v1.ObjectDetails details = 1;
}
message ResendMyPhoneVerificationRequest {} message ResendMyPhoneVerificationRequest {}

View File

@ -388,7 +388,7 @@ service ManagementService {
rpc RemoveHumanAuthFactorU2F(RemoveHumanAuthFactorU2FRequest) returns (RemoveHumanAuthFactorU2FResponse) { rpc RemoveHumanAuthFactorU2F(RemoveHumanAuthFactorU2FRequest) returns (RemoveHumanAuthFactorU2FResponse) {
option (google.api.http) = { 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) = { option (zitadel.v1.auth_option) = {
@ -408,7 +408,7 @@ service ManagementService {
rpc RemoveHumanPasswordless(RemoveHumanPasswordlessRequest) returns (RemoveHumanPasswordlessResponse) { rpc RemoveHumanPasswordless(RemoveHumanPasswordlessRequest) returns (RemoveHumanPasswordlessResponse) {
option (google.api.http) = { option (google.api.http) = {
delete: "/users/{user_id}/passwordless" delete: "/users/{user_id}/passwordless/{token_id}"
}; };
option (zitadel.v1.auth_option) = { option (zitadel.v1.auth_option) = {
@ -429,8 +429,7 @@ service ManagementService {
rpc GetMachineKeyByIDs(GetMachineKeyByIDsRequest) returns (GetMachineKeyByIDsResponse) { rpc GetMachineKeyByIDs(GetMachineKeyByIDsRequest) returns (GetMachineKeyByIDsResponse) {
option (google.api.http) = { option (google.api.http) = {
post: "/users/{user_id}/keys/{key_id}" get: "/users/{user_id}/keys/{key_id}"
body: "*"
}; };
option (zitadel.v1.auth_option) = { option (zitadel.v1.auth_option) = {
@ -2206,9 +2205,8 @@ message GenerateOrgDomainValidationRequest {
} }
message GenerateOrgDomainValidationResponse { message GenerateOrgDomainValidationResponse {
zitadel.v1.ObjectDetails details = 1; string token = 1;
string token = 2; string url = 2;
string url = 3;
} }
message ValidateOrgDomainRequest { message ValidateOrgDomainRequest {

View File

@ -172,8 +172,7 @@ message AuthFactorU2F {
} }
message WebAuthNKey { message WebAuthNKey {
string id = 1; bytes public_key = 1;
bytes public_key = 2;
} }
message WebAuthNVerification { message WebAuthNVerification {