mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:47:33 +00:00
feat: Policy (#79)
* policy added * Make it executable * Make it executable, corrections * password age policy added * password lockout policy added * corrections * policy added * Make it executable * Make it executable, corrections * password age policy added * password lockout policy added * corrections * fix(repository): remove second policy * complaints corrected * Init tests * add some tests * more tests added * systemfefaults added * default values load added * check for default value added * fixes * fixed * create policy if not exists * eventstore tests added Co-authored-by: adlerhurst <silvan.reusser@gmail.com>
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
package systemdefaults
|
||||
|
||||
import "github.com/caos/zitadel/internal/crypto"
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
pol "github.com/caos/zitadel/internal/policy"
|
||||
)
|
||||
|
||||
type SystemDefaults struct {
|
||||
SecretGenerators SecretGenerators
|
||||
UserVerificationKey *crypto.KeyConfig
|
||||
Multifactors MultifactorConfig
|
||||
DefaultPolicies DefaultPolicies
|
||||
}
|
||||
|
||||
type SecretGenerators struct {
|
||||
@@ -25,3 +29,9 @@ type OTPConfig struct {
|
||||
Issuer string
|
||||
VerificationKey *crypto.KeyConfig
|
||||
}
|
||||
|
||||
type DefaultPolicies struct {
|
||||
Age pol.PasswordAgePolicyDefault
|
||||
Complexity pol.PasswordComplexityPolicyDefault
|
||||
Lockout pol.PasswordLockoutPolicyDefault
|
||||
}
|
||||
|
45
internal/management/repository/eventsourcing/policy.go
Normal file
45
internal/management/repository/eventsourcing/policy.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
pol_model "github.com/caos/zitadel/internal/policy/model"
|
||||
pol_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
)
|
||||
|
||||
type PolicyRepo struct {
|
||||
PolicyEvents *pol_event.PolicyEventstore
|
||||
//view *view.View
|
||||
}
|
||||
|
||||
func (repo *PolicyRepo) CreatePasswordComplexityPolicy(ctx context.Context, policy *pol_model.PasswordComplexityPolicy) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
return repo.PolicyEvents.CreatePasswordComplexityPolicy(ctx, policy)
|
||||
}
|
||||
func (repo *PolicyRepo) GetPasswordComplexityPolicy(ctx context.Context) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
return repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, ctxData.OrgID)
|
||||
}
|
||||
func (repo *PolicyRepo) UpdatePasswordComplexityPolicy(ctx context.Context, policy *pol_model.PasswordComplexityPolicy) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
return repo.PolicyEvents.UpdatePasswordComplexityPolicy(ctx, policy)
|
||||
}
|
||||
func (repo *PolicyRepo) CreatePasswordAgePolicy(ctx context.Context, policy *pol_model.PasswordAgePolicy) (*pol_model.PasswordAgePolicy, error) {
|
||||
return repo.PolicyEvents.CreatePasswordAgePolicy(ctx, policy)
|
||||
}
|
||||
func (repo *PolicyRepo) GetPasswordAgePolicy(ctx context.Context) (*pol_model.PasswordAgePolicy, error) {
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
return repo.PolicyEvents.GetPasswordAgePolicy(ctx, ctxData.OrgID)
|
||||
}
|
||||
func (repo *PolicyRepo) UpdatePasswordAgePolicy(ctx context.Context, policy *pol_model.PasswordAgePolicy) (*pol_model.PasswordAgePolicy, error) {
|
||||
return repo.PolicyEvents.UpdatePasswordAgePolicy(ctx, policy)
|
||||
}
|
||||
func (repo *PolicyRepo) CreatePasswordLockoutPolicy(ctx context.Context, policy *pol_model.PasswordLockoutPolicy) (*pol_model.PasswordLockoutPolicy, error) {
|
||||
return repo.PolicyEvents.CreatePasswordLockoutPolicy(ctx, policy)
|
||||
}
|
||||
func (repo *PolicyRepo) GetPasswordLockoutPolicy(ctx context.Context) (*pol_model.PasswordLockoutPolicy, error) {
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
return repo.PolicyEvents.GetPasswordLockoutPolicy(ctx, ctxData.OrgID)
|
||||
}
|
||||
func (repo *PolicyRepo) UpdatePasswordLockoutPolicy(ctx context.Context, policy *pol_model.PasswordLockoutPolicy) (*pol_model.PasswordLockoutPolicy, error) {
|
||||
return repo.PolicyEvents.UpdatePasswordLockoutPolicy(ctx, policy)
|
||||
}
|
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/management/repository/eventsourcing/spooler"
|
||||
mgmt_view "github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
||||
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||
es_pol "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
es_grant "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing"
|
||||
@@ -30,6 +31,7 @@ type EsRepository struct {
|
||||
eventstore.ProjectRepo
|
||||
eventstore.UserRepo
|
||||
eventstore.UserGrantRepo
|
||||
PolicyRepo
|
||||
}
|
||||
|
||||
func Start(conf Config, systemDefaults sd.SystemDefaults) (*EsRepository, error) {
|
||||
@@ -54,6 +56,13 @@ func Start(conf Config, systemDefaults sd.SystemDefaults) (*EsRepository, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy, err := es_pol.StartPolicy(es_pol.PolicyConfig{
|
||||
Eventstore: es,
|
||||
Cache: conf.Eventstore.Cache,
|
||||
}, systemDefaults)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user, err := es_usr.StartUser(es_usr.UserConfig{
|
||||
Eventstore: es,
|
||||
Cache: conf.Eventstore.Cache,
|
||||
@@ -79,6 +88,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults) (*EsRepository, error)
|
||||
ProjectRepo: eventstore.ProjectRepo{conf.SearchLimit, project, view},
|
||||
UserRepo: eventstore.UserRepo{conf.SearchLimit, user, view},
|
||||
UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view},
|
||||
PolicyRepo: PolicyRepo{policy},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
19
internal/management/repository/policy.go
Normal file
19
internal/management/repository/policy.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
type PolicyRepository interface {
|
||||
CreatePasswordComplexityPolicy(ctx context.Context, policy *model.PasswordComplexityPolicy) (*model.PasswordComplexityPolicy, error)
|
||||
GetPasswordComplexityPolicy(ctx context.Context) (*model.PasswordComplexityPolicy, error)
|
||||
UpdatePasswordComplexityPolicy(ctx context.Context, policy *model.PasswordComplexityPolicy) (*model.PasswordComplexityPolicy, error)
|
||||
CreatePasswordAgePolicy(ctx context.Context, policy *model.PasswordAgePolicy) (*model.PasswordAgePolicy, error)
|
||||
GetPasswordAgePolicy(ctx context.Context) (*model.PasswordAgePolicy, error)
|
||||
UpdatePasswordAgePolicy(ctx context.Context, policy *model.PasswordAgePolicy) (*model.PasswordAgePolicy, error)
|
||||
CreatePasswordLockoutPolicy(ctx context.Context, policy *model.PasswordLockoutPolicy) (*model.PasswordLockoutPolicy, error)
|
||||
GetPasswordLockoutPolicy(ctx context.Context) (*model.PasswordLockoutPolicy, error)
|
||||
UpdatePasswordLockoutPolicy(ctx context.Context, policy *model.PasswordLockoutPolicy) (*model.PasswordLockoutPolicy, error)
|
||||
}
|
@@ -3,6 +3,7 @@ package repository
|
||||
type Repository interface {
|
||||
Health() error
|
||||
ProjectRepository
|
||||
PolicyRepository
|
||||
OrgRepository
|
||||
OrgMemberRepository
|
||||
UserRepository
|
||||
|
22
internal/policy/default.go
Normal file
22
internal/policy/default.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package policy
|
||||
|
||||
type PasswordAgePolicyDefault struct {
|
||||
Description string
|
||||
MaxAgeDays uint64
|
||||
ExpireWarnDays uint64
|
||||
}
|
||||
|
||||
type PasswordComplexityPolicyDefault struct {
|
||||
Description string
|
||||
MinLength uint64
|
||||
HasLowercase bool
|
||||
HasUppercase bool
|
||||
HasNumber bool
|
||||
HasSymbol bool
|
||||
}
|
||||
|
||||
type PasswordLockoutPolicyDefault struct {
|
||||
Description string
|
||||
MaxAttempts uint64
|
||||
ShowLockOutFailures bool
|
||||
}
|
16
internal/policy/model/policy_age.go
Normal file
16
internal/policy/model/policy_age.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
type PasswordAgePolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Description string
|
||||
State PolicyState
|
||||
MaxAgeDays uint64
|
||||
ExpireWarnDays uint64
|
||||
}
|
||||
|
||||
func (p *PasswordAgePolicy) IsValid() bool {
|
||||
return p.Description != ""
|
||||
}
|
19
internal/policy/model/policy_complexity.go
Normal file
19
internal/policy/model/policy_complexity.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
type PasswordComplexityPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Description string
|
||||
State PolicyState
|
||||
MinLength uint64
|
||||
HasLowercase bool
|
||||
HasUppercase bool
|
||||
HasNumber bool
|
||||
HasSymbol bool
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) IsValid() bool {
|
||||
return p.Description != ""
|
||||
}
|
16
internal/policy/model/policy_lockout.go
Normal file
16
internal/policy/model/policy_lockout.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
type PasswordLockoutPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Description string
|
||||
State PolicyState
|
||||
MaxAttempts uint64
|
||||
ShowLockOutFailures bool
|
||||
}
|
||||
|
||||
func (p *PasswordLockoutPolicy) IsValid() bool {
|
||||
return p.Description != ""
|
||||
}
|
30
internal/policy/model/types.go
Normal file
30
internal/policy/model/types.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
const (
|
||||
// complexity
|
||||
PasswordComplexityPolicyAggregate models.AggregateType = "policy.password.complexity"
|
||||
|
||||
PasswordComplexityPolicyAdded models.EventType = "policy.password.complexity.added"
|
||||
PasswordComplexityPolicyChanged models.EventType = "policy.password.complexity.changed"
|
||||
|
||||
// age
|
||||
PasswordAgePolicyAggregate models.AggregateType = "policy.password.age"
|
||||
|
||||
PasswordAgePolicyAdded models.EventType = "policy.password.age.added"
|
||||
PasswordAgePolicyChanged models.EventType = "policy.password.age.changed"
|
||||
|
||||
// lockout
|
||||
PasswordLockoutPolicyAggregate models.AggregateType = "policy.password.lockout"
|
||||
|
||||
PasswordLockoutPolicyAdded models.EventType = "policy.password.lockout.added"
|
||||
PasswordLockoutPolicyChanged models.EventType = "policy.password.lockout.changed"
|
||||
)
|
||||
|
||||
type PolicyState int32
|
||||
|
||||
const (
|
||||
POLICYSTATE_ACTIVE PolicyState = iota
|
||||
POLICYSTATE_INACTIVE
|
||||
)
|
34
internal/policy/repository/eventsourcing/cache.go
Normal file
34
internal/policy/repository/eventsourcing/cache.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/cache"
|
||||
"github.com/caos/zitadel/internal/cache/config"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type PolicyCache struct {
|
||||
policyCache cache.Cache
|
||||
}
|
||||
|
||||
func StartCache(conf *config.CacheConfig) (*PolicyCache, error) {
|
||||
policyCache, err := conf.Config.NewCache()
|
||||
logging.Log("EVENT-vDneN").OnError(err).Panic("unable to create policy cache")
|
||||
|
||||
return &PolicyCache{policyCache: policyCache}, nil
|
||||
}
|
||||
|
||||
func (c *PolicyCache) getPolicy(id string) (policy *PasswordComplexityPolicy) {
|
||||
policy = &PasswordComplexityPolicy{ObjectRoot: models.ObjectRoot{AggregateID: id}}
|
||||
if err := c.policyCache.Get(id, policy); err != nil {
|
||||
logging.Log("EVENT-4eTZh").WithError(err).Debug("error in getting cache")
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func (c *PolicyCache) cachePolicy(policy *PasswordComplexityPolicy) {
|
||||
err := c.policyCache.Set(policy.AggregateID, policy)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-ThnBb").WithError(err).Debug("error in setting policy cache")
|
||||
}
|
||||
}
|
20
internal/policy/repository/eventsourcing/cache_age.go
Normal file
20
internal/policy/repository/eventsourcing/cache_age.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
)
|
||||
|
||||
func (c *PolicyCache) getAgePolicy(id string) (policy *PasswordAgePolicy) {
|
||||
policy = new(PasswordAgePolicy)
|
||||
if err := c.policyCache.Get(id, policy); err != nil {
|
||||
logging.Log("EVENT-NqMFM").WithError(err).Debug("error in getting cache")
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func (c *PolicyCache) cacheAgePolicy(policy *PasswordAgePolicy) {
|
||||
err := c.policyCache.Set(policy.AggregateID, policy)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-6vRvM").WithError(err).Debug("error in setting policy cache")
|
||||
}
|
||||
}
|
20
internal/policy/repository/eventsourcing/cache_complexity.go
Normal file
20
internal/policy/repository/eventsourcing/cache_complexity.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
)
|
||||
|
||||
func (c *PolicyCache) getComplexityPolicy(id string) (policy *PasswordComplexityPolicy) {
|
||||
policy = new(PasswordComplexityPolicy)
|
||||
if err := c.policyCache.Get(id, policy); err != nil {
|
||||
logging.Log("EVENT-Wgrph").WithError(err).Debug("error in getting cache")
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func (c *PolicyCache) cacheComplexityPolicy(policy *PasswordComplexityPolicy) {
|
||||
err := c.policyCache.Set(policy.AggregateID, policy)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-ylGny").WithError(err).Debug("error in setting policy cache")
|
||||
}
|
||||
}
|
20
internal/policy/repository/eventsourcing/cache_lockout.go
Normal file
20
internal/policy/repository/eventsourcing/cache_lockout.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
)
|
||||
|
||||
func (c *PolicyCache) getLockoutPolicy(id string) (policy *PasswordLockoutPolicy) {
|
||||
policy = new(PasswordLockoutPolicy)
|
||||
if err := c.policyCache.Get(id, policy); err != nil {
|
||||
logging.Log("EVENT-Zoljf").WithError(err).Debug("error in getting cache")
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func (c *PolicyCache) cacheLockoutPolicy(policy *PasswordLockoutPolicy) {
|
||||
err := c.policyCache.Set(policy.AggregateID, policy)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-6klAf").WithError(err).Debug("error in setting policy cache")
|
||||
}
|
||||
}
|
38
internal/policy/repository/eventsourcing/eventstore.go
Normal file
38
internal/policy/repository/eventsourcing/eventstore.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/cache/config"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/policy"
|
||||
"github.com/sony/sonyflake"
|
||||
)
|
||||
|
||||
var idGenerator = sonyflake.NewSonyflake(sonyflake.Settings{})
|
||||
|
||||
type PolicyEventstore struct {
|
||||
es_int.Eventstore
|
||||
policyCache *PolicyCache
|
||||
passwordAgePolicyDefault policy.PasswordAgePolicyDefault
|
||||
passwordComplexityPolicyDefault policy.PasswordComplexityPolicyDefault
|
||||
passwordLockoutPolicyDefault policy.PasswordLockoutPolicyDefault
|
||||
}
|
||||
|
||||
type PolicyConfig struct {
|
||||
es_int.Eventstore
|
||||
Cache *config.CacheConfig
|
||||
}
|
||||
|
||||
func StartPolicy(conf PolicyConfig, systemDefaults sd.SystemDefaults) (*PolicyEventstore, error) {
|
||||
policyCache, err := StartCache(conf.Cache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PolicyEventstore{
|
||||
Eventstore: conf.Eventstore,
|
||||
policyCache: policyCache,
|
||||
passwordAgePolicyDefault: systemDefaults.DefaultPolicies.Age,
|
||||
passwordComplexityPolicyDefault: systemDefaults.DefaultPolicies.Complexity,
|
||||
passwordLockoutPolicyDefault: systemDefaults.DefaultPolicies.Lockout,
|
||||
}, nil
|
||||
}
|
83
internal/policy/repository/eventsourcing/eventstore_age.go
Normal file
83
internal/policy/repository/eventsourcing/eventstore_age.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
||||
pol_model "github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func (es *PolicyEventstore) GetPasswordAgePolicy(ctx context.Context, id string) (*pol_model.PasswordAgePolicy, error) {
|
||||
policy := es.policyCache.getAgePolicy(id)
|
||||
|
||||
query := PasswordAgePolicyQuery(id, policy.Sequence)
|
||||
err := es_sdk.Filter(ctx, es.FilterEvents, policy.AppendEvents, query)
|
||||
if caos_errs.IsNotFound(err) && es.passwordAgePolicyDefault.Description != "" {
|
||||
policy.Description = es.passwordAgePolicyDefault.Description
|
||||
policy.MaxAgeDays = es.passwordAgePolicyDefault.MaxAgeDays
|
||||
policy.ExpireWarnDays = es.passwordAgePolicyDefault.ExpireWarnDays
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
es.policyCache.cacheAgePolicy(policy)
|
||||
return PasswordAgePolicyToModel(policy), nil
|
||||
}
|
||||
|
||||
func (es *PolicyEventstore) CreatePasswordAgePolicy(ctx context.Context, policy *pol_model.PasswordAgePolicy) (*pol_model.PasswordAgePolicy, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-fbX5K", "Description is required")
|
||||
}
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
existingPolicy, err := es.GetPasswordAgePolicy(ctx, ctxData.OrgID)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy != nil && existingPolicy.Sequence > 0 {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-yDJ5I", "Policy allready exists")
|
||||
}
|
||||
|
||||
id, err := idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy.AggregateID = strconv.FormatUint(id, 10)
|
||||
|
||||
repoPolicy := PasswordAgePolicyFromModel(policy)
|
||||
|
||||
createAggregate := PasswordAgePolicyCreateAggregate(es.AggregateCreator(), repoPolicy)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoPolicy.AppendEvents, createAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.policyCache.cacheAgePolicy(repoPolicy)
|
||||
return PasswordAgePolicyToModel(repoPolicy), nil
|
||||
}
|
||||
|
||||
func (es *PolicyEventstore) UpdatePasswordAgePolicy(ctx context.Context, policy *pol_model.PasswordAgePolicy) (*pol_model.PasswordAgePolicy, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-44jB3", "Description is required")
|
||||
}
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
existingPolicy, err := es.GetPasswordAgePolicy(ctx, ctxData.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.Sequence <= 0 {
|
||||
return es.CreatePasswordAgePolicy(ctx, policy)
|
||||
}
|
||||
repoExisting := PasswordAgePolicyFromModel(existingPolicy)
|
||||
repoNew := PasswordAgePolicyFromModel(policy)
|
||||
|
||||
updateAggregate := PasswordAgePolicyUpdateAggregate(es.AggregateCreator(), repoExisting, repoNew)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoExisting.AppendEvents, updateAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.policyCache.cacheAgePolicy(repoExisting)
|
||||
return PasswordAgePolicyToModel(repoExisting), nil
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
mock_cache "github.com/caos/zitadel/internal/cache/mock"
|
||||
"github.com/caos/zitadel/internal/eventstore/mock"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func GetMockedEventstoreAge(ctrl *gomock.Controller, mockEs *mock.MockEventstore) *PolicyEventstore {
|
||||
return &PolicyEventstore{
|
||||
Eventstore: mockEs,
|
||||
policyCache: GetMockCacheAge(ctrl),
|
||||
}
|
||||
}
|
||||
|
||||
func GetMockCacheAge(ctrl *gomock.Controller) *PolicyCache {
|
||||
mockCache := mock_cache.NewMockCache(ctrl)
|
||||
mockCache.EXPECT().Get(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
mockCache.EXPECT().Set(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
return &PolicyCache{policyCache: mockCache}
|
||||
}
|
||||
|
||||
func GetMockGetPasswordAgePolicyOK(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
data, _ := json.Marshal(model.PasswordAgePolicy{Description: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.PasswordAgePolicyAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstoreAge(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockGetPasswordAgePolicyNoEvents(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstoreAge(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockPasswordAgePolicy(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
data, _ := json.Marshal(model.PasswordAgePolicy{Description: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.PasswordAgePolicyAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreAge(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockPasswordAgePolicyNoEvents(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreAge(ctrl, mockEs)
|
||||
}
|
192
internal/policy/repository/eventsourcing/eventstore_age_test.go
Normal file
192
internal/policy/repository/eventsourcing/eventstore_age_test.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func TestGetPasswordAgePolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
policy *model.PasswordAgePolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordAgePolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy from events, ok",
|
||||
args: args{
|
||||
es: GetMockGetPasswordAgePolicyOK(ctrl),
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "policy from events, no events",
|
||||
args: args{
|
||||
es: GetMockGetPasswordAgePolicyNoEvents(ctrl),
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 2}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.GetPasswordAgePolicy(nil, tt.args.policy.AggregateID)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID != tt.res.policy.AggregateID {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.AggregateID, result.AggregateID)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePasswordAgePolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
ctx context.Context
|
||||
policy *model.PasswordAgePolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordAgePolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordAgePolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create policy no name",
|
||||
args: args{
|
||||
es: GetMockPasswordAgePolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.CreatePasswordAgePolicy(tt.args.ctx, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePasswordAgePolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
ctx context.Context
|
||||
new *model.PasswordAgePolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordAgePolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "update policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordAgePolicy(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update policy no name",
|
||||
args: args{
|
||||
es: GetMockPasswordAgePolicy(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: ""},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing policy not found",
|
||||
args: args{
|
||||
es: GetMockPasswordAgePolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordAgePolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.UpdatePasswordAgePolicy(tt.args.ctx, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
||||
pol_model "github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func (es *PolicyEventstore) GetPasswordComplexityPolicy(ctx context.Context, id string) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
policy := es.policyCache.getComplexityPolicy(id)
|
||||
|
||||
query := PasswordComplexityPolicyQuery(id, policy.Sequence)
|
||||
err := es_sdk.Filter(ctx, es.FilterEvents, policy.AppendEvents, query)
|
||||
if caos_errs.IsNotFound(err) && es.passwordComplexityPolicyDefault.Description != "" {
|
||||
policy.Description = es.passwordComplexityPolicyDefault.Description
|
||||
policy.MinLength = es.passwordComplexityPolicyDefault.MinLength
|
||||
policy.HasLowercase = es.passwordComplexityPolicyDefault.HasLowercase
|
||||
policy.HasUppercase = es.passwordComplexityPolicyDefault.HasUppercase
|
||||
policy.HasNumber = es.passwordComplexityPolicyDefault.HasNumber
|
||||
policy.HasSymbol = es.passwordComplexityPolicyDefault.HasSymbol
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
es.policyCache.cacheComplexityPolicy(policy)
|
||||
return PasswordComplexityPolicyToModel(policy), nil
|
||||
}
|
||||
|
||||
func (es *PolicyEventstore) CreatePasswordComplexityPolicy(ctx context.Context, policy *pol_model.PasswordComplexityPolicy) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Description is required")
|
||||
}
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
existingPolicy, err := es.GetPasswordComplexityPolicy(ctx, ctxData.OrgID)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy != nil && existingPolicy.Sequence > 0 {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-yDJ5I", "Policy allready exists")
|
||||
}
|
||||
|
||||
id, err := idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy.AggregateID = strconv.FormatUint(id, 10)
|
||||
|
||||
repoPolicy := PasswordComplexityPolicyFromModel(policy)
|
||||
|
||||
createAggregate := PasswordComplexityPolicyCreateAggregate(es.AggregateCreator(), repoPolicy)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoPolicy.AppendEvents, createAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.policyCache.cacheComplexityPolicy(repoPolicy)
|
||||
return PasswordComplexityPolicyToModel(repoPolicy), nil
|
||||
}
|
||||
|
||||
func (es *PolicyEventstore) UpdatePasswordComplexityPolicy(ctx context.Context, policy *pol_model.PasswordComplexityPolicy) (*pol_model.PasswordComplexityPolicy, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Description is required")
|
||||
}
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
existingPolicy, err := es.GetPasswordComplexityPolicy(ctx, ctxData.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.Sequence <= 0 {
|
||||
return es.CreatePasswordComplexityPolicy(ctx, policy)
|
||||
}
|
||||
repoExisting := PasswordComplexityPolicyFromModel(existingPolicy)
|
||||
repoNew := PasswordComplexityPolicyFromModel(policy)
|
||||
|
||||
updateAggregate := PasswordComplexityPolicyUpdateAggregate(es.AggregateCreator(), repoExisting, repoNew)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoExisting.AppendEvents, updateAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.policyCache.cacheComplexityPolicy(repoExisting)
|
||||
return PasswordComplexityPolicyToModel(repoExisting), nil
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
mock_cache "github.com/caos/zitadel/internal/cache/mock"
|
||||
"github.com/caos/zitadel/internal/eventstore/mock"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func GetMockedEventstoreComplexity(ctrl *gomock.Controller, mockEs *mock.MockEventstore) *PolicyEventstore {
|
||||
return &PolicyEventstore{
|
||||
Eventstore: mockEs,
|
||||
policyCache: GetMockCacheComplexity(ctrl),
|
||||
}
|
||||
}
|
||||
|
||||
func GetMockCacheComplexity(ctrl *gomock.Controller) *PolicyCache {
|
||||
mockCache := mock_cache.NewMockCache(ctrl)
|
||||
mockCache.EXPECT().Get(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
mockCache.EXPECT().Set(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
return &PolicyCache{policyCache: mockCache}
|
||||
}
|
||||
|
||||
func GetMockGetPasswordComplexityPolicyOK(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
data, _ := json.Marshal(model.PasswordComplexityPolicy{Description: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.PasswordComplexityPolicyAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstoreComplexity(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockGetPasswordComplexityPolicyNoEvents(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstoreComplexity(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockPasswordComplexityPolicy(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
data, _ := json.Marshal(model.PasswordComplexityPolicy{Description: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.PasswordComplexityPolicyAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreComplexity(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockPasswordComplexityPolicyNoEvents(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreComplexity(ctrl, mockEs)
|
||||
}
|
@@ -0,0 +1,192 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func TestGetPasswordComplexityPolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
policy *model.PasswordComplexityPolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordComplexityPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy from events, ok",
|
||||
args: args{
|
||||
es: GetMockGetPasswordComplexityPolicyOK(ctrl),
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "policy from events, no events",
|
||||
args: args{
|
||||
es: GetMockGetPasswordComplexityPolicyNoEvents(ctrl),
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 2}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.GetPasswordComplexityPolicy(nil, tt.args.policy.AggregateID)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID != tt.res.policy.AggregateID {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.AggregateID, result.AggregateID)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePasswordComplexityPolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
ctx context.Context
|
||||
policy *model.PasswordComplexityPolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordComplexityPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create policy no name",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.CreatePasswordComplexityPolicy(tt.args.ctx, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePasswordComplexityPolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
ctx context.Context
|
||||
new *model.PasswordComplexityPolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordComplexityPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "update policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicy(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update policy no name",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicy(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: ""},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing policy not found",
|
||||
args: args{
|
||||
es: GetMockPasswordComplexityPolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordComplexityPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.UpdatePasswordComplexityPolicy(tt.args.ctx, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
||||
pol_model "github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func (es *PolicyEventstore) GetPasswordLockoutPolicy(ctx context.Context, id string) (*pol_model.PasswordLockoutPolicy, error) {
|
||||
policy := es.policyCache.getLockoutPolicy(id)
|
||||
|
||||
query := PasswordLockoutPolicyQuery(id, policy.Sequence)
|
||||
err := es_sdk.Filter(ctx, es.FilterEvents, policy.AppendEvents, query)
|
||||
if caos_errs.IsNotFound(err) && es.passwordLockoutPolicyDefault.Description != "" {
|
||||
policy.Description = es.passwordLockoutPolicyDefault.Description
|
||||
policy.MaxAttempts = es.passwordLockoutPolicyDefault.MaxAttempts
|
||||
policy.ShowLockOutFailures = es.passwordLockoutPolicyDefault.ShowLockOutFailures
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
es.policyCache.cacheLockoutPolicy(policy)
|
||||
return PasswordLockoutPolicyToModel(policy), nil
|
||||
}
|
||||
|
||||
func (es *PolicyEventstore) CreatePasswordLockoutPolicy(ctx context.Context, policy *pol_model.PasswordLockoutPolicy) (*pol_model.PasswordLockoutPolicy, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Description is required")
|
||||
}
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
existingPolicy, err := es.GetPasswordLockoutPolicy(ctx, ctxData.OrgID)
|
||||
if err != nil && !caos_errs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy != nil && existingPolicy.Sequence > 0 {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-yDJ5I", "Policy allready exists")
|
||||
}
|
||||
|
||||
id, err := idGenerator.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policy.AggregateID = strconv.FormatUint(id, 10)
|
||||
|
||||
repoPolicy := PasswordLockoutPolicyFromModel(policy)
|
||||
|
||||
createAggregate := PasswordLockoutPolicyCreateAggregate(es.AggregateCreator(), repoPolicy)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoPolicy.AppendEvents, createAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.policyCache.cacheLockoutPolicy(repoPolicy)
|
||||
return PasswordLockoutPolicyToModel(repoPolicy), nil
|
||||
}
|
||||
|
||||
func (es *PolicyEventstore) UpdatePasswordLockoutPolicy(ctx context.Context, policy *pol_model.PasswordLockoutPolicy) (*pol_model.PasswordLockoutPolicy, error) {
|
||||
if !policy.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "Description is required")
|
||||
}
|
||||
ctxData := auth.GetCtxData(ctx)
|
||||
existingPolicy, err := es.GetPasswordLockoutPolicy(ctx, ctxData.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.Sequence <= 0 {
|
||||
return es.CreatePasswordLockoutPolicy(ctx, policy)
|
||||
}
|
||||
repoExisting := PasswordLockoutPolicyFromModel(existingPolicy)
|
||||
repoNew := PasswordLockoutPolicyFromModel(policy)
|
||||
|
||||
updateAggregate := PasswordLockoutPolicyUpdateAggregate(es.AggregateCreator(), repoExisting, repoNew)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoExisting.AppendEvents, updateAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
es.policyCache.cacheLockoutPolicy(repoExisting)
|
||||
return PasswordLockoutPolicyToModel(repoExisting), nil
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
mock_cache "github.com/caos/zitadel/internal/cache/mock"
|
||||
"github.com/caos/zitadel/internal/eventstore/mock"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func GetMockedEventstoreLockout(ctrl *gomock.Controller, mockEs *mock.MockEventstore) *PolicyEventstore {
|
||||
return &PolicyEventstore{
|
||||
Eventstore: mockEs,
|
||||
policyCache: GetMockCacheLockout(ctrl),
|
||||
}
|
||||
}
|
||||
|
||||
func GetMockCacheLockout(ctrl *gomock.Controller) *PolicyCache {
|
||||
mockCache := mock_cache.NewMockCache(ctrl)
|
||||
mockCache.EXPECT().Get(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
mockCache.EXPECT().Set(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
return &PolicyCache{policyCache: mockCache}
|
||||
}
|
||||
|
||||
func GetMockGetPasswordLockoutPolicyOK(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
data, _ := json.Marshal(model.PasswordLockoutPolicy{Description: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.PasswordLockoutPolicyAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstoreLockout(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockGetPasswordLockoutPolicyNoEvents(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
return GetMockedEventstoreLockout(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockPasswordLockoutPolicy(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
data, _ := json.Marshal(model.PasswordLockoutPolicy{Description: "Name"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.PasswordLockoutPolicyAdded, Data: data},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreLockout(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockPasswordLockoutPolicyNoEvents(ctrl *gomock.Controller) *PolicyEventstore {
|
||||
events := []*es_models.Event{}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstoreLockout(ctrl, mockEs)
|
||||
}
|
@@ -0,0 +1,192 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func TestGetPasswordLockoutPolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
policy *model.PasswordLockoutPolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordLockoutPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy from events, ok",
|
||||
args: args{
|
||||
es: GetMockGetPasswordLockoutPolicyOK(ctrl),
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "policy from events, no events",
|
||||
args: args{
|
||||
es: GetMockGetPasswordLockoutPolicyNoEvents(ctrl),
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 2}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.GetPasswordLockoutPolicy(nil, tt.args.policy.AggregateID)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID != tt.res.policy.AggregateID {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.AggregateID, result.AggregateID)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePasswordLockoutPolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
ctx context.Context
|
||||
policy *model.PasswordLockoutPolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordLockoutPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordLockoutPolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID1", Sequence: 2}, Description: "Name"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create policy no name",
|
||||
args: args{
|
||||
es: GetMockPasswordLockoutPolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.CreatePasswordLockoutPolicy(tt.args.ctx, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePasswordLockoutPolicy(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *PolicyEventstore
|
||||
ctx context.Context
|
||||
new *model.PasswordLockoutPolicy
|
||||
}
|
||||
type res struct {
|
||||
policy *model.PasswordLockoutPolicy
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "update policy, ok",
|
||||
args: args{
|
||||
es: GetMockPasswordLockoutPolicy(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
policy: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update policy no name",
|
||||
args: args{
|
||||
es: GetMockPasswordLockoutPolicy(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: ""},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing policy not found",
|
||||
args: args{
|
||||
es: GetMockPasswordLockoutPolicyNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &model.PasswordLockoutPolicy{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "NameNew"},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.UpdatePasswordLockoutPolicy(tt.args.ctx, tt.args.new)
|
||||
|
||||
if !tt.res.wantErr && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
}
|
||||
if !tt.res.wantErr && result.Description != tt.res.policy.Description {
|
||||
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.policy.Description, result.Description)
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
80
internal/policy/repository/eventsourcing/model_age.go
Normal file
80
internal/policy/repository/eventsourcing/model_age.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
const (
|
||||
policyAgeVersion = "v1"
|
||||
)
|
||||
|
||||
type PasswordAgePolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
State int32 `json:"-"`
|
||||
MaxAgeDays uint64 `json:"maxAgeDays"`
|
||||
ExpireWarnDays uint64 `json:"expireWarnDays"`
|
||||
}
|
||||
|
||||
func (p *PasswordAgePolicy) AgeChanges(changed *PasswordAgePolicy) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
if changed.Description != "" && p.Description != changed.Description {
|
||||
changes["description"] = changed.Description
|
||||
}
|
||||
if p.MaxAgeDays != changed.MaxAgeDays {
|
||||
changes["maxAgeDays"] = changed.MaxAgeDays
|
||||
}
|
||||
if p.ExpireWarnDays != changed.ExpireWarnDays {
|
||||
changes["expireWarnDays"] = changed.ExpireWarnDays
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func PasswordAgePolicyFromModel(policy *model.PasswordAgePolicy) *PasswordAgePolicy {
|
||||
return &PasswordAgePolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
Description: policy.Description,
|
||||
State: int32(policy.State),
|
||||
MaxAgeDays: policy.MaxAgeDays,
|
||||
ExpireWarnDays: policy.ExpireWarnDays,
|
||||
}
|
||||
}
|
||||
|
||||
func PasswordAgePolicyToModel(policy *PasswordAgePolicy) *model.PasswordAgePolicy {
|
||||
return &model.PasswordAgePolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
Description: policy.Description,
|
||||
State: model.PolicyState(policy.State),
|
||||
MaxAgeDays: policy.MaxAgeDays,
|
||||
ExpireWarnDays: policy.ExpireWarnDays,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PasswordAgePolicy) AppendEvents(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
if err := p.AppendEvent(event); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PasswordAgePolicy) AppendEvent(event *es_models.Event) error {
|
||||
p.ObjectRoot.AppendEvent(event)
|
||||
|
||||
switch event.Type {
|
||||
case model.PasswordAgePolicyAdded, model.PasswordAgePolicyChanged:
|
||||
if err := json.Unmarshal(event.Data, p); err != nil {
|
||||
logging.Log("EVEN-idl93").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
98
internal/policy/repository/eventsourcing/model_complexity.go
Normal file
98
internal/policy/repository/eventsourcing/model_complexity.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
const (
|
||||
policyComplexityVersion = "v1"
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
State int32 `json:"-"`
|
||||
MinLength uint64 `json:"minLength"`
|
||||
HasLowercase bool `json:"hasLowercase"`
|
||||
HasUppercase bool `json:"hasUppercase"`
|
||||
HasNumber bool `json:"hasNumber"`
|
||||
HasSymbol bool `json:"hasSymbol"`
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) ComplexityChanges(changed *PasswordComplexityPolicy) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
if changed.Description != "" && p.Description != changed.Description {
|
||||
changes["description"] = changed.Description
|
||||
}
|
||||
if p.MinLength != changed.MinLength {
|
||||
changes["minLength"] = changed.MinLength
|
||||
}
|
||||
if p.HasLowercase != changed.HasLowercase {
|
||||
changes["hasLowercase"] = changed.HasLowercase
|
||||
}
|
||||
if p.HasUppercase != changed.HasUppercase {
|
||||
changes["hasUppercase"] = changed.HasUppercase
|
||||
}
|
||||
if p.HasNumber != changed.HasNumber {
|
||||
changes["hasNumber"] = changed.HasNumber
|
||||
}
|
||||
if p.HasSymbol != changed.HasSymbol {
|
||||
changes["hasSymbol"] = changed.HasSymbol
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func PasswordComplexityPolicyFromModel(policy *model.PasswordComplexityPolicy) *PasswordComplexityPolicy {
|
||||
return &PasswordComplexityPolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
Description: policy.Description,
|
||||
State: int32(policy.State),
|
||||
MinLength: policy.MinLength,
|
||||
HasLowercase: policy.HasLowercase,
|
||||
HasUppercase: policy.HasUppercase,
|
||||
HasNumber: policy.HasNumber,
|
||||
HasSymbol: policy.HasSymbol,
|
||||
}
|
||||
}
|
||||
|
||||
func PasswordComplexityPolicyToModel(policy *PasswordComplexityPolicy) *model.PasswordComplexityPolicy {
|
||||
return &model.PasswordComplexityPolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
Description: policy.Description,
|
||||
State: model.PolicyState(policy.State),
|
||||
MinLength: policy.MinLength,
|
||||
HasLowercase: policy.HasLowercase,
|
||||
HasUppercase: policy.HasUppercase,
|
||||
HasNumber: policy.HasNumber,
|
||||
HasSymbol: policy.HasSymbol,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) AppendEvents(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
if err := p.AppendEvent(event); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) AppendEvent(event *es_models.Event) error {
|
||||
p.ObjectRoot.AppendEvent(event)
|
||||
|
||||
switch event.Type {
|
||||
case model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyChanged:
|
||||
if err := json.Unmarshal(event.Data, p); err != nil {
|
||||
logging.Log("EVEN-idl93").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
80
internal/policy/repository/eventsourcing/model_lockout.go
Normal file
80
internal/policy/repository/eventsourcing/model_lockout.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
const (
|
||||
policyLockoutVersion = "v1"
|
||||
)
|
||||
|
||||
type PasswordLockoutPolicy struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
State int32 `json:"-"`
|
||||
MaxAttempts uint64 `json:"maxAttempts"`
|
||||
ShowLockOutFailures bool `json:"showLockOutFailures"`
|
||||
}
|
||||
|
||||
func (p *PasswordLockoutPolicy) LockoutChanges(changed *PasswordLockoutPolicy) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
if changed.Description != "" && p.Description != changed.Description {
|
||||
changes["description"] = changed.Description
|
||||
}
|
||||
if p.MaxAttempts != changed.MaxAttempts {
|
||||
changes["maxAttempts"] = changed.MaxAttempts
|
||||
}
|
||||
if p.ShowLockOutFailures != changed.ShowLockOutFailures {
|
||||
changes["showLockOutFailures"] = changed.ShowLockOutFailures
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func PasswordLockoutPolicyFromModel(policy *model.PasswordLockoutPolicy) *PasswordLockoutPolicy {
|
||||
return &PasswordLockoutPolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
Description: policy.Description,
|
||||
State: int32(policy.State),
|
||||
MaxAttempts: policy.MaxAttempts,
|
||||
ShowLockOutFailures: policy.ShowLockOutFailures,
|
||||
}
|
||||
}
|
||||
|
||||
func PasswordLockoutPolicyToModel(policy *PasswordLockoutPolicy) *model.PasswordLockoutPolicy {
|
||||
return &model.PasswordLockoutPolicy{
|
||||
ObjectRoot: policy.ObjectRoot,
|
||||
Description: policy.Description,
|
||||
State: model.PolicyState(policy.State),
|
||||
MaxAttempts: policy.MaxAttempts,
|
||||
ShowLockOutFailures: policy.ShowLockOutFailures,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PasswordLockoutPolicy) AppendEvents(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
if err := p.AppendEvent(event); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PasswordLockoutPolicy) AppendEvent(event *es_models.Event) error {
|
||||
p.ObjectRoot.AppendEvent(event)
|
||||
|
||||
switch event.Type {
|
||||
case model.PasswordLockoutPolicyAdded, model.PasswordLockoutPolicyChanged:
|
||||
if err := json.Unmarshal(event.Data, p); err != nil {
|
||||
logging.Log("EVEN-idl93").WithError(err).Error("could not unmarshal event data")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
52
internal/policy/repository/eventsourcing/policy_age.go
Normal file
52
internal/policy/repository/eventsourcing/policy_age.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func PasswordAgePolicyQuery(recourceOwner string, latestSequence uint64) *es_models.SearchQuery {
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.PasswordAgePolicyAggregate).
|
||||
LatestSequenceFilter(latestSequence).
|
||||
ResourceOwnerFilter(recourceOwner)
|
||||
|
||||
}
|
||||
|
||||
func PasswordAgePolicyAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, policy *PasswordAgePolicy) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-1T05i", "existing policy should not be nil")
|
||||
}
|
||||
return aggCreator.NewAggregate(ctx, policy.AggregateID, model.PasswordAgePolicyAggregate, policyAgeVersion, policy.Sequence)
|
||||
}
|
||||
|
||||
func PasswordAgePolicyCreateAggregate(aggCreator *es_models.AggregateCreator, policy *PasswordAgePolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-kdie6", "policy should not be nil")
|
||||
}
|
||||
agg, err := PasswordAgePolicyAggregate(ctx, aggCreator, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return agg.AppendEvent(model.PasswordAgePolicyAdded, policy)
|
||||
}
|
||||
}
|
||||
|
||||
func PasswordAgePolicyUpdateAggregate(aggCreator *es_models.AggregateCreator, existing *PasswordAgePolicy, new *PasswordAgePolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if new == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dhr74", "new policy should not be nil")
|
||||
}
|
||||
agg, err := PasswordAgePolicyAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := existing.AgeChanges(new)
|
||||
return agg.AppendEvent(model.PasswordAgePolicyChanged, changes)
|
||||
}
|
||||
}
|
268
internal/policy/repository/eventsourcing/policy_age_test.go
Normal file
268
internal/policy/repository/eventsourcing/policy_age_test.go
Normal file
@@ -0,0 +1,268 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func TestGetPasswordAgePolicyQuery(t *testing.T) {
|
||||
type args struct {
|
||||
recourceOwner string
|
||||
sequence uint64
|
||||
}
|
||||
type res struct {
|
||||
filterLen int
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "Get password age policy query ok",
|
||||
args: args{
|
||||
recourceOwner: "org",
|
||||
sequence: 14,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get password age policy query, no org",
|
||||
args: args{
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
query := PasswordAgePolicyQuery(tt.args.recourceOwner, tt.args.sequence)
|
||||
if !tt.res.wantErr && query == nil {
|
||||
t.Errorf("query should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(query.Filters) != tt.res.filterLen {
|
||||
t.Errorf("got wrong filter len: expected: %v, actual: %v ", tt.res.filterLen, len(query.Filters))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordAgePolicyAggregate(t *testing.T) {
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
aggCreator *models.AggregateCreator
|
||||
policy *PasswordAgePolicy
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
aggType models.AggregateType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create aggregate",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
policy: &PasswordAgePolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "Test"},
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: policy_model.PasswordAgePolicyAggregate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: policy_model.PasswordAgePolicyAggregate,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordAgePolicyAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && agg == nil {
|
||||
t.Errorf("agg should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordAgePolicyCreateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
new *PasswordAgePolicy
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &PasswordAgePolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordAgePolicyAdded,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordAgePolicyAdded,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordAgePolicyCreateAggregate(tt.args.aggCreator, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordAgePolicyUpdateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *PasswordAgePolicy
|
||||
new *PasswordAgePolicy
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &PasswordAgePolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
new: &PasswordAgePolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName_Changed", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordAgePolicyChanged,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordAgePolicyChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &PasswordAgePolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "ProjectName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordAgePolicyChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordAgePolicyUpdateAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func PasswordComplexityPolicyQuery(recourceOwner string, latestSequence uint64) *es_models.SearchQuery {
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.PasswordComplexityPolicyAggregate).
|
||||
LatestSequenceFilter(latestSequence).
|
||||
ResourceOwnerFilter(recourceOwner)
|
||||
|
||||
}
|
||||
|
||||
func PasswordComplexityPolicyAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, policy *PasswordComplexityPolicy) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-fRVr9", "existing policy should not be nil")
|
||||
}
|
||||
return aggCreator.NewAggregate(ctx, policy.AggregateID, model.PasswordComplexityPolicyAggregate, policyComplexityVersion, policy.Sequence)
|
||||
}
|
||||
|
||||
func PasswordComplexityPolicyCreateAggregate(aggCreator *es_models.AggregateCreator, policy *PasswordComplexityPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-kdie6", "policy should not be nil")
|
||||
}
|
||||
agg, err := PasswordComplexityPolicyAggregate(ctx, aggCreator, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return agg.AppendEvent(model.PasswordComplexityPolicyAdded, policy)
|
||||
}
|
||||
}
|
||||
|
||||
func PasswordComplexityPolicyUpdateAggregate(aggCreator *es_models.AggregateCreator, existing *PasswordComplexityPolicy, new *PasswordComplexityPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if new == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dhr74", "new policy should not be nil")
|
||||
}
|
||||
agg, err := PasswordComplexityPolicyAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := existing.ComplexityChanges(new)
|
||||
return agg.AppendEvent(model.PasswordComplexityPolicyChanged, changes)
|
||||
}
|
||||
}
|
@@ -0,0 +1,268 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func TestPasswordComplexityPolicyQuery(t *testing.T) {
|
||||
type args struct {
|
||||
recourceOwner string
|
||||
sequence uint64
|
||||
}
|
||||
type res struct {
|
||||
filterLen int
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "Get password complexity policy query ok",
|
||||
args: args{
|
||||
recourceOwner: "org",
|
||||
sequence: 0,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get password complexity policy query, no org",
|
||||
args: args{
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
query := PasswordComplexityPolicyQuery(tt.args.recourceOwner, tt.args.sequence)
|
||||
if !tt.res.wantErr && query == nil {
|
||||
t.Errorf("query should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(query.Filters) != tt.res.filterLen {
|
||||
t.Errorf("got wrong filter len: expected: %v, actual: %v ", tt.res.filterLen, len(query.Filters))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordComplexityPolicyAggregate(t *testing.T) {
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
aggCreator *models.AggregateCreator
|
||||
policy *PasswordComplexityPolicy
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
aggType models.AggregateType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create aggregate",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
policy: &PasswordComplexityPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "Test"},
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: policy_model.PasswordComplexityPolicyAggregate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: policy_model.PasswordComplexityPolicyAggregate,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordComplexityPolicyAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && agg == nil {
|
||||
t.Errorf("agg should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordComplexityPolicyCreateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
new *PasswordComplexityPolicy
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &PasswordComplexityPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordComplexityPolicyAdded,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordComplexityPolicyAdded,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordComplexityPolicyCreateAggregate(tt.args.aggCreator, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordComplexityPolicyUpdateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *PasswordComplexityPolicy
|
||||
new *PasswordComplexityPolicy
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &PasswordComplexityPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
new: &PasswordComplexityPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName_Changed", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordComplexityPolicyChanged,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordComplexityPolicyChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &PasswordComplexityPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "ProjectName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordComplexityPolicyChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordComplexityPolicyUpdateAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
53
internal/policy/repository/eventsourcing/policy_lockout.go
Normal file
53
internal/policy/repository/eventsourcing/policy_lockout.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func PasswordLockoutPolicyQuery(recourceOwner string, latestSequence uint64) *es_models.SearchQuery {
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.PasswordLockoutPolicyAggregate).
|
||||
LatestSequenceFilter(latestSequence).
|
||||
ResourceOwnerFilter(recourceOwner)
|
||||
|
||||
}
|
||||
|
||||
func PasswordLockoutPolicyAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, policy *PasswordLockoutPolicy) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-aTRlj", "existing policy should not be nil")
|
||||
}
|
||||
return aggCreator.NewAggregate(ctx, policy.AggregateID, model.PasswordLockoutPolicyAggregate, policyLockoutVersion, policy.Sequence)
|
||||
}
|
||||
|
||||
func PasswordLockoutPolicyCreateAggregate(aggCreator *es_models.AggregateCreator, policy *PasswordLockoutPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-kdie6", "policy should not be nil")
|
||||
}
|
||||
|
||||
agg, err := PasswordLockoutPolicyAggregate(ctx, aggCreator, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return agg.AppendEvent(model.PasswordLockoutPolicyAdded, policy)
|
||||
}
|
||||
}
|
||||
|
||||
func PasswordLockoutPolicyUpdateAggregate(aggCreator *es_models.AggregateCreator, existing *PasswordLockoutPolicy, new *PasswordLockoutPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if new == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-dhr74", "new policy should not be nil")
|
||||
}
|
||||
agg, err := PasswordLockoutPolicyAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := existing.LockoutChanges(new)
|
||||
return agg.AppendEvent(model.PasswordLockoutPolicyChanged, changes)
|
||||
}
|
||||
}
|
268
internal/policy/repository/eventsourcing/policy_lockout_test.go
Normal file
268
internal/policy/repository/eventsourcing/policy_lockout_test.go
Normal file
@@ -0,0 +1,268 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
)
|
||||
|
||||
func TestGetPasswordLockoutPolicyQuery(t *testing.T) {
|
||||
type args struct {
|
||||
recourceOwner string
|
||||
sequence uint64
|
||||
}
|
||||
type res struct {
|
||||
filterLen int
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "Get password lockout policy query ok",
|
||||
args: args{
|
||||
recourceOwner: "org",
|
||||
sequence: 14,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get password lockout policy query, no org",
|
||||
args: args{
|
||||
sequence: 1,
|
||||
},
|
||||
res: res{
|
||||
filterLen: 3,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
query := PasswordLockoutPolicyQuery(tt.args.recourceOwner, tt.args.sequence)
|
||||
if !tt.res.wantErr && query == nil {
|
||||
t.Errorf("query should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(query.Filters) != tt.res.filterLen {
|
||||
t.Errorf("got wrong filter len: expected: %v, actual: %v ", tt.res.filterLen, len(query.Filters))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordLockoutPolicyAggregate(t *testing.T) {
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
aggCreator *models.AggregateCreator
|
||||
policy *PasswordLockoutPolicy
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
aggType models.AggregateType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "create aggregate",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
policy: &PasswordLockoutPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Description: "Test"},
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: policy_model.PasswordLockoutPolicyAggregate,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 0,
|
||||
aggType: policy_model.PasswordLockoutPolicyAggregate,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordLockoutPolicyAggregate(tt.args.ctx, tt.args.aggCreator, tt.args.policy)
|
||||
|
||||
if !tt.res.wantErr && agg == nil {
|
||||
t.Errorf("agg should not be nil")
|
||||
}
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordLockoutPolicyCreateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
new *PasswordLockoutPolicy
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: &PasswordLockoutPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordLockoutPolicyAdded,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordLockoutPolicyAdded,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordLockoutPolicyCreateAggregate(tt.args.aggCreator, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordLockoutPolicyUpdateAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *PasswordLockoutPolicy
|
||||
new *PasswordLockoutPolicy
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventType models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "policy update aggregate ok",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &PasswordLockoutPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
new: &PasswordLockoutPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "PolicyName_Changed", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordLockoutPolicyChanged,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordLockoutPolicyChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new policy nil",
|
||||
args: args{
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
existing: &PasswordLockoutPolicy{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Description: "ProjectName", State: int32(policy_model.POLICYSTATE_ACTIVE)},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventType: policy_model.PasswordLockoutPolicyChanged,
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := PasswordLockoutPolicyUpdateAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Type != tt.res.eventType {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventType, agg.Events[0].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[0].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -83,7 +83,7 @@ func templatesAuth_method_mappingGoTmpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1013, mode: os.FileMode(420), modTime: time.Unix(1586159062, 0)}
|
||||
info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1013, mode: os.FileMode(420), modTime: time.Unix(1586333177, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user