mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:07:31 +00:00
feat: Lockout policy feature (#2341)
* feat: add lockoutpolicy feature * feat: add tests * fix: err handling
This commit is contained in:
@@ -30,6 +30,7 @@ type FeaturesWriteModel struct {
|
||||
MetadataUser bool
|
||||
CustomTextMessage bool
|
||||
CustomTextLogin bool
|
||||
LockoutPolicy bool
|
||||
}
|
||||
|
||||
func (wm *FeaturesWriteModel) Reduce() error {
|
||||
@@ -94,6 +95,9 @@ func (wm *FeaturesWriteModel) Reduce() error {
|
||||
if e.CustomTextLogin != nil {
|
||||
wm.CustomTextLogin = *e.CustomTextLogin
|
||||
}
|
||||
if e.LockoutPolicy != nil {
|
||||
wm.LockoutPolicy = *e.LockoutPolicy
|
||||
}
|
||||
case *features.FeaturesRemovedEvent:
|
||||
wm.State = domain.FeaturesStateRemoved
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *IAM
|
||||
features.MetadataUser,
|
||||
features.CustomTextMessage,
|
||||
features.CustomTextLogin,
|
||||
features.LockoutPolicy,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||
|
@@ -70,7 +70,8 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
||||
privacyPolicy,
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin bool,
|
||||
customTextLogin,
|
||||
lockoutPolicy bool,
|
||||
) (*iam.FeaturesSetEvent, bool) {
|
||||
|
||||
changes := make([]features.FeaturesChanges, 0)
|
||||
@@ -129,6 +130,9 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
||||
if wm.CustomTextLogin != customTextLogin {
|
||||
changes = append(changes, features.ChangeCustomTextLogin(customTextLogin))
|
||||
}
|
||||
if wm.LockoutPolicy != lockoutPolicy {
|
||||
changes = append(changes, features.ChangeLockoutPolicy(lockoutPolicy))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
@@ -44,6 +44,7 @@ func (c *Commands) SetOrgFeatures(ctx context.Context, resourceOwner string, fea
|
||||
features.MetadataUser,
|
||||
features.CustomTextMessage,
|
||||
features.CustomTextLogin,
|
||||
features.LockoutPolicy,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||
@@ -157,6 +158,15 @@ func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string
|
||||
events = append(events, removePrivacyPolicyEvent)
|
||||
}
|
||||
}
|
||||
if !features.LockoutPolicy {
|
||||
removeLockoutPolicyEvent, err := c.removeLockoutPolicyIfExists(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if removeLockoutPolicyEvent != nil {
|
||||
events = append(events, removeLockoutPolicyEvent)
|
||||
}
|
||||
}
|
||||
if !features.MetadataUser {
|
||||
removeOrgUserMetadatas, err := c.removeUserMetadataFromOrg(ctx, orgID)
|
||||
if err != nil {
|
||||
|
@@ -77,7 +77,8 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
||||
privacyPolicy,
|
||||
metadataUser,
|
||||
customTextMessage,
|
||||
customTextLogin bool,
|
||||
customTextLogin,
|
||||
lockoutPolicy bool,
|
||||
) (*org.FeaturesSetEvent, bool) {
|
||||
|
||||
changes := make([]features.FeaturesChanges, 0)
|
||||
@@ -139,6 +140,9 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
||||
if wm.CustomTextLogin != customTextLogin {
|
||||
changes = append(changes, features.ChangeCustomTextLogin(customTextLogin))
|
||||
}
|
||||
if wm.LockoutPolicy != lockoutPolicy {
|
||||
changes = append(changes, features.ChangeLockoutPolicy(lockoutPolicy))
|
||||
}
|
||||
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
|
@@ -264,6 +264,16 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
@@ -296,6 +306,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
CustomTextLogin: false,
|
||||
PrivacyPolicy: false,
|
||||
MetadataUser: false,
|
||||
LockoutPolicy: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -450,6 +461,16 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
@@ -486,6 +507,8 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
LabelPolicyWatermark: false,
|
||||
CustomDomain: false,
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -647,6 +670,16 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
@@ -686,6 +719,8 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
LabelPolicyWatermark: false,
|
||||
CustomDomain: false,
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -854,6 +889,16 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
@@ -896,6 +941,8 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
LabelPolicyWatermark: false,
|
||||
CustomDomain: false,
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -1116,6 +1163,16 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
@@ -1146,6 +1203,9 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
eventFromEventPusher(
|
||||
org.NewPrivacyPolicyRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewLockoutPolicyRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
newFeaturesSetEvent(context.Background(), "org1", "Test", domain.FeaturesStateActive, time.Hour),
|
||||
),
|
||||
@@ -1172,6 +1232,8 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
LabelPolicyWatermark: false,
|
||||
CustomDomain: false,
|
||||
MetadataUser: false,
|
||||
PrivacyPolicy: false,
|
||||
LockoutPolicy: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -1305,6 +1367,16 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
@@ -1349,6 +1421,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
||||
CustomTextLogin: false,
|
||||
PrivacyPolicy: false,
|
||||
MetadataUser: false,
|
||||
LockoutPolicy: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -1551,6 +1624,16 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewLockoutPolicyAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
5,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
|
@@ -11,8 +11,7 @@ func (c *Commands) AddLockoutPolicy(ctx context.Context, resourceOwner string, p
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-8fJif", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
addedPolicy := NewOrgLockoutPolicyWriteModel(resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
addedPolicy, err := c.orgLockoutPolicyWriteModelByID(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -36,8 +35,7 @@ func (c *Commands) ChangeLockoutPolicy(ctx context.Context, resourceOwner string
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-3J9fs", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
existingPolicy := NewOrgLockoutPolicyWriteModel(resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
existingPolicy, err := c.orgLockoutPolicyWriteModelByID(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -66,8 +64,7 @@ func (c *Commands) RemoveLockoutPolicy(ctx context.Context, orgID string) error
|
||||
if orgID == "" {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "Org-4J9fs", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
existingPolicy := NewOrgLockoutPolicyWriteModel(orgID)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
existingPolicy, err := c.orgLockoutPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -79,3 +76,24 @@ func (c *Commands) RemoveLockoutPolicy(ctx context.Context, orgID string) error
|
||||
_, err = c.eventstore.PushEvents(ctx, org.NewLockoutPolicyRemovedEvent(ctx, orgAgg))
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Commands) removeLockoutPolicyIfExists(ctx context.Context, orgID string) (*org.LockoutPolicyRemovedEvent, error) {
|
||||
existingPolicy, err := c.orgLockoutPolicyWriteModelByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State != domain.PolicyStateActive {
|
||||
return nil, nil
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
||||
return org.NewLockoutPolicyRemovedEvent(ctx, orgAgg), nil
|
||||
}
|
||||
|
||||
func (c *Commands) orgLockoutPolicyWriteModelByID(ctx context.Context, orgID string) (*OrgLockoutPolicyWriteModel, error) {
|
||||
policy := NewOrgLockoutPolicyWriteModel(orgID)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return policy, nil
|
||||
}
|
Reference in New Issue
Block a user