mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-14 08:07:32 +00:00
feat: allow domain discovery for unknown usernames (#4484)
* fix: wait for projection initialization to be done * feat: allow domain discovery for unknown usernames * fix linting * Update console/src/assets/i18n/de.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/en.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/it.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/fr.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * fix zh i18n text * fix projection table name Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com>
This commit is contained in:
@@ -17,6 +17,7 @@ func updateLoginPolicyToDomain(p *admin_pb.UpdateLoginPolicyRequest) *domain.Log
|
||||
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
|
@@ -26,7 +26,7 @@ func (s *Server) GetMyOrg(ctx context.Context, req *mgmt_pb.GetMyOrgRequest) (*m
|
||||
}
|
||||
|
||||
func (s *Server) GetOrgByDomainGlobal(ctx context.Context, req *mgmt_pb.GetOrgByDomainGlobalRequest) (*mgmt_pb.GetOrgByDomainGlobalResponse, error) {
|
||||
org, err := s.query.OrgByDomainGlobal(ctx, req.Domain)
|
||||
org, err := s.query.OrgByPrimaryDomain(ctx, req.Domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ func AddLoginPolicyToDomain(p *mgmt_pb.AddCustomLoginPolicyRequest) *domain.Logi
|
||||
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
@@ -49,6 +50,7 @@ func updateLoginPolicyToDomain(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *domai
|
||||
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
|
@@ -21,6 +21,7 @@ func ModelLoginPolicyToPb(policy *query.LoginPolicy) *policy_pb.LoginPolicy {
|
||||
PasswordlessType: ModelPasswordlessTypeToPb(policy.PasswordlessType),
|
||||
HidePasswordReset: policy.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: policy.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: policy.AllowDomainDiscovery,
|
||||
DefaultRedirectUri: policy.DefaultRedirectURI,
|
||||
PasswordCheckLifetime: durationpb.New(policy.PasswordCheckLifetime),
|
||||
ExternalLoginCheckLifetime: durationpb.New(policy.ExternalLoginCheckLifetime),
|
||||
|
@@ -91,7 +91,7 @@ func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string
|
||||
scope := scopes[i]
|
||||
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
|
||||
var orgID string
|
||||
org, err := o.query.OrgByDomainGlobal(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
org, err := o.query.OrgByPrimaryDomain(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
if err == nil {
|
||||
orgID = org.ID
|
||||
}
|
||||
|
@@ -59,11 +59,15 @@ func (l *Login) handleExternalRegister(w http.ResponseWriter, r *http.Request) {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
l.handleExternalRegisterByConfigID(w, r, authReq, data.IDPConfigID)
|
||||
}
|
||||
|
||||
func (l *Login) handleExternalRegisterByConfigID(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, configID string) {
|
||||
if authReq == nil {
|
||||
l.defaultRedirect(w, r)
|
||||
return
|
||||
}
|
||||
idpConfig, err := l.getIDPConfigByID(r, data.IDPConfigID)
|
||||
idpConfig, err := l.getIDPConfigByID(r, configID)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
|
@@ -33,12 +33,29 @@ func (l *Login) renderRegisterOption(w http.ResponseWriter, r *http.Request, aut
|
||||
if err != nil {
|
||||
errID, errMessage = l.getErrorMessage(r, err)
|
||||
}
|
||||
allowed := registrationAllowed(authReq)
|
||||
externalAllowed := externalRegistrationAllowed(authReq)
|
||||
if err == nil {
|
||||
// if only external allowed with a single idp then use that
|
||||
if !allowed && externalAllowed && len(authReq.AllowedExternalIDPs) == 1 {
|
||||
l.handleExternalRegisterByConfigID(w, r, authReq, authReq.AllowedExternalIDPs[0].IDPConfigID)
|
||||
return
|
||||
}
|
||||
// if only direct registration is allowed, show the form
|
||||
if allowed && !externalAllowed {
|
||||
l.renderRegister(w, r, authReq, nil, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
data := registerOptionData{
|
||||
baseData: l.getBaseData(r, authReq, "RegisterOption", errID, errMessage),
|
||||
}
|
||||
funcs := map[string]interface{}{
|
||||
"hasRegistration": func() bool {
|
||||
return allowed
|
||||
},
|
||||
"hasExternalLogin": func() bool {
|
||||
return authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
|
||||
return externalAllowed
|
||||
},
|
||||
}
|
||||
translator := l.getTranslator(r.Context(), authReq)
|
||||
@@ -58,3 +75,11 @@ func (l *Login) handleRegisterOptionCheck(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
l.handleRegisterOption(w, r)
|
||||
}
|
||||
|
||||
func registrationAllowed(authReq *domain.AuthRequest) bool {
|
||||
return authReq != nil && authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowRegister
|
||||
}
|
||||
|
||||
func externalRegistrationAllowed(authReq *domain.AuthRequest) bool {
|
||||
return authReq != nil && authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="lgn-register-options">
|
||||
{{if .LoginPolicy.AllowUsernamePassword }}
|
||||
{{if hasRegistration }}
|
||||
<button class="lgn-raised-button lgn-primary" name="usernamepassword" value="true"
|
||||
formnovalidate>{{t "RegisterOption.RegisterUsernamePasswordButtonText"}}</button>
|
||||
{{end}}
|
||||
@@ -42,4 +42,4 @@
|
||||
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
|
||||
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
|
||||
|
||||
{{template "main-bottom" .}}
|
||||
{{template "main-bottom" .}}
|
||||
|
@@ -93,7 +93,7 @@ type userCommandProvider interface {
|
||||
|
||||
type orgViewProvider interface {
|
||||
OrgByID(context.Context, bool, string) (*query.Org, error)
|
||||
OrgByDomainGlobal(context.Context, string) (*query.Org, error)
|
||||
OrgByPrimaryDomain(context.Context, string) (*query.Org, error)
|
||||
}
|
||||
|
||||
type userGrantProvider interface {
|
||||
@@ -651,23 +651,57 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
||||
}
|
||||
}
|
||||
}
|
||||
if request.LoginPolicy != nil && request.LoginPolicy.IgnoreUnknownUsernames {
|
||||
if errors.IsNotFound(err) || (user != nil && user.State == int32(domain.UserStateInactive)) {
|
||||
if request.LabelPolicy != nil && request.LabelPolicy.HideLoginNameSuffix {
|
||||
preferredLoginName = loginName
|
||||
}
|
||||
request.SetUserInfo(unknownUserID, preferredLoginName, preferredLoginName, preferredLoginName, "", request.RequestedOrgID)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// return any error apart from not found ones directly
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if user.State == int32(domain.UserStateInactive) {
|
||||
// if there's an active user, let's use it
|
||||
if user != nil && user.State == int32(domain.UserStateActive) {
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||
return nil
|
||||
}
|
||||
// the user was either not found or not active
|
||||
// so check if the loginname suffix matches a verified org domain
|
||||
if repo.checkDomainDiscovery(ctx, request, loginName) {
|
||||
return nil
|
||||
}
|
||||
// let's just check for if unknown usernames are ignored
|
||||
if request.LoginPolicy != nil && request.LoginPolicy.IgnoreUnknownUsernames {
|
||||
if request.LabelPolicy != nil && request.LabelPolicy.HideLoginNameSuffix {
|
||||
preferredLoginName = loginName
|
||||
}
|
||||
request.SetUserInfo(unknownUserID, preferredLoginName, preferredLoginName, preferredLoginName, "", request.RequestedOrgID)
|
||||
return nil
|
||||
}
|
||||
// there was no policy that allowed unknown loginnames in any case
|
||||
// let's once again check if the user was just inactive
|
||||
if user != nil && user.State == int32(domain.UserStateInactive) {
|
||||
return errors.ThrowPreconditionFailed(nil, "AUTH-2n8fs", "Errors.User.Inactive")
|
||||
}
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||
return nil
|
||||
// user was not found
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkDomainDiscovery(ctx context.Context, request *domain.AuthRequest, loginName string) bool {
|
||||
// check if there's a suffix in the loginname
|
||||
split := strings.Split(loginName, "@")
|
||||
if len(split) < 2 {
|
||||
return false
|
||||
}
|
||||
// check if the suffix matches a verified domain
|
||||
org, err := repo.Query.OrgByVerifiedDomain(ctx, split[len(split)-1])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// and if the login policy allows domain discovery
|
||||
policy, err := repo.Query.LoginPolicyByID(ctx, true, org.ID)
|
||||
if err != nil || !policy.AllowDomainDiscovery {
|
||||
return false
|
||||
}
|
||||
// discovery was allowed, so set the org as requested org
|
||||
request.SetOrgInformation(org.ID, org.Name, org.Domain, false)
|
||||
request.Prompt = append(request.Prompt, domain.PromptCreate)
|
||||
return true
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginPolicyWithResourceOwner(ctx context.Context, request *domain.AuthRequest, user *user_view_model.UserView) error {
|
||||
@@ -1075,9 +1109,7 @@ func setOrgID(ctx context.Context, orgViewProvider orgViewProvider, request *dom
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = org.Domain
|
||||
request.SetOrgInformation(org.ID, org.Name, org.Domain, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1086,14 +1118,11 @@ func setOrgID(ctx context.Context, orgViewProvider orgViewProvider, request *dom
|
||||
return nil
|
||||
}
|
||||
|
||||
org, err := orgViewProvider.OrgByDomainGlobal(ctx, primaryDomain)
|
||||
org, err := orgViewProvider.OrgByPrimaryDomain(ctx, primaryDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = primaryDomain
|
||||
request.RequestedOrgDomain = true
|
||||
request.SetOrgInformation(org.ID, org.Name, primaryDomain, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -174,7 +174,7 @@ func (m *mockViewOrg) OrgByID(context.Context, bool, string) (*query.Org, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockViewOrg) OrgByDomainGlobal(context.Context, string) (*query.Org, error) {
|
||||
func (m *mockViewOrg) OrgByPrimaryDomain(context.Context, string) (*query.Org, error) {
|
||||
return &query.Org{
|
||||
State: m.State,
|
||||
}, nil
|
||||
@@ -186,7 +186,7 @@ func (m *mockViewErrOrg) OrgByID(context.Context, bool, string) (*query.Org, err
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
func (m *mockViewErrOrg) OrgByDomainGlobal(context.Context, string) (*query.Org, error) {
|
||||
func (m *mockViewErrOrg) OrgByPrimaryDomain(context.Context, string) (*query.Org, error) {
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
|
@@ -71,6 +71,7 @@ type InstanceSetup struct {
|
||||
ForceMFA bool
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsername bool
|
||||
AllowDomainDiscovery bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
@@ -217,6 +218,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
setup.LoginPolicy.ForceMFA,
|
||||
setup.LoginPolicy.HidePasswordReset,
|
||||
setup.LoginPolicy.IgnoreUnknownUsername,
|
||||
setup.LoginPolicy.AllowDomainDiscovery,
|
||||
setup.LoginPolicy.PasswordlessType,
|
||||
setup.LoginPolicy.DefaultRedirectURI,
|
||||
setup.LoginPolicy.PasswordCheckLifetime,
|
||||
|
@@ -32,6 +32,7 @@ func writeModelToLoginPolicy(wm *LoginPolicyWriteModel) *domain.LoginPolicy {
|
||||
AllowExternalIDP: wm.AllowExternalIDP,
|
||||
HidePasswordReset: wm.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: wm.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: wm.AllowDomainDiscovery,
|
||||
ForceMFA: wm.ForceMFA,
|
||||
PasswordlessType: wm.PasswordlessType,
|
||||
DefaultRedirectURI: wm.DefaultRedirectURI,
|
||||
|
@@ -15,37 +15,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddDefaultLoginPolicy(
|
||||
ctx context.Context,
|
||||
allowUsernamePassword, allowRegister, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime, externalLoginCheckLifetime, mfaInitSkipLifetime, secondFactorCheckLifetime, multiFactorCheckLifetime time.Duration,
|
||||
) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareAddDefaultLoginPolicy(instanceAgg, allowUsernamePassword,
|
||||
allowRegister,
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
externalLoginCheckLifetime,
|
||||
mfaInitSkipLifetime,
|
||||
secondFactorCheckLifetime,
|
||||
multiFactorCheckLifetime))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeDefaultLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
existingPolicy := NewInstanceLoginPolicyWriteModel(ctx)
|
||||
instanceAgg := InstanceAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
@@ -83,6 +52,7 @@ func (c *Commands) changeDefaultLoginPolicy(ctx context.Context, instanceAgg *ev
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
@@ -293,6 +263,7 @@ func prepareAddDefaultLoginPolicy(
|
||||
forceMFA bool,
|
||||
hidePasswordReset bool,
|
||||
ignoreUnknownUsernames bool,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime time.Duration,
|
||||
@@ -323,6 +294,7 @@ func prepareAddDefaultLoginPolicy(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@@ -66,7 +66,8 @@ func (wm *InstanceLoginPolicyWriteModel) NewChangedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -98,6 +99,9 @@ func (wm *InstanceLoginPolicyWriteModel) NewChangedEvent(
|
||||
if wm.IgnoreUnknownUsernames != ignoreUnknownUsernames {
|
||||
changes = append(changes, policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames))
|
||||
}
|
||||
if wm.AllowDomainDiscovery != allowDomainDiscovery {
|
||||
changes = append(changes, policy.ChangeAllowDomainDiscovery(allowDomainDiscovery))
|
||||
}
|
||||
if wm.DefaultRedirectURI != defaultRedirectURI {
|
||||
changes = append(changes, policy.ChangeDefaultRedirectURI(defaultRedirectURI))
|
||||
}
|
||||
|
@@ -18,161 +18,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddDefaultLoginPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
allowUsernamePassword bool
|
||||
allowRegister bool
|
||||
allowExternalIDP bool
|
||||
forceMFA bool
|
||||
hidePasswordReset bool
|
||||
ignoreUnknownUsernames bool
|
||||
passwordlessType domain.PasswordlessType
|
||||
defaultRedirectURI string
|
||||
passwordCheckLifetime time.Duration
|
||||
externalLoginCheckLifetime time.Duration
|
||||
mfaInitSkipLifetime time.Duration
|
||||
secondFactorCheckLifetime time.Duration
|
||||
multiFactorCheckLifetime time.Duration
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "loginpolicy already existing, already exists error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
allowRegister: true,
|
||||
allowUsernamePassword: true,
|
||||
passwordlessType: domain.PasswordlessTypeAllowed,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add policy,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"INSTANCE",
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
allowRegister: true,
|
||||
allowUsernamePassword: true,
|
||||
allowExternalIDP: true,
|
||||
forceMFA: true,
|
||||
hidePasswordReset: true,
|
||||
ignoreUnknownUsernames: true,
|
||||
passwordlessType: domain.PasswordlessTypeAllowed,
|
||||
defaultRedirectURI: "https://example.com/redirect",
|
||||
passwordCheckLifetime: time.Hour * 1,
|
||||
externalLoginCheckLifetime: time.Hour * 2,
|
||||
mfaInitSkipLifetime: time.Hour * 3,
|
||||
secondFactorCheckLifetime: time.Hour * 4,
|
||||
multiFactorCheckLifetime: time.Hour * 5,
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddDefaultLoginPolicy(
|
||||
tt.args.ctx,
|
||||
tt.args.allowUsernamePassword,
|
||||
tt.args.allowRegister,
|
||||
tt.args.allowExternalIDP,
|
||||
tt.args.forceMFA,
|
||||
tt.args.hidePasswordReset,
|
||||
tt.args.ignoreUnknownUsernames,
|
||||
tt.args.passwordlessType,
|
||||
tt.args.defaultRedirectURI,
|
||||
tt.args.passwordCheckLifetime,
|
||||
tt.args.externalLoginCheckLifetime,
|
||||
tt.args.mfaInitSkipLifetime,
|
||||
tt.args.secondFactorCheckLifetime,
|
||||
tt.args.multiFactorCheckLifetime,
|
||||
)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
@@ -225,6 +70,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -246,6 +92,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -275,6 +122,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -296,6 +144,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*10,
|
||||
@@ -317,6 +166,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@@ -339,6 +189,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@@ -435,6 +286,7 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -473,6 +325,7 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -531,6 +384,7 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -671,6 +525,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -709,6 +564,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -760,6 +616,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -816,6 +673,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -880,6 +738,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1434,7 +1293,7 @@ func TestCommandSide_RemoveMultiFactorDefaultLoginPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allowUsernamePassword, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames bool,
|
||||
func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allowUsernamePassword, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames, allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
redirectURI string,
|
||||
passwordLifetime, externalLoginLifetime, mfaInitSkipLifetime, secondFactorLifetime, multiFactorLifetime time.Duration) *instance.LoginPolicyChangedEvent {
|
||||
@@ -1447,6 +1306,7 @@ func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allow
|
||||
policy.ChangeAllowUserNamePassword(allowUsernamePassword),
|
||||
policy.ChangeHidePasswordReset(hidePasswordReset),
|
||||
policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames),
|
||||
policy.ChangeAllowDomainDiscovery(allowDomainDiscovery),
|
||||
policy.ChangePasswordlessType(passwordlessType),
|
||||
policy.ChangeDefaultRedirectURI(redirectURI),
|
||||
policy.ChangePasswordCheckLifetime(passwordLifetime),
|
||||
|
@@ -39,6 +39,7 @@ func (c *Commands) AddLoginPolicy(ctx context.Context, resourceOwner string, pol
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
@@ -127,6 +128,7 @@ func (c *Commands) ChangeLoginPolicy(ctx context.Context, resourceOwner string,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
|
@@ -68,7 +68,8 @@ func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -97,6 +98,9 @@ func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
if wm.IgnoreUnknownUsernames != ignoreUnknownUsernames {
|
||||
changes = append(changes, policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames))
|
||||
}
|
||||
if wm.AllowDomainDiscovery != allowDomainDiscovery {
|
||||
changes = append(changes, policy.ChangeAllowDomainDiscovery(allowDomainDiscovery))
|
||||
}
|
||||
if wm.PasswordCheckLifetime != passwordCheckLifetime {
|
||||
changes = append(changes, policy.ChangePasswordCheckLifetime(passwordCheckLifetime))
|
||||
}
|
||||
|
@@ -79,6 +79,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -100,6 +101,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -130,6 +132,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -153,6 +156,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -174,6 +178,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -202,6 +207,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -233,6 +239,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -268,6 +275,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -291,6 +299,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -320,6 +329,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -368,6 +378,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -398,6 +409,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -425,6 +437,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -489,6 +502,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
},
|
||||
@@ -514,6 +528,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
},
|
||||
@@ -537,6 +552,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -559,6 +575,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -587,6 +604,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -608,6 +626,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
&duration10,
|
||||
@@ -630,6 +649,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: false,
|
||||
ForceMFA: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@@ -651,6 +671,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@@ -744,6 +765,7 @@ func TestCommandSide_RemoveLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -884,6 +906,7 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -925,6 +948,7 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -986,6 +1010,7 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1150,6 +1175,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1191,6 +1217,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1244,6 +1271,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1304,6 +1332,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1372,6 +1401,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1990,7 +2020,7 @@ func TestCommandSide_RemoveMultiFactorLoginPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassword, register, externalIDP, mfa, passwordReset, ignoreUnknownUsernames bool,
|
||||
func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassword, register, externalIDP, mfa, passwordReset, ignoreUnknownUsernames, allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
redirectURI string,
|
||||
passwordLifetime, externalLoginLifetime, mfaInitSkipLifetime, secondFactorLifetime, multiFactorLifetime *time.Duration) *org.LoginPolicyChangedEvent {
|
||||
@@ -2001,6 +2031,7 @@ func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassw
|
||||
policy.ChangeForceMFA(mfa),
|
||||
policy.ChangeHidePasswordReset(passwordReset),
|
||||
policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames),
|
||||
policy.ChangeAllowDomainDiscovery(allowDomainDiscovery),
|
||||
policy.ChangePasswordlessType(passwordlessType),
|
||||
policy.ChangeDefaultRedirectURI(redirectURI),
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ type LoginPolicyWriteModel struct {
|
||||
ForceMFA bool
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
@@ -38,6 +39,7 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
wm.PasswordlessType = e.PasswordlessType
|
||||
wm.HidePasswordReset = e.HidePasswordReset
|
||||
wm.IgnoreUnknownUsernames = e.IgnoreUnknownUsernames
|
||||
wm.AllowDomainDiscovery = e.AllowDomainDiscovery
|
||||
wm.DefaultRedirectURI = e.DefaultRedirectURI
|
||||
wm.PasswordCheckLifetime = e.PasswordCheckLifetime
|
||||
wm.ExternalLoginCheckLifetime = e.ExternalLoginCheckLifetime
|
||||
@@ -64,6 +66,9 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
if e.IgnoreUnknownUsernames != nil {
|
||||
wm.IgnoreUnknownUsernames = *e.IgnoreUnknownUsernames
|
||||
}
|
||||
if e.AllowDomainDiscovery != nil {
|
||||
wm.AllowDomainDiscovery = *e.AllowDomainDiscovery
|
||||
}
|
||||
if e.PasswordlessType != nil {
|
||||
wm.PasswordlessType = *e.PasswordlessType
|
||||
}
|
||||
|
@@ -1157,6 +1157,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1194,6 +1195,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1232,6 +1234,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1286,6 +1289,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1374,6 +1378,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1469,6 +1474,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
|
@@ -1679,6 +1679,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1745,6 +1746,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1811,6 +1813,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1894,6 +1897,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2035,6 +2039,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2144,6 +2149,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2247,6 +2253,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2372,6 +2379,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
|
@@ -140,6 +140,13 @@ func (a *AuthRequest) SetUserInfo(userID, userName, loginName, displayName, avat
|
||||
a.UserOrgID = userOrgID
|
||||
}
|
||||
|
||||
func (a *AuthRequest) SetOrgInformation(id, name, primaryDomain string, requestedByDomain bool) {
|
||||
a.RequestedOrgID = id
|
||||
a.RequestedOrgName = name
|
||||
a.RequestedPrimaryDomain = primaryDomain
|
||||
a.RequestedOrgDomain = requestedByDomain
|
||||
}
|
||||
|
||||
func (a *AuthRequest) MFALevel() MFALevel {
|
||||
return -1
|
||||
//PLANNED: check a.PossibleLOAs (and Prompt Login?)
|
||||
|
@@ -21,6 +21,7 @@ type LoginPolicy struct {
|
||||
PasswordlessType PasswordlessType
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
|
@@ -30,6 +30,7 @@ type LoginPolicy struct {
|
||||
IsDefault bool
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
@@ -113,6 +114,10 @@ var (
|
||||
name: projection.IgnoreUnknownUsernames,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnAllowDomainDiscovery = Column{
|
||||
name: projection.AllowDomainDiscovery,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnDefaultRedirectURI = Column{
|
||||
name: projection.DefaultRedirectURI,
|
||||
table: loginPolicyTable,
|
||||
@@ -305,6 +310,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
|
||||
LoginPolicyColumnIsDefault.identifier(),
|
||||
LoginPolicyColumnHidePasswordReset.identifier(),
|
||||
LoginPolicyColumnIgnoreUnknownUsernames.identifier(),
|
||||
LoginPolicyColumnAllowDomainDiscovery.identifier(),
|
||||
LoginPolicyColumnDefaultRedirectURI.identifier(),
|
||||
LoginPolicyColumnPasswordCheckLifetime.identifier(),
|
||||
LoginPolicyColumnExternalLoginCheckLifetime.identifier(),
|
||||
@@ -343,6 +349,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
|
||||
&p.IsDefault,
|
||||
&p.HidePasswordReset,
|
||||
&p.IgnoreUnknownUsernames,
|
||||
&p.AllowDomainDiscovery,
|
||||
&defaultRedirectURI,
|
||||
&p.PasswordCheckLifetime,
|
||||
&p.ExternalLoginCheckLifetime,
|
||||
|
@@ -30,32 +30,33 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.aggregate_id,`+
|
||||
` projections.login_policies.creation_date,`+
|
||||
` projections.login_policies.change_date,`+
|
||||
` projections.login_policies.sequence,`+
|
||||
` projections.login_policies.allow_register,`+
|
||||
` projections.login_policies.allow_username_password,`+
|
||||
` projections.login_policies.allow_external_idps,`+
|
||||
` projections.login_policies.force_mfa,`+
|
||||
` projections.login_policies.second_factors,`+
|
||||
` projections.login_policies.multi_factors,`+
|
||||
` projections.login_policies.passwordless_type,`+
|
||||
` projections.login_policies.is_default,`+
|
||||
` projections.login_policies.hide_password_reset,`+
|
||||
` projections.login_policies.ignore_unknown_usernames,`+
|
||||
` projections.login_policies.default_redirect_uri,`+
|
||||
` projections.login_policies.password_check_lifetime,`+
|
||||
` projections.login_policies.external_login_check_lifetime,`+
|
||||
` projections.login_policies.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies.second_factor_check_lifetime,`+
|
||||
` projections.login_policies.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies`+
|
||||
` FROM projections.login_policies2`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
nil,
|
||||
@@ -75,32 +76,33 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.aggregate_id,`+
|
||||
` projections.login_policies.creation_date,`+
|
||||
` projections.login_policies.change_date,`+
|
||||
` projections.login_policies.sequence,`+
|
||||
` projections.login_policies.allow_register,`+
|
||||
` projections.login_policies.allow_username_password,`+
|
||||
` projections.login_policies.allow_external_idps,`+
|
||||
` projections.login_policies.force_mfa,`+
|
||||
` projections.login_policies.second_factors,`+
|
||||
` projections.login_policies.multi_factors,`+
|
||||
` projections.login_policies.passwordless_type,`+
|
||||
` projections.login_policies.is_default,`+
|
||||
` projections.login_policies.hide_password_reset,`+
|
||||
` projections.login_policies.ignore_unknown_usernames,`+
|
||||
` projections.login_policies.default_redirect_uri,`+
|
||||
` projections.login_policies.password_check_lifetime,`+
|
||||
` projections.login_policies.external_login_check_lifetime,`+
|
||||
` projections.login_policies.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies.second_factor_check_lifetime,`+
|
||||
` projections.login_policies.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies`+
|
||||
` FROM projections.login_policies2`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
[]string{
|
||||
@@ -118,6 +120,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
"is_default",
|
||||
"hide_password_reset",
|
||||
"ignore_unknown_usernames",
|
||||
"allow_domain_discovery",
|
||||
"default_redirect_uri",
|
||||
"password_check_lifetime",
|
||||
"external_login_check_lifetime",
|
||||
@@ -143,6 +146,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Hour * 2,
|
||||
time.Hour * 2,
|
||||
@@ -170,6 +174,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
IsDefault: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 2,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
@@ -190,32 +195,33 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.aggregate_id,`+
|
||||
` projections.login_policies.creation_date,`+
|
||||
` projections.login_policies.change_date,`+
|
||||
` projections.login_policies.sequence,`+
|
||||
` projections.login_policies.allow_register,`+
|
||||
` projections.login_policies.allow_username_password,`+
|
||||
` projections.login_policies.allow_external_idps,`+
|
||||
` projections.login_policies.force_mfa,`+
|
||||
` projections.login_policies.second_factors,`+
|
||||
` projections.login_policies.multi_factors,`+
|
||||
` projections.login_policies.passwordless_type,`+
|
||||
` projections.login_policies.is_default,`+
|
||||
` projections.login_policies.hide_password_reset,`+
|
||||
` projections.login_policies.ignore_unknown_usernames,`+
|
||||
` projections.login_policies.default_redirect_uri,`+
|
||||
` projections.login_policies.password_check_lifetime,`+
|
||||
` projections.login_policies.external_login_check_lifetime,`+
|
||||
` projections.login_policies.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies.second_factor_check_lifetime,`+
|
||||
` projections.login_policies.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies`+
|
||||
` FROM projections.login_policies2`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
sql.ErrConnDone,
|
||||
@@ -234,8 +240,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@@ -255,8 +261,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@@ -277,8 +283,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@@ -294,8 +300,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
@@ -312,8 +318,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@@ -333,8 +339,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@@ -355,8 +361,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@@ -372,8 +378,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
|
@@ -104,7 +104,7 @@ func (q *Queries) OrgByID(ctx context.Context, shouldTriggerBulk bool, id string
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) OrgByDomainGlobal(ctx context.Context, domain string) (*Org, error) {
|
||||
func (q *Queries) OrgByPrimaryDomain(ctx context.Context, domain string) (*Org, error) {
|
||||
stmt, scan := prepareOrgQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
OrgColumnDomain.identifier(): domain,
|
||||
@@ -118,6 +118,21 @@ func (q *Queries) OrgByDomainGlobal(ctx context.Context, domain string) (*Org, e
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) OrgByVerifiedDomain(ctx context.Context, domain string) (*Org, error) {
|
||||
stmt, scan := prepareOrgWithDomainsQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
OrgDomainDomainCol.identifier(): domain,
|
||||
OrgDomainIsVerifiedCol.identifier(): true,
|
||||
OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-TYUCE", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
row := q.client.QueryRowContext(ctx, query, args...)
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) IsOrgUnique(ctx context.Context, name, domain string) (isUnique bool, err error) {
|
||||
if name == "" && domain == "" {
|
||||
return false, errors.ThrowInvalidArgument(nil, "QUERY-DGqfd", "Errors.Query.InvalidRequest")
|
||||
@@ -268,6 +283,42 @@ func prepareOrgQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
|
||||
}
|
||||
}
|
||||
|
||||
func prepareOrgWithDomainsQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
|
||||
return sq.Select(
|
||||
OrgColumnID.identifier(),
|
||||
OrgColumnCreationDate.identifier(),
|
||||
OrgColumnChangeDate.identifier(),
|
||||
OrgColumnResourceOwner.identifier(),
|
||||
OrgColumnState.identifier(),
|
||||
OrgColumnSequence.identifier(),
|
||||
OrgColumnName.identifier(),
|
||||
OrgColumnDomain.identifier(),
|
||||
).
|
||||
From(orgsTable.identifier()).
|
||||
LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID)).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*Org, error) {
|
||||
o := new(Org)
|
||||
err := row.Scan(
|
||||
&o.ID,
|
||||
&o.CreationDate,
|
||||
&o.ChangeDate,
|
||||
&o.ResourceOwner,
|
||||
&o.State,
|
||||
&o.Sequence,
|
||||
&o.Name,
|
||||
&o.Domain,
|
||||
)
|
||||
if err != nil {
|
||||
if errs.Is(err, sql.ErrNoRows) {
|
||||
return nil, errors.ThrowNotFound(err, "QUERY-iTTGJ", "Errors.Org.NotFound")
|
||||
}
|
||||
return nil, errors.ThrowInternal(err, "QUERY-pWS5H", "Errors.Internal")
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareOrgUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
|
||||
return sq.Select(uniqueColumn.identifier()).
|
||||
From(orgsTable.identifier()).PlaceholderFormat(sq.Dollar),
|
||||
|
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
LoginPolicyTable = "projections.login_policies"
|
||||
LoginPolicyTable = "projections.login_policies2"
|
||||
|
||||
LoginPolicyIDCol = "aggregate_id"
|
||||
LoginPolicyInstanceIDCol = "instance_id"
|
||||
@@ -30,6 +30,7 @@ const (
|
||||
LoginPolicyPasswordlessTypeCol = "passwordless_type"
|
||||
LoginPolicyHidePWResetCol = "hide_password_reset"
|
||||
IgnoreUnknownUsernames = "ignore_unknown_usernames"
|
||||
AllowDomainDiscovery = "allow_domain_discovery"
|
||||
DefaultRedirectURI = "default_redirect_uri"
|
||||
PasswordCheckLifetimeCol = "password_check_lifetime"
|
||||
ExternalLoginCheckLifetimeCol = "external_login_check_lifetime"
|
||||
@@ -63,6 +64,7 @@ func newLoginPolicyProjection(ctx context.Context, config crdb.StatementHandlerC
|
||||
crdb.NewColumn(LoginPolicyPasswordlessTypeCol, crdb.ColumnTypeEnum),
|
||||
crdb.NewColumn(LoginPolicyHidePWResetCol, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(IgnoreUnknownUsernames, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(AllowDomainDiscovery, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(DefaultRedirectURI, crdb.ColumnTypeText, crdb.Nullable()),
|
||||
crdb.NewColumn(PasswordCheckLifetimeCol, crdb.ColumnTypeInt64),
|
||||
crdb.NewColumn(ExternalLoginCheckLifetimeCol, crdb.ColumnTypeInt64),
|
||||
@@ -172,6 +174,7 @@ func (p *loginPolicyProjection) reduceLoginPolicyAdded(event eventstore.Event) (
|
||||
handler.NewCol(LoginPolicyIsDefaultCol, isDefault),
|
||||
handler.NewCol(LoginPolicyHidePWResetCol, policyEvent.HidePasswordReset),
|
||||
handler.NewCol(IgnoreUnknownUsernames, policyEvent.IgnoreUnknownUsernames),
|
||||
handler.NewCol(AllowDomainDiscovery, policyEvent.AllowDomainDiscovery),
|
||||
handler.NewCol(DefaultRedirectURI, policyEvent.DefaultRedirectURI),
|
||||
handler.NewCol(PasswordCheckLifetimeCol, policyEvent.PasswordCheckLifetime),
|
||||
handler.NewCol(ExternalLoginCheckLifetimeCol, policyEvent.ExternalLoginCheckLifetime),
|
||||
@@ -217,6 +220,9 @@ func (p *loginPolicyProjection) reduceLoginPolicyChanged(event eventstore.Event)
|
||||
if policyEvent.IgnoreUnknownUsernames != nil {
|
||||
cols = append(cols, handler.NewCol(IgnoreUnknownUsernames, *policyEvent.IgnoreUnknownUsernames))
|
||||
}
|
||||
if policyEvent.AllowDomainDiscovery != nil {
|
||||
cols = append(cols, handler.NewCol(AllowDomainDiscovery, *policyEvent.AllowDomainDiscovery))
|
||||
}
|
||||
if policyEvent.DefaultRedirectURI != nil {
|
||||
cols = append(cols, handler.NewCol(DefaultRedirectURI, *policyEvent.DefaultRedirectURI))
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
want wantReduce
|
||||
}{
|
||||
{
|
||||
name: "org.reduceLoginPolicyAdded",
|
||||
name: "org reduceLoginPolicyAdded",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(org.LoginPolicyAddedEventType),
|
||||
@@ -36,6 +36,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": false,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@@ -55,7 +56,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.login_policies (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)",
|
||||
expectedStmt: "INSERT INTO projections.login_policies2 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -70,6 +71,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@@ -83,7 +85,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceLoginPolicyChanged",
|
||||
name: "org reduceLoginPolicyChanged",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyChanged,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -96,6 +98,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": true,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@@ -114,7 +117,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) WHERE (aggregate_id = $16)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) WHERE (aggregate_id = $17)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -125,6 +128,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
domain.PasswordlessTypeAllowed,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@@ -139,7 +143,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceMFAAdded",
|
||||
name: "org reduceMFAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -158,7 +162,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -171,7 +175,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceMFARemoved",
|
||||
name: "org reduceMFARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -190,7 +194,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -203,7 +207,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceLoginPolicyRemoved",
|
||||
name: "org reduceLoginPolicyRemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyRemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -220,7 +224,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.login_policies WHERE (aggregate_id = $1)",
|
||||
expectedStmt: "DELETE FROM projections.login_policies2 WHERE (aggregate_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
@@ -230,7 +234,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduce2FAAdded",
|
||||
name: "org reduce2FAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -249,7 +253,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -262,7 +266,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduce2FARemoved",
|
||||
name: "org reduce2FARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -281,7 +285,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -294,7 +298,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceLoginPolicyAdded",
|
||||
name: "instance reduceLoginPolicyAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -307,6 +311,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": false,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@@ -325,7 +330,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.login_policies (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)",
|
||||
expectedStmt: "INSERT INTO projections.login_policies2 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -340,6 +345,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@@ -353,7 +359,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceLoginPolicyChanged",
|
||||
name: "instance reduceLoginPolicyChanged",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyChanged,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -366,6 +372,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": true,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect"
|
||||
}`),
|
||||
@@ -379,7 +386,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, default_redirect_uri) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) WHERE (aggregate_id = $11)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) WHERE (aggregate_id = $12)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -390,6 +397,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
domain.PasswordlessTypeAllowed,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
"agg-id",
|
||||
},
|
||||
@@ -399,7 +407,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceMFAAdded",
|
||||
name: "instance reduceMFAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -418,7 +426,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -431,7 +439,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceMFARemoved",
|
||||
name: "instance reduceMFARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -450,7 +458,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -463,7 +471,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduce2FAAdded",
|
||||
name: "instance reduce2FAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -482,7 +490,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -495,7 +503,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduce2FARemoved",
|
||||
name: "instance reduce2FARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@@ -514,7 +522,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
|
@@ -28,7 +28,8 @@ func NewLoginPolicyAddedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -49,6 +50,7 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@@ -29,7 +29,8 @@ func NewLoginPolicyAddedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -50,6 +51,7 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@@ -26,6 +26,7 @@ type LoginPolicyAddedEvent struct {
|
||||
ForceMFA bool `json:"forceMFA,omitempty"`
|
||||
HidePasswordReset bool `json:"hidePasswordReset,omitempty"`
|
||||
IgnoreUnknownUsernames bool `json:"ignoreUnknownUsernames,omitempty"`
|
||||
AllowDomainDiscovery bool `json:"allowDomainDiscovery,omitempty"`
|
||||
PasswordlessType domain.PasswordlessType `json:"passwordlessType,omitempty"`
|
||||
DefaultRedirectURI string `json:"defaultRedirectURI,omitempty"`
|
||||
PasswordCheckLifetime time.Duration `json:"passwordCheckLifetime,omitempty"`
|
||||
@@ -50,7 +51,8 @@ func NewLoginPolicyAddedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -68,6 +70,7 @@ func NewLoginPolicyAddedEvent(
|
||||
PasswordlessType: passwordlessType,
|
||||
HidePasswordReset: hidePasswordReset,
|
||||
IgnoreUnknownUsernames: ignoreUnknownUsernames,
|
||||
AllowDomainDiscovery: allowDomainDiscovery,
|
||||
DefaultRedirectURI: defaultRedirectURI,
|
||||
PasswordCheckLifetime: passwordCheckLifetime,
|
||||
ExternalLoginCheckLifetime: externalLoginCheckLifetime,
|
||||
@@ -99,6 +102,7 @@ type LoginPolicyChangedEvent struct {
|
||||
ForceMFA *bool `json:"forceMFA,omitempty"`
|
||||
HidePasswordReset *bool `json:"hidePasswordReset,omitempty"`
|
||||
IgnoreUnknownUsernames *bool `json:"ignoreUnknownUsernames,omitempty"`
|
||||
AllowDomainDiscovery *bool `json:"allowDomainDiscovery,omitempty"`
|
||||
PasswordlessType *domain.PasswordlessType `json:"passwordlessType,omitempty"`
|
||||
DefaultRedirectURI *string `json:"defaultRedirectURI,omitempty"`
|
||||
PasswordCheckLifetime *time.Duration `json:"passwordCheckLifetime,omitempty"`
|
||||
@@ -206,6 +210,12 @@ func ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames bool) func(*LoginPolicy
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeAllowDomainDiscovery(allowDomainDiscovery bool) func(*LoginPolicyChangedEvent) {
|
||||
return func(e *LoginPolicyChangedEvent) {
|
||||
e.AllowDomainDiscovery = &allowDomainDiscovery
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeDefaultRedirectURI(defaultRedirectURI string) func(*LoginPolicyChangedEvent) {
|
||||
return func(e *LoginPolicyChangedEvent) {
|
||||
e.DefaultRedirectURI = &defaultRedirectURI
|
||||
|
Reference in New Issue
Block a user