diff --git a/internal/api/grpc/admin/iam_member_converter.go b/internal/api/grpc/admin/iam_member_converter.go index 7e3918e85..5df58491f 100644 --- a/internal/api/grpc/admin/iam_member_converter.go +++ b/internal/api/grpc/admin/iam_member_converter.go @@ -11,17 +11,11 @@ import ( ) func addIamMemberToDomain(member *admin.AddIamMemberRequest) *domain.Member { - return &domain.Member{ - UserID: member.UserId, - Roles: member.Roles, - } + return domain.NewMember(domain.IAMID, member.UserId, member.Roles...) } func changeIamMemberToDomain(member *admin.ChangeIamMemberRequest) *domain.Member { - return &domain.Member{ - UserID: member.UserId, - Roles: member.Roles, - } + return domain.NewMember(domain.IAMID, member.UserId, member.Roles...) } func iamMemberFromDomain(member *domain.Member) *admin.IamMember { diff --git a/internal/api/grpc/admin/idp_config.go b/internal/api/grpc/admin/idp_config.go index 5558f609b..e5c04bd39 100644 --- a/internal/api/grpc/admin/idp_config.go +++ b/internal/api/grpc/admin/idp_config.go @@ -47,9 +47,8 @@ func (s *Server) ReactivateIdpConfig(ctx context.Context, id *admin.IdpID) (*adm return idpFromDomain(config), nil } -//TODO: Change To V2 func (s *Server) RemoveIdpConfig(ctx context.Context, id *admin.IdpID) (*empty.Empty, error) { - err := s.iam.RemoveIDPConfig(ctx, id.Id) + err := s.command.RemoveDefaultIDPConfig(ctx, id.Id) return &empty.Empty{}, err } diff --git a/internal/api/grpc/admin/login_policy.go b/internal/api/grpc/admin/login_policy.go index 101c9f5c8..2155e2e0e 100644 --- a/internal/api/grpc/admin/login_policy.go +++ b/internal/api/grpc/admin/login_policy.go @@ -38,9 +38,8 @@ func (s *Server) AddIdpProviderToDefaultLoginPolicy(ctx context.Context, provide return idpProviderFromDomain(result), nil } -//TODO: Change to v2 func (s *Server) RemoveIdpProviderFromDefaultLoginPolicy(ctx context.Context, provider *admin.IdpProviderID) (*empty.Empty, error) { - err := s.iam.RemoveIDPProviderFromLoginPolicy(ctx, idpProviderToModel(provider)) + err := s.command.RemoveIDPProviderFromDefaultLoginPolicy(ctx, idpProviderToDomain(provider)) return &empty.Empty{}, err } @@ -53,15 +52,15 @@ func (s *Server) GetDefaultLoginPolicySecondFactors(ctx context.Context, _ *empt } func (s *Server) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, mfa *admin.SecondFactor) (*admin.SecondFactor, error) { - result, err := s.command.AddSecondFactorToDefaultLoginPolicy(ctx, secondFactorTypeToModel(mfa)) + result, err := s.command.AddSecondFactorToDefaultLoginPolicy(ctx, secondFactorTypeToDomain(mfa)) if err != nil { return nil, err } - return secondFactorFromModel(result), nil + return secondFactorFromDomain(result), nil } func (s *Server) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Context, mfa *admin.SecondFactor) (*empty.Empty, error) { - err := s.command.RemoveSecondFactorFromDefaultLoginPolicy(ctx, secondFactorTypeToModel(mfa)) + err := s.command.RemoveSecondFactorFromDefaultLoginPolicy(ctx, secondFactorTypeToDomain(mfa)) return &empty.Empty{}, err } @@ -74,14 +73,14 @@ func (s *Server) GetDefaultLoginPolicyMultiFactors(ctx context.Context, _ *empty } func (s *Server) AddMultiFactorToDefaultLoginPolicy(ctx context.Context, mfa *admin.MultiFactor) (*admin.MultiFactor, error) { - result, err := s.command.AddMultiFactorToDefaultLoginPolicy(ctx, multiFactorTypeToModel(mfa)) + result, err := s.command.AddMultiFactorToDefaultLoginPolicy(ctx, multiFactorTypeToDomain(mfa)) if err != nil { return nil, err } - return multiFactorFromModel(result), nil + return multiFactorFromDomain(result), nil } func (s *Server) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Context, mfa *admin.MultiFactor) (*empty.Empty, error) { - err := s.command.RemoveMultiFactorFromDefaultLoginPolicy(ctx, multiFactorTypeToModel(mfa)) + err := s.command.RemoveMultiFactorFromDefaultLoginPolicy(ctx, multiFactorTypeToDomain(mfa)) return &empty.Empty{}, err } diff --git a/internal/api/grpc/admin/login_policy_converter.go b/internal/api/grpc/admin/login_policy_converter.go index 4f146e1f9..a00eebfd9 100644 --- a/internal/api/grpc/admin/login_policy_converter.go +++ b/internal/api/grpc/admin/login_policy_converter.go @@ -128,9 +128,20 @@ func secondFactorsResultFromModel(result *iam_model.SecondFactorsSearchResponse) } } -func secondFactorFromModel(mfaType iam_model.SecondFactorType) *admin.SecondFactor { +func secondFactorFromDomain(mfaType domain.SecondFactorType) *admin.SecondFactor { return &admin.SecondFactor{ - SecondFactor: secondFactorTypeFromModel(mfaType), + SecondFactor: secondFactorTypeFromDomain(mfaType), + } +} + +func secondFactorTypeFromDomain(mfaType domain.SecondFactorType) admin.SecondFactorType { + switch mfaType { + case domain.SecondFactorTypeOTP: + return admin.SecondFactorType_SECONDFACTORTYPE_OTP + case domain.SecondFactorTypeU2F: + return admin.SecondFactorType_SECONDFACTORTYPE_U2F + default: + return admin.SecondFactorType_SECONDFACTORTYPE_UNSPECIFIED } } @@ -145,14 +156,14 @@ func secondFactorTypeFromModel(mfaType iam_model.SecondFactorType) admin.SecondF } } -func secondFactorTypeToModel(mfaType *admin.SecondFactor) iam_model.SecondFactorType { +func secondFactorTypeToDomain(mfaType *admin.SecondFactor) domain.SecondFactorType { switch mfaType.SecondFactor { case admin.SecondFactorType_SECONDFACTORTYPE_OTP: - return iam_model.SecondFactorTypeOTP + return domain.SecondFactorTypeOTP case admin.SecondFactorType_SECONDFACTORTYPE_U2F: - return iam_model.SecondFactorTypeU2F + return domain.SecondFactorTypeU2F default: - return iam_model.SecondFactorTypeUnspecified + return domain.SecondFactorTypeUnspecified } } @@ -184,9 +195,18 @@ func multiFactorResultFromModel(result *iam_model.MultiFactorsSearchResponse) *a } } -func multiFactorFromModel(mfaType iam_model.MultiFactorType) *admin.MultiFactor { +func multiFactorFromDomain(mfaType domain.MultiFactorType) *admin.MultiFactor { return &admin.MultiFactor{ - MultiFactor: multiFactorTypeFromModel(mfaType), + MultiFactor: multiFactorTypeFromDomain(mfaType), + } +} + +func multiFactorTypeFromDomain(mfaType domain.MultiFactorType) admin.MultiFactorType { + switch mfaType { + case domain.MultiFactorTypeU2FWithPIN: + return admin.MultiFactorType_MULTIFACTORTYPE_U2F_WITH_PIN + default: + return admin.MultiFactorType_MULTIFACTORTYPE_UNSPECIFIED } } @@ -199,11 +219,11 @@ func multiFactorTypeFromModel(mfaType iam_model.MultiFactorType) admin.MultiFact } } -func multiFactorTypeToModel(mfaType *admin.MultiFactor) iam_model.MultiFactorType { +func multiFactorTypeToDomain(mfaType *admin.MultiFactor) domain.MultiFactorType { switch mfaType.MultiFactor { case admin.MultiFactorType_MULTIFACTORTYPE_U2F_WITH_PIN: - return iam_model.MultiFactorTypeU2FWithPIN + return domain.MultiFactorTypeU2FWithPIN default: - return iam_model.MultiFactorTypeUnspecified + return domain.MultiFactorTypeUnspecified } } diff --git a/internal/api/grpc/admin/org.go b/internal/api/grpc/admin/org.go index 73ebf7f00..d301a0b8a 100644 --- a/internal/api/grpc/admin/org.go +++ b/internal/api/grpc/admin/org.go @@ -81,6 +81,6 @@ func (s *Server) UpdateOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyR } func (s *Server) RemoveOrgIamPolicy(ctx context.Context, in *admin.OrgIamPolicyID) (_ *empty.Empty, err error) { - err = s.org.RemoveOrgIAMPolicy(ctx, in.OrgId) + err = s.command.RemoveOrgIAMPolicy(ctx, in.OrgId) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/login_policy.go b/internal/api/grpc/management/login_policy.go index 7cae72726..a03e0c5ce 100644 --- a/internal/api/grpc/management/login_policy.go +++ b/internal/api/grpc/management/login_policy.go @@ -2,8 +2,11 @@ package management import ( "context" - "github.com/caos/zitadel/pkg/grpc/management" + "github.com/golang/protobuf/ptypes/empty" + + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/pkg/grpc/management" ) func (s *Server) GetLoginPolicy(ctx context.Context, _ *empty.Empty) (*management.LoginPolicyView, error) { @@ -23,23 +26,23 @@ func (s *Server) GetDefaultLoginPolicy(ctx context.Context, _ *empty.Empty) (*ma } func (s *Server) CreateLoginPolicy(ctx context.Context, policy *management.LoginPolicyRequest) (*management.LoginPolicy, error) { - result, err := s.org.AddLoginPolicy(ctx, loginPolicyRequestToModel(policy)) + result, err := s.command.AddLoginPolicy(ctx, loginPolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return loginPolicyFromModel(result), nil + return loginPolicyFromDomain(result), nil } func (s *Server) UpdateLoginPolicy(ctx context.Context, policy *management.LoginPolicyRequest) (*management.LoginPolicy, error) { - result, err := s.org.ChangeLoginPolicy(ctx, loginPolicyRequestToModel(policy)) + result, err := s.command.ChangeLoginPolicy(ctx, loginPolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return loginPolicyFromModel(result), nil + return loginPolicyFromDomain(result), nil } func (s *Server) RemoveLoginPolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) { - err := s.org.RemoveLoginPolicy(ctx) + err := s.command.RemoveLoginPolicy(ctx, authz.GetCtxData(ctx).OrgID) return &empty.Empty{}, err } @@ -52,15 +55,15 @@ func (s *Server) GetLoginPolicyIdpProviders(ctx context.Context, request *manage } func (s *Server) AddIdpProviderToLoginPolicy(ctx context.Context, provider *management.IdpProviderAdd) (*management.IdpProvider, error) { - result, err := s.org.AddIDPProviderToLoginPolicy(ctx, idpProviderAddToModel(provider)) + result, err := s.command.AddIDPProviderToLoginPolicy(ctx, idpProviderAddToDomain(ctx, provider)) if err != nil { return nil, err } - return idpProviderFromModel(result), nil + return idpProviderFromDomain(result), nil } func (s *Server) RemoveIdpProviderFromLoginPolicy(ctx context.Context, provider *management.IdpProviderID) (*empty.Empty, error) { - err := s.org.RemoveIDPProviderFromLoginPolicy(ctx, idpProviderToModel(provider)) + err := s.command.RemoveIDPProviderFromLoginPolicy(ctx, idpProviderIDToDomain(ctx, provider)) return &empty.Empty{}, err } @@ -73,15 +76,15 @@ func (s *Server) GetLoginPolicySecondFactors(ctx context.Context, _ *empty.Empty } func (s *Server) AddSecondFactorToLoginPolicy(ctx context.Context, mfa *management.SecondFactor) (*management.SecondFactor, error) { - result, err := s.org.AddSecondFactorToLoginPolicy(ctx, secondFactorTypeToModel(mfa)) + result, err := s.command.AddSecondFactorToLoginPolicy(ctx, secondFactorTypeToDomain(mfa), authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - return secondFactorFromModel(result), nil + return secondFactorFromDomain(result), nil } func (s *Server) RemoveSecondFactorFromLoginPolicy(ctx context.Context, mfa *management.SecondFactor) (*empty.Empty, error) { - err := s.org.RemoveSecondFactorFromLoginPolicy(ctx, secondFactorTypeToModel(mfa)) + err := s.command.RemoveSecondFactorFromLoginPolicy(ctx, secondFactorTypeToDomain(mfa), authz.GetCtxData(ctx).OrgID) return &empty.Empty{}, err } @@ -94,14 +97,14 @@ func (s *Server) GetLoginPolicyMultiFactors(ctx context.Context, _ *empty.Empty) } func (s *Server) AddMultiFactorToLoginPolicy(ctx context.Context, mfa *management.MultiFactor) (*management.MultiFactor, error) { - result, err := s.org.AddMultiFactorToLoginPolicy(ctx, multiFactorTypeToModel(mfa)) + result, err := s.command.AddMultiFactorToLoginPolicy(ctx, multiFactorTypeToDomain(mfa), authz.GetCtxData(ctx).OrgID) if err != nil { return nil, err } - return multiFactorFromModel(result), nil + return multiFactorFromDomain(result), nil } func (s *Server) RemoveMultiFactorFromLoginPolicy(ctx context.Context, mfa *management.MultiFactor) (*empty.Empty, error) { - err := s.org.RemoveMultiFactorFromLoginPolicy(ctx, multiFactorTypeToModel(mfa)) + err := s.command.RemoveMultiFactorFromLoginPolicy(ctx, multiFactorTypeToDomain(mfa), authz.GetCtxData(ctx).OrgID) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/login_policy_converter.go b/internal/api/grpc/management/login_policy_converter.go index a1925b58b..b1e6b68b8 100644 --- a/internal/api/grpc/management/login_policy_converter.go +++ b/internal/api/grpc/management/login_policy_converter.go @@ -1,37 +1,41 @@ package management import ( + "context" + "github.com/caos/logging" - iam_model "github.com/caos/zitadel/internal/iam/model" - "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/eventstore/models" + iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/pkg/grpc/management" ) -func loginPolicyRequestToModel(policy *management.LoginPolicyRequest) *iam_model.LoginPolicy { - return &iam_model.LoginPolicy{ +func loginPolicyRequestToDomain(ctx context.Context, policy *management.LoginPolicyRequest) *domain.LoginPolicy { + return &domain.LoginPolicy{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, AllowUsernamePassword: policy.AllowUsernamePassword, AllowExternalIdp: policy.AllowExternalIdp, AllowRegister: policy.AllowRegister, ForceMFA: policy.ForceMfa, - PasswordlessType: passwordlessTypeToModel(policy.PasswordlessType), + PasswordlessType: passwordlessTypeToDomain(policy.PasswordlessType), } } -func loginPolicyFromModel(policy *iam_model.LoginPolicy) *management.LoginPolicy { - creationDate, err := ptypes.TimestampProto(policy.CreationDate) - logging.Log("GRPC-2Fsm8").OnError(err).Debug("date parse failed") - - changeDate, err := ptypes.TimestampProto(policy.ChangeDate) - logging.Log("GRPC-3Flo0").OnError(err).Debug("date parse failed") - +func loginPolicyFromDomain(policy *domain.LoginPolicy) *management.LoginPolicy { return &management.LoginPolicy{ AllowUsernamePassword: policy.AllowUsernamePassword, AllowExternalIdp: policy.AllowExternalIdp, AllowRegister: policy.AllowRegister, - CreationDate: creationDate, - ChangeDate: changeDate, + CreationDate: timestamppb.New(policy.CreationDate), + ChangeDate: timestamppb.New(policy.ChangeDate), ForceMfa: policy.ForceMFA, - PasswordlessType: passwordlessTypeFromModel(policy.PasswordlessType), + PasswordlessType: passwordlessTypeFromDomain(policy.PasswordlessType), } } @@ -70,17 +74,22 @@ func idpProviderSearchResponseFromModel(response *iam_model.IDPProviderSearchRes } } -func idpProviderToModel(provider *management.IdpProviderID) *iam_model.IDPProvider { - return &iam_model.IDPProvider{ +func idpProviderIDToDomain(ctx context.Context, provider *management.IdpProviderID) *domain.IDPProvider { + return &domain.IDPProvider{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, IDPConfigID: provider.IdpConfigId, - Type: iam_model.IDPProviderTypeSystem, } } -func idpProviderAddToModel(provider *management.IdpProviderAdd) *iam_model.IDPProvider { - return &iam_model.IDPProvider{ +func idpProviderAddToDomain(ctx context.Context, provider *management.IdpProviderAdd) *domain.IDPProvider { + return &domain.IDPProvider{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, IDPConfigID: provider.IdpConfigId, - Type: idpProviderTypeToModel(provider.IdpProviderType), + Type: idpProviderTypeToDomain(provider.IdpProviderType), } } @@ -90,10 +99,10 @@ func idpProviderIDFromModel(provider *iam_model.IDPProvider) *management.IdpProv } } -func idpProviderFromModel(provider *iam_model.IDPProvider) *management.IdpProvider { +func idpProviderFromDomain(provider *domain.IDPProvider) *management.IdpProvider { return &management.IdpProvider{ IdpConfigId: provider.IDPConfigID, - IdpProvider_Type: idpProviderTypeFromModel(provider.Type), + IdpProvider_Type: idpProviderTypeFromDomain(provider.Type), } } @@ -125,14 +134,25 @@ func idpConfigTypeToModel(providerType iam_model.IdpConfigType) management.IdpTy } } -func idpProviderTypeToModel(providerType management.IdpProviderType) iam_model.IDPProviderType { +func idpProviderTypeToDomain(providerType management.IdpProviderType) domain.IdentityProviderType { switch providerType { case management.IdpProviderType_IDPPROVIDERTYPE_SYSTEM: - return iam_model.IDPProviderTypeSystem + return domain.IdentityProviderTypeSystem case management.IdpProviderType_IDPPROVIDERTYPE_ORG: - return iam_model.IDPProviderTypeOrg + return domain.IdentityProviderTypeOrg default: - return iam_model.IDPProviderTypeSystem + return domain.IdentityProviderTypeSystem + } +} + +func idpProviderTypeFromDomain(providerType domain.IdentityProviderType) management.IdpProviderType { + switch providerType { + case domain.IdentityProviderTypeSystem: + return management.IdpProviderType_IDPPROVIDERTYPE_SYSTEM + case domain.IdentityProviderTypeOrg: + return management.IdpProviderType_IDPPROVIDERTYPE_ORG + default: + return management.IdpProviderType_IDPPROVIDERTYPE_UNSPECIFIED } } @@ -157,12 +177,29 @@ func secondFactorResultFromModel(result *iam_model.SecondFactorsSearchResponse) } } +func secondFactorFromDomain(mfaType domain.SecondFactorType) *management.SecondFactor { + return &management.SecondFactor{ + SecondFactor: secondFactorTypeFromDomain(mfaType), + } +} + func secondFactorFromModel(mfaType iam_model.SecondFactorType) *management.SecondFactor { return &management.SecondFactor{ SecondFactor: secondFactorTypeFromModel(mfaType), } } +func secondFactorTypeFromDomain(mfaType domain.SecondFactorType) management.SecondFactorType { + switch mfaType { + case domain.SecondFactorTypeOTP: + return management.SecondFactorType_SECONDFACTORTYPE_OTP + case domain.SecondFactorTypeU2F: + return management.SecondFactorType_SECONDFACTORTYPE_U2F + default: + return management.SecondFactorType_SECONDFACTORTYPE_UNSPECIFIED + } +} + func secondFactorTypeFromModel(mfaType iam_model.SecondFactorType) management.SecondFactorType { switch mfaType { case iam_model.SecondFactorTypeOTP: @@ -174,14 +211,14 @@ func secondFactorTypeFromModel(mfaType iam_model.SecondFactorType) management.Se } } -func secondFactorTypeToModel(mfaType *management.SecondFactor) iam_model.SecondFactorType { +func secondFactorTypeToDomain(mfaType *management.SecondFactor) domain.SecondFactorType { switch mfaType.SecondFactor { case management.SecondFactorType_SECONDFACTORTYPE_OTP: - return iam_model.SecondFactorTypeOTP + return domain.SecondFactorTypeOTP case management.SecondFactorType_SECONDFACTORTYPE_U2F: - return iam_model.SecondFactorTypeU2F + return domain.SecondFactorTypeU2F default: - return iam_model.SecondFactorTypeUnspecified + return domain.SecondFactorTypeUnspecified } } @@ -195,9 +232,18 @@ func multiFactorResultFromModel(result *iam_model.MultiFactorsSearchResponse) *m } } -func multiFactorFromModel(mfaType iam_model.MultiFactorType) *management.MultiFactor { +func multiFactorFromDomain(mfaType domain.MultiFactorType) *management.MultiFactor { return &management.MultiFactor{ - MultiFactor: multiFactorTypeFromModel(mfaType), + MultiFactor: multiFactorTypeFromDomain(mfaType), + } +} + +func multiFactorTypeFromDomain(mfaType domain.MultiFactorType) management.MultiFactorType { + switch mfaType { + case domain.MultiFactorTypeU2FWithPIN: + return management.MultiFactorType_MULTIFACTORTYPE_U2F_WITH_PIN + default: + return management.MultiFactorType_MULTIFACTORTYPE_UNSPECIFIED } } @@ -210,12 +256,12 @@ func multiFactorTypeFromModel(mfaType iam_model.MultiFactorType) management.Mult } } -func multiFactorTypeToModel(mfaType *management.MultiFactor) iam_model.MultiFactorType { +func multiFactorTypeToDomain(mfaType *management.MultiFactor) domain.MultiFactorType { switch mfaType.MultiFactor { case management.MultiFactorType_MULTIFACTORTYPE_U2F_WITH_PIN: - return iam_model.MultiFactorTypeU2FWithPIN + return domain.MultiFactorTypeU2FWithPIN default: - return iam_model.MultiFactorTypeUnspecified + return domain.MultiFactorTypeUnspecified } } @@ -228,11 +274,20 @@ func passwordlessTypeFromModel(passwordlessType iam_model.PasswordlessType) mana } } -func passwordlessTypeToModel(passwordlessType management.PasswordlessType) iam_model.PasswordlessType { +func passwordlessTypeFromDomain(passwordlessType domain.PasswordlessType) management.PasswordlessType { switch passwordlessType { - case management.PasswordlessType_PASSWORDLESSTYPE_ALLOWED: - return iam_model.PasswordlessTypeAllowed + case domain.PasswordlessTypeAllowed: + return management.PasswordlessType_PASSWORDLESSTYPE_ALLOWED default: - return iam_model.PasswordlessTypeNotAllowed + return management.PasswordlessType_PASSWORDLESSTYPE_NOT_ALLOWED + } +} + +func passwordlessTypeToDomain(passwordlessType management.PasswordlessType) domain.PasswordlessType { + switch passwordlessType { + case management.PasswordlessType_PASSWORDLESSTYPE_ALLOWED: + return domain.PasswordlessTypeAllowed + default: + return domain.PasswordlessTypeNotAllowed } } diff --git a/internal/api/grpc/management/org.go b/internal/api/grpc/management/org.go index f05578def..9a3867352 100644 --- a/internal/api/grpc/management/org.go +++ b/internal/api/grpc/management/org.go @@ -10,11 +10,12 @@ import ( ) func (s *Server) CreateOrg(ctx context.Context, request *management.OrgCreateRequest) (_ *management.Org, err error) { - org, err := s.org.CreateOrg(ctx, request.Name) + ctxData := authz.GetCtxData(ctx) + org, err := s.command.AddOrg(ctx, request.Name, ctxData.UserID, ctxData.ResourceOwner) if err != nil { return nil, err } - return orgFromModel(org), err + return orgFromDomain(org), err } func (s *Server) GetMyOrg(ctx context.Context, _ *empty.Empty) (*management.OrgView, error) { @@ -33,20 +34,14 @@ func (s *Server) GetOrgByDomainGlobal(ctx context.Context, in *management.Domain return orgViewFromModel(org), nil } -func (s *Server) DeactivateMyOrg(ctx context.Context, _ *empty.Empty) (*management.Org, error) { - org, err := s.org.DeactivateOrg(ctx, authz.GetCtxData(ctx).OrgID) - if err != nil { - return nil, err - } - return orgFromModel(org), nil +func (s *Server) DeactivateMyOrg(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) { + err := s.command.DeactivateOrg(ctx, authz.GetCtxData(ctx).OrgID) + return &empty.Empty{}, err } -func (s *Server) ReactivateMyOrg(ctx context.Context, _ *empty.Empty) (*management.Org, error) { - org, err := s.org.ReactivateOrg(ctx, authz.GetCtxData(ctx).OrgID) - if err != nil { - return nil, err - } - return orgFromModel(org), nil +func (s *Server) ReactivateMyOrg(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) { + err := s.command.ReactivateOrg(ctx, authz.GetCtxData(ctx).OrgID) + return &empty.Empty{}, err } func (s *Server) SearchMyOrgDomains(ctx context.Context, in *management.OrgDomainSearchRequest) (*management.OrgDomainSearchResponse, error) { @@ -58,15 +53,15 @@ func (s *Server) SearchMyOrgDomains(ctx context.Context, in *management.OrgDomai } func (s *Server) AddMyOrgDomain(ctx context.Context, in *management.AddOrgDomainRequest) (*management.OrgDomain, error) { - domain, err := s.org.AddMyOrgDomain(ctx, addOrgDomainToModel(in)) + domain, err := s.command.AddOrgDomain(ctx, addOrgDomainToDomain(ctx, in)) if err != nil { return nil, err } - return orgDomainFromModel(domain), nil + return orgDomainFromDomain(domain), nil } func (s *Server) GenerateMyOrgDomainValidation(ctx context.Context, in *management.OrgDomainValidationRequest) (*management.OrgDomainValidationResponse, error) { - token, url, err := s.org.GenerateMyOrgDomainValidation(ctx, orgDomainValidationToModel(in)) + token, url, err := s.command.GenerateOrgDomainValidation(ctx, orgDomainValidationToDomain(ctx, in)) if err != nil { return nil, err } @@ -77,16 +72,16 @@ func (s *Server) GenerateMyOrgDomainValidation(ctx context.Context, in *manageme } func (s *Server) ValidateMyOrgDomain(ctx context.Context, in *management.ValidateOrgDomainRequest) (*empty.Empty, error) { - err := s.org.ValidateMyOrgDomain(ctx, validateOrgDomainToModel(in)) + err := s.command.ValidateOrgDomain(ctx, validateOrgDomainToDomain(ctx, in)) return &empty.Empty{}, err } func (s *Server) SetMyPrimaryOrgDomain(ctx context.Context, in *management.PrimaryOrgDomainRequest) (*empty.Empty, error) { - err := s.org.SetMyPrimaryOrgDomain(ctx, primaryOrgDomainToModel(in)) + err := s.command.SetPrimaryOrgDomain(ctx, primaryOrgDomainToDomain(ctx, in)) return &empty.Empty{}, err } func (s *Server) RemoveMyOrgDomain(ctx context.Context, in *management.RemoveOrgDomainRequest) (*empty.Empty, error) { - err := s.org.RemoveMyOrgDomain(ctx, in.Domain) + err := s.command.RemoveOrgDomain(ctx, removeOrgDomainToDomain(ctx, in)) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/org_converter.go b/internal/api/grpc/management/org_converter.go index 97cbb6bf0..48e177971 100644 --- a/internal/api/grpc/management/org_converter.go +++ b/internal/api/grpc/management/org_converter.go @@ -1,8 +1,15 @@ package management import ( + "context" "encoding/json" + + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/logging" "github.com/golang/protobuf/ptypes" @@ -14,27 +21,13 @@ import ( "github.com/caos/zitadel/pkg/grpc/message" ) -func orgsFromModel(orgs []*org_model.Org) []*management.Org { - orgList := make([]*management.Org, len(orgs)) - for i, org := range orgs { - orgList[i] = orgFromModel(org) - } - return orgList -} - -func orgFromModel(org *org_model.Org) *management.Org { - creationDate, err := ptypes.TimestampProto(org.CreationDate) - logging.Log("GRPC-GTHsZ").OnError(err).Debug("unable to get timestamp from time") - - changeDate, err := ptypes.TimestampProto(org.ChangeDate) - logging.Log("GRPC-dVnoj").OnError(err).Debug("unable to get timestamp from time") - +func orgFromDomain(org *domain.Org) *management.Org { return &management.Org{ - ChangeDate: changeDate, - CreationDate: creationDate, + ChangeDate: timestamppb.New(org.ChangeDate), + CreationDate: timestamppb.New(org.CreationDate), Id: org.AggregateID, Name: org.Name, - State: orgStateFromModel(org.State), + State: orgStateFromDomain(org.State), } } @@ -54,6 +47,17 @@ func orgViewFromModel(org *org_model.OrgView) *management.OrgView { } } +func orgStateFromDomain(state domain.OrgState) management.OrgState { + switch state { + case domain.OrgStateActive: + return management.OrgState_ORGSTATE_ACTIVE + case domain.OrgStateInactive: + return management.OrgState_ORGSTATE_INACTIVE + default: + return management.OrgState_ORGSTATE_UNSPECIFIED + } +} + func orgStateFromModel(state org_model.OrgState) management.OrgState { switch state { case org_model.OrgStateActive: @@ -65,29 +69,42 @@ func orgStateFromModel(state org_model.OrgState) management.OrgState { } } -func addOrgDomainToModel(domain *management.AddOrgDomainRequest) *org_model.OrgDomain { - return &org_model.OrgDomain{Domain: domain.Domain} -} - -func orgDomainValidationToModel(domain *management.OrgDomainValidationRequest) *org_model.OrgDomain { - return &org_model.OrgDomain{ - Domain: domain.Domain, - ValidationType: orgDomainValidationTypeToModel(domain.Type), +func addOrgDomainToDomain(ctx context.Context, orgDomain *management.AddOrgDomainRequest) *domain.OrgDomain { + return &domain.OrgDomain{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, + Domain: orgDomain.Domain, } } -func validateOrgDomainToModel(domain *management.ValidateOrgDomainRequest) *org_model.OrgDomain { - return &org_model.OrgDomain{Domain: domain.Domain} +func orgDomainValidationToDomain(ctx context.Context, orgDomain *management.OrgDomainValidationRequest) *domain.OrgDomain { + return &domain.OrgDomain{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, + Domain: orgDomain.Domain, + ValidationType: orgDomainValidationTypeToDomain(orgDomain.Type), + } } -func orgDomainValidationTypeToModel(key management.OrgDomainValidationType) org_model.OrgDomainValidationType { - switch key { +func validateOrgDomainToDomain(ctx context.Context, orgDomain *management.ValidateOrgDomainRequest) *domain.OrgDomain { + return &domain.OrgDomain{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, + Domain: orgDomain.Domain, + } +} + +func orgDomainValidationTypeToDomain(validationType management.OrgDomainValidationType) domain.OrgDomainValidationType { + switch validationType { case management.OrgDomainValidationType_ORGDOMAINVALIDATIONTYPE_HTTP: - return org_model.OrgDomainValidationTypeHTTP + return domain.OrgDomainValidationTypeHTTP case management.OrgDomainValidationType_ORGDOMAINVALIDATIONTYPE_DNS: - return org_model.OrgDomainValidationTypeDNS + return domain.OrgDomainValidationTypeDNS default: - return org_model.OrgDomainValidationTypeUnspecified + return domain.OrgDomainValidationTypeUnspecified } } @@ -102,24 +119,32 @@ func orgDomainValidationTypeFromModel(key org_model.OrgDomainValidationType) man } } -func primaryOrgDomainToModel(domain *management.PrimaryOrgDomainRequest) *org_model.OrgDomain { - return &org_model.OrgDomain{Domain: domain.Domain} +func primaryOrgDomainToDomain(ctx context.Context, ordDomain *management.PrimaryOrgDomainRequest) *domain.OrgDomain { + return &domain.OrgDomain{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, + Domain: ordDomain.Domain, + } } -func orgDomainFromModel(domain *org_model.OrgDomain) *management.OrgDomain { - creationDate, err := ptypes.TimestampProto(domain.CreationDate) - logging.Log("GRPC-u8Ksj").OnError(err).Debug("unable to get timestamp from time") - - changeDate, err := ptypes.TimestampProto(domain.ChangeDate) - logging.Log("GRPC-9osFS").OnError(err).Debug("unable to get timestamp from time") +func removeOrgDomainToDomain(ctx context.Context, ordDomain *management.RemoveOrgDomainRequest) *domain.OrgDomain { + return &domain.OrgDomain{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, + Domain: ordDomain.Domain, + } +} +func orgDomainFromDomain(orgDomain *domain.OrgDomain) *management.OrgDomain { return &management.OrgDomain{ - ChangeDate: changeDate, - CreationDate: creationDate, - OrgId: domain.AggregateID, - Domain: domain.Domain, - Verified: domain.Verified, - Primary: domain.Primary, + ChangeDate: timestamppb.New(orgDomain.ChangeDate), + CreationDate: timestamppb.New(orgDomain.CreationDate), + OrgId: orgDomain.AggregateID, + Domain: orgDomain.Domain, + Verified: orgDomain.Verified, + Primary: orgDomain.Primary, } } diff --git a/internal/api/grpc/management/org_member.go b/internal/api/grpc/management/org_member.go index e8ceba20e..c4eaef9eb 100644 --- a/internal/api/grpc/management/org_member.go +++ b/internal/api/grpc/management/org_member.go @@ -5,6 +5,7 @@ import ( "github.com/golang/protobuf/ptypes/empty" + "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/pkg/grpc/management" ) @@ -21,23 +22,23 @@ func (s *Server) SearchMyOrgMembers(ctx context.Context, in *management.OrgMembe } func (s *Server) AddMyOrgMember(ctx context.Context, member *management.AddOrgMemberRequest) (*management.OrgMember, error) { - addedMember, err := s.org.AddMyOrgMember(ctx, addOrgMemberToModel(member)) + addedMember, err := s.command.AddOrgMember(ctx, addOrgMemberToDomain(ctx, member)) if err != nil { return nil, err } - return orgMemberFromModel(addedMember), nil + return orgMemberFromDomain(addedMember), nil } func (s *Server) ChangeMyOrgMember(ctx context.Context, member *management.ChangeOrgMemberRequest) (*management.OrgMember, error) { - changedMember, err := s.org.ChangeMyOrgMember(ctx, changeOrgMemberToModel(member)) + changedMember, err := s.command.ChangeOrgMember(ctx, changeOrgMemberToModel(ctx, member)) if err != nil { return nil, err } - return orgMemberFromModel(changedMember), nil + return orgMemberFromDomain(changedMember), nil } func (s *Server) RemoveMyOrgMember(ctx context.Context, member *management.RemoveOrgMemberRequest) (*empty.Empty, error) { - err := s.org.RemoveMyOrgMember(ctx, member.UserId) + err := s.command.RemoveOrgMember(ctx, authz.GetCtxData(ctx).OrgID, member.UserId) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/org_member_converter.go b/internal/api/grpc/management/org_member_converter.go index 860c0dcb4..0cba99789 100644 --- a/internal/api/grpc/management/org_member_converter.go +++ b/internal/api/grpc/management/org_member_converter.go @@ -1,43 +1,32 @@ package management import ( + "context" + "github.com/caos/logging" "github.com/golang/protobuf/ptypes" + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/model" org_model "github.com/caos/zitadel/internal/org/model" + "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/pkg/grpc/management" ) -func addOrgMemberToModel(member *management.AddOrgMemberRequest) *org_model.OrgMember { - memberModel := &org_model.OrgMember{ - UserID: member.UserId, - } - memberModel.Roles = member.Roles - - return memberModel +func addOrgMemberToDomain(ctx context.Context, member *management.AddOrgMemberRequest) *domain.Member { + return domain.NewMember(authz.GetCtxData(ctx).OrgID, member.UserId, member.Roles...) } -func changeOrgMemberToModel(member *management.ChangeOrgMemberRequest) *org_model.OrgMember { - memberModel := &org_model.OrgMember{ - UserID: member.UserId, - } - memberModel.Roles = member.Roles - - return memberModel +func changeOrgMemberToModel(ctx context.Context, member *management.ChangeOrgMemberRequest) *domain.Member { + return domain.NewMember(authz.GetCtxData(ctx).OrgID, member.UserId, member.Roles...) } -func orgMemberFromModel(member *org_model.OrgMember) *management.OrgMember { - creationDate, err := ptypes.TimestampProto(member.CreationDate) - logging.Log("GRPC-jC5wY").OnError(err).Debug("date parse failed") - - changeDate, err := ptypes.TimestampProto(member.ChangeDate) - logging.Log("GRPC-Nc2jJ").OnError(err).Debug("date parse failed") - +func orgMemberFromDomain(member *domain.Member) *management.OrgMember { return &management.OrgMember{ UserId: member.UserID, - CreationDate: creationDate, - ChangeDate: changeDate, + CreationDate: timestamppb.New(member.CreationDate), + ChangeDate: timestamppb.New(member.ChangeDate), Roles: member.Roles, Sequence: member.Sequence, } diff --git a/internal/api/grpc/management/password_age_policy.go b/internal/api/grpc/management/password_age_policy.go index 20cae2d2c..9432faf21 100644 --- a/internal/api/grpc/management/password_age_policy.go +++ b/internal/api/grpc/management/password_age_policy.go @@ -2,6 +2,7 @@ package management import ( "context" + "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes/empty" ) @@ -23,22 +24,22 @@ func (s *Server) GetDefaultPasswordAgePolicy(ctx context.Context, _ *empty.Empty } func (s *Server) CreatePasswordAgePolicy(ctx context.Context, policy *management.PasswordAgePolicyRequest) (*management.PasswordAgePolicy, error) { - result, err := s.org.AddPasswordAgePolicy(ctx, passwordAgePolicyRequestToModel(policy)) + result, err := s.command.AddPasswordAgePolicy(ctx, passwordAgePolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return passwordAgePolicyFromModel(result), nil + return passwordAgePolicyFromDomain(result), nil } func (s *Server) UpdatePasswordAgePolicy(ctx context.Context, policy *management.PasswordAgePolicyRequest) (*management.PasswordAgePolicy, error) { - result, err := s.org.ChangePasswordAgePolicy(ctx, passwordAgePolicyRequestToModel(policy)) + result, err := s.command.ChangePasswordAgePolicy(ctx, passwordAgePolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return passwordAgePolicyFromModel(result), nil + return passwordAgePolicyFromDomain(result), nil } func (s *Server) RemovePasswordAgePolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) { - err := s.org.RemovePasswordAgePolicy(ctx) + err := s.command.RemovePasswordAgePolicy(ctx, authz.GetCtxData(ctx).OrgID) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/password_age_policy_converter.go b/internal/api/grpc/management/password_age_policy_converter.go index df655c545..bae10bca5 100644 --- a/internal/api/grpc/management/password_age_policy_converter.go +++ b/internal/api/grpc/management/password_age_policy_converter.go @@ -1,31 +1,34 @@ package management import ( + "context" + "github.com/caos/logging" + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes" + "google.golang.org/protobuf/types/known/timestamppb" ) -func passwordAgePolicyRequestToModel(policy *management.PasswordAgePolicyRequest) *iam_model.PasswordAgePolicy { - return &iam_model.PasswordAgePolicy{ +func passwordAgePolicyRequestToDomain(ctx context.Context, policy *management.PasswordAgePolicyRequest) *domain.PasswordAgePolicy { + return &domain.PasswordAgePolicy{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, MaxAgeDays: policy.MaxAgeDays, ExpireWarnDays: policy.ExpireWarnDays, } } -func passwordAgePolicyFromModel(policy *iam_model.PasswordAgePolicy) *management.PasswordAgePolicy { - creationDate, err := ptypes.TimestampProto(policy.CreationDate) - logging.Log("GRPC-bMd9o").OnError(err).Debug("date parse failed") - - changeDate, err := ptypes.TimestampProto(policy.ChangeDate) - logging.Log("GRPC-jFs89").OnError(err).Debug("date parse failed") - +func passwordAgePolicyFromDomain(policy *domain.PasswordAgePolicy) *management.PasswordAgePolicy { return &management.PasswordAgePolicy{ MaxAgeDays: policy.MaxAgeDays, ExpireWarnDays: policy.ExpireWarnDays, - CreationDate: changeDate, - ChangeDate: creationDate, + CreationDate: timestamppb.New(policy.CreationDate), + ChangeDate: timestamppb.New(policy.ChangeDate), } } diff --git a/internal/api/grpc/management/password_complexity_policy.go b/internal/api/grpc/management/password_complexity_policy.go index 87fa95735..2fb8b0956 100644 --- a/internal/api/grpc/management/password_complexity_policy.go +++ b/internal/api/grpc/management/password_complexity_policy.go @@ -2,6 +2,7 @@ package management import ( "context" + "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes/empty" ) @@ -23,22 +24,22 @@ func (s *Server) GetDefaultPasswordComplexityPolicy(ctx context.Context, _ *empt } func (s *Server) CreatePasswordComplexityPolicy(ctx context.Context, policy *management.PasswordComplexityPolicyRequest) (*management.PasswordComplexityPolicy, error) { - result, err := s.org.AddPasswordComplexityPolicy(ctx, passwordComplexityPolicyRequestToModel(policy)) + result, err := s.command.AddPasswordComplexityPolicy(ctx, passwordComplexityPolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return passwordComplexityPolicyFromModel(result), nil + return passwordComplexityPolicyFromDomain(result), nil } func (s *Server) UpdatePasswordComplexityPolicy(ctx context.Context, policy *management.PasswordComplexityPolicyRequest) (*management.PasswordComplexityPolicy, error) { - result, err := s.org.ChangePasswordComplexityPolicy(ctx, passwordComplexityPolicyRequestToModel(policy)) + result, err := s.command.ChangePasswordComplexityPolicy(ctx, passwordComplexityPolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return passwordComplexityPolicyFromModel(result), nil + return passwordComplexityPolicyFromDomain(result), nil } func (s *Server) RemovePasswordComplexityPolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) { - err := s.org.RemovePasswordComplexityPolicy(ctx) + err := s.command.RemovePasswordComplexityPolicy(ctx, authz.GetCtxData(ctx).OrgID) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/password_complexity_policy_converter.go b/internal/api/grpc/management/password_complexity_policy_converter.go index 9a674115d..971c88799 100644 --- a/internal/api/grpc/management/password_complexity_policy_converter.go +++ b/internal/api/grpc/management/password_complexity_policy_converter.go @@ -1,14 +1,23 @@ package management import ( + "context" + "github.com/caos/logging" + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes" + "google.golang.org/protobuf/types/known/timestamppb" ) -func passwordComplexityPolicyRequestToModel(policy *management.PasswordComplexityPolicyRequest) *iam_model.PasswordComplexityPolicy { - return &iam_model.PasswordComplexityPolicy{ +func passwordComplexityPolicyRequestToDomain(ctx context.Context, policy *management.PasswordComplexityPolicyRequest) *domain.PasswordComplexityPolicy { + return &domain.PasswordComplexityPolicy{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, MinLength: policy.MinLength, HasLowercase: policy.HasLowercase, HasUppercase: policy.HasUppercase, @@ -17,21 +26,15 @@ func passwordComplexityPolicyRequestToModel(policy *management.PasswordComplexit } } -func passwordComplexityPolicyFromModel(policy *iam_model.PasswordComplexityPolicy) *management.PasswordComplexityPolicy { - creationDate, err := ptypes.TimestampProto(policy.CreationDate) - logging.Log("GRPC-5Gslo").OnError(err).Debug("date parse failed") - - changeDate, err := ptypes.TimestampProto(policy.ChangeDate) - logging.Log("GRPC-Bmd9e").OnError(err).Debug("date parse failed") - +func passwordComplexityPolicyFromDomain(policy *domain.PasswordComplexityPolicy) *management.PasswordComplexityPolicy { return &management.PasswordComplexityPolicy{ MinLength: policy.MinLength, HasLowercase: policy.HasLowercase, HasUppercase: policy.HasUppercase, HasSymbol: policy.HasSymbol, HasNumber: policy.HasNumber, - CreationDate: changeDate, - ChangeDate: creationDate, + CreationDate: timestamppb.New(policy.CreationDate), + ChangeDate: timestamppb.New(policy.ChangeDate), } } diff --git a/internal/api/grpc/management/password_lockout_policy.go b/internal/api/grpc/management/password_lockout_policy.go index 9468454a8..83d490bec 100644 --- a/internal/api/grpc/management/password_lockout_policy.go +++ b/internal/api/grpc/management/password_lockout_policy.go @@ -2,6 +2,7 @@ package management import ( "context" + "github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes/empty" ) @@ -23,22 +24,22 @@ func (s *Server) GetDefaultPasswordLockoutPolicy(ctx context.Context, _ *empty.E } func (s *Server) CreatePasswordLockoutPolicy(ctx context.Context, policy *management.PasswordLockoutPolicyRequest) (*management.PasswordLockoutPolicy, error) { - result, err := s.org.AddPasswordLockoutPolicy(ctx, passwordLockoutPolicyRequestToModel(policy)) + result, err := s.command.AddPasswordLockoutPolicy(ctx, passwordLockoutPolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return passwordLockoutPolicyFromModel(result), nil + return passwordLockoutPolicyFromDomain(result), nil } func (s *Server) UpdatePasswordLockoutPolicy(ctx context.Context, policy *management.PasswordLockoutPolicyRequest) (*management.PasswordLockoutPolicy, error) { - result, err := s.org.ChangePasswordLockoutPolicy(ctx, passwordLockoutPolicyRequestToModel(policy)) + result, err := s.command.ChangePasswordLockoutPolicy(ctx, passwordLockoutPolicyRequestToDomain(ctx, policy)) if err != nil { return nil, err } - return passwordLockoutPolicyFromModel(result), nil + return passwordLockoutPolicyFromDomain(result), nil } func (s *Server) RemovePasswordLockoutPolicy(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) { - err := s.org.RemovePasswordLockoutPolicy(ctx) + err := s.command.RemovePasswordLockoutPolicy(ctx, authz.GetCtxData(ctx).OrgID) return &empty.Empty{}, err } diff --git a/internal/api/grpc/management/password_lockout_policy_converter.go b/internal/api/grpc/management/password_lockout_policy_converter.go index 3bbaf2f89..8aaf4d83e 100644 --- a/internal/api/grpc/management/password_lockout_policy_converter.go +++ b/internal/api/grpc/management/password_lockout_policy_converter.go @@ -1,31 +1,34 @@ package management import ( + "context" + "github.com/caos/logging" + "github.com/caos/zitadel/internal/api/authz" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/pkg/grpc/management" "github.com/golang/protobuf/ptypes" + "google.golang.org/protobuf/types/known/timestamppb" ) -func passwordLockoutPolicyRequestToModel(policy *management.PasswordLockoutPolicyRequest) *iam_model.PasswordLockoutPolicy { - return &iam_model.PasswordLockoutPolicy{ +func passwordLockoutPolicyRequestToDomain(ctx context.Context, policy *management.PasswordLockoutPolicyRequest) *domain.PasswordLockoutPolicy { + return &domain.PasswordLockoutPolicy{ + ObjectRoot: models.ObjectRoot{ + AggregateID: authz.GetCtxData(ctx).OrgID, + }, MaxAttempts: policy.MaxAttempts, ShowLockOutFailures: policy.ShowLockoutFailure, } } -func passwordLockoutPolicyFromModel(policy *iam_model.PasswordLockoutPolicy) *management.PasswordLockoutPolicy { - creationDate, err := ptypes.TimestampProto(policy.CreationDate) - logging.Log("GRPC-bMd9o").OnError(err).Debug("date parse failed") - - changeDate, err := ptypes.TimestampProto(policy.ChangeDate) - logging.Log("GRPC-jFs89").OnError(err).Debug("date parse failed") - +func passwordLockoutPolicyFromDomain(policy *domain.PasswordLockoutPolicy) *management.PasswordLockoutPolicy { return &management.PasswordLockoutPolicy{ MaxAttempts: policy.MaxAttempts, ShowLockoutFailure: policy.ShowLockOutFailures, - CreationDate: changeDate, - ChangeDate: creationDate, + CreationDate: timestamppb.New(policy.CreationDate), + ChangeDate: timestamppb.New(policy.ChangeDate), } } diff --git a/internal/management/repository/org.go b/internal/management/repository/org.go index 268aa83d8..8355d017a 100644 --- a/internal/management/repository/org.go +++ b/internal/management/repository/org.go @@ -11,23 +11,12 @@ import ( type OrgRepository interface { OrgByID(ctx context.Context, id string) (*org_model.OrgView, error) OrgByDomainGlobal(ctx context.Context, domain string) (*org_model.OrgView, error) - CreateOrg(ctx context.Context, name string) (*org_model.Org, error) UpdateOrg(ctx context.Context, org *org_model.Org) (*org_model.Org, error) - DeactivateOrg(ctx context.Context, id string) (*org_model.Org, error) - ReactivateOrg(ctx context.Context, id string) (*org_model.Org, error) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error) SearchMyOrgDomains(ctx context.Context, request *org_model.OrgDomainSearchRequest) (*org_model.OrgDomainSearchResponse, error) - AddMyOrgDomain(ctx context.Context, domain *org_model.OrgDomain) (*org_model.OrgDomain, error) - GenerateMyOrgDomainValidation(ctx context.Context, domain *org_model.OrgDomain) (string, string, error) - ValidateMyOrgDomain(ctx context.Context, domain *org_model.OrgDomain) error - SetMyPrimaryOrgDomain(ctx context.Context, domain *org_model.OrgDomain) error - RemoveMyOrgDomain(ctx context.Context, domain string) error SearchMyOrgMembers(ctx context.Context, request *org_model.OrgMemberSearchRequest) (*org_model.OrgMemberSearchResponse, error) - AddMyOrgMember(ctx context.Context, member *org_model.OrgMember) (*org_model.OrgMember, error) - ChangeMyOrgMember(ctx context.Context, member *org_model.OrgMember) (*org_model.OrgMember, error) - RemoveMyOrgMember(ctx context.Context, userID string) error GetOrgMemberRoles() []string @@ -59,19 +48,10 @@ type OrgRepository interface { GetPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) - AddPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) - ChangePasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) - RemovePasswordComplexityPolicy(ctx context.Context) error GetPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) GetDefaultPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) - AddPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) - ChangePasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) - RemovePasswordAgePolicy(ctx context.Context) error GetPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) GetDefaultPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) - AddPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) - ChangePasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) - RemovePasswordLockoutPolicy(ctx context.Context) error } diff --git a/internal/v2/command/command.go b/internal/v2/command/command.go index e05095ac7..53ef01010 100644 --- a/internal/v2/command/command.go +++ b/internal/v2/command/command.go @@ -2,16 +2,18 @@ package command import ( "context" - global_model "github.com/caos/zitadel/internal/model" - webauthn_helper "github.com/caos/zitadel/internal/webauthn" + "github.com/caos/zitadel/internal/api/http" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/id" + global_model "github.com/caos/zitadel/internal/model" "github.com/caos/zitadel/internal/telemetry/tracing" iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/org" usr_repo "github.com/caos/zitadel/internal/v2/repository/user" + webauthn_helper "github.com/caos/zitadel/internal/webauthn" ) type CommandSide struct { @@ -21,18 +23,20 @@ type CommandSide struct { idpConfigSecretCrypto crypto.Crypto - userPasswordAlg crypto.HashAlgorithm - initializeUserCode crypto.Generator - emailVerificationCode crypto.Generator - phoneVerificationCode crypto.Generator - passwordVerificationCode crypto.Generator - machineKeyAlg crypto.EncryptionAlgorithm - machineKeySize int + userPasswordAlg crypto.HashAlgorithm + initializeUserCode crypto.Generator + emailVerificationCode crypto.Generator + phoneVerificationCode crypto.Generator + passwordVerificationCode crypto.Generator + machineKeyAlg crypto.EncryptionAlgorithm + machineKeySize int + applicationSecretGenerator crypto.Generator + domainVerificationAlg *crypto.AESCrypto + domainVerificationGenerator crypto.Generator + domainVerificationValidator func(domain, token, verifier string, checkType http.CheckType) error //TODO: remove global model, or move to domain - multifactors global_model.Multifactors - applicationSecretGenerator crypto.Generator - - webauthn *webauthn_helper.WebAuthN + multifactors global_model.Multifactors + webauthn *webauthn_helper.WebAuthN } type Config struct { @@ -47,6 +51,7 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) { iamDomain: config.SystemDefaults.Domain, } iam_repo.RegisterEventMappers(repo.eventstore) + org.RegisterEventMappers(repo.eventstore) usr_repo.RegisterEventMappers(repo.eventstore) //TODO: simplify!!!! @@ -78,6 +83,13 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) { } passwordAlg := crypto.NewBCrypt(config.SystemDefaults.SecretGenerators.PasswordSaltCost) repo.applicationSecretGenerator = crypto.NewHashGenerator(config.SystemDefaults.SecretGenerators.ClientSecretGenerator, passwordAlg) + + repo.domainVerificationAlg, err = crypto.NewAESCrypto(config.SystemDefaults.DomainVerification.VerificationKey) + if err != nil { + return nil, err + } + repo.domainVerificationGenerator = crypto.NewEncryptionGenerator(config.SystemDefaults.DomainVerification.VerificationGenerator, repo.domainVerificationAlg) + repo.domainVerificationValidator = http.ValidateDomain web, err := webauthn_helper.StartServer(config.SystemDefaults.WebAuthN) if err != nil { return nil, err diff --git a/internal/v2/command/iam_converter.go b/internal/v2/command/iam_converter.go index 7f00f4eab..3782f61a8 100644 --- a/internal/v2/command/iam_converter.go +++ b/internal/v2/command/iam_converter.go @@ -33,9 +33,9 @@ func memberWriteModelToMember(writeModel *MemberWriteModel) *domain.Member { } } -func writeModelToLoginPolicy(wm *IAMLoginPolicyWriteModel) *domain.LoginPolicy { +func writeModelToLoginPolicy(wm *LoginPolicyWriteModel) *domain.LoginPolicy { return &domain.LoginPolicy{ - ObjectRoot: writeModelToObjectRoot(wm.LoginPolicyWriteModel.WriteModel), + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), AllowUsernamePassword: wm.AllowUserNamePassword, AllowRegister: wm.AllowRegister, AllowExternalIdp: wm.AllowExternalIDP, @@ -44,9 +44,9 @@ func writeModelToLoginPolicy(wm *IAMLoginPolicyWriteModel) *domain.LoginPolicy { } } -func writeModelToLabelPolicy(wm *IAMLabelPolicyWriteModel) *domain.LabelPolicy { +func writeModelToLabelPolicy(wm *LabelPolicyWriteModel) *domain.LabelPolicy { return &domain.LabelPolicy{ - ObjectRoot: writeModelToObjectRoot(wm.LabelPolicyWriteModel.WriteModel), + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), PrimaryColor: wm.PrimaryColor, SecondaryColor: wm.SecondaryColor, } @@ -59,28 +59,28 @@ func writeModelToOrgIAMPolicy(wm *IAMOrgIAMPolicyWriteModel) *domain.OrgIAMPolic } } -func writeModelToPasswordAgePolicy(wm *IAMPasswordAgePolicyWriteModel) *domain.PasswordAgePolicy { +func writeModelToPasswordAgePolicy(wm *PasswordAgePolicyWriteModel) *domain.PasswordAgePolicy { return &domain.PasswordAgePolicy{ - ObjectRoot: writeModelToObjectRoot(wm.PasswordAgePolicyWriteModel.WriteModel), + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), MaxAgeDays: wm.MaxAgeDays, ExpireWarnDays: wm.ExpireWarnDays, } } -func writeModelToPasswordComplexityPolicy(wm *IAMPasswordComplexityPolicyWriteModel) *domain.PasswordComplexityPolicy { +func writeModelToPasswordComplexityPolicy(wm *PasswordComplexityPolicyWriteModel) *domain.PasswordComplexityPolicy { return &domain.PasswordComplexityPolicy{ - ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel), + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), MinLength: wm.MinLength, HasLowercase: wm.HasLowercase, - HasUppercase: wm.HasUpperCase, + HasUppercase: wm.HasUppercase, HasNumber: wm.HasNumber, HasSymbol: wm.HasSymbol, } } -func writeModelToPasswordLockoutPolicy(wm *IAMPasswordLockoutPolicyWriteModel) *domain.PasswordLockoutPolicy { +func writeModelToPasswordLockoutPolicy(wm *PasswordLockoutPolicyWriteModel) *domain.PasswordLockoutPolicy { return &domain.PasswordLockoutPolicy{ - ObjectRoot: writeModelToObjectRoot(wm.PasswordLockoutPolicyWriteModel.WriteModel), + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), MaxAttempts: wm.MaxAttempts, ShowLockOutFailures: wm.ShowLockOutFailures, } @@ -109,9 +109,9 @@ func writeModelToIDPOIDCConfig(wm *OIDCConfigWriteModel) *domain.OIDCIDPConfig { } } -func writeModelToIDPProvider(wm *IAMIdentityProviderWriteModel) *domain.IDPProvider { +func writeModelToIDPProvider(wm *IdentityProviderWriteModel) *domain.IDPProvider { return &domain.IDPProvider{ - ObjectRoot: writeModelToObjectRoot(wm.IdentityProviderWriteModel.WriteModel), + ObjectRoot: writeModelToObjectRoot(wm.WriteModel), IDPConfigID: wm.IDPConfigID, Type: wm.IDPProviderType, } diff --git a/internal/v2/command/iam_idp_config.go b/internal/v2/command/iam_idp_config.go index 2b47ad27f..81f8b7b47 100644 --- a/internal/v2/command/iam_idp_config.go +++ b/internal/v2/command/iam_idp_config.go @@ -2,6 +2,7 @@ package command import ( "context" + caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/v2/domain" @@ -117,16 +118,12 @@ func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID stri return writeModelToIDPConfig(existingIDP), nil } -func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string) (*domain.IDPConfig, error) { - writeModel, err := r.pushDefaultIDPWriteModel(ctx, idpID, func(a *iam.Aggregate, _ *IAMIDPConfigWriteModel) *iam.Aggregate { +func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string) error { + _, err := r.pushDefaultIDPWriteModel(ctx, idpID, func(a *iam.Aggregate, _ *IAMIDPConfigWriteModel) *iam.Aggregate { a.Aggregate = *a.PushEvents(iam_repo.NewIDPConfigRemovedEvent(ctx, idpID)) return a }) - if err != nil { - return nil, err - } - - return writeModelToIDPConfig(writeModel), nil + return err } func (r *CommandSide) pushDefaultIDPWriteModel(ctx context.Context, idpID string, eventSetter func(*iam.Aggregate, *IAMIDPConfigWriteModel) *iam.Aggregate) (*IAMIDPConfigWriteModel, error) { diff --git a/internal/v2/command/iam_policy_label.go b/internal/v2/command/iam_policy_label.go index 070d5330c..141528ccd 100644 --- a/internal/v2/command/iam_policy_label.go +++ b/internal/v2/command/iam_policy_label.go @@ -21,7 +21,7 @@ func (r *CommandSide) AddDefaultLabelPolicy(ctx context.Context, policy *domain. return nil, err } - return writeModelToLabelPolicy(addedPolicy), nil + return writeModelToLabelPolicy(&addedPolicy.LabelPolicyWriteModel), nil } func (r *CommandSide) addDefaultLabelPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, addedPolicy *IAMLabelPolicyWriteModel, policy *domain.LabelPolicy) error { @@ -61,7 +61,7 @@ func (r *CommandSide) ChangeDefaultLabelPolicy(ctx context.Context, policy *doma return nil, err } - return writeModelToLabelPolicy(existingPolicy), nil + return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil } func (r *CommandSide) defaultLabelPolicyWriteModelByID(ctx context.Context) (policy *IAMLabelPolicyWriteModel, err error) { diff --git a/internal/v2/command/iam_policy_label_model.go b/internal/v2/command/iam_policy_label_model.go index 41cfae9ed..61325c3f0 100644 --- a/internal/v2/command/iam_policy_label_model.go +++ b/internal/v2/command/iam_policy_label_model.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type IAMLabelPolicyWriteModel struct { @@ -49,15 +50,19 @@ func (wm *IAMLabelPolicyWriteModel) NewChangedEvent( primaryColor, secondaryColor string, ) (*iam.LabelPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := iam.NewLabelPolicyChangedEvent(ctx) + changes := make([]policy.LabelPolicyChanges, 0) if wm.PrimaryColor != primaryColor { - hasChanged = true - changedEvent.PrimaryColor = &primaryColor + changes = append(changes, policy.ChangePrimaryColor(primaryColor)) } if wm.SecondaryColor != secondaryColor { - hasChanged = true - changedEvent.SecondaryColor = &secondaryColor + changes = append(changes, policy.ChangeSecondaryColor(secondaryColor)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := iam.NewLabelPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/iam_policy_login.go b/internal/v2/command/iam_policy_login.go index 1dcb4799c..83a28447e 100644 --- a/internal/v2/command/iam_policy_login.go +++ b/internal/v2/command/iam_policy_login.go @@ -4,19 +4,18 @@ import ( "context" caos_errs "github.com/caos/zitadel/internal/errors" - iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/v2/domain" iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" ) -func (r *CommandSide) GetDefaultLoginPolicy(ctx context.Context) (*domain.LoginPolicy, error) { +func (r *CommandSide) getDefaultLoginPolicy(ctx context.Context) (*domain.LoginPolicy, error) { policyWriteModel := NewIAMLoginPolicyWriteModel() err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel) if err != nil { return nil, err } - policy := writeModelToLoginPolicy(policyWriteModel) + policy := writeModelToLoginPolicy(&policyWriteModel.LoginPolicyWriteModel) policy.Default = true return policy, nil } @@ -33,7 +32,7 @@ func (r *CommandSide) AddDefaultLoginPolicy(ctx context.Context, policy *domain. return nil, err } - return writeModelToLoginPolicy(addedPolicy), nil + return writeModelToLoginPolicy(&addedPolicy.LoginPolicyWriteModel), nil } func (r *CommandSide) addDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, addedPolicy *IAMLoginPolicyWriteModel, policy *domain.LoginPolicy) error { @@ -62,7 +61,7 @@ func (r *CommandSide) ChangeDefaultLoginPolicy(ctx context.Context, policy *doma return nil, err } - return writeModelToLoginPolicy(existingPolicy), nil + return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil } func (r *CommandSide) changeDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, existingPolicy *IAMLoginPolicyWriteModel, policy *domain.LoginPolicy) error { @@ -73,7 +72,7 @@ func (r *CommandSide) changeDefaultLoginPolicy(ctx context.Context, iamAgg *iam_ if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { return caos_errs.ThrowNotFound(nil, "IAM-M0sif", "Errors.IAM.LoginPolicy.NotFound") } - changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType)) + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, policy.PasswordlessType) if !hasChanged { return caos_errs.ThrowPreconditionFailed(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged") } @@ -99,10 +98,10 @@ func (r *CommandSide) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, id return nil, err } - return writeModelToIDPProvider(idpModel), nil + return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil } -func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) error { +func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) error { idpModel := NewIAMIdentityProviderWriteModel(idpProvider.IDPConfigID) err := r.eventstore.FilterToQueryReducer(ctx, idpModel) if err != nil { @@ -117,22 +116,22 @@ func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Contex return r.eventstore.PushAggregate(ctx, idpModel, iamAgg) } -func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, secondFactor iam_model.SecondFactorType) (iam_model.SecondFactorType, error) { +func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType) (domain.SecondFactorType, error) { secondFactorModel := NewIAMSecondFactorWriteModel() iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel) err := r.addSecondFactorToDefaultLoginPolicy(ctx, nil, secondFactorModel, secondFactor) if err != nil { - return iam_model.SecondFactorTypeUnspecified, err + return domain.SecondFactorTypeUnspecified, err } if err = r.eventstore.PushAggregate(ctx, secondFactorModel, iamAgg); err != nil { - return iam_model.SecondFactorTypeUnspecified, err + return domain.SecondFactorTypeUnspecified, err } - return iam_model.SecondFactorType(secondFactorModel.MFAType), nil + return domain.SecondFactorType(secondFactorModel.MFAType), nil } -func (r *CommandSide) addSecondFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, secondFactorModel *IAMSecondFactorWriteModel, secondFactor iam_model.SecondFactorType) error { +func (r *CommandSide) addSecondFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, secondFactorModel *IAMSecondFactorWriteModel, secondFactor domain.SecondFactorType) error { err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel) if err != nil { return err @@ -147,7 +146,7 @@ func (r *CommandSide) addSecondFactorToDefaultLoginPolicy(ctx context.Context, i return nil } -func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Context, secondFactor iam_model.SecondFactorType) error { +func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType) error { secondFactorModel := NewIAMSecondFactorWriteModel() err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel) if err != nil { @@ -162,22 +161,22 @@ func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Conte return r.eventstore.PushAggregate(ctx, secondFactorModel, iamAgg) } -func (r *CommandSide) AddMultiFactorToDefaultLoginPolicy(ctx context.Context, multiFactor iam_model.MultiFactorType) (iam_model.MultiFactorType, error) { +func (r *CommandSide) AddMultiFactorToDefaultLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType) (domain.MultiFactorType, error) { multiFactorModel := NewIAMMultiFactorWriteModel() iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel) err := r.addMultiFactorToDefaultLoginPolicy(ctx, iamAgg, multiFactorModel, multiFactor) if err != nil { - return iam_model.MultiFactorTypeUnspecified, err + return domain.MultiFactorTypeUnspecified, err } if err = r.eventstore.PushAggregate(ctx, multiFactorModel, iamAgg); err != nil { - return iam_model.MultiFactorTypeUnspecified, err + return domain.MultiFactorTypeUnspecified, err } - return iam_model.MultiFactorType(multiFactorModel.MultiFactoryWriteModel.MFAType), nil + return domain.MultiFactorType(multiFactorModel.MultiFactoryWriteModel.MFAType), nil } -func (r *CommandSide) addMultiFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, multiFactorModel *IAMMultiFactorWriteModel, multiFactor iam_model.MultiFactorType) error { +func (r *CommandSide) addMultiFactorToDefaultLoginPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, multiFactorModel *IAMMultiFactorWriteModel, multiFactor domain.MultiFactorType) error { err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel) if err != nil { return err @@ -191,7 +190,7 @@ func (r *CommandSide) addMultiFactorToDefaultLoginPolicy(ctx context.Context, ia return nil } -func (r *CommandSide) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Context, multiFactor iam_model.MultiFactorType) error { +func (r *CommandSide) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType) error { multiFactorModel := NewIAMMultiFactorWriteModel() err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel) if err != nil { diff --git a/internal/v2/command/iam_policy_login_factors_model.go b/internal/v2/command/iam_policy_login_factors_model.go index cf85cca0a..e7d264645 100644 --- a/internal/v2/command/iam_policy_login_factors_model.go +++ b/internal/v2/command/iam_policy_login_factors_model.go @@ -26,6 +26,8 @@ func (wm *IAMSecondFactorWriteModel) AppendEvents(events ...eventstore.EventRead switch e := event.(type) { case *iam.LoginPolicySecondFactorAddedEvent: wm.WriteModel.AppendEvents(&e.SecondFactorAddedEvent) + case *iam.LoginPolicySecondFactorRemovedEvent: + wm.WriteModel.AppendEvents(&e.SecondFactorRemovedEvent) } } } @@ -60,6 +62,8 @@ func (wm *IAMMultiFactorWriteModel) AppendEvents(events ...eventstore.EventReade switch e := event.(type) { case *iam.LoginPolicyMultiFactorAddedEvent: wm.WriteModel.AppendEvents(&e.MultiFactorAddedEvent) + case *iam.LoginPolicyMultiFactorRemovedEvent: + wm.WriteModel.AppendEvents(&e.MultiFactorRemovedEvent) } } } diff --git a/internal/v2/command/iam_policy_login_identity_provider_model.go b/internal/v2/command/iam_policy_login_identity_provider_model.go index 77d31ed6b..7f0cd896b 100644 --- a/internal/v2/command/iam_policy_login_identity_provider_model.go +++ b/internal/v2/command/iam_policy_login_identity_provider_model.go @@ -30,6 +30,11 @@ func (wm *IAMIdentityProviderWriteModel) AppendEvents(events ...eventstore.Event continue } wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderAddedEvent) + case *iam.IdentityProviderRemovedEvent: + if e.IDPConfigID != wm.IDPConfigID { + continue + } + wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderRemovedEvent) } } } diff --git a/internal/v2/command/iam_policy_login_model.go b/internal/v2/command/iam_policy_login_model.go index 6ecfcc90c..31227ee69 100644 --- a/internal/v2/command/iam_policy_login_model.go +++ b/internal/v2/command/iam_policy_login_model.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type IAMLoginPolicyWriteModel struct { @@ -57,27 +58,28 @@ func (wm *IAMLoginPolicyWriteModel) NewChangedEvent( passwordlessType domain.PasswordlessType, ) (*iam.LoginPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := iam.NewLoginPolicyChangedEvent(ctx) - if wm.AllowUserNamePassword == allowUsernamePassword { - hasChanged = true - changedEvent.AllowUserNamePassword = &allowUsernamePassword + changes := make([]policy.LoginPolicyChanges, 0) + if wm.AllowUserNamePassword != allowUsernamePassword { + changes = append(changes, policy.ChangeAllowUserNamePassword(allowUsernamePassword)) } - if wm.AllowRegister == allowRegister { - hasChanged = true - changedEvent.AllowRegister = &allowRegister + if wm.AllowRegister != allowRegister { + changes = append(changes, policy.ChangeAllowRegister(allowRegister)) } - if wm.AllowExternalIDP == allowExternalIDP { - hasChanged = true - changedEvent.AllowExternalIDP = &allowExternalIDP + if wm.AllowExternalIDP != allowExternalIDP { + changes = append(changes, policy.ChangeAllowExternalIDP(allowExternalIDP)) } if wm.ForceMFA != forceMFA { - hasChanged = true - changedEvent.ForceMFA = &forceMFA + changes = append(changes, policy.ChangeForceMFA(forceMFA)) } if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType { - hasChanged = true - changedEvent.PasswordlessType = &passwordlessType + changes = append(changes, policy.ChangePasswordlessType(passwordlessType)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := iam.NewLoginPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/iam_policy_org_iam_model.go b/internal/v2/command/iam_policy_org_iam_model.go index c788900f5..304ce12bc 100644 --- a/internal/v2/command/iam_policy_org_iam_model.go +++ b/internal/v2/command/iam_policy_org_iam_model.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type IAMOrgIAMPolicyWriteModel struct { @@ -45,11 +46,16 @@ func (wm *IAMOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder { } func (wm *IAMOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLoginMustBeDomain bool) (*iam.OrgIAMPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := iam.NewOrgIAMPolicyChangedEvent(ctx) + changes := make([]policy.OrgIAMPolicyChanges, 0) if wm.UserLoginMustBeDomain != userLoginMustBeDomain { - hasChanged = true - changedEvent.UserLoginMustBeDomain = &userLoginMustBeDomain + changes = append(changes, policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := iam.NewOrgIAMPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/iam_policy_password_age.go b/internal/v2/command/iam_policy_password_age.go index 1e437b3f1..d1d085117 100644 --- a/internal/v2/command/iam_policy_password_age.go +++ b/internal/v2/command/iam_policy_password_age.go @@ -21,7 +21,7 @@ func (r *CommandSide) AddDefaultPasswordAgePolicy(ctx context.Context, policy *d return nil, err } - return writeModelToPasswordAgePolicy(addedPolicy), nil + return writeModelToPasswordAgePolicy(&addedPolicy.PasswordAgePolicyWriteModel), nil } func (r *CommandSide) addDefaultPasswordAgePolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, addedPolicy *IAMPasswordAgePolicyWriteModel, policy *domain.PasswordAgePolicy) error { @@ -60,7 +60,7 @@ func (r *CommandSide) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy return nil, err } - return writeModelToPasswordAgePolicy(existingPolicy), nil + return writeModelToPasswordAgePolicy(&existingPolicy.PasswordAgePolicyWriteModel), nil } func (r *CommandSide) defaultPasswordAgePolicyWriteModelByID(ctx context.Context) (policy *IAMPasswordAgePolicyWriteModel, err error) { diff --git a/internal/v2/command/iam_policy_password_age_model.go b/internal/v2/command/iam_policy_password_age_model.go index 9003bbcd2..704e341e3 100644 --- a/internal/v2/command/iam_policy_password_age_model.go +++ b/internal/v2/command/iam_policy_password_age_model.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type IAMPasswordAgePolicyWriteModel struct { @@ -45,15 +46,19 @@ func (wm *IAMPasswordAgePolicyWriteModel) Query() *eventstore.SearchQueryBuilder } func (wm *IAMPasswordAgePolicyWriteModel) NewChangedEvent(ctx context.Context, expireWarnDays, maxAgeDays uint64) (*iam.PasswordAgePolicyChangedEvent, bool) { - hasChanged := false - changedEvent := iam.NewPasswordAgePolicyChangedEvent(ctx) + changes := make([]policy.PasswordAgePolicyChanges, 0) if wm.ExpireWarnDays != expireWarnDays { - hasChanged = true - changedEvent.ExpireWarnDays = &expireWarnDays + changes = append(changes, policy.ChangeExpireWarnDays(expireWarnDays)) } if wm.MaxAgeDays != maxAgeDays { - hasChanged = true - changedEvent.MaxAgeDays = &maxAgeDays + changes = append(changes, policy.ChangeMaxAgeDays(maxAgeDays)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := iam.NewPasswordAgePolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/iam_policy_password_complexity.go b/internal/v2/command/iam_policy_password_complexity.go index cf0fe62c9..27d60ace6 100644 --- a/internal/v2/command/iam_policy_password_complexity.go +++ b/internal/v2/command/iam_policy_password_complexity.go @@ -8,13 +8,13 @@ import ( iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" ) -func (r *CommandSide) GetDefaultPasswordComplexityPolicy(ctx context.Context) (*domain.PasswordComplexityPolicy, error) { +func (r *CommandSide) getDefaultPasswordComplexityPolicy(ctx context.Context) (*domain.PasswordComplexityPolicy, error) { policyWriteModel := NewIAMPasswordComplexityPolicyWriteModel() err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel) if err != nil { return nil, err } - policy := writeModelToPasswordComplexityPolicy(policyWriteModel) + policy := writeModelToPasswordComplexityPolicy(&policyWriteModel.PasswordComplexityPolicyWriteModel) policy.Default = true return policy, nil } @@ -32,7 +32,7 @@ func (r *CommandSide) AddDefaultPasswordComplexityPolicy(ctx context.Context, po return nil, err } - return writeModelToPasswordComplexityPolicy(addedPolicy), nil + return writeModelToPasswordComplexityPolicy(&addedPolicy.PasswordComplexityPolicyWriteModel), nil } func (r *CommandSide) addDefaultPasswordComplexityPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, addedPolicy *IAMPasswordComplexityPolicyWriteModel, policy *domain.PasswordComplexityPolicy) error { @@ -78,7 +78,7 @@ func (r *CommandSide) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, return nil, err } - return writeModelToPasswordComplexityPolicy(existingPolicy), nil + return writeModelToPasswordComplexityPolicy(&existingPolicy.PasswordComplexityPolicyWriteModel), nil } func (r *CommandSide) defaultPasswordComplexityPolicyWriteModelByID(ctx context.Context) (policy *IAMPasswordComplexityPolicyWriteModel, err error) { diff --git a/internal/v2/command/iam_policy_password_complexity_model.go b/internal/v2/command/iam_policy_password_complexity_model.go index 70b6da595..6aada2cae 100644 --- a/internal/v2/command/iam_policy_password_complexity_model.go +++ b/internal/v2/command/iam_policy_password_complexity_model.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type IAMPasswordComplexityPolicyWriteModel struct { @@ -53,27 +54,28 @@ func (wm *IAMPasswordComplexityPolicyWriteModel) NewChangedEvent( hasSymbol bool, ) (*iam.PasswordComplexityPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := iam.NewPasswordComplexityPolicyChangedEvent(ctx) + changes := make([]policy.PasswordComplexityPolicyChanges, 0) if wm.MinLength != minLength { - hasChanged = true - changedEvent.MinLength = &minLength + changes = append(changes, policy.ChangeMinLength(minLength)) } if wm.HasLowercase != hasLowercase { - hasChanged = true - changedEvent.HasLowercase = &hasLowercase + changes = append(changes, policy.ChangeHasLowercase(hasLowercase)) } - if wm.HasUpperCase != hasUppercase { - hasChanged = true - changedEvent.HasUpperCase = &hasUppercase + if wm.HasUppercase != hasUppercase { + changes = append(changes, policy.ChangeHasUppercase(hasUppercase)) } if wm.HasNumber != hasNumber { - hasChanged = true - changedEvent.HasNumber = &hasNumber + changes = append(changes, policy.ChangeHasNumber(hasNumber)) } if wm.HasSymbol != hasSymbol { - hasChanged = true - changedEvent.HasSymbol = &hasSymbol + changes = append(changes, policy.ChangeHasSymbol(hasSymbol)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := iam.NewPasswordComplexityPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/iam_policy_password_lockout.go b/internal/v2/command/iam_policy_password_lockout.go index 06aa83ba1..635b753d1 100644 --- a/internal/v2/command/iam_policy_password_lockout.go +++ b/internal/v2/command/iam_policy_password_lockout.go @@ -21,7 +21,7 @@ func (r *CommandSide) AddDefaultPasswordLockoutPolicy(ctx context.Context, polic return nil, err } - return writeModelToPasswordLockoutPolicy(addedPolicy), nil + return writeModelToPasswordLockoutPolicy(&addedPolicy.PasswordLockoutPolicyWriteModel), nil } func (r *CommandSide) addDefaultPasswordLockoutPolicy(ctx context.Context, iamAgg *iam_repo.Aggregate, addedPolicy *IAMPasswordLockoutPolicyWriteModel, policy *domain.PasswordLockoutPolicy) error { @@ -60,7 +60,7 @@ func (r *CommandSide) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, po return nil, err } - return writeModelToPasswordLockoutPolicy(existingPolicy), nil + return writeModelToPasswordLockoutPolicy(&existingPolicy.PasswordLockoutPolicyWriteModel), nil } func (r *CommandSide) defaultPasswordLockoutPolicyWriteModelByID(ctx context.Context) (policy *IAMPasswordLockoutPolicyWriteModel, err error) { diff --git a/internal/v2/command/iam_policy_password_lockout_model.go b/internal/v2/command/iam_policy_password_lockout_model.go index 70a7c7d06..21aa48f6e 100644 --- a/internal/v2/command/iam_policy_password_lockout_model.go +++ b/internal/v2/command/iam_policy_password_lockout_model.go @@ -6,6 +6,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/iam" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type IAMPasswordLockoutPolicyWriteModel struct { @@ -45,15 +46,19 @@ func (wm *IAMPasswordLockoutPolicyWriteModel) Query() *eventstore.SearchQueryBui } func (wm *IAMPasswordLockoutPolicyWriteModel) NewChangedEvent(ctx context.Context, maxAttempts uint64, showLockoutFailure bool) (*iam.PasswordLockoutPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := iam.NewPasswordLockoutPolicyChangedEvent(ctx) + changes := make([]policy.PasswordLockoutPolicyChanges, 0) if wm.MaxAttempts != maxAttempts { - hasChanged = true - changedEvent.MaxAttempts = &maxAttempts + changes = append(changes, policy.ChangeMaxAttempts(maxAttempts)) } if wm.ShowLockOutFailures != showLockoutFailure { - hasChanged = true - changedEvent.ShowLockOutFailures = &showLockoutFailure + changes = append(changes, policy.ChangeShowLockOutFailures(showLockoutFailure)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := iam.NewPasswordLockoutPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/org.go b/internal/v2/command/org.go index 23afca291..601eceeb2 100644 --- a/internal/v2/command/org.go +++ b/internal/v2/command/org.go @@ -30,6 +30,65 @@ func (r *CommandSide) SetUpOrg(ctx context.Context, organisation *domain.Org, ad return err } +func (r *CommandSide) AddOrg(ctx context.Context, name, userID, resourceOwner string) (*domain.Org, error) { + orgAgg, addedOrg, err := r.addOrg(ctx, &domain.Org{Name: name}) + if err != nil { + return nil, err + } + + active, err := r.checkUserExists(ctx, userID, resourceOwner) + if err != nil { + return nil, err + } + if !active { + return nil, caos_errs.ThrowPreconditionFailed(err, "ORG-HBR2z", "Errors.User.NotFound") + } + addedMember := NewOrgMemberWriteModel(orgAgg.ID(), userID) + err = r.addOrgMember(ctx, orgAgg, addedMember, domain.NewMember(orgAgg.ID(), userID, domain.RoleOrgOwner)) + if err != nil { + return nil, err + } + err = r.eventstore.PushAggregate(ctx, addedOrg, orgAgg) + if err != nil { + return nil, err + } + return orgWriteModelToOrg(addedOrg), nil +} + +func (r *CommandSide) DeactivateOrg(ctx context.Context, orgID string) error { + orgWriteModel, err := r.getOrgWriteModelByID(ctx, orgID) + if err != nil { + return err + } + if orgWriteModel.State == domain.OrgStateUnspecified || orgWriteModel.State == domain.OrgStateRemoved { + return caos_errs.ThrowNotFound(nil, "ORG-oL9nT", "Errors.Org.NotFound") + } + if orgWriteModel.State == domain.OrgStateInactive { + return caos_errs.ThrowInvalidArgument(nil, "EVENT-Dbs2g", "Errors.Org.AlreadyDeactivated") + } + orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel) + orgAgg.PushEvents(org.NewOrgDeactivatedEvent(ctx)) + + return r.eventstore.PushAggregate(ctx, orgWriteModel, orgAgg) +} + +func (r *CommandSide) ReactivateOrg(ctx context.Context, orgID string) error { + orgWriteModel, err := r.getOrgWriteModelByID(ctx, orgID) + if err != nil { + return err + } + if orgWriteModel.State == domain.OrgStateUnspecified || orgWriteModel.State == domain.OrgStateRemoved { + return caos_errs.ThrowNotFound(nil, "ORG-Dgf3g", "Errors.Org.NotFound") + } + if orgWriteModel.State == domain.OrgStateActive { + return caos_errs.ThrowInvalidArgument(nil, "EVENT-bfnrh", "Errors.Org.AlreadyActive") + } + orgAgg := OrgAggregateFromWriteModel(&orgWriteModel.WriteModel) + orgAgg.PushEvents(org.NewOrgReactivatedEvent(ctx)) + + return r.eventstore.PushAggregate(ctx, orgWriteModel, orgAgg) +} + func (r *CommandSide) setUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human) (*org.Aggregate, *user.Aggregate, *org.Aggregate, error) { orgAgg, _, err := r.addOrg(ctx, organisation) if err != nil { diff --git a/internal/v2/command/org_converter.go b/internal/v2/command/org_converter.go index 5f655d3c3..e7732b934 100644 --- a/internal/v2/command/org_converter.go +++ b/internal/v2/command/org_converter.go @@ -25,7 +25,7 @@ func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWrit ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel), MinLength: wm.MinLength, HasLowercase: wm.HasLowercase, - HasUppercase: wm.HasUpperCase, + HasUppercase: wm.HasUppercase, HasNumber: wm.HasNumber, HasSymbol: wm.HasSymbol, } diff --git a/internal/v2/command/org_domain.go b/internal/v2/command/org_domain.go index 2b773d10a..8fda17066 100644 --- a/internal/v2/command/org_domain.go +++ b/internal/v2/command/org_domain.go @@ -3,6 +3,10 @@ package command import ( "context" + "github.com/caos/logging" + + http_utils "github.com/caos/zitadel/internal/api/http" + "github.com/caos/zitadel/internal/crypto" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/org" @@ -22,6 +26,116 @@ func (r *CommandSide) AddOrgDomain(ctx context.Context, orgDomain *domain.OrgDom return orgDomainWriteModelToOrgDomain(domainWriteModel), nil } +func (r *CommandSide) GenerateOrgDomainValidation(ctx context.Context, orgDomain *domain.OrgDomain) (token, url string, err error) { + if orgDomain == nil || !orgDomain.IsValid() { + return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-R24hb", "Errors.Org.InvalidDomain") + } + checkType, ok := orgDomain.ValidationType.CheckType() + if !ok { + return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-Gsw31", "Errors.Org.DomainVerificationTypeInvalid") + } + domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain) + if err != nil { + return "", "", err + } + if domainWriteModel.State != domain.OrgDomainStateActive { + return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-AGD31", "Errors.Org.DomainNotOnOrg") + } + if domainWriteModel.Verified { + return "", "", caos_errs.ThrowPreconditionFailed(nil, "ORG-HGw21", "Errors.Org.DomainAlreadyVerified") + } + token, err = orgDomain.GenerateVerificationCode(r.domainVerificationGenerator) + if err != nil { + return "", "", err + } + url, err = http_utils.TokenUrl(orgDomain.Domain, token, checkType) + if err != nil { + return "", "", caos_errs.ThrowPreconditionFailed(err, "ORG-Bae21", "Errors.Org.DomainVerificationTypeInvalid") + } + + orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel) + orgAgg.PushEvents(org.NewDomainVerificationAddedEvent(ctx, orgDomain.Domain, orgDomain.ValidationType, orgDomain.ValidationCode)) + + err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg) + if err != nil { + return "", "", err + } + return token, url, nil +} + +func (r *CommandSide) ValidateOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) error { + if orgDomain == nil || !orgDomain.IsValid() { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-R24hb", "Errors.Org.InvalidDomain") + } + domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain) + if err != nil { + return err + } + if domainWriteModel.State != domain.OrgDomainStateActive { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-Sjdi3", "Errors.Org.DomainNotOnOrg") + } + if domainWriteModel.Verified { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-HGw21", "Errors.Org.DomainAlreadyVerified") + } + if domainWriteModel.ValidationCode == nil || domainWriteModel.ValidationType == domain.OrgDomainValidationTypeUnspecified { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-SFBB3", "Errors.Org.DomainVerificationMissing") + } + + validationCode, err := crypto.DecryptString(domainWriteModel.ValidationCode, r.domainVerificationAlg) + if err != nil { + return err + } + checkType, _ := domainWriteModel.ValidationType.CheckType() + err = r.domainVerificationValidator(domainWriteModel.Domain, validationCode, validationCode, checkType) + orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel) + if err == nil { + orgAgg.PushEvents(org.NewDomainVerifiedEvent(ctx, orgDomain.Domain)) + return r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg) + } + orgAgg.PushEvents(org.NewDomainVerificationFailedEvent(ctx, orgDomain.Domain)) + err = r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg) + logging.LogWithFields("ORG-dhTE", "orgID", orgAgg.ID(), "domain", orgDomain.Domain).OnError(err).Error("NewDomainVerificationFailedEvent push failed") + return caos_errs.ThrowInvalidArgument(err, "ORG-GH3s", "Errors.Org.DomainVerificationFailed") +} + +func (r *CommandSide) SetPrimaryOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) error { + if orgDomain == nil || !orgDomain.IsValid() { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-SsDG2", "Errors.Org.InvalidDomain") + } + domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain) + if err != nil { + return err + } + if domainWriteModel.State != domain.OrgDomainStateActive { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-GDfA3", "Errors.Org.DomainNotOnOrg") + } + if !domainWriteModel.Verified { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-Ggd32", "Errors.Org.DomainNotVerified") + } + orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel) + orgAgg.PushEvents(org.NewDomainPrimarySetEvent(ctx, orgDomain.Domain)) + return r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg) +} + +func (r *CommandSide) RemoveOrgDomain(ctx context.Context, orgDomain *domain.OrgDomain) error { + if orgDomain == nil || !orgDomain.IsValid() { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-SJsK3", "Errors.Org.InvalidDomain") + } + domainWriteModel, err := r.getOrgDomainWriteModel(ctx, orgDomain.AggregateID, orgDomain.Domain) + if err != nil { + return err + } + if domainWriteModel.State != domain.OrgDomainStateActive { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-GDfA3", "Errors.Org.DomainNotOnOrg") + } + if domainWriteModel.Primary { + return caos_errs.ThrowPreconditionFailed(nil, "ORG-Sjdi3", "Errors.Org.PrimaryDomainNotDeletable") + } + orgAgg := OrgAggregateFromWriteModel(&domainWriteModel.WriteModel) + orgAgg.PushEvents(org.NewDomainRemovedEvent(ctx, orgDomain.Domain)) + return r.eventstore.PushAggregate(ctx, domainWriteModel, orgAgg) +} + func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *org.Aggregate, addedDomain *OrgDomainWriteModel, orgDomain *domain.OrgDomain) error { err := r.eventstore.FilterToQueryReducer(ctx, addedDomain) if err != nil { @@ -41,3 +155,12 @@ func (r *CommandSide) addOrgDomain(ctx context.Context, orgAgg *org.Aggregate, a } return nil } + +func (r *CommandSide) getOrgDomainWriteModel(ctx context.Context, orgID, domain string) (*OrgDomainWriteModel, error) { + domainWriteModel := NewOrgDomainWriteModel(orgID, domain) + err := r.eventstore.FilterToQueryReducer(ctx, domainWriteModel) + if err != nil { + return nil, err + } + return domainWriteModel, nil +} diff --git a/internal/v2/command/org_policy_label.go b/internal/v2/command/org_policy_label.go new file mode 100644 index 000000000..77ee5f177 --- /dev/null +++ b/internal/v2/command/org_policy_label.go @@ -0,0 +1,71 @@ +package command + +import ( + "context" + + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/org" +) + +func (r *CommandSide) AddLabelPolicy(ctx context.Context, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) { + addedPolicy := NewOrgLabelPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy) + if err != nil { + return nil, err + } + if addedPolicy.State == domain.PolicyStateActive { + return nil, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LabelPolicy.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel) + orgAgg.PushEvents(org.NewLabelPolicyAddedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)) + + err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToLabelPolicy(&addedPolicy.LabelPolicyWriteModel), nil +} + +func (r *CommandSide) ChangeLabelPolicy(ctx context.Context, policy *domain.LabelPolicy) (*domain.LabelPolicy, error) { + existingPolicy := NewOrgLabelPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return nil, err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return nil, caos_errs.ThrowNotFound(nil, "Org-0K9dq", "Errors.Org.LabelPolicy.NotFound") + } + + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor) + if !hasChanged { + return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged") + } + + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel) + orgAgg.PushEvents(changedEvent) + + err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToLabelPolicy(&existingPolicy.LabelPolicyWriteModel), nil +} + +func (r *CommandSide) RemoveLabelPolicy(ctx context.Context, orgID string) error { + existingPolicy := NewOrgLabelPolicyWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return caos_errs.ThrowNotFound(nil, "Org-3M9df", "Errors.Org.LabelPolicy.NotFound") + } + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel) + orgAgg.PushEvents(org.NewLabelPolicyRemovedEvent(ctx)) + + return r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) +} diff --git a/internal/v2/command/org_policy_label_model.go b/internal/v2/command/org_policy_label_model.go new file mode 100644 index 000000000..3a6286521 --- /dev/null +++ b/internal/v2/command/org_policy_label_model.go @@ -0,0 +1,67 @@ +package command + +import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/repository/org" + "github.com/caos/zitadel/internal/v2/repository/policy" +) + +type OrgLabelPolicyWriteModel struct { + LabelPolicyWriteModel +} + +func NewOrgLabelPolicyWriteModel(orgID string) *OrgLabelPolicyWriteModel { + return &OrgLabelPolicyWriteModel{ + LabelPolicyWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + }, + } +} + +func (wm *OrgLabelPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *org.LabelPolicyAddedEvent: + wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent) + case *org.LabelPolicyChangedEvent: + wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent) + } + } +} + +func (wm *OrgLabelPolicyWriteModel) Reduce() error { + return wm.LabelPolicyWriteModel.Reduce() +} + +func (wm *OrgLabelPolicyWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType). + AggregateIDs(wm.LabelPolicyWriteModel.AggregateID). + ResourceOwner(wm.ResourceOwner) +} + +func (wm *OrgLabelPolicyWriteModel) NewChangedEvent( + ctx context.Context, + primaryColor, + secondaryColor string, +) (*org.LabelPolicyChangedEvent, bool) { + changes := make([]policy.LabelPolicyChanges, 0) + if wm.PrimaryColor != primaryColor { + changes = append(changes, policy.ChangePrimaryColor(primaryColor)) + } + if wm.SecondaryColor != secondaryColor { + changes = append(changes, policy.ChangeSecondaryColor(secondaryColor)) + } + if len(changes) == 0 { + return nil, false + } + changedEvent, err := org.NewLabelPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true +} diff --git a/internal/v2/command/org_policy_login.go b/internal/v2/command/org_policy_login.go new file mode 100644 index 000000000..79593b5e8 --- /dev/null +++ b/internal/v2/command/org_policy_login.go @@ -0,0 +1,176 @@ +package command + +import ( + "context" + + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/org" +) + +func (r *CommandSide) AddLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) { + addedPolicy := NewOrgLoginPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy) + if err != nil { + return nil, err + } + if addedPolicy.State == domain.PolicyStateActive { + return nil, caos_errs.ThrowAlreadyExists(nil, "Org-Dgfb2", "Errors.Org.LoginPolicy.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel) + orgAgg.PushEvents(org.NewLoginPolicyAddedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, policy.PasswordlessType)) + + err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToLoginPolicy(&addedPolicy.LoginPolicyWriteModel), nil +} + +func (r *CommandSide) ChangeLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) { + existingPolicy := NewOrgLoginPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return nil, err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return nil, caos_errs.ThrowNotFound(nil, "Org-M0sif", "Errors.Org.LoginPolicy.NotFound") + } + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType)) + if !hasChanged { + return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-5M9vdd", "Errors.Org.LoginPolicy.NotChanged") + } + + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel) + orgAgg.PushEvents(changedEvent) + + err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil +} + +func (r *CommandSide) RemoveLoginPolicy(ctx context.Context, orgID string) error { + existingPolicy := NewOrgLoginPolicyWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return caos_errs.ThrowNotFound(nil, "Org-GHB37", "Errors.Org.LoginPolicy.NotFound") + } + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel) + orgAgg.PushEvents(org.NewLoginPolicyRemovedEvent(ctx)) + + return r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) +} + +func (r *CommandSide) AddIDPProviderToLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) (*domain.IDPProvider, error) { + idpModel := NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID) + err := r.eventstore.FilterToQueryReducer(ctx, idpModel) + if err != nil { + return nil, err + } + if idpModel.State == domain.IdentityProviderStateActive { + return nil, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LoginPolicy.IDP.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&idpModel.WriteModel) + orgAgg.PushEvents(org.NewIdentityProviderAddedEvent(ctx, idpProvider.IDPConfigID, idpProvider.Type)) + + if err = r.eventstore.PushAggregate(ctx, idpModel, orgAgg); err != nil { + return nil, err + } + + return writeModelToIDPProvider(&idpModel.IdentityProviderWriteModel), nil +} + +func (r *CommandSide) RemoveIDPProviderFromLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) error { + idpModel := NewOrgIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID) + err := r.eventstore.FilterToQueryReducer(ctx, idpModel) + if err != nil { + return err + } + if idpModel.State == domain.IdentityProviderStateUnspecified || idpModel.State == domain.IdentityProviderStateRemoved { + return caos_errs.ThrowNotFound(nil, "Org-39fjs", "Errors.Org.LoginPolicy.IDP.NotExisting") + } + orgAgg := OrgAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel) + orgAgg.PushEvents(org.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID)) + + return r.eventstore.PushAggregate(ctx, idpModel, orgAgg) +} + +func (r *CommandSide) AddSecondFactorToLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType, orgID string) (domain.SecondFactorType, error) { + secondFactorModel := NewOrgSecondFactorWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel) + if err != nil { + return domain.SecondFactorTypeUnspecified, err + } + + if secondFactorModel.State == domain.FactorStateActive { + return domain.SecondFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "Org-2B0ps", "Errors.Org.LoginPolicy.MFA.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel) + orgAgg.PushEvents(org.NewLoginPolicySecondFactorAddedEvent(ctx, secondFactor)) + + if err = r.eventstore.PushAggregate(ctx, secondFactorModel, orgAgg); err != nil { + return domain.SecondFactorTypeUnspecified, err + } + + return secondFactorModel.MFAType, nil +} + +func (r *CommandSide) RemoveSecondFactorFromLoginPolicy(ctx context.Context, secondFactor domain.SecondFactorType, orgID string) error { + secondFactorModel := NewOrgSecondFactorWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel) + if err != nil { + return err + } + if secondFactorModel.State == domain.FactorStateUnspecified || secondFactorModel.State == domain.FactorStateRemoved { + return caos_errs.ThrowNotFound(nil, "Org-3M9od", "Errors.Org.LoginPolicy.MFA.NotExisting") + } + orgAgg := OrgAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel) + orgAgg.PushEvents(org.NewLoginPolicySecondFactorRemovedEvent(ctx, domain.SecondFactorType(secondFactor))) + + return r.eventstore.PushAggregate(ctx, secondFactorModel, orgAgg) +} + +func (r *CommandSide) AddMultiFactorToLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType, orgID string) (domain.MultiFactorType, error) { + multiFactorModel := NewOrgMultiFactorWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel) + if err != nil { + return domain.MultiFactorTypeUnspecified, err + } + if multiFactorModel.State == domain.FactorStateActive { + return domain.MultiFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "Org-3M9od", "Errors.Org.LoginPolicy.MFA.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&multiFactorModel.WriteModel) + orgAgg.PushEvents(org.NewLoginPolicyMultiFactorAddedEvent(ctx, multiFactor)) + + if err = r.eventstore.PushAggregate(ctx, multiFactorModel, orgAgg); err != nil { + return domain.MultiFactorTypeUnspecified, err + } + + return multiFactorModel.MFAType, nil +} + +func (r *CommandSide) RemoveMultiFactorFromLoginPolicy(ctx context.Context, multiFactor domain.MultiFactorType, orgID string) error { + multiFactorModel := NewOrgMultiFactorWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel) + if err != nil { + return err + } + if multiFactorModel.State == domain.FactorStateUnspecified || multiFactorModel.State == domain.FactorStateRemoved { + return caos_errs.ThrowNotFound(nil, "Org-3M9df", "Errors.Org.LoginPolicy.MFA.NotExisting") + } + orgAgg := OrgAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel) + orgAgg.PushEvents(org.NewLoginPolicyMultiFactorRemovedEvent(ctx, domain.MultiFactorType(multiFactor))) + + return r.eventstore.PushAggregate(ctx, multiFactorModel, orgAgg) +} diff --git a/internal/v2/command/org_policy_login_factors_model.go b/internal/v2/command/org_policy_login_factors_model.go new file mode 100644 index 000000000..5cbc7d42b --- /dev/null +++ b/internal/v2/command/org_policy_login_factors_model.go @@ -0,0 +1,74 @@ +package command + +import ( + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/repository/iam" +) + +type OrgSecondFactorWriteModel struct { + SecondFactorWriteModel +} + +func NewOrgSecondFactorWriteModel(orgID string) *OrgSecondFactorWriteModel { + return &OrgSecondFactorWriteModel{ + SecondFactorWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + }, + } +} + +func (wm *OrgSecondFactorWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *iam.LoginPolicySecondFactorAddedEvent: + wm.WriteModel.AppendEvents(&e.SecondFactorAddedEvent) + } + } +} + +func (wm *OrgSecondFactorWriteModel) Reduce() error { + return wm.WriteModel.Reduce() +} + +func (wm *OrgSecondFactorWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType). + AggregateIDs(wm.WriteModel.AggregateID). + ResourceOwner(wm.ResourceOwner) +} + +type OrgMultiFactorWriteModel struct { + MultiFactoryWriteModel +} + +func NewOrgMultiFactorWriteModel(orgID string) *OrgMultiFactorWriteModel { + return &OrgMultiFactorWriteModel{ + MultiFactoryWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + }, + } +} + +func (wm *OrgMultiFactorWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *iam.LoginPolicyMultiFactorAddedEvent: + wm.WriteModel.AppendEvents(&e.MultiFactorAddedEvent) + } + } +} + +func (wm *OrgMultiFactorWriteModel) Reduce() error { + return wm.WriteModel.Reduce() +} + +func (wm *OrgMultiFactorWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType). + AggregateIDs(wm.WriteModel.AggregateID). + ResourceOwner(wm.ResourceOwner) +} diff --git a/internal/v2/command/org_policy_login_identity_provider_model.go b/internal/v2/command/org_policy_login_identity_provider_model.go new file mode 100644 index 000000000..8545cd586 --- /dev/null +++ b/internal/v2/command/org_policy_login_identity_provider_model.go @@ -0,0 +1,44 @@ +package command + +import ( + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/repository/iam" +) + +type OrgIdentityProviderWriteModel struct { + IdentityProviderWriteModel +} + +func NewOrgIdentityProviderWriteModel(orgID, idpConfigID string) *OrgIdentityProviderWriteModel { + return &OrgIdentityProviderWriteModel{ + IdentityProviderWriteModel: IdentityProviderWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + IDPConfigID: idpConfigID, + }, + } +} + +func (wm *OrgIdentityProviderWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *iam.IdentityProviderAddedEvent: + if e.IDPConfigID != wm.IDPConfigID { + continue + } + wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderAddedEvent) + } + } +} + +func (wm *OrgIdentityProviderWriteModel) Reduce() error { + return wm.IdentityProviderWriteModel.Reduce() +} + +func (wm *OrgIdentityProviderWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType). + AggregateIDs(wm.AggregateID). + ResourceOwner(wm.ResourceOwner) +} diff --git a/internal/v2/command/org_policy_login_model.go b/internal/v2/command/org_policy_login_model.go new file mode 100644 index 000000000..3bab9fba4 --- /dev/null +++ b/internal/v2/command/org_policy_login_model.go @@ -0,0 +1,87 @@ +package command + +import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/org" + "github.com/caos/zitadel/internal/v2/repository/policy" +) + +type OrgLoginPolicyWriteModel struct { + LoginPolicyWriteModel +} + +func NewOrgLoginPolicyWriteModel(orgID string) *OrgLoginPolicyWriteModel { + return &OrgLoginPolicyWriteModel{ + LoginPolicyWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + }, + } +} + +func (wm *OrgLoginPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *org.LoginPolicyAddedEvent: + wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyAddedEvent) + case *org.LoginPolicyChangedEvent: + wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyChangedEvent) + case *org.LoginPolicyRemovedEvent: + wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyRemovedEvent) + } + } +} + +func (wm *OrgLoginPolicyWriteModel) IsValid() bool { + return wm.AggregateID != "" +} + +func (wm *OrgLoginPolicyWriteModel) Reduce() error { + return wm.LoginPolicyWriteModel.Reduce() +} + +func (wm *OrgLoginPolicyWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType). + AggregateIDs(wm.LoginPolicyWriteModel.AggregateID). + ResourceOwner(wm.ResourceOwner) +} + +func (wm *OrgLoginPolicyWriteModel) NewChangedEvent( + ctx context.Context, + allowUsernamePassword, + allowRegister, + allowExternalIDP, + forceMFA bool, + passwordlessType domain.PasswordlessType, +) (*org.LoginPolicyChangedEvent, bool) { + + changes := make([]policy.LoginPolicyChanges, 0) + if wm.AllowUserNamePassword != allowUsernamePassword { + changes = append(changes, policy.ChangeAllowUserNamePassword(allowUsernamePassword)) + } + if wm.AllowRegister != allowRegister { + changes = append(changes, policy.ChangeAllowRegister(allowRegister)) + } + if wm.AllowExternalIDP != allowExternalIDP { + changes = append(changes, policy.ChangeAllowExternalIDP(allowExternalIDP)) + } + if wm.ForceMFA != forceMFA { + changes = append(changes, policy.ChangeForceMFA(forceMFA)) + } + if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType { + changes = append(changes, policy.ChangePasswordlessType(passwordlessType)) + } + if len(changes) == 0 { + return nil, false + } + changedEvent, err := org.NewLoginPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true +} diff --git a/internal/v2/command/org_policy_org_iam.go b/internal/v2/command/org_policy_org_iam.go index 6b9661fd1..a79bb78e8 100644 --- a/internal/v2/command/org_policy_org_iam.go +++ b/internal/v2/command/org_policy_org_iam.go @@ -65,6 +65,21 @@ func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.Org return orgWriteModelToOrgIAMPolicy(existingPolicy), nil } +func (r *CommandSide) RemoveOrgIAMPolicy(ctx context.Context, orgID string) error { + existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, orgID) + if err != nil { + return err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return caos_errs.ThrowNotFound(nil, "ORG-Dvsh3", "Errors.Org.OrgIAMPolicy.NotFound") + } + + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel) + orgAgg.PushEvents(org.NewOrgIAMPolicyRemovedEvent(ctx)) + + return r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) +} + func (r *CommandSide) getOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error) { policy, err := r.orgIAMPolicyWriteModelByID(ctx, orgID) if err != nil { diff --git a/internal/v2/command/org_policy_org_iam_model.go b/internal/v2/command/org_policy_org_iam_model.go index f1dea71aa..41b3cffb3 100644 --- a/internal/v2/command/org_policy_org_iam_model.go +++ b/internal/v2/command/org_policy_org_iam_model.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/repository/org" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type ORGOrgIAMPolicyWriteModel struct { @@ -44,11 +45,16 @@ func (wm *ORGOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder { } func (wm *ORGOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLoginMustBeDomain bool) (*org.OrgIAMPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := org.NewOrgIAMPolicyChangedEvent(ctx) + changes := make([]policy.OrgIAMPolicyChanges, 0) if wm.UserLoginMustBeDomain != userLoginMustBeDomain { - hasChanged = true - changedEvent.UserLoginMustBeDomain = &userLoginMustBeDomain + changes = append(changes, policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := org.NewOrgIAMPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/org_policy_password_age.go b/internal/v2/command/org_policy_password_age.go new file mode 100644 index 000000000..9e21d0b68 --- /dev/null +++ b/internal/v2/command/org_policy_password_age.go @@ -0,0 +1,70 @@ +package command + +import ( + "context" + + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/org" +) + +func (r *CommandSide) AddPasswordAgePolicy(ctx context.Context, policy *domain.PasswordAgePolicy) (*domain.PasswordAgePolicy, error) { + addedPolicy := NewOrgPasswordAgePolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy) + if err != nil { + return nil, err + } + if addedPolicy.State == domain.PolicyStateActive { + return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-Lk0dS", "Errors.Org.PasswordAgePolicy.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel) + orgAgg.PushEvents(org.NewPasswordAgePolicyAddedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)) + + err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToPasswordAgePolicy(&addedPolicy.PasswordAgePolicyWriteModel), nil +} + +func (r *CommandSide) ChangePasswordAgePolicy(ctx context.Context, policy *domain.PasswordAgePolicy) (*domain.PasswordAgePolicy, error) { + existingPolicy := NewOrgPasswordAgePolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return nil, err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return nil, caos_errs.ThrowNotFound(nil, "ORG-0oPew", "Errors.Org.PasswordAgePolicy.NotFound") + } + + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays) + if !hasChanged { + return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-dsgjR", "Errors.ORg.LabelPolicy.NotChanged") + } + + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel) + orgAgg.PushEvents(changedEvent) + + err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToPasswordAgePolicy(&existingPolicy.PasswordAgePolicyWriteModel), nil +} + +func (r *CommandSide) RemovePasswordAgePolicy(ctx context.Context, orgID string) error { + existingPolicy := NewOrgPasswordAgePolicyWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return caos_errs.ThrowNotFound(nil, "ORG-Dgs1g", "Errors.Org.PasswordAgePolicy.NotFound") + } + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel) + orgAgg.PushEvents(org.NewPasswordAgePolicyRemovedEvent(ctx)) + return r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) +} diff --git a/internal/v2/command/org_policy_password_age_model.go b/internal/v2/command/org_policy_password_age_model.go new file mode 100644 index 000000000..5e5df99ec --- /dev/null +++ b/internal/v2/command/org_policy_password_age_model.go @@ -0,0 +1,65 @@ +package command + +import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/repository/org" + "github.com/caos/zitadel/internal/v2/repository/policy" +) + +type OrgPasswordAgePolicyWriteModel struct { + PasswordAgePolicyWriteModel +} + +func NewOrgPasswordAgePolicyWriteModel(orgID string) *OrgPasswordAgePolicyWriteModel { + return &OrgPasswordAgePolicyWriteModel{ + PasswordAgePolicyWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + }, + } +} + +func (wm *OrgPasswordAgePolicyWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *org.PasswordAgePolicyAddedEvent: + wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyAddedEvent) + case *org.PasswordAgePolicyChangedEvent: + wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyChangedEvent) + case *org.PasswordAgePolicyRemovedEvent: + wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyRemovedEvent) + } + } +} + +func (wm *OrgPasswordAgePolicyWriteModel) Reduce() error { + return wm.PasswordAgePolicyWriteModel.Reduce() +} + +func (wm *OrgPasswordAgePolicyWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType). + AggregateIDs(wm.PasswordAgePolicyWriteModel.AggregateID). + ResourceOwner(wm.ResourceOwner) +} + +func (wm *OrgPasswordAgePolicyWriteModel) NewChangedEvent(ctx context.Context, expireWarnDays, maxAgeDays uint64) (*org.PasswordAgePolicyChangedEvent, bool) { + changes := make([]policy.PasswordAgePolicyChanges, 0) + if wm.ExpireWarnDays != expireWarnDays { + changes = append(changes, policy.ChangeExpireWarnDays(expireWarnDays)) + } + if wm.MaxAgeDays != maxAgeDays { + changes = append(changes, policy.ChangeMaxAgeDays(maxAgeDays)) + } + if len(changes) == 0 { + return nil, false + } + changedEvent, err := org.NewPasswordAgePolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true +} diff --git a/internal/v2/command/org_policy_password_complexity.go b/internal/v2/command/org_policy_password_complexity.go index 88139a8cb..272a6eb74 100644 --- a/internal/v2/command/org_policy_password_complexity.go +++ b/internal/v2/command/org_policy_password_complexity.go @@ -2,10 +2,13 @@ package command import ( "context" + + caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/org" ) -func (r *CommandSide) GetOrgPasswordComplexityPolicy(ctx context.Context, orgID string) (*domain.PasswordComplexityPolicy, error) { +func (r *CommandSide) getOrgPasswordComplexityPolicy(ctx context.Context, orgID string) (*domain.PasswordComplexityPolicy, error) { policy := NewOrgPasswordComplexityPolicyWriteModel(orgID) err := r.eventstore.FilterToQueryReducer(ctx, policy) if err != nil { @@ -14,5 +17,72 @@ func (r *CommandSide) GetOrgPasswordComplexityPolicy(ctx context.Context, orgID if policy.State == domain.PolicyStateActive { return orgWriteModelToPasswordComplexityPolicy(policy), nil } - return r.GetDefaultPasswordComplexityPolicy(ctx) + return r.getDefaultPasswordComplexityPolicy(ctx) +} + +func (r *CommandSide) AddPasswordComplexityPolicy(ctx context.Context, policy *domain.PasswordComplexityPolicy) (*domain.PasswordComplexityPolicy, error) { + if err := policy.IsValid(); err != nil { + return nil, err + } + addedPolicy := NewOrgPasswordComplexityPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy) + if err != nil { + return nil, err + } + if addedPolicy.State == domain.PolicyStateActive { + return nil, caos_errs.ThrowAlreadyExists(nil, "Org-LdhbS", "Errors.Org.PasswordComplexityPolicy.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel) + orgAgg.PushEvents(org.NewPasswordComplexityPolicyAddedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)) + + err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToPasswordComplexityPolicy(&addedPolicy.PasswordComplexityPolicyWriteModel), nil +} + +func (r *CommandSide) ChangePasswordComplexityPolicy(ctx context.Context, policy *domain.PasswordComplexityPolicy) (*domain.PasswordComplexityPolicy, error) { + if err := policy.IsValid(); err != nil { + return nil, err + } + + existingPolicy := NewOrgPasswordComplexityPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return nil, err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return nil, caos_errs.ThrowNotFound(nil, "ORG-Dgs3g", "Errors.Org.PasswordComplexityPolicy.NotFound") + } + + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol) + if !hasChanged { + return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-DAs21", "Errors.Org.PasswordComplexityPolicy.NotChanged") + } + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel) + orgAgg.PushEvents(changedEvent) + + err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToPasswordComplexityPolicy(&existingPolicy.PasswordComplexityPolicyWriteModel), nil +} + +func (r *CommandSide) RemovePasswordComplexityPolicy(ctx context.Context, orgID string) error { + existingPolicy := NewOrgPasswordComplexityPolicyWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return caos_errs.ThrowNotFound(nil, "ORG-ADgs2", "Errors.Org.PasswordComplexityPolicy.NotFound") + } + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel) + orgAgg.PushEvents(org.NewPasswordComplexityPolicyRemovedEvent(ctx)) + return r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) } diff --git a/internal/v2/command/org_policy_password_complexity_model.go b/internal/v2/command/org_policy_password_complexity_model.go index 337767feb..ba0aae8ce 100644 --- a/internal/v2/command/org_policy_password_complexity_model.go +++ b/internal/v2/command/org_policy_password_complexity_model.go @@ -5,6 +5,7 @@ import ( "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/v2/repository/org" + "github.com/caos/zitadel/internal/v2/repository/policy" ) type OrgPasswordComplexityPolicyWriteModel struct { @@ -29,6 +30,8 @@ func (wm *OrgPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventsto wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent) case *org.PasswordComplexityPolicyChangedEvent: wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent) + case *org.PasswordComplexityPolicyRemovedEvent: + wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyRemovedEvent) } } } @@ -52,27 +55,28 @@ func (wm *OrgPasswordComplexityPolicyWriteModel) NewChangedEvent( hasSymbol bool, ) (*org.PasswordComplexityPolicyChangedEvent, bool) { - hasChanged := false - changedEvent := org.NewPasswordComplexityPolicyChangedEvent(ctx) + changes := make([]policy.PasswordComplexityPolicyChanges, 0) if wm.MinLength != minLength { - hasChanged = true - changedEvent.MinLength = &minLength + changes = append(changes, policy.ChangeMinLength(minLength)) } if wm.HasLowercase != hasLowercase { - hasChanged = true - changedEvent.HasLowercase = &hasLowercase + changes = append(changes, policy.ChangeHasLowercase(hasLowercase)) } - if wm.HasUpperCase != hasUppercase { - hasChanged = true - changedEvent.HasUpperCase = &hasUppercase + if wm.HasUppercase != hasUppercase { + changes = append(changes, policy.ChangeHasUppercase(hasUppercase)) } if wm.HasNumber != hasNumber { - hasChanged = true - changedEvent.HasNumber = &hasNumber + changes = append(changes, policy.ChangeHasNumber(hasNumber)) } if wm.HasSymbol != hasSymbol { - hasChanged = true - changedEvent.HasSymbol = &hasSymbol + changes = append(changes, policy.ChangeHasSymbol(hasSymbol)) } - return changedEvent, hasChanged + if len(changes) == 0 { + return nil, false + } + changedEvent, err := org.NewPasswordComplexityPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true } diff --git a/internal/v2/command/org_policy_password_lockout.go b/internal/v2/command/org_policy_password_lockout.go new file mode 100644 index 000000000..260ca987c --- /dev/null +++ b/internal/v2/command/org_policy_password_lockout.go @@ -0,0 +1,70 @@ +package command + +import ( + "context" + + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/org" +) + +func (r *CommandSide) AddPasswordLockoutPolicy(ctx context.Context, policy *domain.PasswordLockoutPolicy) (*domain.PasswordLockoutPolicy, error) { + addedPolicy := NewOrgPasswordLockoutPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy) + if err != nil { + return nil, err + } + if addedPolicy.State == domain.PolicyStateActive { + return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-0olDf", "Errors.ORG.PasswordLockoutPolicy.AlreadyExists") + } + + orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel) + orgAgg.PushEvents(org.NewPasswordLockoutPolicyAddedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)) + + err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToPasswordLockoutPolicy(&addedPolicy.PasswordLockoutPolicyWriteModel), nil +} + +func (r *CommandSide) ChangePasswordLockoutPolicy(ctx context.Context, policy *domain.PasswordLockoutPolicy) (*domain.PasswordLockoutPolicy, error) { + existingPolicy := NewOrgPasswordLockoutPolicyWriteModel(policy.AggregateID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return nil, err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return nil, caos_errs.ThrowNotFound(nil, "ORG-ADfs1", "Errors.Org.PasswordLockoutPolicy.NotFound") + } + + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures) + if !hasChanged { + return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-4M9vs", "Errors.Org.PasswordLockoutPolicy.NotChanged") + } + + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel) + orgAgg.PushEvents(changedEvent) + + err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) + if err != nil { + return nil, err + } + + return writeModelToPasswordLockoutPolicy(&existingPolicy.PasswordLockoutPolicyWriteModel), nil +} + +func (r *CommandSide) RemovePasswordLockoutPolicy(ctx context.Context, orgID string) error { + existingPolicy := NewOrgPasswordLockoutPolicyWriteModel(orgID) + err := r.eventstore.FilterToQueryReducer(ctx, existingPolicy) + if err != nil { + return err + } + if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved { + return caos_errs.ThrowNotFound(nil, "ORG-D4zuz", "Errors.Org.PasswordLockoutPolicy.NotFound") + } + orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel) + orgAgg.PushEvents(org.NewPasswordLockoutPolicyRemovedEvent(ctx)) + return r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg) +} diff --git a/internal/v2/command/org_policy_password_lockout_model.go b/internal/v2/command/org_policy_password_lockout_model.go new file mode 100644 index 000000000..b3a78f183 --- /dev/null +++ b/internal/v2/command/org_policy_password_lockout_model.go @@ -0,0 +1,65 @@ +package command + +import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/v2/repository/org" + "github.com/caos/zitadel/internal/v2/repository/policy" +) + +type OrgPasswordLockoutPolicyWriteModel struct { + PasswordLockoutPolicyWriteModel +} + +func NewOrgPasswordLockoutPolicyWriteModel(orgID string) *OrgPasswordLockoutPolicyWriteModel { + return &OrgPasswordLockoutPolicyWriteModel{ + PasswordLockoutPolicyWriteModel{ + WriteModel: eventstore.WriteModel{ + AggregateID: orgID, + ResourceOwner: orgID, + }, + }, + } +} + +func (wm *OrgPasswordLockoutPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) { + for _, event := range events { + switch e := event.(type) { + case *org.PasswordLockoutPolicyAddedEvent: + wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyAddedEvent) + case *org.PasswordLockoutPolicyChangedEvent: + wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyChangedEvent) + case *org.PasswordComplexityPolicyRemovedEvent: + wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyRemovedEvent) + } + } +} + +func (wm *OrgPasswordLockoutPolicyWriteModel) Reduce() error { + return wm.PasswordLockoutPolicyWriteModel.Reduce() +} + +func (wm *OrgPasswordLockoutPolicyWriteModel) Query() *eventstore.SearchQueryBuilder { + return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType). + AggregateIDs(wm.PasswordLockoutPolicyWriteModel.AggregateID). + ResourceOwner(wm.ResourceOwner) +} + +func (wm *OrgPasswordLockoutPolicyWriteModel) NewChangedEvent(ctx context.Context, maxAttempts uint64, showLockoutFailure bool) (*org.PasswordLockoutPolicyChangedEvent, bool) { + changes := make([]policy.PasswordLockoutPolicyChanges, 0) + if wm.MaxAttempts != maxAttempts { + changes = append(changes, policy.ChangeMaxAttempts(maxAttempts)) + } + if wm.ShowLockOutFailures != showLockoutFailure { + changes = append(changes, policy.ChangeShowLockOutFailures(showLockoutFailure)) + } + if len(changes) == 0 { + return nil, false + } + changedEvent, err := org.NewPasswordLockoutPolicyChangedEvent(ctx, changes) + if err != nil { + return nil, false + } + return changedEvent, true +} diff --git a/internal/v2/command/policy_password_age_model.go b/internal/v2/command/policy_password_age_model.go index d9dc244f7..3883f4098 100644 --- a/internal/v2/command/policy_password_age_model.go +++ b/internal/v2/command/policy_password_age_model.go @@ -25,8 +25,8 @@ func (wm *PasswordAgePolicyWriteModel) Reduce() error { if e.ExpireWarnDays != nil { wm.ExpireWarnDays = *e.ExpireWarnDays } - if e.ExpireWarnDays != nil { - wm.ExpireWarnDays = *e.ExpireWarnDays + if e.MaxAgeDays != nil { + wm.MaxAgeDays = *e.MaxAgeDays } case *policy.PasswordAgePolicyRemovedEvent: wm.State = domain.PolicyStateRemoved diff --git a/internal/v2/command/policy_password_complexity_model.go b/internal/v2/command/policy_password_complexity_model.go index fd4e24d36..67ac2580b 100644 --- a/internal/v2/command/policy_password_complexity_model.go +++ b/internal/v2/command/policy_password_complexity_model.go @@ -11,7 +11,7 @@ type PasswordComplexityPolicyWriteModel struct { MinLength uint64 HasLowercase bool - HasUpperCase bool + HasUppercase bool HasNumber bool HasSymbol bool State domain.PolicyState @@ -23,7 +23,7 @@ func (wm *PasswordComplexityPolicyWriteModel) Reduce() error { case *policy.PasswordComplexityPolicyAddedEvent: wm.MinLength = e.MinLength wm.HasLowercase = e.HasLowercase - wm.HasUpperCase = e.HasUpperCase + wm.HasUppercase = e.HasUppercase wm.HasNumber = e.HasNumber wm.HasSymbol = e.HasSymbol wm.State = domain.PolicyStateActive @@ -34,8 +34,8 @@ func (wm *PasswordComplexityPolicyWriteModel) Reduce() error { if e.HasLowercase != nil { wm.HasLowercase = *e.HasLowercase } - if e.HasUpperCase != nil { - wm.HasUpperCase = *e.HasUpperCase + if e.HasUppercase != nil { + wm.HasUppercase = *e.HasUppercase } if e.HasNumber != nil { wm.HasNumber = *e.HasNumber diff --git a/internal/v2/command/setup_step7.go b/internal/v2/command/setup_step7.go index 0a80283d5..e917857ac 100644 --- a/internal/v2/command/setup_step7.go +++ b/internal/v2/command/setup_step7.go @@ -5,7 +5,6 @@ import ( "github.com/caos/logging" - iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/v2/domain" iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" ) @@ -29,7 +28,7 @@ func (r *CommandSide) SetupStep7(ctx context.Context, step *Step7) error { if !step.OTP { return iamAgg, nil } - err := r.addSecondFactorToDefaultLoginPolicy(ctx, iamAgg, secondFactorModel, iam_model.SecondFactorTypeOTP) + err := r.addSecondFactorToDefaultLoginPolicy(ctx, iamAgg, secondFactorModel, domain.SecondFactorTypeOTP) if err != nil { return nil, err } diff --git a/internal/v2/command/setup_step8.go b/internal/v2/command/setup_step8.go index 14a53446d..6db58e095 100644 --- a/internal/v2/command/setup_step8.go +++ b/internal/v2/command/setup_step8.go @@ -5,7 +5,6 @@ import ( "github.com/caos/logging" - iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/v2/domain" iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" ) @@ -29,7 +28,7 @@ func (r *CommandSide) SetupStep8(ctx context.Context, step *Step8) error { if !step.U2F { return iamAgg, nil } - err := r.addSecondFactorToDefaultLoginPolicy(ctx, iamAgg, secondFactorModel, iam_model.SecondFactorTypeU2F) + err := r.addSecondFactorToDefaultLoginPolicy(ctx, iamAgg, secondFactorModel, domain.SecondFactorTypeU2F) if err != nil { return nil, err } diff --git a/internal/v2/command/setup_step9.go b/internal/v2/command/setup_step9.go index f563611d7..21791bfd9 100644 --- a/internal/v2/command/setup_step9.go +++ b/internal/v2/command/setup_step9.go @@ -5,7 +5,6 @@ import ( "github.com/caos/logging" - iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/v2/domain" iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" ) @@ -34,7 +33,7 @@ func (r *CommandSide) SetupStep9(ctx context.Context, step *Step9) error { return nil, err } logging.Log("SETUP-AEG2t").Info("allowed passwordless in login policy") - err = r.addMultiFactorToDefaultLoginPolicy(ctx, iamAgg, multiFactorModel, iam_model.MultiFactorTypeU2FWithPIN) + err = r.addMultiFactorToDefaultLoginPolicy(ctx, iamAgg, multiFactorModel, domain.MultiFactorTypeU2FWithPIN) if err != nil { return nil, err } @@ -45,7 +44,7 @@ func (r *CommandSide) SetupStep9(ctx context.Context, step *Step9) error { } func setPasswordlessAllowedInPolicy(ctx context.Context, c *CommandSide, iamAgg *iam_repo.Aggregate) error { - policy, err := c.GetDefaultLoginPolicy(ctx) + policy, err := c.getDefaultLoginPolicy(ctx) if err != nil { return err } diff --git a/internal/v2/command/user.go b/internal/v2/command/user.go index 7cb9eb700..1f890b8a3 100644 --- a/internal/v2/command/user.go +++ b/internal/v2/command/user.go @@ -138,6 +138,14 @@ func (r *CommandSide) RemoveUser(ctx context.Context, userID, resourceOwner stri return r.eventstore.PushAggregate(ctx, existingUser, userAgg) } +func (r *CommandSide) checkUserExists(ctx context.Context, userID, resourceOwner string) (bool, error) { + userWriteModel, err := r.userWriteModelByID(ctx, userID, resourceOwner) + if err != nil { + return false, err + } + return userWriteModel.UserState != domain.UserStateUnspecified && userWriteModel.UserState != domain.UserStateDeleted, nil +} + func (r *CommandSide) userWriteModelByID(ctx context.Context, userID, resourceOwner string) (writeModel *UserWriteModel, err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() diff --git a/internal/v2/command/user_human.go b/internal/v2/command/user_human.go index ab4a5befc..a22b163d6 100644 --- a/internal/v2/command/user_human.go +++ b/internal/v2/command/user_human.go @@ -70,7 +70,7 @@ func (r *CommandSide) createHuman(ctx context.Context, orgID string, human *doma if err != nil { return nil, nil, err } - pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID) + pwPolicy, err := r.getOrgPasswordComplexityPolicy(ctx, orgID) if err != nil { return nil, nil, err } diff --git a/internal/v2/command/user_human_password.go b/internal/v2/command/user_human_password.go index 1d4a8ee22..6f1e4f0e6 100644 --- a/internal/v2/command/user_human_password.go +++ b/internal/v2/command/user_human_password.go @@ -62,7 +62,7 @@ func (r *CommandSide) changePassword(ctx context.Context, orgID, userID, userAge if existingPassword.UserState == domain.UserStateInitial { return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-M9dse", "Errors.User.NotInitialised") } - pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID) + pwPolicy, err := r.getOrgPasswordComplexityPolicy(ctx, orgID) if err != nil { return err } diff --git a/internal/v2/domain/org.go b/internal/v2/domain/org.go index 5f6bc11db..52d303272 100644 --- a/internal/v2/domain/org.go +++ b/internal/v2/domain/org.go @@ -42,4 +42,5 @@ const ( OrgStateUnspecified OrgState = iota OrgStateActive OrgStateInactive + OrgStateRemoved ) diff --git a/internal/v2/domain/org_domain.go b/internal/v2/domain/org_domain.go index 2fa229159..7b2ffd6fe 100644 --- a/internal/v2/domain/org_domain.go +++ b/internal/v2/domain/org_domain.go @@ -1,6 +1,7 @@ package domain import ( + http_util "github.com/caos/zitadel/internal/api/http" "github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/eventstore/models" ) @@ -15,6 +16,19 @@ type OrgDomain struct { ValidationCode *crypto.CryptoValue } +func (domain *OrgDomain) IsValid() bool { + return domain.AggregateID != "" && domain.Domain != "" +} + +func (domain *OrgDomain) GenerateVerificationCode(codeGenerator crypto.Generator) (string, error) { + validationCodeCrypto, validationCode, err := crypto.NewCode(codeGenerator) + if err != nil { + return "", err + } + domain.ValidationCode = validationCodeCrypto + return validationCode, nil +} + type OrgDomainValidationType int32 const ( @@ -23,6 +37,17 @@ const ( OrgDomainValidationTypeDNS ) +func (t OrgDomainValidationType) CheckType() (http_util.CheckType, bool) { + switch t { + case OrgDomainValidationTypeHTTP: + return http_util.CheckTypeHTTP, true + case OrgDomainValidationTypeDNS: + return http_util.CheckTypeDNS, true + default: + return -1, false + } +} + type OrgDomainState int32 const ( diff --git a/internal/v2/query/policy_password_complexity_model.go b/internal/v2/query/policy_password_complexity_model.go index 19e722e0e..b1588b235 100644 --- a/internal/v2/query/policy_password_complexity_model.go +++ b/internal/v2/query/policy_password_complexity_model.go @@ -21,7 +21,7 @@ func (rm *PasswordComplexityPolicyReadModel) Reduce() error { case *policy.PasswordComplexityPolicyAddedEvent: rm.MinLength = e.MinLength rm.HasLowercase = e.HasLowercase - rm.HasUpperCase = e.HasUpperCase + rm.HasUpperCase = e.HasUppercase rm.HasNumber = e.HasNumber rm.HasSymbol = e.HasSymbol case *policy.PasswordComplexityPolicyChangedEvent: @@ -31,8 +31,8 @@ func (rm *PasswordComplexityPolicyReadModel) Reduce() error { if e.HasLowercase != nil { rm.HasLowercase = *e.HasLowercase } - if e.HasUpperCase != nil { - rm.HasUpperCase = *e.HasUpperCase + if e.HasUppercase != nil { + rm.HasUpperCase = *e.HasUppercase } if e.HasNumber != nil { rm.HasNumber = *e.HasNumber diff --git a/internal/v2/repository/iam/policy_label.go b/internal/v2/repository/iam/policy_label.go index 247e84fa9..aa1ce125c 100644 --- a/internal/v2/repository/iam/policy_label.go +++ b/internal/v2/repository/iam/policy_label.go @@ -44,12 +44,16 @@ type LabelPolicyChangedEvent struct { func NewLabelPolicyChangedEvent( ctx context.Context, -) *LabelPolicyChangedEvent { - return &LabelPolicyChangedEvent{ - LabelPolicyChangedEvent: *policy.NewLabelPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, LabelPolicyChangedEventType), - ), + changes []policy.LabelPolicyChanges, +) (*LabelPolicyChangedEvent, error) { + changedEvent, err := policy.NewLabelPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, LabelPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &LabelPolicyChangedEvent{LabelPolicyChangedEvent: *changedEvent}, nil } func LabelPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/iam/policy_login.go b/internal/v2/repository/iam/policy_login.go index 549becf25..da1826bee 100644 --- a/internal/v2/repository/iam/policy_login.go +++ b/internal/v2/repository/iam/policy_login.go @@ -51,12 +51,16 @@ type LoginPolicyChangedEvent struct { func NewLoginPolicyChangedEvent( ctx context.Context, -) *LoginPolicyChangedEvent { - return &LoginPolicyChangedEvent{ - LoginPolicyChangedEvent: *policy.NewLoginPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, LoginPolicyChangedEventType), - ), + changes []policy.LoginPolicyChanges, +) (*LoginPolicyChangedEvent, error) { + changedEvent, err := policy.NewLoginPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &LoginPolicyChangedEvent{LoginPolicyChangedEvent: *changedEvent}, nil } func LoginPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/iam/policy_org_iam.go b/internal/v2/repository/iam/policy_org_iam.go index d7a3e8f1f..4b0dad186 100644 --- a/internal/v2/repository/iam/policy_org_iam.go +++ b/internal/v2/repository/iam/policy_org_iam.go @@ -2,6 +2,7 @@ package iam import ( "context" + "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" @@ -43,12 +44,16 @@ type OrgIAMPolicyChangedEvent struct { func NewOrgIAMPolicyChangedEvent( ctx context.Context, -) *OrgIAMPolicyChangedEvent { - return &OrgIAMPolicyChangedEvent{ - OrgIAMPolicyChangedEvent: *policy.NewOrgIAMPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyChangedEventType), - ), + changes []policy.OrgIAMPolicyChanges, +) (*OrgIAMPolicyChangedEvent, error) { + changedEvent, err := policy.NewOrgIAMPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &OrgIAMPolicyChangedEvent{OrgIAMPolicyChangedEvent: *changedEvent}, nil } func OrgIAMPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/iam/policy_password_age.go b/internal/v2/repository/iam/policy_password_age.go index a0fd537d2..801c69abb 100644 --- a/internal/v2/repository/iam/policy_password_age.go +++ b/internal/v2/repository/iam/policy_password_age.go @@ -2,6 +2,7 @@ package iam import ( "context" + "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" @@ -44,12 +45,16 @@ type PasswordAgePolicyChangedEvent struct { func NewPasswordAgePolicyChangedEvent( ctx context.Context, -) *PasswordAgePolicyChangedEvent { - return &PasswordAgePolicyChangedEvent{ - PasswordAgePolicyChangedEvent: *policy.NewPasswordAgePolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, PasswordAgePolicyChangedEventType), - ), + changes []policy.PasswordAgePolicyChanges, +) (*PasswordAgePolicyChangedEvent, error) { + changedEvent, err := policy.NewPasswordAgePolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordAgePolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &PasswordAgePolicyChangedEvent{PasswordAgePolicyChangedEvent: *changedEvent}, nil } func PasswordAgePolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/iam/policy_password_complexity.go b/internal/v2/repository/iam/policy_password_complexity.go index 571c88af3..d90f28f2c 100644 --- a/internal/v2/repository/iam/policy_password_complexity.go +++ b/internal/v2/repository/iam/policy_password_complexity.go @@ -2,6 +2,7 @@ package iam import ( "context" + "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" @@ -50,12 +51,16 @@ type PasswordComplexityPolicyChangedEvent struct { func NewPasswordComplexityPolicyChangedEvent( ctx context.Context, -) *PasswordComplexityPolicyChangedEvent { - return &PasswordComplexityPolicyChangedEvent{ - PasswordComplexityPolicyChangedEvent: *policy.NewPasswordComplexityPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, PasswordComplexityPolicyAddedEventType), - ), + changes []policy.PasswordComplexityPolicyChanges, +) (*PasswordComplexityPolicyChangedEvent, error) { + changedEvent, err := policy.NewPasswordComplexityPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordComplexityPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &PasswordComplexityPolicyChangedEvent{PasswordComplexityPolicyChangedEvent: *changedEvent}, nil } func PasswordComplexityPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/iam/policy_password_lockout.go b/internal/v2/repository/iam/policy_password_lockout.go index 3caf3d449..5dec4234d 100644 --- a/internal/v2/repository/iam/policy_password_lockout.go +++ b/internal/v2/repository/iam/policy_password_lockout.go @@ -2,6 +2,7 @@ package iam import ( "context" + "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" @@ -44,12 +45,16 @@ type PasswordLockoutPolicyChangedEvent struct { func NewPasswordLockoutPolicyChangedEvent( ctx context.Context, -) *PasswordLockoutPolicyChangedEvent { - return &PasswordLockoutPolicyChangedEvent{ - PasswordLockoutPolicyChangedEvent: *policy.NewPasswordLockoutPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, PasswordLockoutPolicyChangedEventType), - ), + changes []policy.PasswordLockoutPolicyChanges, +) (*PasswordLockoutPolicyChangedEvent, error) { + changedEvent, err := policy.NewPasswordLockoutPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordLockoutPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &PasswordLockoutPolicyChangedEvent{PasswordLockoutPolicyChangedEvent: *changedEvent}, nil } func PasswordLockoutPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/org/aggregate.go b/internal/v2/repository/org/aggregate.go index 886e9e0be..d09fe5e6f 100644 --- a/internal/v2/repository/org/aggregate.go +++ b/internal/v2/repository/org/aggregate.go @@ -5,7 +5,7 @@ import ( ) const ( - iamEventTypePrefix = eventstore.EventType("org.") + orgEventTypePrefix = eventstore.EventType("org.") ) const ( diff --git a/internal/v2/repository/org/domain.go b/internal/v2/repository/org/domain.go index 61116bea8..c3505e8b6 100644 --- a/internal/v2/repository/org/domain.go +++ b/internal/v2/repository/org/domain.go @@ -12,13 +12,13 @@ import ( ) const ( - domainEventPrefix = orgEventTypePrefix + "domain." - OrgDomainAdded = domainEventPrefix + "added" - OrgDomainVerificationAdded = domainEventPrefix + "verification.added" - OrgDomainVerificationFailed = domainEventPrefix + "verification.failed" - OrgDomainVerified = domainEventPrefix + "verified" - OrgDomainPrimarySet = domainEventPrefix + "primary.set" - OrgDomainRemoved = domainEventPrefix + "removed" + domainEventPrefix = orgEventTypePrefix + "domain." + OrgDomainAddedEventType = domainEventPrefix + "added" + OrgDomainVerificationAddedEventType = domainEventPrefix + "verification.added" + OrgDomainVerificationFailedEventType = domainEventPrefix + "verification.failed" + OrgDomainVerifiedEventType = domainEventPrefix + "verified" + OrgDomainPrimarySetEventType = domainEventPrefix + "primary.set" + OrgDomainRemovedEventType = domainEventPrefix + "removed" ) type DomainAddedEvent struct { @@ -35,7 +35,7 @@ func NewDomainAddedEvent(ctx context.Context, domain string) *DomainAddedEvent { return &DomainAddedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgDomainAdded, + OrgDomainAddedEventType, ), Domain: domain, } @@ -73,7 +73,7 @@ func NewDomainVerificationAddedEvent( return &DomainVerificationAddedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgDomainVerificationAdded, + OrgDomainVerificationAddedEventType, ), Domain: domain, ValidationType: validationType, @@ -107,7 +107,7 @@ func NewDomainVerificationFailedEvent(ctx context.Context, domain string) *Domai return &DomainVerificationFailedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgDomainVerificationFailed, + OrgDomainVerificationFailedEventType, ), Domain: domain, } @@ -139,7 +139,7 @@ func NewDomainVerifiedEvent(ctx context.Context, domain string) *DomainVerifiedE return &DomainVerifiedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgDomainVerified, + OrgDomainVerifiedEventType, ), Domain: domain, } @@ -171,7 +171,7 @@ func NewDomainPrimarySetEvent(ctx context.Context, domain string) *DomainPrimary return &DomainPrimarySetEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgDomainPrimarySet, + OrgDomainPrimarySetEventType, ), Domain: domain, } @@ -203,7 +203,7 @@ func NewDomainRemovedEvent(ctx context.Context, domain string) *DomainRemovedEve return &DomainRemovedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgDomainRemoved, + OrgDomainRemovedEventType, ), Domain: domain, } diff --git a/internal/v2/repository/org/eventstore.go b/internal/v2/repository/org/eventstore.go index 67d2e2b78..d8a676d58 100644 --- a/internal/v2/repository/org/eventstore.go +++ b/internal/v2/repository/org/eventstore.go @@ -5,15 +5,42 @@ import ( ) func RegisterEventMappers(es *eventstore.Eventstore) { - es.RegisterFilterEventMapper(OrgAdded, OrgAddedEventMapper). - RegisterFilterEventMapper(OrgChanged, OrgChangedEventMapper). - //RegisterFilterEventMapper(OrgDeactivated, OrgChangedEventMapper). TODO: ! - //RegisterFilterEventMapper(OrgReactivated, OrgChangedEventMapper). - //RegisterFilterEventMapper(OrgRemoved, OrgChangedEventMapper). - RegisterFilterEventMapper(OrgDomainAdded, DomainAddedEventMapper). - RegisterFilterEventMapper(OrgDomainVerificationAdded, DomainVerificationAddedEventMapper). - RegisterFilterEventMapper(OrgDomainVerificationFailed, DomainVerificationFailedEventMapper). - RegisterFilterEventMapper(OrgDomainVerified, DomainVerifiedEventMapper). - RegisterFilterEventMapper(OrgDomainPrimarySet, DomainPrimarySetEventMapper). - RegisterFilterEventMapper(OrgDomainRemoved, DomainRemovedEventMapper) + es.RegisterFilterEventMapper(OrgAddedEventType, OrgAddedEventMapper). + RegisterFilterEventMapper(OrgChangedEventType, OrgChangedEventMapper). + RegisterFilterEventMapper(OrgDeactivatedEventType, OrgDeactivatedEventMapper). + RegisterFilterEventMapper(OrgReactivatedEventType, OrgReactivatedEventMapper). + //RegisterFilterEventMapper(OrgRemovedEventType, OrgRemovedEventMapper). //TODO: implement + RegisterFilterEventMapper(OrgDomainAddedEventType, DomainAddedEventMapper). + RegisterFilterEventMapper(OrgDomainVerificationAddedEventType, DomainVerificationAddedEventMapper). + RegisterFilterEventMapper(OrgDomainVerificationFailedEventType, DomainVerificationFailedEventMapper). + RegisterFilterEventMapper(OrgDomainVerifiedEventType, DomainVerifiedEventMapper). + RegisterFilterEventMapper(OrgDomainPrimarySetEventType, DomainPrimarySetEventMapper). + RegisterFilterEventMapper(OrgDomainRemovedEventType, DomainRemovedEventMapper). + RegisterFilterEventMapper(MemberAddedEventType, MemberAddedEventMapper). + RegisterFilterEventMapper(MemberChangedEventType, MemberChangedEventMapper). + RegisterFilterEventMapper(MemberRemovedEventType, MemberRemovedEventMapper). + RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper). + RegisterFilterEventMapper(LabelPolicyChangedEventType, LabelPolicyChangedEventMapper). + RegisterFilterEventMapper(LabelPolicyRemovedEventType, LabelPolicyRemovedEventMapper). + RegisterFilterEventMapper(LoginPolicyAddedEventType, LoginPolicyAddedEventMapper). + RegisterFilterEventMapper(LoginPolicyChangedEventType, LoginPolicyChangedEventMapper). + RegisterFilterEventMapper(LoginPolicyRemovedEventType, LoginPolicyRemovedEventMapper). + RegisterFilterEventMapper(LoginPolicySecondFactorAddedEventType, SecondFactorAddedEventEventMapper). + RegisterFilterEventMapper(LoginPolicySecondFactorRemovedEventType, SecondFactorRemovedEventEventMapper). + RegisterFilterEventMapper(LoginPolicyMultiFactorAddedEventType, MultiFactorAddedEventEventMapper). + RegisterFilterEventMapper(LoginPolicyMultiFactorRemovedEventType, MultiFactorRemovedEventEventMapper). + RegisterFilterEventMapper(LoginPolicyIDPProviderAddedEventType, IdentityProviderAddedEventMapper). + RegisterFilterEventMapper(LoginPolicyIDPProviderRemovedEventType, IdentityProviderRemovedEventMapper). + RegisterFilterEventMapper(OrgIAMPolicyAddedEventType, OrgIAMPolicyAddedEventMapper). + RegisterFilterEventMapper(OrgIAMPolicyChangedEventType, OrgIAMPolicyChangedEventMapper). + RegisterFilterEventMapper(OrgIAMPolicyRemovedEventType, OrgIAMPolicyRemovedEventMapper). + RegisterFilterEventMapper(PasswordAgePolicyAddedEventType, PasswordAgePolicyAddedEventMapper). + RegisterFilterEventMapper(PasswordAgePolicyChangedEventType, PasswordAgePolicyChangedEventMapper). + RegisterFilterEventMapper(PasswordAgePolicyRemovedEventType, PasswordAgePolicyRemovedEventMapper). + RegisterFilterEventMapper(PasswordComplexityPolicyAddedEventType, PasswordComplexityPolicyAddedEventMapper). + RegisterFilterEventMapper(PasswordComplexityPolicyChangedEventType, PasswordComplexityPolicyChangedEventMapper). + RegisterFilterEventMapper(PasswordComplexityPolicyRemovedEventType, PasswordComplexityPolicyRemovedEventMapper). + RegisterFilterEventMapper(PasswordLockoutPolicyAddedEventType, PasswordLockoutPolicyAddedEventMapper). + RegisterFilterEventMapper(PasswordLockoutPolicyChangedEventType, PasswordLockoutPolicyChangedEventMapper). + RegisterFilterEventMapper(PasswordLockoutPolicyRemovedEventType, PasswordLockoutPolicyRemovedEventMapper) } diff --git a/internal/v2/repository/org/member.go b/internal/v2/repository/org/member.go index 74995b673..c80800514 100644 --- a/internal/v2/repository/org/member.go +++ b/internal/v2/repository/org/member.go @@ -3,13 +3,10 @@ package org import ( "context" "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/member" ) -const ( - orgEventTypePrefix = eventstore.EventType("org.") -) - var ( MemberAddedEventType = orgEventTypePrefix + member.AddedEventType MemberChangedEventType = orgEventTypePrefix + member.ChangedEventType @@ -37,6 +34,15 @@ func NewMemberAddedEvent( } } +func MemberAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := member.MemberAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &MemberAddedEvent{MemberAddedEvent: *e.(*member.MemberAddedEvent)}, nil +} + type MemberChangedEvent struct { member.MemberChangedEvent } @@ -59,6 +65,15 @@ func NewMemberChangedEvent( } } +func MemberChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := member.ChangedEventMapper(event) + if err != nil { + return nil, err + } + + return &MemberChangedEvent{MemberChangedEvent: *e.(*member.MemberChangedEvent)}, nil +} + type MemberRemovedEvent struct { member.MemberRemovedEvent } @@ -78,3 +93,12 @@ func NewMemberRemovedEvent( ), } } + +func MemberRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := member.RemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &MemberRemovedEvent{MemberRemovedEvent: *e.(*member.MemberRemovedEvent)}, nil +} diff --git a/internal/v2/repository/org/org.go b/internal/v2/repository/org/org.go index 005e8bb11..064c38a9d 100644 --- a/internal/v2/repository/org/org.go +++ b/internal/v2/repository/org/org.go @@ -10,11 +10,11 @@ import ( ) const ( - OrgAdded = orgEventTypePrefix + "added" - OrgChanged = orgEventTypePrefix + "changed" - OrgDeactivated = orgEventTypePrefix + "deactivated" - OrgReactivated = orgEventTypePrefix + "reactivated" - OrgRemoved = orgEventTypePrefix + "removed" + OrgAddedEventType = orgEventTypePrefix + "added" + OrgChangedEventType = orgEventTypePrefix + "changed" + OrgDeactivatedEventType = orgEventTypePrefix + "deactivated" + OrgReactivatedEventType = orgEventTypePrefix + "reactivated" + OrgRemovedEventType = orgEventTypePrefix + "removed" ) type OrgAddedEvent struct { @@ -31,7 +31,7 @@ func NewOrgAddedEvent(ctx context.Context, name string) *OrgAddedEvent { return &OrgAddedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgAdded, + OrgAddedEventType, ), Name: name, } @@ -63,7 +63,7 @@ func NewOrgChangedEvent(ctx context.Context, name string) *OrgChangedEvent { return &OrgChangedEvent{ BaseEvent: *eventstore.NewBaseEventForPush( ctx, - OrgChanged, + OrgChangedEventType, ), Name: name, } @@ -80,3 +80,61 @@ func OrgChangedEventMapper(event *repository.Event) (eventstore.EventReader, err return orgChanged, nil } + +type OrgDeactivatedEvent struct { + eventstore.BaseEvent `json:"-"` +} + +func (e *OrgDeactivatedEvent) Data() interface{} { + return e +} + +func NewOrgDeactivatedEvent(ctx context.Context) *OrgDeactivatedEvent { + return &OrgDeactivatedEvent{ + BaseEvent: *eventstore.NewBaseEventForPush( + ctx, + OrgDeactivatedEventType, + ), + } +} + +func OrgDeactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + orgChanged := &OrgDeactivatedEvent{ + BaseEvent: *eventstore.BaseEventFromRepo(event), + } + err := json.Unmarshal(event.Data, orgChanged) + if err != nil { + return nil, errors.ThrowInternal(err, "ORG-DAfbs", "unable to unmarshal org deactivated") + } + + return orgChanged, nil +} + +type OrgReactivatedEvent struct { + eventstore.BaseEvent `json:"-"` +} + +func (e *OrgReactivatedEvent) Data() interface{} { + return e +} + +func NewOrgReactivatedEvent(ctx context.Context) *OrgReactivatedEvent { + return &OrgReactivatedEvent{ + BaseEvent: *eventstore.NewBaseEventForPush( + ctx, + OrgReactivatedEventType, + ), + } +} + +func OrgReactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + orgChanged := &OrgReactivatedEvent{ + BaseEvent: *eventstore.BaseEventFromRepo(event), + } + err := json.Unmarshal(event.Data, orgChanged) + if err != nil { + return nil, errors.ThrowInternal(err, "ORG-DAfbs", "unable to unmarshal org deactivated") + } + + return orgChanged, nil +} diff --git a/internal/v2/repository/org/policy_label.go b/internal/v2/repository/org/policy_label.go index 2d0869786..5079638bd 100644 --- a/internal/v2/repository/org/policy_label.go +++ b/internal/v2/repository/org/policy_label.go @@ -1,18 +1,91 @@ package org import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" ) var ( LabelPolicyAddedEventType = orgEventTypePrefix + policy.LabelPolicyAddedEventType LabelPolicyChangedEventType = orgEventTypePrefix + policy.LabelPolicyChangedEventType + LabelPolicyRemovedEventType = orgEventTypePrefix + policy.LabelPolicyRemovedEventType ) type LabelPolicyAddedEvent struct { policy.LabelPolicyAddedEvent } +func NewLabelPolicyAddedEvent( + ctx context.Context, + primaryColor, + secondaryColor string, +) *LabelPolicyAddedEvent { + return &LabelPolicyAddedEvent{ + LabelPolicyAddedEvent: *policy.NewLabelPolicyAddedEvent( + eventstore.NewBaseEventForPush(ctx, LabelPolicyAddedEventType), + primaryColor, + secondaryColor), + } +} + +func LabelPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.LabelPolicyAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &LabelPolicyAddedEvent{LabelPolicyAddedEvent: *e.(*policy.LabelPolicyAddedEvent)}, nil +} + type LabelPolicyChangedEvent struct { policy.LabelPolicyChangedEvent } + +func NewLabelPolicyChangedEvent( + ctx context.Context, + changes []policy.LabelPolicyChanges, +) (*LabelPolicyChangedEvent, error) { + changedEvent, err := policy.NewLabelPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, LabelPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err + } + return &LabelPolicyChangedEvent{LabelPolicyChangedEvent: *changedEvent}, nil +} + +func LabelPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.LabelPolicyChangedEventMapper(event) + if err != nil { + return nil, err + } + + return &LabelPolicyChangedEvent{LabelPolicyChangedEvent: *e.(*policy.LabelPolicyChangedEvent)}, nil +} + +type LabelPolicyRemovedEvent struct { + policy.LabelPolicyRemovedEvent +} + +func NewLabelPolicyRemovedEvent( + ctx context.Context, +) *LabelPolicyRemovedEvent { + return &LabelPolicyRemovedEvent{ + LabelPolicyRemovedEvent: *policy.NewLabelPolicyRemovedEvent( + eventstore.NewBaseEventForPush(ctx, LabelPolicyRemovedEventType), + ), + } +} + +func LabelPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.LabelPolicyRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &LabelPolicyRemovedEvent{LabelPolicyRemovedEvent: *e.(*policy.LabelPolicyRemovedEvent)}, nil +} diff --git a/internal/v2/repository/org/policy_login.go b/internal/v2/repository/org/policy_login.go index 2323c932b..a5f39e0f5 100644 --- a/internal/v2/repository/org/policy_login.go +++ b/internal/v2/repository/org/policy_login.go @@ -1,18 +1,98 @@ package org import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" + "github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/repository/policy" ) var ( LoginPolicyAddedEventType = orgEventTypePrefix + policy.LoginPolicyAddedEventType LoginPolicyChangedEventType = orgEventTypePrefix + policy.LoginPolicyChangedEventType + LoginPolicyRemovedEventType = orgEventTypePrefix + policy.LoginPolicyRemovedEventType ) type LoginPolicyAddedEvent struct { policy.LoginPolicyAddedEvent } +func NewLoginPolicyAddedEvent( + ctx context.Context, + allowUsernamePassword, + allowRegister, + allowExternalIDP, + forceMFA bool, + passwordlessType domain.PasswordlessType, +) *LoginPolicyAddedEvent { + return &LoginPolicyAddedEvent{ + LoginPolicyAddedEvent: *policy.NewLoginPolicyAddedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyAddedEventType), + allowUsernamePassword, + allowRegister, + allowExternalIDP, + forceMFA, + passwordlessType), + } +} + +func LoginPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.LoginPolicyAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicyAddedEvent{LoginPolicyAddedEvent: *e.(*policy.LoginPolicyAddedEvent)}, nil +} + type LoginPolicyChangedEvent struct { policy.LoginPolicyChangedEvent } + +func NewLoginPolicyChangedEvent( + ctx context.Context, + changes []policy.LoginPolicyChanges, +) (*LoginPolicyChangedEvent, error) { + changedEvent, err := policy.NewLoginPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err + } + return &LoginPolicyChangedEvent{LoginPolicyChangedEvent: *changedEvent}, nil +} + +func LoginPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.LoginPolicyChangedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicyChangedEvent{LoginPolicyChangedEvent: *e.(*policy.LoginPolicyChangedEvent)}, nil +} + +type LoginPolicyRemovedEvent struct { + policy.LoginPolicyRemovedEvent +} + +func NewLoginPolicyRemovedEvent( + ctx context.Context, +) *LoginPolicyRemovedEvent { + return &LoginPolicyRemovedEvent{ + LoginPolicyRemovedEvent: *policy.NewLoginPolicyRemovedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyRemovedEventType), + ), + } +} + +func LoginPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.LoginPolicyRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicyRemovedEvent{LoginPolicyRemovedEvent: *e.(*policy.LoginPolicyRemovedEvent)}, nil +} diff --git a/internal/v2/repository/org/policy_login_factors.go b/internal/v2/repository/org/policy_login_factors.go new file mode 100644 index 000000000..7bcf3297e --- /dev/null +++ b/internal/v2/repository/org/policy_login_factors.go @@ -0,0 +1,123 @@ +package org + +import ( + "context" + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/policy" +) + +var ( + LoginPolicySecondFactorAddedEventType = orgEventTypePrefix + policy.LoginPolicySecondFactorAddedEventType + LoginPolicySecondFactorRemovedEventType = orgEventTypePrefix + policy.LoginPolicySecondFactorRemovedEventType + + LoginPolicyMultiFactorAddedEventType = orgEventTypePrefix + policy.LoginPolicyMultiFactorAddedEventType + LoginPolicyMultiFactorRemovedEventType = orgEventTypePrefix + policy.LoginPolicyMultiFactorRemovedEventType +) + +type LoginPolicySecondFactorAddedEvent struct { + policy.SecondFactorAddedEvent +} + +func NewLoginPolicySecondFactorAddedEvent( + ctx context.Context, + mfaType domain.SecondFactorType, +) *LoginPolicySecondFactorAddedEvent { + return &LoginPolicySecondFactorAddedEvent{ + SecondFactorAddedEvent: *policy.NewSecondFactorAddedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicySecondFactorAddedEventType), + mfaType), + } +} + +func SecondFactorAddedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.SecondFactorAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicySecondFactorAddedEvent{ + SecondFactorAddedEvent: *e.(*policy.SecondFactorAddedEvent), + }, nil +} + +type LoginPolicySecondFactorRemovedEvent struct { + policy.SecondFactorRemovedEvent +} + +func NewLoginPolicySecondFactorRemovedEvent( + ctx context.Context, + mfaType domain.SecondFactorType, +) *LoginPolicySecondFactorRemovedEvent { + + return &LoginPolicySecondFactorRemovedEvent{ + SecondFactorRemovedEvent: *policy.NewSecondFactorRemovedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicySecondFactorRemovedEventType), + mfaType), + } +} + +func SecondFactorRemovedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.SecondFactorRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicySecondFactorRemovedEvent{ + SecondFactorRemovedEvent: *e.(*policy.SecondFactorRemovedEvent), + }, nil +} + +type LoginPolicyMultiFactorAddedEvent struct { + policy.MultiFactorAddedEvent +} + +func NewLoginPolicyMultiFactorAddedEvent( + ctx context.Context, + mfaType domain.MultiFactorType, +) *LoginPolicyMultiFactorAddedEvent { + return &LoginPolicyMultiFactorAddedEvent{ + MultiFactorAddedEvent: *policy.NewMultiFactorAddedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyMultiFactorAddedEventType), + mfaType), + } +} + +func MultiFactorAddedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.MultiFactorAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicyMultiFactorAddedEvent{ + MultiFactorAddedEvent: *e.(*policy.MultiFactorAddedEvent), + }, nil +} + +type LoginPolicyMultiFactorRemovedEvent struct { + policy.MultiFactorRemovedEvent +} + +func NewLoginPolicyMultiFactorRemovedEvent( + ctx context.Context, + mfaType domain.MultiFactorType, +) *LoginPolicyMultiFactorRemovedEvent { + + return &LoginPolicyMultiFactorRemovedEvent{ + MultiFactorRemovedEvent: *policy.NewMultiFactorRemovedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyMultiFactorRemovedEventType), + mfaType), + } +} + +func MultiFactorRemovedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.MultiFactorRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &LoginPolicyMultiFactorRemovedEvent{ + MultiFactorRemovedEvent: *e.(*policy.MultiFactorRemovedEvent), + }, nil +} diff --git a/internal/v2/repository/org/policy_login_identity_provider.go b/internal/v2/repository/org/policy_login_identity_provider.go new file mode 100644 index 000000000..ea15506fe --- /dev/null +++ b/internal/v2/repository/org/policy_login_identity_provider.go @@ -0,0 +1,69 @@ +package org + +import ( + "context" + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" + "github.com/caos/zitadel/internal/v2/domain" + "github.com/caos/zitadel/internal/v2/repository/policy" +) + +var ( + LoginPolicyIDPProviderAddedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderAddedType + LoginPolicyIDPProviderRemovedEventType = orgEventTypePrefix + policy.LoginPolicyIDPProviderRemovedType +) + +type IdentityProviderAddedEvent struct { + policy.IdentityProviderAddedEvent +} + +func NewIdentityProviderAddedEvent( + ctx context.Context, + idpConfigID string, + idpProviderType domain.IdentityProviderType, +) *IdentityProviderAddedEvent { + + return &IdentityProviderAddedEvent{ + IdentityProviderAddedEvent: *policy.NewIdentityProviderAddedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyIDPProviderAddedEventType), + idpConfigID, + idpProviderType), + } +} + +func IdentityProviderAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.IdentityProviderAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &IdentityProviderAddedEvent{ + IdentityProviderAddedEvent: *e.(*policy.IdentityProviderAddedEvent), + }, nil +} + +type IdentityProviderRemovedEvent struct { + policy.IdentityProviderRemovedEvent +} + +func NewIdentityProviderRemovedEvent( + ctx context.Context, + idpConfigID string, +) *IdentityProviderRemovedEvent { + return &IdentityProviderRemovedEvent{ + IdentityProviderRemovedEvent: *policy.NewIdentityProviderRemovedEvent( + eventstore.NewBaseEventForPush(ctx, LoginPolicyIDPProviderRemovedEventType), + idpConfigID), + } +} + +func IdentityProviderRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.IdentityProviderRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &IdentityProviderRemovedEvent{ + IdentityProviderRemovedEvent: *e.(*policy.IdentityProviderRemovedEvent), + }, nil +} diff --git a/internal/v2/repository/org/policy_org_iam.go b/internal/v2/repository/org/policy_org_iam.go index 8616dd401..3cd870121 100644 --- a/internal/v2/repository/org/policy_org_iam.go +++ b/internal/v2/repository/org/policy_org_iam.go @@ -13,6 +13,7 @@ var ( //OrgIAMPolicyChangedEventType = orgEventTypePrefix + policy.OrgIAMPolicyChangedEventType OrgIAMPolicyAddedEventType = orgEventTypePrefix + "iam.policy.added" OrgIAMPolicyChangedEventType = orgEventTypePrefix + "iam.policy.changed" + OrgIAMPolicyRemovedEventType = orgEventTypePrefix + "iam.policy.removed" ) type OrgIAMPolicyAddedEvent struct { @@ -46,12 +47,16 @@ type OrgIAMPolicyChangedEvent struct { func NewOrgIAMPolicyChangedEvent( ctx context.Context, -) *OrgIAMPolicyChangedEvent { - return &OrgIAMPolicyChangedEvent{ - OrgIAMPolicyChangedEvent: *policy.NewOrgIAMPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyChangedEventType), - ), + changes []policy.OrgIAMPolicyChanges, +) (*OrgIAMPolicyChangedEvent, error) { + changedEvent, err := policy.NewOrgIAMPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &OrgIAMPolicyChangedEvent{OrgIAMPolicyChangedEvent: *changedEvent}, nil } func OrgIAMPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { @@ -62,3 +67,26 @@ func OrgIAMPolicyChangedEventMapper(event *repository.Event) (eventstore.EventRe return &OrgIAMPolicyChangedEvent{OrgIAMPolicyChangedEvent: *e.(*policy.OrgIAMPolicyChangedEvent)}, nil } + +type OrgIAMPolicyRemovedEvent struct { + policy.OrgIAMPolicyRemovedEvent +} + +func NewOrgIAMPolicyRemovedEvent( + ctx context.Context, +) *OrgIAMPolicyRemovedEvent { + return &OrgIAMPolicyRemovedEvent{ + OrgIAMPolicyRemovedEvent: *policy.NewOrgIAMPolicyRemovedEvent( + eventstore.NewBaseEventForPush(ctx, OrgIAMPolicyRemovedEventType), + ), + } +} + +func OrgIAMPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.OrgIAMPolicyRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &OrgIAMPolicyRemovedEvent{OrgIAMPolicyRemovedEvent: *e.(*policy.OrgIAMPolicyRemovedEvent)}, nil +} diff --git a/internal/v2/repository/org/policy_password_age.go b/internal/v2/repository/org/policy_password_age.go index da92f15c1..4cffb4a19 100644 --- a/internal/v2/repository/org/policy_password_age.go +++ b/internal/v2/repository/org/policy_password_age.go @@ -1,18 +1,91 @@ package org import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" ) var ( PasswordAgePolicyAddedEventType = orgEventTypePrefix + policy.PasswordAgePolicyAddedEventType PasswordAgePolicyChangedEventType = orgEventTypePrefix + policy.PasswordAgePolicyChangedEventType + PasswordAgePolicyRemovedEventType = orgEventTypePrefix + policy.PasswordAgePolicyRemovedEventType ) type PasswordAgePolicyAddedEvent struct { policy.PasswordAgePolicyAddedEvent } +func NewPasswordAgePolicyAddedEvent( + ctx context.Context, + expireWarnDays, + maxAgeDays uint64, +) *PasswordAgePolicyAddedEvent { + return &PasswordAgePolicyAddedEvent{ + PasswordAgePolicyAddedEvent: *policy.NewPasswordAgePolicyAddedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordAgePolicyAddedEventType), + expireWarnDays, + maxAgeDays), + } +} + +func PasswordAgePolicyAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordAgePolicyAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordAgePolicyAddedEvent{PasswordAgePolicyAddedEvent: *e.(*policy.PasswordAgePolicyAddedEvent)}, nil +} + type PasswordAgePolicyChangedEvent struct { policy.PasswordAgePolicyChangedEvent } + +func NewPasswordAgePolicyChangedEvent( + ctx context.Context, + changes []policy.PasswordAgePolicyChanges, +) (*PasswordAgePolicyChangedEvent, error) { + changedEvent, err := policy.NewPasswordAgePolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordAgePolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err + } + return &PasswordAgePolicyChangedEvent{PasswordAgePolicyChangedEvent: *changedEvent}, nil +} + +func PasswordAgePolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordAgePolicyChangedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordAgePolicyChangedEvent{PasswordAgePolicyChangedEvent: *e.(*policy.PasswordAgePolicyChangedEvent)}, nil +} + +type PasswordAgePolicyRemovedEvent struct { + policy.PasswordAgePolicyRemovedEvent +} + +func NewPasswordAgePolicyRemovedEvent( + ctx context.Context, +) *PasswordAgePolicyRemovedEvent { + return &PasswordAgePolicyRemovedEvent{ + PasswordAgePolicyRemovedEvent: *policy.NewPasswordAgePolicyRemovedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordAgePolicyRemovedEventType), + ), + } +} + +func PasswordAgePolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordAgePolicyRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordAgePolicyRemovedEvent{PasswordAgePolicyRemovedEvent: *e.(*policy.PasswordAgePolicyRemovedEvent)}, nil +} diff --git a/internal/v2/repository/org/policy_password_complexity.go b/internal/v2/repository/org/policy_password_complexity.go index 471cf0c0e..ad5f18e9d 100644 --- a/internal/v2/repository/org/policy_password_complexity.go +++ b/internal/v2/repository/org/policy_password_complexity.go @@ -10,6 +10,7 @@ import ( var ( PasswordComplexityPolicyAddedEventType = orgEventTypePrefix + policy.PasswordComplexityPolicyAddedEventType PasswordComplexityPolicyChangedEventType = orgEventTypePrefix + policy.PasswordComplexityPolicyChangedEventType + PasswordComplexityPolicyRemovedEventType = orgEventTypePrefix + policy.PasswordComplexityPolicyRemovedEventType ) type PasswordComplexityPolicyAddedEvent struct { @@ -50,12 +51,16 @@ type PasswordComplexityPolicyChangedEvent struct { func NewPasswordComplexityPolicyChangedEvent( ctx context.Context, -) *PasswordComplexityPolicyChangedEvent { - return &PasswordComplexityPolicyChangedEvent{ - PasswordComplexityPolicyChangedEvent: *policy.NewPasswordComplexityPolicyChangedEvent( - eventstore.NewBaseEventForPush(ctx, PasswordComplexityPolicyAddedEventType), - ), + changes []policy.PasswordComplexityPolicyChanges, +) (*PasswordComplexityPolicyChangedEvent, error) { + changedEvent, err := policy.NewPasswordComplexityPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordComplexityPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err } + return &PasswordComplexityPolicyChangedEvent{PasswordComplexityPolicyChangedEvent: *changedEvent}, nil } func PasswordComplexityPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { @@ -66,3 +71,26 @@ func PasswordComplexityPolicyChangedEventMapper(event *repository.Event) (events return &PasswordComplexityPolicyChangedEvent{PasswordComplexityPolicyChangedEvent: *e.(*policy.PasswordComplexityPolicyChangedEvent)}, nil } + +type PasswordComplexityPolicyRemovedEvent struct { + policy.PasswordComplexityPolicyRemovedEvent +} + +func NewPasswordComplexityPolicyRemovedEvent( + ctx context.Context, +) *PasswordComplexityPolicyRemovedEvent { + return &PasswordComplexityPolicyRemovedEvent{ + PasswordComplexityPolicyRemovedEvent: *policy.NewPasswordComplexityPolicyRemovedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordComplexityPolicyRemovedEventType), + ), + } +} + +func PasswordComplexityPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordComplexityPolicyRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordComplexityPolicyRemovedEvent{PasswordComplexityPolicyRemovedEvent: *e.(*policy.PasswordComplexityPolicyRemovedEvent)}, nil +} diff --git a/internal/v2/repository/org/policy_password_lockout.go b/internal/v2/repository/org/policy_password_lockout.go index 0eb2b18a1..b0b94dec8 100644 --- a/internal/v2/repository/org/policy_password_lockout.go +++ b/internal/v2/repository/org/policy_password_lockout.go @@ -1,18 +1,91 @@ package org import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" + "github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/v2/repository/policy" ) var ( PasswordLockoutPolicyAddedEventType = orgEventTypePrefix + policy.PasswordLockoutPolicyAddedEventType PasswordLockoutPolicyChangedEventType = orgEventTypePrefix + policy.PasswordLockoutPolicyChangedEventType + PasswordLockoutPolicyRemovedEventType = orgEventTypePrefix + policy.PasswordLockoutPolicyRemovedEventType ) type PasswordLockoutPolicyAddedEvent struct { policy.PasswordLockoutPolicyAddedEvent } +func NewPasswordLockoutPolicyAddedEvent( + ctx context.Context, + maxAttempts uint64, + showLockoutFailure bool, +) *PasswordLockoutPolicyAddedEvent { + return &PasswordLockoutPolicyAddedEvent{ + PasswordLockoutPolicyAddedEvent: *policy.NewPasswordLockoutPolicyAddedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordLockoutPolicyAddedEventType), + maxAttempts, + showLockoutFailure), + } +} + +func PasswordLockoutPolicyAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordLockoutPolicyAddedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordLockoutPolicyAddedEvent{PasswordLockoutPolicyAddedEvent: *e.(*policy.PasswordLockoutPolicyAddedEvent)}, nil +} + type PasswordLockoutPolicyChangedEvent struct { policy.PasswordLockoutPolicyChangedEvent } + +func NewPasswordLockoutPolicyChangedEvent( + ctx context.Context, + changes []policy.PasswordLockoutPolicyChanges, +) (*PasswordLockoutPolicyChangedEvent, error) { + changedEvent, err := policy.NewPasswordLockoutPolicyChangedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordLockoutPolicyChangedEventType), + changes, + ) + if err != nil { + return nil, err + } + return &PasswordLockoutPolicyChangedEvent{PasswordLockoutPolicyChangedEvent: *changedEvent}, nil +} + +func PasswordLockoutPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordLockoutPolicyChangedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordLockoutPolicyChangedEvent{PasswordLockoutPolicyChangedEvent: *e.(*policy.PasswordLockoutPolicyChangedEvent)}, nil +} + +type PasswordLockoutPolicyRemovedEvent struct { + policy.PasswordLockoutPolicyRemovedEvent +} + +func NewPasswordLockoutPolicyRemovedEvent( + ctx context.Context, +) *PasswordLockoutPolicyRemovedEvent { + return &PasswordLockoutPolicyRemovedEvent{ + PasswordLockoutPolicyRemovedEvent: *policy.NewPasswordLockoutPolicyRemovedEvent( + eventstore.NewBaseEventForPush(ctx, PasswordLockoutPolicyRemovedEventType), + ), + } +} + +func PasswordLockoutPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + e, err := policy.PasswordLockoutPolicyRemovedEventMapper(event) + if err != nil { + return nil, err + } + + return &PasswordLockoutPolicyRemovedEvent{PasswordLockoutPolicyRemovedEvent: *e.(*policy.PasswordLockoutPolicyRemovedEvent)}, nil +} diff --git a/internal/v2/repository/policy/label.go b/internal/v2/repository/policy/label.go index 77a625952..b34903791 100644 --- a/internal/v2/repository/policy/label.go +++ b/internal/v2/repository/policy/label.go @@ -63,10 +63,32 @@ func (e *LabelPolicyChangedEvent) Data() interface{} { func NewLabelPolicyChangedEvent( base *eventstore.BaseEvent, -) *LabelPolicyChangedEvent { - return &LabelPolicyChangedEvent{ + changes []LabelPolicyChanges, +) (*LabelPolicyChangedEvent, error) { + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "POLICY-Asfd3", "Errors.NoChangesFound") + } + changeEvent := &LabelPolicyChangedEvent{ BaseEvent: *base, } + for _, change := range changes { + change(changeEvent) + } + return changeEvent, nil +} + +type LabelPolicyChanges func(*LabelPolicyChangedEvent) + +func ChangePrimaryColor(primaryColor string) func(*LabelPolicyChangedEvent) { + return func(e *LabelPolicyChangedEvent) { + e.PrimaryColor = &primaryColor + } +} + +func ChangeSecondaryColor(secondaryColor string) func(*LabelPolicyChangedEvent) { + return func(e *LabelPolicyChangedEvent) { + e.SecondaryColor = &secondaryColor + } } func LabelPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { @@ -90,13 +112,13 @@ func (e *LabelPolicyRemovedEvent) Data() interface{} { return nil } -func NewRemovedEvent(base *eventstore.BaseEvent) *LabelPolicyRemovedEvent { +func NewLabelPolicyRemovedEvent(base *eventstore.BaseEvent) *LabelPolicyRemovedEvent { return &LabelPolicyRemovedEvent{ BaseEvent: *base, } } -func RemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { +func LabelPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { return &LabelPolicyRemovedEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), }, nil diff --git a/internal/v2/repository/policy/login.go b/internal/v2/repository/policy/login.go index c7fdc4ff6..3f2fb07bd 100644 --- a/internal/v2/repository/policy/login.go +++ b/internal/v2/repository/policy/login.go @@ -79,10 +79,50 @@ func (e *LoginPolicyChangedEvent) Data() interface{} { func NewLoginPolicyChangedEvent( base *eventstore.BaseEvent, -) *LoginPolicyChangedEvent { - return &LoginPolicyChangedEvent{ + changes []LoginPolicyChanges, +) (*LoginPolicyChangedEvent, error) { + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "POLICY-ADg34", "Errors.NoChangesFound") + } + changeEvent := &LoginPolicyChangedEvent{ BaseEvent: *base, } + for _, change := range changes { + change(changeEvent) + } + return changeEvent, nil +} + +type LoginPolicyChanges func(*LoginPolicyChangedEvent) + +func ChangeAllowUserNamePassword(allowUserNamePassword bool) func(*LoginPolicyChangedEvent) { + return func(e *LoginPolicyChangedEvent) { + e.AllowUserNamePassword = &allowUserNamePassword + } +} + +func ChangeAllowRegister(allowRegister bool) func(*LoginPolicyChangedEvent) { + return func(e *LoginPolicyChangedEvent) { + e.AllowRegister = &allowRegister + } +} + +func ChangeAllowExternalIDP(allowExternalIDP bool) func(*LoginPolicyChangedEvent) { + return func(e *LoginPolicyChangedEvent) { + e.AllowExternalIDP = &allowExternalIDP + } +} + +func ChangeForceMFA(forceMFA bool) func(*LoginPolicyChangedEvent) { + return func(e *LoginPolicyChangedEvent) { + e.ForceMFA = &forceMFA + } +} + +func ChangePasswordlessType(passwordlessType domain.PasswordlessType) func(*LoginPolicyChangedEvent) { + return func(e *LoginPolicyChangedEvent) { + e.PasswordlessType = &passwordlessType + } } func LoginPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/policy/policy_org_iam.go b/internal/v2/repository/policy/policy_org_iam.go index 2b0f2c4d8..c5cde6465 100644 --- a/internal/v2/repository/policy/policy_org_iam.go +++ b/internal/v2/repository/policy/policy_org_iam.go @@ -2,6 +2,7 @@ package policy import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" @@ -59,10 +60,26 @@ func (e *OrgIAMPolicyChangedEvent) Data() interface{} { func NewOrgIAMPolicyChangedEvent( base *eventstore.BaseEvent, -) *OrgIAMPolicyChangedEvent { - return &OrgIAMPolicyChangedEvent{ + changes []OrgIAMPolicyChanges, +) (*OrgIAMPolicyChangedEvent, error) { + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "POLICY-DAf3h", "Errors.NoChangesFound") + } + changeEvent := &OrgIAMPolicyChangedEvent{ BaseEvent: *base, } + for _, change := range changes { + change(changeEvent) + } + return changeEvent, nil +} + +type OrgIAMPolicyChanges func(*OrgIAMPolicyChangedEvent) + +func ChangeUserLoginMustBeDomain(userLoginMustBeDomain bool) func(*OrgIAMPolicyChangedEvent) { + return func(e *OrgIAMPolicyChangedEvent) { + e.UserLoginMustBeDomain = &userLoginMustBeDomain + } } func OrgIAMPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { @@ -77,3 +94,23 @@ func OrgIAMPolicyChangedEventMapper(event *repository.Event) (eventstore.EventRe return e, nil } + +type OrgIAMPolicyRemovedEvent struct { + eventstore.BaseEvent `json:"-"` +} + +func (e *OrgIAMPolicyRemovedEvent) Data() interface{} { + return nil +} + +func NewOrgIAMPolicyRemovedEvent(base *eventstore.BaseEvent) *OrgIAMPolicyRemovedEvent { + return &OrgIAMPolicyRemovedEvent{ + BaseEvent: *base, + } +} + +func OrgIAMPolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { + return &OrgIAMPolicyRemovedEvent{ + BaseEvent: *eventstore.BaseEventFromRepo(event), + }, nil +} diff --git a/internal/v2/repository/policy/policy_password_age.go b/internal/v2/repository/policy/policy_password_age.go index adf1df496..e3ead7b2e 100644 --- a/internal/v2/repository/policy/policy_password_age.go +++ b/internal/v2/repository/policy/policy_password_age.go @@ -63,10 +63,32 @@ func (e *PasswordAgePolicyChangedEvent) Data() interface{} { func NewPasswordAgePolicyChangedEvent( base *eventstore.BaseEvent, -) *PasswordAgePolicyChangedEvent { - return &PasswordAgePolicyChangedEvent{ + changes []PasswordAgePolicyChanges, +) (*PasswordAgePolicyChangedEvent, error) { + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "POLICY-DAgt5", "Errors.NoChangesFound") + } + changeEvent := &PasswordAgePolicyChangedEvent{ BaseEvent: *base, } + for _, change := range changes { + change(changeEvent) + } + return changeEvent, nil +} + +type PasswordAgePolicyChanges func(*PasswordAgePolicyChangedEvent) + +func ChangeExpireWarnDays(expireWarnDay uint64) func(*PasswordAgePolicyChangedEvent) { + return func(e *PasswordAgePolicyChangedEvent) { + e.ExpireWarnDays = &expireWarnDay + } +} + +func ChangeMaxAgeDays(maxAgeDays uint64) func(*PasswordAgePolicyChangedEvent) { + return func(e *PasswordAgePolicyChangedEvent) { + e.MaxAgeDays = &maxAgeDays + } } func PasswordAgePolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { @@ -90,23 +112,14 @@ func (e *PasswordAgePolicyRemovedEvent) Data() interface{} { return nil } -func NewPasswordAgePolicyRemovedEvent( - base *eventstore.BaseEvent, -) *PasswordAgePolicyRemovedEvent { +func NewPasswordAgePolicyRemovedEvent(base *eventstore.BaseEvent) *PasswordAgePolicyRemovedEvent { return &PasswordAgePolicyRemovedEvent{ BaseEvent: *base, } } func PasswordAgePolicyRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) { - e := &PasswordAgePolicyRemovedEvent{ + return &PasswordAgePolicyRemovedEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), - } - - err := json.Unmarshal(event.Data, e) - if err != nil { - return nil, errors.ThrowInternal(err, "POLIC-02878", "unable to unmarshal policy") - } - - return e, nil + }, nil } diff --git a/internal/v2/repository/policy/policy_password_complexity.go b/internal/v2/repository/policy/policy_password_complexity.go index 0abf8a3d9..aafe10022 100644 --- a/internal/v2/repository/policy/policy_password_complexity.go +++ b/internal/v2/repository/policy/policy_password_complexity.go @@ -2,6 +2,7 @@ package policy import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" @@ -18,7 +19,7 @@ type PasswordComplexityPolicyAddedEvent struct { MinLength uint64 `json:"minLength,omitempty"` HasLowercase bool `json:"hasLowercase,omitempty"` - HasUpperCase bool `json:"hasUppercase,omitempty"` + HasUppercase bool `json:"hasUppercase,omitempty"` HasNumber bool `json:"hasNumber,omitempty"` HasSymbol bool `json:"hasSymbol,omitempty"` } @@ -39,9 +40,9 @@ func NewPasswordComplexityPolicyAddedEvent( BaseEvent: *base, MinLength: minLength, HasLowercase: hasLowerCase, + HasUppercase: hasUpperCase, HasNumber: hasNumber, HasSymbol: hasSymbol, - HasUpperCase: hasUpperCase, } } @@ -63,7 +64,7 @@ type PasswordComplexityPolicyChangedEvent struct { MinLength *uint64 `json:"minLength,omitempty"` HasLowercase *bool `json:"hasLowercase,omitempty"` - HasUpperCase *bool `json:"hasUppercase,omitempty"` + HasUppercase *bool `json:"hasUppercase,omitempty"` HasNumber *bool `json:"hasNumber,omitempty"` HasSymbol *bool `json:"hasSymbol,omitempty"` } @@ -74,10 +75,50 @@ func (e *PasswordComplexityPolicyChangedEvent) Data() interface{} { func NewPasswordComplexityPolicyChangedEvent( base *eventstore.BaseEvent, -) *PasswordComplexityPolicyChangedEvent { - return &PasswordComplexityPolicyChangedEvent{ + changes []PasswordComplexityPolicyChanges, +) (*PasswordComplexityPolicyChangedEvent, error) { + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "POLICY-Rdhu3", "Errors.NoChangesFound") + } + changeEvent := &PasswordComplexityPolicyChangedEvent{ BaseEvent: *base, } + for _, change := range changes { + change(changeEvent) + } + return changeEvent, nil +} + +type PasswordComplexityPolicyChanges func(*PasswordComplexityPolicyChangedEvent) + +func ChangeMinLength(minLength uint64) func(*PasswordComplexityPolicyChangedEvent) { + return func(e *PasswordComplexityPolicyChangedEvent) { + e.MinLength = &minLength + } +} + +func ChangeHasLowercase(hasLowercase bool) func(*PasswordComplexityPolicyChangedEvent) { + return func(e *PasswordComplexityPolicyChangedEvent) { + e.HasLowercase = &hasLowercase + } +} + +func ChangeHasUppercase(hasUppercase bool) func(*PasswordComplexityPolicyChangedEvent) { + return func(e *PasswordComplexityPolicyChangedEvent) { + e.HasUppercase = &hasUppercase + } +} + +func ChangeHasNumber(hasNumber bool) func(*PasswordComplexityPolicyChangedEvent) { + return func(e *PasswordComplexityPolicyChangedEvent) { + e.HasNumber = &hasNumber + } +} + +func ChangeHasSymbol(hasSymbol bool) func(*PasswordComplexityPolicyChangedEvent) { + return func(e *PasswordComplexityPolicyChangedEvent) { + e.HasSymbol = &hasSymbol + } } func PasswordComplexityPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { diff --git a/internal/v2/repository/policy/policy_password_lockout.go b/internal/v2/repository/policy/policy_password_lockout.go index 086dac445..820ca44d5 100644 --- a/internal/v2/repository/policy/policy_password_lockout.go +++ b/internal/v2/repository/policy/policy_password_lockout.go @@ -2,6 +2,7 @@ package policy import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2/repository" @@ -63,10 +64,32 @@ func (e *PasswordLockoutPolicyChangedEvent) Data() interface{} { func NewPasswordLockoutPolicyChangedEvent( base *eventstore.BaseEvent, -) *PasswordLockoutPolicyChangedEvent { - return &PasswordLockoutPolicyChangedEvent{ + changes []PasswordLockoutPolicyChanges, +) (*PasswordLockoutPolicyChangedEvent, error) { + if len(changes) == 0 { + return nil, errors.ThrowPreconditionFailed(nil, "POLICY-sdgh6", "Errors.NoChangesFound") + } + changeEvent := &PasswordLockoutPolicyChangedEvent{ BaseEvent: *base, } + for _, change := range changes { + change(changeEvent) + } + return changeEvent, nil +} + +type PasswordLockoutPolicyChanges func(*PasswordLockoutPolicyChangedEvent) + +func ChangeMaxAttempts(maxAttempts uint64) func(*PasswordLockoutPolicyChangedEvent) { + return func(e *PasswordLockoutPolicyChangedEvent) { + e.MaxAttempts = &maxAttempts + } +} + +func ChangeShowLockOutFailures(showLockOutFailures bool) func(*PasswordLockoutPolicyChangedEvent) { + return func(e *PasswordLockoutPolicyChangedEvent) { + e.ShowLockOutFailures = &showLockOutFailures + } } func PasswordLockoutPolicyChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { @@ -90,10 +113,7 @@ func (e *PasswordLockoutPolicyRemovedEvent) Data() interface{} { return nil } -func NewPasswordLockoutPolicyRemovedEvent( - base *eventstore.BaseEvent, -) *PasswordLockoutPolicyRemovedEvent { - +func NewPasswordLockoutPolicyRemovedEvent(base *eventstore.BaseEvent) *PasswordLockoutPolicyRemovedEvent { return &PasswordLockoutPolicyRemovedEvent{ BaseEvent: *base, } diff --git a/pkg/grpc/management/proto/management.proto b/pkg/grpc/management/proto/management.proto index 2ee3cdef3..120921c66 100644 --- a/pkg/grpc/management/proto/management.proto +++ b/pkg/grpc/management/proto/management.proto @@ -518,7 +518,7 @@ service ManagementService { }; } - rpc DeactivateMyOrg(google.protobuf.Empty) returns (Org) { + rpc DeactivateMyOrg(google.protobuf.Empty) returns (google.protobuf.Empty) { option (google.api.http) = { put: "/orgs/me/_deactivate" body: "*" @@ -529,7 +529,7 @@ service ManagementService { }; } - rpc ReactivateMyOrg(google.protobuf.Empty) returns (Org) { + rpc ReactivateMyOrg(google.protobuf.Empty) returns (google.protobuf.Empty) { option (google.api.http) = { put: "/orgs/me/_reactivate" body: "*"