mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 20:07:23 +00:00
feat: Policy check (#149)
* check password complexity policy * check password complexity policy * fix tests * Update internal/admin/repository/eventsourcing/setup/setup.go Co-authored-by: Livio Amstutz <livio.a@gmail.com> * changes for mr Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
parent
5a7d44327e
commit
a4c7b39552
@ -10,13 +10,19 @@ import (
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||
org_view "github.com/caos/zitadel/internal/org/repository/view"
|
||||
policy_es "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_POLICY = "0"
|
||||
)
|
||||
|
||||
type OrgRepo struct {
|
||||
Eventstore eventstore.Eventstore
|
||||
OrgEventstore *org_es.OrgEventstore
|
||||
UserEventstore *usr_es.UserEventstore
|
||||
Eventstore eventstore.Eventstore
|
||||
OrgEventstore *org_es.OrgEventstore
|
||||
UserEventstore *usr_es.UserEventstore
|
||||
PolicyEventstore *policy_es.PolicyEventstore
|
||||
|
||||
View *admin_view.View
|
||||
|
||||
@ -24,12 +30,16 @@ type OrgRepo struct {
|
||||
}
|
||||
|
||||
func (repo *OrgRepo) SetUpOrg(ctx context.Context, setUp *admin_model.SetupOrg) (*admin_model.SetupOrg, error) {
|
||||
policy, err := repo.PolicyEventstore.GetPasswordComplexityPolicy(ctx, DEFAULT_POLICY)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
org, aggregates, err := repo.OrgEventstore.PrepareCreateOrg(ctx, setUp.Org)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, userAggregates, err := repo.UserEventstore.PrepareCreateUser(ctx, setUp.User, org.AggregateID)
|
||||
user, userAggregates, err := repo.UserEventstore.PrepareCreateUser(ctx, setUp.User, policy, org.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,12 +2,15 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
usr_model "github.com/caos/zitadel/internal/user/model"
|
||||
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
)
|
||||
|
||||
type UserRepo struct {
|
||||
UserEvents *usr_event.UserEventstore
|
||||
UserEvents *usr_event.UserEventstore
|
||||
PolicyEvents *policy_event.PolicyEventstore
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_model.User, err error) {
|
||||
@ -15,9 +18,21 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_mod
|
||||
}
|
||||
|
||||
func (repo *UserRepo) CreateUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
|
||||
return repo.UserEvents.CreateUser(ctx, user)
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, auth.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.CreateUser(ctx, user, policy)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
|
||||
return repo.UserEvents.RegisterUser(ctx, user, resourceOwner)
|
||||
policyResourceOwner := auth.GetCtxData(ctx).OrgID
|
||||
if resourceOwner != "" {
|
||||
policyResourceOwner = resourceOwner
|
||||
}
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, policyResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.RegisterUser(ctx, user, policy, resourceOwner)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
es_policy "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/eventstore"
|
||||
@ -61,7 +62,13 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policy, err := es_policy.StartPolicy(es_policy.PolicyConfig{
|
||||
Eventstore: es,
|
||||
Cache: conf.Eventstore.Cache,
|
||||
}, systemDefaults)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sqlClient, err := conf.View.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -71,7 +78,7 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eventstoreRepos := setup.EventstoreRepos{OrgEvents: org, UserEvents: user, ProjectEvents: project, IamEvents: iam}
|
||||
eventstoreRepos := setup.EventstoreRepos{OrgEvents: org, UserEvents: user, ProjectEvents: project, IamEvents: iam, PolicyEvents: policy}
|
||||
err = setup.StartSetup(systemDefaults, eventstoreRepos).Execute(ctx)
|
||||
logging.Log("SERVE-k280HZ").OnError(err).Panic("failed to execute setup")
|
||||
|
||||
|
@ -2,6 +2,8 @@ package setup
|
||||
|
||||
import (
|
||||
"context"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
@ -31,13 +33,15 @@ type EventstoreRepos struct {
|
||||
OrgEvents *org_event.OrgEventstore
|
||||
UserEvents *usr_event.UserEventstore
|
||||
ProjectEvents *proj_event.ProjectEventstore
|
||||
PolicyEvents *policy_event.PolicyEventstore
|
||||
}
|
||||
|
||||
type initializer struct {
|
||||
*Setup
|
||||
createdUsers map[string]*usr_model.User
|
||||
createdOrgs map[string]*org_model.Org
|
||||
createdProjects map[string]*proj_model.Project
|
||||
createdUsers map[string]*usr_model.User
|
||||
createdOrgs map[string]*org_model.Org
|
||||
createdProjects map[string]*proj_model.Project
|
||||
pwComplexityPolicy *policy_model.PasswordComplexityPolicy
|
||||
}
|
||||
|
||||
const (
|
||||
@ -55,6 +59,7 @@ const (
|
||||
OIDCAuthMethodType_NONE = "NONE"
|
||||
OIDCAuthMethodType_BASIC = "BASIC"
|
||||
OIDCAuthMethodType_POST = "POST"
|
||||
DEFAULT_POLICY = "0"
|
||||
)
|
||||
|
||||
func StartSetup(sd systemdefaults.SystemDefaults, repos EventstoreRepos) *Setup {
|
||||
@ -92,6 +97,13 @@ func (s *Setup) Execute(ctx context.Context) error {
|
||||
createdProjects: make(map[string]*proj_model.Project),
|
||||
}
|
||||
|
||||
pwComplexityPolicy, err := s.repos.PolicyEvents.GetPasswordComplexityPolicy(ctx, DEFAULT_POLICY)
|
||||
if err != nil {
|
||||
logging.Log("SETUP-9osWF").WithError(err).Error("unable to read complexity policy")
|
||||
return err
|
||||
}
|
||||
setUp.pwComplexityPolicy = pwComplexityPolicy
|
||||
|
||||
err = setUp.orgs(ctx, s.setUpConfig.Orgs)
|
||||
if err != nil {
|
||||
logging.Log("SETUP-p4oWq").WithError(err).Error("unable to set up orgs")
|
||||
@ -264,7 +276,7 @@ func (setUp *initializer) user(ctx context.Context, user types.User) (*usr_model
|
||||
SecretString: user.Password,
|
||||
},
|
||||
}
|
||||
return setUp.repos.UserEvents.CreateUser(ctx, createUser)
|
||||
return setUp.repos.UserEvents.CreateUser(ctx, createUser, setUp.pwComplexityPolicy)
|
||||
}
|
||||
|
||||
func (setUp *initializer) orgOwners(ctx context.Context, org *org_model.Org, owners []string) error {
|
||||
|
@ -7,13 +7,15 @@ import (
|
||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
"github.com/caos/zitadel/internal/user/model"
|
||||
user_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
)
|
||||
|
||||
type UserRepo struct {
|
||||
UserEvents *user_event.UserEventstore
|
||||
View *view.View
|
||||
UserEvents *user_event.UserEventstore
|
||||
PolicyEvents *policy_event.PolicyEventstore
|
||||
View *view.View
|
||||
}
|
||||
|
||||
func (repo *UserRepo) Health(ctx context.Context) error {
|
||||
@ -21,7 +23,15 @@ func (repo *UserRepo) Health(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (repo *UserRepo) Register(ctx context.Context, user *model.User, resourceOwner string) (*model.User, error) {
|
||||
return repo.UserEvents.RegisterUser(ctx, user, resourceOwner)
|
||||
policyResourceOwner := auth.GetCtxData(ctx).OrgID
|
||||
if resourceOwner != "" {
|
||||
policyResourceOwner = resourceOwner
|
||||
}
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, policyResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.RegisterUser(ctx, user, policy, resourceOwner)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyProfile(ctx context.Context) (*model.Profile, error) {
|
||||
@ -85,7 +95,11 @@ func (repo *UserRepo) ChangeMyAddress(ctx context.Context, address *model.Addres
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyPassword(ctx context.Context, old, new string) error {
|
||||
_, err := repo.UserEvents.ChangePassword(ctx, auth.GetCtxData(ctx).UserID, old, new)
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, auth.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = repo.UserEvents.ChangePassword(ctx, policy, auth.GetCtxData(ctx).UserID, old, new)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -114,7 +128,11 @@ func (repo *UserRepo) RequestPasswordReset(ctx context.Context, username string)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SetPassword(ctx context.Context, userID, code, password string) error {
|
||||
return repo.UserEvents.SetPassword(ctx, userID, code, password)
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, auth.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return repo.UserEvents.SetPassword(ctx, policy, userID, code, password)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SignOut(ctx context.Context, agentID, userID string) error {
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
"github.com/caos/zitadel/internal/id"
|
||||
es_policy "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
)
|
||||
|
||||
@ -44,7 +45,16 @@ func Start(conf Config, systemDefaults sd.SystemDefaults) (*EsRepository, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policy, err := es_policy.StartPolicy(
|
||||
es_policy.PolicyConfig{
|
||||
Eventstore: es,
|
||||
Cache: conf.Eventstore.Cache,
|
||||
},
|
||||
systemDefaults,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user, err := es_user.StartUser(
|
||||
es_user.UserConfig{
|
||||
Eventstore: es,
|
||||
@ -66,8 +76,9 @@ func Start(conf Config, systemDefaults sd.SystemDefaults) (*EsRepository, error)
|
||||
return &EsRepository{
|
||||
spool,
|
||||
eventstore.UserRepo{
|
||||
UserEvents: user,
|
||||
View: view,
|
||||
UserEvents: user,
|
||||
PolicyEvents: policy,
|
||||
View: view,
|
||||
},
|
||||
eventstore.AuthRequestRepo{
|
||||
UserEvents: user,
|
||||
|
@ -2,16 +2,19 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/auth"
|
||||
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
||||
policy_event "github.com/caos/zitadel/internal/policy/repository/eventsourcing"
|
||||
usr_model "github.com/caos/zitadel/internal/user/model"
|
||||
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||
"github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
type UserRepo struct {
|
||||
SearchLimit uint64
|
||||
UserEvents *usr_event.UserEventstore
|
||||
View *view.View
|
||||
SearchLimit uint64
|
||||
UserEvents *usr_event.UserEventstore
|
||||
PolicyEvents *policy_event.PolicyEventstore
|
||||
View *view.View
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_model.User, err error) {
|
||||
@ -19,11 +22,23 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (project *usr_mod
|
||||
}
|
||||
|
||||
func (repo *UserRepo) CreateUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
|
||||
return repo.UserEvents.CreateUser(ctx, user)
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, auth.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.CreateUser(ctx, user, policy)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
|
||||
return repo.UserEvents.RegisterUser(ctx, user, resourceOwner)
|
||||
policyResourceOwner := auth.GetCtxData(ctx).OrgID
|
||||
if resourceOwner != "" {
|
||||
policyResourceOwner = resourceOwner
|
||||
}
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, policyResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.RegisterUser(ctx, user, policy, resourceOwner)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) DeactivateUser(ctx context.Context, id string) (*usr_model.User, error) {
|
||||
@ -73,7 +88,11 @@ func (repo *UserRepo) UserMfas(ctx context.Context, userID string) ([]*usr_model
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SetOneTimePassword(ctx context.Context, password *usr_model.Password) (*usr_model.Password, error) {
|
||||
return repo.UserEvents.SetOneTimePassword(ctx, password)
|
||||
policy, err := repo.PolicyEvents.GetPasswordComplexityPolicy(ctx, auth.GetCtxData(ctx).OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.SetOneTimePassword(ctx, policy, password)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RequestSetPassword(ctx context.Context, id string, notifyType usr_model.NotificationType) error {
|
||||
|
@ -86,7 +86,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
|
||||
spooler: spool,
|
||||
OrgRepository: eventstore.OrgRepository{conf.SearchLimit, org, view, roles},
|
||||
ProjectRepo: eventstore.ProjectRepo{conf.SearchLimit, project, view, roles},
|
||||
UserRepo: eventstore.UserRepo{conf.SearchLimit, user, view},
|
||||
UserRepo: eventstore.UserRepo{conf.SearchLimit, user, policy, view},
|
||||
UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view},
|
||||
PolicyRepo: eventstore.PolicyRepo{policy},
|
||||
}, nil
|
||||
|
@ -1,6 +1,8 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type PasswordAgePolicy struct {
|
||||
models.ObjectRoot
|
||||
|
197
internal/policy/model/policy_complecity_test.go
Normal file
197
internal/policy/model/policy_complecity_test.go
Normal file
@ -0,0 +1,197 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCheckPasswordComplexityPolicy(t *testing.T) {
|
||||
type args struct {
|
||||
policy *PasswordComplexityPolicy
|
||||
password string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
hasError bool
|
||||
}{
|
||||
{
|
||||
name: "has minlength ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: false,
|
||||
HasSymbol: false,
|
||||
HasNumber: false,
|
||||
MinLength: 10,
|
||||
},
|
||||
password: "password12",
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "has minlength not ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: false,
|
||||
HasSymbol: false,
|
||||
HasNumber: false,
|
||||
MinLength: 10,
|
||||
},
|
||||
password: "password",
|
||||
},
|
||||
hasError: true,
|
||||
},
|
||||
{
|
||||
name: "has lowercase ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: true,
|
||||
HasUppercase: false,
|
||||
HasSymbol: false,
|
||||
HasNumber: false,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "password",
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "has lowercase not ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: true,
|
||||
HasUppercase: false,
|
||||
HasSymbol: false,
|
||||
HasNumber: false,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "PASSWORD",
|
||||
},
|
||||
hasError: true,
|
||||
},
|
||||
{
|
||||
name: "has uppercase ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: true,
|
||||
HasSymbol: false,
|
||||
HasNumber: false,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "PASSWORD",
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "has uppercase not ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: true,
|
||||
HasSymbol: false,
|
||||
HasNumber: false,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "password",
|
||||
},
|
||||
hasError: true,
|
||||
},
|
||||
{
|
||||
name: "has symbol ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: false,
|
||||
HasSymbol: true,
|
||||
HasNumber: false,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "!G$",
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "has symbol not ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: false,
|
||||
HasSymbol: true,
|
||||
HasNumber: false,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "PASSWORD",
|
||||
},
|
||||
hasError: true,
|
||||
},
|
||||
{
|
||||
name: "has number ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: false,
|
||||
HasSymbol: false,
|
||||
HasNumber: true,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "123456",
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "has number not ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: false,
|
||||
HasUppercase: false,
|
||||
HasSymbol: false,
|
||||
HasNumber: true,
|
||||
MinLength: 0,
|
||||
},
|
||||
password: "PASSWORD",
|
||||
},
|
||||
hasError: true,
|
||||
},
|
||||
{
|
||||
name: "has everything ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: true,
|
||||
HasUppercase: true,
|
||||
HasSymbol: true,
|
||||
HasNumber: true,
|
||||
MinLength: 10,
|
||||
},
|
||||
password: "Password1!",
|
||||
},
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "has everything not ok",
|
||||
args: args{
|
||||
policy: &PasswordComplexityPolicy{
|
||||
HasLowercase: true,
|
||||
HasUppercase: true,
|
||||
HasSymbol: true,
|
||||
HasNumber: true,
|
||||
MinLength: 10,
|
||||
},
|
||||
password: "password",
|
||||
},
|
||||
hasError: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.policy.Check(tt.args.password)
|
||||
if !tt.hasError && err != nil {
|
||||
t.Errorf("should not get err: %v", err)
|
||||
}
|
||||
if tt.hasError && err == nil {
|
||||
t.Errorf("should have error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +1,17 @@
|
||||
package model
|
||||
|
||||
import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
import (
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
hasStringLowerCase = regexp.MustCompile(`[a-z]`).MatchString
|
||||
hasStringUpperCase = regexp.MustCompile(`[A-Z]`).MatchString
|
||||
hasNumber = regexp.MustCompile(`[0-9]`).MatchString
|
||||
hasSymbol = regexp.MustCompile(`[^A-Za-z0-9]`).MatchString
|
||||
)
|
||||
|
||||
type PasswordComplexityPolicy struct {
|
||||
models.ObjectRoot
|
||||
@ -17,3 +28,26 @@ type PasswordComplexityPolicy struct {
|
||||
func (p *PasswordComplexityPolicy) IsValid() bool {
|
||||
return p.Description != ""
|
||||
}
|
||||
|
||||
func (p *PasswordComplexityPolicy) Check(password string) error {
|
||||
if p.MinLength != 0 && uint64(len(password)) < p.MinLength {
|
||||
return caos_errs.ThrowInvalidArgumentf(nil, "MODEL-HuJf6", "Passwordpolicy doesn't match: Minlength %v", p.MinLength)
|
||||
}
|
||||
|
||||
if p.HasLowercase && !hasStringLowerCase(password) {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "MODEL-co3Xw", "Passwordpolicy doesn't match: HasLowerCase")
|
||||
}
|
||||
|
||||
if p.HasUppercase && !hasStringUpperCase(password) {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "MODEL-VoaRj", "Passwordpolicy doesn't match: HasUpperCase")
|
||||
}
|
||||
|
||||
if p.HasNumber && !hasNumber(password) {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "MODEL-ZBv4H", "Passwordpolicy doesn't match: HasNumber")
|
||||
}
|
||||
|
||||
if p.HasSymbol && !hasSymbol(password) {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "MODEL-ZDLwA", "Passwordpolicy doesn't match: HasSymbol")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -33,10 +35,16 @@ func (p *Password) IsValid() bool {
|
||||
return p.AggregateID != "" && p.SecretString != ""
|
||||
}
|
||||
|
||||
func (p *Password) HashPasswordIfExisting(passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
||||
func (p *Password) HashPasswordIfExisting(policy *policy_model.PasswordComplexityPolicy, passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
||||
if p.SecretString == "" {
|
||||
return nil
|
||||
}
|
||||
if policy == nil {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "MODEL-s8ifS", "Policy should not be nil")
|
||||
}
|
||||
if err := policy.Check(p.SecretString); err != nil {
|
||||
return err
|
||||
}
|
||||
secret, err := crypto.Hash([]byte(p.SecretString), passwordAlg)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1,6 +1,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
@ -85,9 +86,9 @@ func (u *User) IsOTPReady() bool {
|
||||
return u.OTP != nil && u.OTP.State == MFASTATE_READY
|
||||
}
|
||||
|
||||
func (u *User) HashPasswordIfExisting(passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
||||
func (u *User) HashPasswordIfExisting(policy *policy_model.PasswordComplexityPolicy, passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
||||
if u.Password != nil {
|
||||
return u.Password.HashPasswordIfExisting(passwordAlg, onetime)
|
||||
return u.Password.HashPasswordIfExisting(policy, passwordAlg, onetime)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package eventsourcing
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/id"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
|
||||
"github.com/pquerna/otp/totp"
|
||||
|
||||
req_model "github.com/caos/zitadel/internal/auth_request/model"
|
||||
@ -87,20 +89,19 @@ func (es *UserEventstore) UserByID(ctx context.Context, id string) (*usr_model.U
|
||||
return model.UserToModel(user), nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||
func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model.User, policy *policy_model.PasswordComplexityPolicy, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||
user.SetEmailAsUsername()
|
||||
if !user.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "User is invalid")
|
||||
}
|
||||
|
||||
//TODO: Check Uniqueness
|
||||
id, err := es.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
user.AggregateID = id
|
||||
|
||||
err = user.HashPasswordIfExisting(es.PasswordAlg, true)
|
||||
err = user.HashPasswordIfExisting(policy, es.PasswordAlg, true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -122,8 +123,8 @@ func (es *UserEventstore) PrepareCreateUser(ctx context.Context, user *usr_model
|
||||
return repoUser, createAggregates, err
|
||||
}
|
||||
|
||||
func (es *UserEventstore) CreateUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
|
||||
repoUser, aggregates, err := es.PrepareCreateUser(ctx, user, "")
|
||||
func (es *UserEventstore) CreateUser(ctx context.Context, user *usr_model.User, policy *policy_model.PasswordComplexityPolicy) (*usr_model.User, error) {
|
||||
repoUser, aggregates, err := es.PrepareCreateUser(ctx, user, policy, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -137,19 +138,18 @@ func (es *UserEventstore) CreateUser(ctx context.Context, user *usr_model.User)
|
||||
return model.UserToModel(repoUser), nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) PrepareRegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||
func (es *UserEventstore) PrepareRegisterUser(ctx context.Context, user *usr_model.User, policy *policy_model.PasswordComplexityPolicy, resourceOwner string) (*model.User, []*es_models.Aggregate, error) {
|
||||
user.SetEmailAsUsername()
|
||||
if !user.IsValid() || user.Password == nil || user.SecretString == "" {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9dk45", "user is invalid")
|
||||
}
|
||||
//TODO: Check Uniqueness
|
||||
id, err := es.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
user.AggregateID = id
|
||||
|
||||
err = user.HashPasswordIfExisting(es.PasswordAlg, false)
|
||||
err = user.HashPasswordIfExisting(policy, es.PasswordAlg, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -165,8 +165,8 @@ func (es *UserEventstore) PrepareRegisterUser(ctx context.Context, user *usr_mod
|
||||
return repoUser, aggregates, err
|
||||
}
|
||||
|
||||
func (es *UserEventstore) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
|
||||
repoUser, createAggregates, err := es.PrepareRegisterUser(ctx, user, resourceOwner)
|
||||
func (es *UserEventstore) RegisterUser(ctx context.Context, user *usr_model.User, policy *policy_model.PasswordComplexityPolicy, resourceOwner string) (*usr_model.User, error) {
|
||||
repoUser, createAggregates, err := es.PrepareRegisterUser(ctx, user, policy, resourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -380,15 +380,15 @@ func (es *UserEventstore) setPasswordCheckResult(ctx context.Context, user *usr_
|
||||
return nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) SetOneTimePassword(ctx context.Context, password *usr_model.Password) (*usr_model.Password, error) {
|
||||
func (es *UserEventstore) SetOneTimePassword(ctx context.Context, policy *policy_model.PasswordComplexityPolicy, password *usr_model.Password) (*usr_model.Password, error) {
|
||||
user, err := es.UserByID(ctx, password.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es.changedPassword(ctx, user, password.SecretString, true)
|
||||
return es.changedPassword(ctx, user, policy, password.SecretString, true)
|
||||
}
|
||||
|
||||
func (es *UserEventstore) SetPassword(ctx context.Context, userID, code, password string) error {
|
||||
func (es *UserEventstore) SetPassword(ctx context.Context, policy *policy_model.PasswordComplexityPolicy, userID, code, password string) error {
|
||||
user, err := es.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -399,11 +399,11 @@ func (es *UserEventstore) SetPassword(ctx context.Context, userID, code, passwor
|
||||
if err := crypto.VerifyCode(user.PasswordCode.CreationDate, user.PasswordCode.Expiry, user.PasswordCode.Code, code, es.PasswordVerificationCode); err != nil {
|
||||
return caos_errs.ThrowPreconditionFailed(err, "EVENT-sd6DF", "code invalid")
|
||||
}
|
||||
_, err = es.changedPassword(ctx, user, password, false)
|
||||
_, err = es.changedPassword(ctx, user, policy, password, false)
|
||||
return err
|
||||
}
|
||||
|
||||
func (es *UserEventstore) ChangePassword(ctx context.Context, userID, old, new string) (*usr_model.Password, error) {
|
||||
func (es *UserEventstore) ChangePassword(ctx context.Context, policy *policy_model.PasswordComplexityPolicy, userID, old, new string) (*usr_model.Password, error) {
|
||||
user, err := es.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -414,16 +414,16 @@ func (es *UserEventstore) ChangePassword(ctx context.Context, userID, old, new s
|
||||
if err := crypto.CompareHash(user.Password.SecretCrypto, []byte(old), es.PasswordAlg); err != nil {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "EVENT-s56a3", "invalid password")
|
||||
}
|
||||
return es.changedPassword(ctx, user, new, false)
|
||||
return es.changedPassword(ctx, user, policy, new, false)
|
||||
}
|
||||
|
||||
func (es *UserEventstore) changedPassword(ctx context.Context, user *usr_model.User, password string, onetime bool) (*usr_model.Password, error) {
|
||||
//TODO: check password policy
|
||||
secret, err := crypto.Hash([]byte(password), es.PasswordAlg)
|
||||
func (es *UserEventstore) changedPassword(ctx context.Context, user *usr_model.User, policy *policy_model.PasswordComplexityPolicy, password string, onetime bool) (*usr_model.Password, error) {
|
||||
pw := &usr_model.Password{SecretString: password}
|
||||
err := pw.HashPasswordIfExisting(policy, es.PasswordAlg, onetime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoPassword := &model.Password{Secret: secret, ChangeRequired: onetime}
|
||||
repoPassword := model.PasswordFromModel(pw)
|
||||
repoUser := model.UserFromModel(user)
|
||||
agg := PasswordChangeAggregate(es.AggregateCreator(), repoUser, repoPassword)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoUser.AppendEvents, agg)
|
||||
|
@ -2,6 +2,7 @@ package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
@ -83,9 +84,10 @@ func TestUserByID(t *testing.T) {
|
||||
func TestCreateUser(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *UserEventstore
|
||||
ctx context.Context
|
||||
user *model.User
|
||||
es *UserEventstore
|
||||
ctx context.Context
|
||||
user *model.User
|
||||
policy *policy_model.PasswordComplexityPolicy
|
||||
}
|
||||
type res struct {
|
||||
user *model.User
|
||||
@ -113,6 +115,7 @@ func TestCreateUser(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
},
|
||||
res: res{
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
|
||||
@ -143,6 +146,7 @@ func TestCreateUser(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
},
|
||||
res: res{
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
|
||||
@ -178,6 +182,7 @@ func TestCreateUser(t *testing.T) {
|
||||
IsPhoneVerified: true,
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
},
|
||||
res: res{
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
|
||||
@ -214,6 +219,7 @@ func TestCreateUser(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
},
|
||||
res: res{
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
|
||||
@ -231,6 +237,18 @@ func TestCreateUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "create user invalid",
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
},
|
||||
res: res{
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "create user policy nil",
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
@ -243,7 +261,7 @@ func TestCreateUser(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.CreateUser(tt.args.ctx, tt.args.user)
|
||||
result, err := tt.args.es.CreateUser(tt.args.ctx, tt.args.user, tt.args.policy)
|
||||
|
||||
if tt.res.errFunc == nil && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
@ -275,6 +293,7 @@ func TestRegisterUser(t *testing.T) {
|
||||
ctx context.Context
|
||||
user *model.User
|
||||
resourceOwner string
|
||||
policy *policy_model.PasswordComplexityPolicy
|
||||
}
|
||||
type res struct {
|
||||
user *model.User
|
||||
@ -304,6 +323,7 @@ func TestRegisterUser(t *testing.T) {
|
||||
SecretString: "Password",
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
resourceOwner: "ResourceOwner",
|
||||
},
|
||||
res: res{
|
||||
@ -336,6 +356,7 @@ func TestRegisterUser(t *testing.T) {
|
||||
SecretString: "Password",
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
resourceOwner: "ResourceOwner",
|
||||
},
|
||||
res: res{
|
||||
@ -357,6 +378,7 @@ func TestRegisterUser(t *testing.T) {
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1}},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
resourceOwner: "ResourceOwner",
|
||||
},
|
||||
res: res{
|
||||
@ -378,6 +400,7 @@ func TestRegisterUser(t *testing.T) {
|
||||
EmailAddress: "EmailAddress",
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
resourceOwner: "ResourceOwner",
|
||||
},
|
||||
res: res{
|
||||
@ -386,6 +409,27 @@ func TestRegisterUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "no resourceowner",
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
|
||||
Profile: &model.Profile{
|
||||
UserName: "EmailAddress",
|
||||
FirstName: "FirstName",
|
||||
LastName: "LastName",
|
||||
},
|
||||
Email: &model.Email{
|
||||
EmailAddress: "EmailAddress",
|
||||
},
|
||||
},
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
},
|
||||
res: res{
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no policy",
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
@ -407,7 +451,7 @@ func TestRegisterUser(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.RegisterUser(tt.args.ctx, tt.args.user, tt.args.resourceOwner)
|
||||
result, err := tt.args.es.RegisterUser(tt.args.ctx, tt.args.user, tt.args.policy, tt.args.resourceOwner)
|
||||
|
||||
if tt.res.errFunc == nil && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
@ -1029,6 +1073,7 @@ func TestSetOneTimePassword(t *testing.T) {
|
||||
type args struct {
|
||||
es *UserEventstore
|
||||
ctx context.Context
|
||||
policy *policy_model.PasswordComplexityPolicy
|
||||
password *model.Password
|
||||
}
|
||||
type res struct {
|
||||
@ -1045,6 +1090,7 @@ func TestSetOneTimePassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}}),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, SecretString: "Password"},
|
||||
},
|
||||
res: res{
|
||||
@ -1056,6 +1102,7 @@ func TestSetOneTimePassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: ""}, SecretString: "Password"},
|
||||
},
|
||||
res: res{
|
||||
@ -1067,6 +1114,7 @@ func TestSetOneTimePassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUserNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, SecretString: "Password"},
|
||||
},
|
||||
res: res{
|
||||
@ -1076,7 +1124,7 @@ func TestSetOneTimePassword(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.SetOneTimePassword(tt.args.ctx, tt.args.password)
|
||||
result, err := tt.args.es.SetOneTimePassword(tt.args.ctx, tt.args.policy, tt.args.password)
|
||||
|
||||
if tt.res.errFunc == nil && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
@ -1226,6 +1274,7 @@ func TestSetPassword(t *testing.T) {
|
||||
type args struct {
|
||||
es *UserEventstore
|
||||
ctx context.Context
|
||||
policy *policy_model.PasswordComplexityPolicy
|
||||
userID string
|
||||
code string
|
||||
password string
|
||||
@ -1253,6 +1302,7 @@ func TestSetPassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
code: "code",
|
||||
password: "password",
|
||||
@ -1264,6 +1314,7 @@ func TestSetPassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "",
|
||||
code: "code",
|
||||
password: "password",
|
||||
@ -1277,6 +1328,7 @@ func TestSetPassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUserNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
code: "code",
|
||||
password: "password",
|
||||
@ -1294,6 +1346,7 @@ func TestSetPassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
code: "code",
|
||||
password: "password",
|
||||
@ -1317,6 +1370,7 @@ func TestSetPassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
code: "code",
|
||||
password: "password",
|
||||
@ -1328,7 +1382,7 @@ func TestSetPassword(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.args.es.SetPassword(tt.args.ctx, tt.args.userID, tt.args.code, tt.args.password)
|
||||
err := tt.args.es.SetPassword(tt.args.ctx, tt.args.policy, tt.args.userID, tt.args.code, tt.args.password)
|
||||
|
||||
if tt.res.errFunc == nil && err != nil {
|
||||
t.Errorf("result has error: %v", err)
|
||||
@ -1345,6 +1399,7 @@ func TestChangePassword(t *testing.T) {
|
||||
type args struct {
|
||||
es *UserEventstore
|
||||
ctx context.Context
|
||||
policy *policy_model.PasswordComplexityPolicy
|
||||
userID string
|
||||
old string
|
||||
new string
|
||||
@ -1372,6 +1427,7 @@ func TestChangePassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
old: "old",
|
||||
new: "new",
|
||||
@ -1385,6 +1441,7 @@ func TestChangePassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUser(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "",
|
||||
old: "old",
|
||||
new: "new",
|
||||
@ -1398,6 +1455,7 @@ func TestChangePassword(t *testing.T) {
|
||||
args: args{
|
||||
es: GetMockManipulateUserNoEvents(ctrl),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
old: "old",
|
||||
new: "new",
|
||||
@ -1415,6 +1473,7 @@ func TestChangePassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
old: "old",
|
||||
new: "new",
|
||||
@ -1437,6 +1496,7 @@ func TestChangePassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
policy: &policy_model.PasswordComplexityPolicy{},
|
||||
userID: "userID",
|
||||
old: "old",
|
||||
new: "new",
|
||||
@ -1445,10 +1505,32 @@ func TestChangePassword(t *testing.T) {
|
||||
errFunc: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no policy",
|
||||
args: args{
|
||||
es: GetMockManipulateUserWithPasswordAndEmailCodeGen(ctrl,
|
||||
repo_model.User{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
Password: &repo_model.Password{Secret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeHash,
|
||||
Algorithm: "hash",
|
||||
Crypted: []byte("old"),
|
||||
}},
|
||||
},
|
||||
),
|
||||
ctx: auth.NewMockContext("orgID", "userID"),
|
||||
userID: "userID",
|
||||
old: "old",
|
||||
new: "new",
|
||||
},
|
||||
res: res{
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ChangePassword(tt.args.ctx, tt.args.userID, tt.args.old, tt.args.new)
|
||||
result, err := tt.args.es.ChangePassword(tt.args.ctx, tt.args.policy, tt.args.userID, tt.args.old, tt.args.new)
|
||||
|
||||
if tt.res.errFunc == nil && result.AggregateID == "" {
|
||||
t.Errorf("result has no id")
|
||||
|
Loading…
x
Reference in New Issue
Block a user