zitadel/internal/user/repository/eventsourcing/eventstore_test.go
Silvan 5abd5b0505
feat: split users into human and machine (#470)
* feat(management): service accounts

* chore: current go version

* init

* refactor: apis

* feat(internal): start impl of service account

* chore: start impl of machine/human users

* code compiles

* fix: tests

* fix: tests

* fix: add new event types to switches

* chore: add cases to event types

* fix(management): definitive proto messages

* fix: machine/human

* fix: add missing tables as todos

* fix: remove unused permissions

* fix: refactoring

* fix: refactor

* fix: human registered

* fix: user id

* fix: logid

* fix: proto remove //equal

* chore(management): remove no comment

* fix: human mfas

* fix: user subobjects

* chore: rename existing to better name

* fix: username in user (#634)

* fix: username in user

* fix: username

* fix remove unused code

* fix add validations

* fix: use new user in all apis

* fix: regexp for username in api

* fix: fill user data for human and machine (#638)

* fix: fill Display name grant/member handlers
fix: add description to grant/member objects in api
fix: check if user is human in login

* fix: remove description from member and grant

* chore: remove todos

* feat: machine keys

* fix: implement missing parts

* feat: machine key management view

* fix: remove keys from machine view

* fix: set default expiration date

* fix: get key by ids

* feat: add machine keys in proto

* feat: machine keys

* fix: add migration

* fix: mig

* fix: correct method name

* feat: user search

* feat: user search

* fix: log ids

* fix partial authconfig prompt, domain c perm

* membership read check

* contributor refresh trigger, observe org write

* fix: migrations

* fix(console): machine build (#660)

* frontend 1

* fix html bindings

* trailing comma

* user permissions, project deactivate

* fix(console): human view (#661)

* fix search user view, user detail form

* rm log

* feat(console): user services list and create (#663)

* fix search user view, user detail form

* rm log

* machine list

* generic table component

* create user service

* proove table for undefined values

* tmp disable user link if machine

* lint

* lint styles

* user table lint

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* feat(console): service user detail view, keys cr_d, fix search user autocomplete (#664)

* service users for sidenav, routing

* i18n

* back routes

* machine detail form

* update machine detail, fix svc user grants

* keys table

* add key dialog, timestamp creation

* check permission on create, delete, fix selection

* lint ts, scss

* Update console/src/assets/i18n/de.json

* Apply suggestions from code review

Co-authored-by: Florian Forster <florian@caos.ch>

* allow user grants for project.write

* management service

* fix mgmt service

* feat: Machine keys (#655)

* fix: memberships (#633)

* feat: add iam members to memberships

* fix: search project grants

* fix: rename

* feat: idp and login policy configurations (#619)

* feat: oidc config

* fix: oidc configurations

* feat: oidc idp config

* feat: add oidc config test

* fix: tests

* fix: tests

* feat: translate new events

* feat: idp eventstore

* feat: idp eventstore

* fix: tests

* feat: command side idp

* feat: query side idp

* feat: idp config on org

* fix: tests

* feat: authz idp on org

* feat: org idps

* feat: login policy

* feat: login policy

* feat: login policy

* feat: add idp func on login policy

* feat: add validation to loginpolicy and idp provider

* feat: add default login policy

* feat: login policy on org

* feat: login policy on org

* fix: id config handlers

* fix: id config handlers

* fix: create idp on org

* fix: create idp on org

* fix: not existing idp config

* fix: default login policy

* fix: add login policy on org

* fix: idp provider search on org

* fix: test

* fix: remove idp on org

* fix: test

* fix: test

* fix: remove admin idp

* fix: logo src as byte

* fix: migration

* fix: tests

* Update internal/iam/repository/eventsourcing/iam.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/iam/repository/eventsourcing/iam_test.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/iam/repository/eventsourcing/iam_test.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/iam/repository/eventsourcing/model/login_policy.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/iam/repository/eventsourcing/model/login_policy.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/org/repository/eventsourcing/org_test.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/iam/repository/eventsourcing/model/login_policy_test.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* Update internal/iam/repository/eventsourcing/model/login_policy_test.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

* fix: pr comments

* fix: tests

* Update types.go

* fix: merge request changes

* fix: reduce optimization

Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: reread user mfas, preferred loginname as otp account name (#636)

* fix: reread user mfas

* fix: use preferred login name as otp account name

* fix: tests

* fix: reduce (#635)

* fix: management reduce optimization

* fix: reduce optimization

* fix: reduce optimization

* fix: merge master

* chore(deps): bump github.com/gorilla/schema from 1.1.0 to 1.2.0 (#627)

Bumps [github.com/gorilla/schema](https://github.com/gorilla/schema) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/gorilla/schema/releases)
- [Commits](https://github.com/gorilla/schema/compare/v1.1.0...v1.2.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump github.com/gorilla/mux from 1.7.4 to 1.8.0 (#624)

Bumps [github.com/gorilla/mux](https://github.com/gorilla/mux) from 1.7.4 to 1.8.0.
- [Release notes](https://github.com/gorilla/mux/releases)
- [Commits](https://github.com/gorilla/mux/compare/v1.7.4...v1.8.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump github.com/DATA-DOG/go-sqlmock from 1.4.1 to 1.5.0 (#591)

Bumps [github.com/DATA-DOG/go-sqlmock](https://github.com/DATA-DOG/go-sqlmock) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/DATA-DOG/go-sqlmock/releases)
- [Commits](https://github.com/DATA-DOG/go-sqlmock/compare/v1.4.1...v1.5.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: auto assign issues and PR to ZTIADEL project board (#643)

* Create main.yml

* Update main.yml

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix(console): project grant members, update deps (#645)

* fix: searchprojectgrantmembers

* chore(deps-dev): bump @angular/cli from 10.0.6 to 10.0.7 in /console (#622)

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 10.0.6 to 10.0.7.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v10.0.6...v10.0.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#626)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1000.6 to 0.1000.7.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>

* chore(deps-dev): bump @types/jasmine from 3.5.12 to 3.5.13 in /console (#623)

Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.5.12 to 3.5.13.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump ts-node from 8.10.2 to 9.0.0 in /console (#629)

Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 8.10.2 to 9.0.0.
- [Release notes](https://github.com/TypeStrong/ts-node/releases)
- [Commits](https://github.com/TypeStrong/ts-node/compare/v8.10.2...v9.0.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* update packlock

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: delete main.yml (#648)

* fix: usergrant (#650)

* fix(console): mfa refresh after verification, member eventemitter (#651)

* refresh mfa

* fix: detail link from contributors

* lint

* feat: add domain verification notification (#649)

* fix: dont (re)generate client secret with auth type none

* fix(cors): allow Origin from request

* feat: add origin allow list and fix some core issues

* rename migration

* fix UserIDsByDomain

* feat: send email to users after domain claim

* username

* check origin on userinfo

* update oidc pkg

* fix: add migration 1.6

* change username

* change username

* remove unique email aggregate

* change username in mgmt

* search global user by login name

* fix test

* change user search in angular

* fix tests

* merge

* userview in angular

* fix merge

* Update pkg/grpc/management/proto/management.proto

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update internal/notification/static/i18n/de.yaml

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* fix

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* fix: translation (#647)

* fix: translation

* fix: translation

* fix: translation

* fix: remove unused code

* fix: log err

* fix: migration numbers (#652)

* chore: issue / feature templates (#642)

* feat: machine keys

* fix: implement missing parts

* feat: machine key management view

* fix: remove keys from machine view

* feat: global org read (#657)

* fix: set default expiration date

* fix: get key by ids

* feat: add machine keys in proto

* feat: machine keys

* fix: add migration

* fix: mig

* fix: correct method name

* feat: user search

* feat: user search

* fix: log ids

* fix: migrations

* fix(console): machine build (#660)

* frontend 1

* fix html bindings

* trailing comma

* fix(console): human view (#661)

* fix search user view, user detail form

* rm log

* feat(console): user services list and create (#663)

* fix search user view, user detail form

* rm log

* machine list

* generic table component

* create user service

* proove table for undefined values

* tmp disable user link if machine

* lint

* lint styles

* user table lint

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* feat(console): service user detail view, keys cr_d, fix search user autocomplete (#664)

* service users for sidenav, routing

* i18n

* back routes

* machine detail form

* update machine detail, fix svc user grants

* keys table

* add key dialog, timestamp creation

* check permission on create, delete, fix selection

* lint ts, scss

* Update console/src/assets/i18n/de.json

* Apply suggestions from code review

Co-authored-by: Florian Forster <florian@caos.ch>

* refactor: protos

* fix(management): key expiration date

* fix: check if user is human

* fix: marshal key details

* fix: correct generate login names

* fix: logid

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Fabiennne <fabienne.gerschwiler@gmail.com>
Co-authored-by: Florian Forster <florian@caos.ch>

* fix: naming

* refactor: findings

* fix: username

* fix: mfa upper case

* fix: tests

* fix: add translations

* reactivatemyorg req typeö

* fix: projectType for console

* fix: user changes

* fix: translate events

* fix: event type translation

* fix: remove unused types

Co-authored-by: Fabiennne <fabienne.gerschwiler@gmail.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-08-31 17:48:01 +02:00

3533 lines
93 KiB
Go

package eventsourcing
import (
"context"
"encoding/json"
"net"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/caos/zitadel/internal/api/authz"
req_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/crypto"
caos_errs "github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
org_model "github.com/caos/zitadel/internal/org/model"
policy_model "github.com/caos/zitadel/internal/policy/model"
"github.com/caos/zitadel/internal/user/model"
repo_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
)
func TestUserByID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
user *model.User
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "user from events, ok",
args: args{
es: GetMockUserByIDOK(ctrl, repo_model.User{Human: &repo_model.Human{Profile: &repo_model.Profile{DisplayName: "DisplayName"}}, UserName: "UserName"}),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
user: &model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{DisplayName: "DisplayName"},
},
},
},
},
{
name: "no events found",
args: args{
es: GetMockUserByIDNoEvents(ctrl),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "no id",
args: args{
es: GetMockUserByIDNoEvents(ctrl),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.UserByID(nil, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID != tt.res.user.AggregateID {
t.Errorf("got wrong result aggregateID: expected: %v, actual: %v ", tt.res.user.AggregateID, result.AggregateID)
}
if tt.res.errFunc == nil && result.UserName != tt.res.user.UserName {
t.Errorf("got wrong result userName: expected: %v, actual: %v ", tt.res.user.UserName, result.UserName)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCreateUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
policy *policy_model.PasswordComplexityPolicy
orgPolicy *org_model.OrgIAMPolicy
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "init mail because no pw",
args: args{
es: GetMockManipulateUserWithInitCodeGen(ctrl, repo_model.User{
UserName: "",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName", FirstName: "FirstName", LastName: "LastName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress", IsEmailVerified: true},
},
}),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{
ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
user: &model.User{
ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
},
},
},
},
{
name: "email as username",
args: args{
es: GetMockManipulateUserWithInitCodeGen(ctrl, repo_model.User{
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName", FirstName: "FirstName", LastName: "LastName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress", IsEmailVerified: true},
},
}),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{UserLoginMustBeDomain: false},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "EmailAddress",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
},
},
},
},
{
name: "with verified phone number",
args: args{
es: GetMockManipulateUserWithInitCodeGen(ctrl, repo_model.User{
UserName: "EmailAddress",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName", FirstName: "FirstName", LastName: "LastName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress", IsEmailVerified: true},
Phone: &repo_model.Phone{PhoneNumber: "+41711234567", IsPhoneVerified: true},
},
}),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "UserName",
IsEmailVerified: true,
},
Phone: &model.Phone{
PhoneNumber: "+41711234567",
IsPhoneVerified: true,
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
Phone: &model.Phone{
PhoneNumber: "+41711234567",
IsPhoneVerified: true,
},
},
},
},
},
{
name: "with password",
args: args{
es: GetMockManipulateUserWithPasswordAndEmailCodeGen(ctrl, repo_model.User{
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName", FirstName: "FirstName", LastName: "LastName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress", IsEmailVerified: true}},
}),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Password: &model.Password{SecretString: "Password"},
Email: &model.Email{
EmailAddress: "UserName",
IsEmailVerified: true,
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
},
},
},
},
{
name: "create user invalid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "create user pw policy nil",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "create user org policy nil",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
policy: &policy_model.PasswordComplexityPolicy{},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.CreateUser(tt.args.ctx, tt.args.user, tt.args.policy, tt.args.orgPolicy)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.UserName != tt.res.user.UserName {
t.Errorf("got wrong result username: expected: %v, actual: %v ", tt.res.user.UserName, result.UserName)
}
if tt.res.errFunc == nil && tt.res.user.Email != nil {
if result.IsEmailVerified != tt.res.user.IsEmailVerified {
t.Errorf("got wrong result IsEmailVerified: expected: %v, actual: %v ", tt.res.user.IsEmailVerified, result.IsEmailVerified)
}
}
if tt.res.errFunc == nil && tt.res.user.Phone != nil {
if result.IsPhoneVerified != tt.res.user.IsPhoneVerified {
t.Errorf("got wrong result IsPhoneVerified: expected: %v, actual: %v ", tt.res.user.IsPhoneVerified, result.IsPhoneVerified)
}
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestRegisterUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
resourceOwner string
policy *policy_model.PasswordComplexityPolicy
orgPolicy *org_model.OrgIAMPolicy
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "register user, ok",
args: args{
es: GetMockManipulateUserWithPasswordInitCodeGen(ctrl, repo_model.User{
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName", FirstName: "FirstName", LastName: "LastName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"}}},
),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{
ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
Password: &model.Password{
SecretString: "Password",
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{UserLoginMustBeDomain: true},
resourceOwner: "ResourceOwner",
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "UserName",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
},
},
},
},
{
name: "email as username",
args: args{
es: GetMockManipulateUserWithPasswordInitCodeGen(ctrl, repo_model.User{
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName", FirstName: "FirstName", LastName: "LastName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"}}},
),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
Password: &model.Password{
SecretString: "Password",
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{UserLoginMustBeDomain: false},
resourceOwner: "ResourceOwner",
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "EmailAddress",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
},
},
},
},
{
name: "invalid user",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1}, Human: &model.Human{}},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
resourceOwner: "ResourceOwner",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "register user no password",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "EmailAddress",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
resourceOwner: "ResourceOwner",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "no resourceowner",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "EmailAddress",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "no pw policy",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "EmailAddress",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
},
},
orgPolicy: &org_model.OrgIAMPolicy{},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "no org policy",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{Sequence: 1},
UserName: "EmailAddress",
Human: &model.Human{
Profile: &model.Profile{
FirstName: "FirstName",
LastName: "LastName",
DisplayName: "DisplayName",
},
Email: &model.Email{
EmailAddress: "EmailAddress",
},
},
},
policy: &policy_model.PasswordComplexityPolicy{},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
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.policy, tt.args.orgPolicy, tt.args.resourceOwner)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.UserName != tt.res.user.UserName {
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.user.UserName, result.UserName)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestDeactivateUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "deactivate user, ok",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, State: model.UserStateInactive},
},
},
{
name: "deactivate user with inactive state",
args: args{
es: GetMockManipulateInactiveUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.DeactivateUser(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.State != tt.res.user.State {
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.user.State, result.State)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestReactivateUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "reactivate user, ok",
args: args{
es: GetMockManipulateInactiveUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, State: model.UserStateActive},
},
},
{
name: "reactivate user with inital state",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ReactivateUser(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.State != tt.res.user.State {
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.user.State, result.State)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestLockUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "lock user, ok",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, State: model.UserStateLocked},
},
},
{
name: "lock user with locked state",
args: args{
es: GetMockManipulateLockedUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.LockUser(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.State != tt.res.user.State {
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.user.State, result.State)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestUnlockUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
user *model.User
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "unlock user, ok",
args: args{
es: GetMockManipulateLockedUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, State: model.UserStateActive},
},
},
{
name: "unlock user not locked state",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.UnlockUser(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.State != tt.res.user.State {
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.user.State, result.State)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestGetInitCodeByID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
code *model.InitUserCode
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserWithInitCode(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{
DisplayName: "DisplayName",
},
},
}),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
code: &model.InitUserCode{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Expiry: time.Hour * 30},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.InitializeUserCodeByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result == nil {
t.Error("got wrong result code should not be nil", result)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCreateInitCode(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
code *model.InitUserCode
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "create init code",
args: args{
es: GetMockManipulateUserWithPasswordInitCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}}),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
},
res: res{
code: &model.InitUserCode{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Expiry: time.Hour * 1},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}, Human: &model.Human{}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.CreateInitializeUserCodeByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result == nil {
t.Errorf("got wrong result code is nil")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestInitCodeSent(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "sent init",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.InitCodeSent(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("rshould not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestInitCodeVerify(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
policy *policy_model.PasswordComplexityPolicy
userID string
verifyCode string
password string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "verify init code, no pw",
args: args{
es: GetMockManipulateUserWithInitCode(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Email: &repo_model.Email{
EmailAddress: "EmailAddress",
},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
verifyCode: "code",
userID: "userID",
},
},
{
name: "verify init code, pw",
args: args{
es: GetMockManipulateUserWithInitCode(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Email: &repo_model.Email{
EmailAddress: "EmailAddress",
IsEmailVerified: true,
},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
verifyCode: "code",
password: "password",
},
},
{
name: "verify init code, email and pw",
args: args{
es: GetMockManipulateUserWithInitCode(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Email: &repo_model.Email{
EmailAddress: "EmailAddress",
},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
verifyCode: "code",
password: "password",
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "",
verifyCode: "code",
password: "password",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "password policy not matched",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{HasNumber: true},
userID: "userID",
verifyCode: "code",
password: "password",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEventsWithPw(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
password: "password",
verifyCode: "code",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.VerifyInitCode(tt.args.ctx, tt.args.policy, tt.args.userID, tt.args.verifyCode, tt.args.password)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not have err: %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v", err)
}
})
}
}
func TestSkipMfaInit(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "skip mfa init",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.SkipMfaInit(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("rshould not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestPasswordID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
password *model.Password
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, ChangeRequired: true},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "existing pw not found",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.UserPasswordByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.ChangeRequired != tt.res.password.ChangeRequired {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.password.ChangeRequired, result.ChangeRequired)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestSetOneTimePassword(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
policy *policy_model.PasswordComplexityPolicy
password *model.Password
}
type res struct {
password *model.Password
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "create one time pw",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, SecretString: "Password"},
},
res: res{
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, ChangeRequired: true},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: ""}, SecretString: "Password"},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, SecretString: "Password"},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
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")
}
if tt.res.errFunc == nil && result.ChangeRequired != true {
t.Errorf("should be one time")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCheckPassword(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
password string
authRequest *req_model.AuthRequest
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "check pw ok",
args: args{
es: GetMockManipulateUserWithPasswordAndEmailCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Password: &repo_model.Password{Secret: &crypto.CryptoValue{
CryptoType: crypto.TypeHash,
Algorithm: "hash",
Crypted: []byte("password"),
}},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
password: "password",
authRequest: &req_model.AuthRequest{
ID: "id",
AgentID: "agentID",
BrowserInfo: &req_model.BrowserInfo{
UserAgent: "user agent",
AcceptLanguage: "accept langugage",
RemoteIP: net.IPv4(29, 4, 20, 19),
},
},
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "",
password: "password",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
password: "password",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "no password",
args: args{
es: GetMockUserByIDOK(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
password: "password",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "invalid password",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Password: &repo_model.Password{Secret: &crypto.CryptoValue{
CryptoType: crypto.TypeHash,
Algorithm: "hash",
Crypted: []byte("password"),
}},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
password: "wrong password",
authRequest: &req_model.AuthRequest{
ID: "id",
AgentID: "agentID",
BrowserInfo: &req_model.BrowserInfo{
UserAgent: "user agent",
AcceptLanguage: "accept langugage",
RemoteIP: net.IPv4(29, 4, 20, 19),
},
},
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.CheckPassword(tt.args.ctx, tt.args.userID, tt.args.password, tt.args.authRequest)
if tt.res.errFunc == nil && err != nil {
t.Errorf("result has error: %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v", err)
}
})
}
}
func TestSetPassword(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
policy *policy_model.PasswordComplexityPolicy
userID string
code string
password string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "create pw",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
PasswordCode: &repo_model.PasswordCode{Code: &crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("code"),
}},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
code: "code",
password: "password",
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "",
code: "code",
password: "password",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
code: "code",
password: "password",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "no passcode",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
code: "code",
password: "password",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "invalid passcode",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
PasswordCode: &repo_model.PasswordCode{Code: &crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc2",
KeyID: "id",
Crypted: []byte("code2"),
}},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
code: "code",
password: "password",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
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)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v", err)
}
})
}
}
func TestChangePassword(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
policy *policy_model.PasswordComplexityPolicy
userID string
old string
new string
}
type res struct {
password string
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "change pw",
args: args{
es: GetMockManipulateUserWithPasswordAndEmailCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Password: &repo_model.Password{Secret: &crypto.CryptoValue{
CryptoType: crypto.TypeHash,
Algorithm: "hash",
Crypted: []byte("old"),
}},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
old: "old",
new: "new",
},
res: res{
password: "new",
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "",
old: "old",
new: "new",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
old: "old",
new: "new",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "no password",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
old: "old",
new: "new",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "invalid password",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Password: &repo_model.Password{Secret: &crypto.CryptoValue{
CryptoType: crypto.TypeHash,
Algorithm: "hash",
Crypted: []byte("older"),
}},
},
},
),
ctx: authz.NewMockContext("orgID", "userID"),
policy: &policy_model.PasswordComplexityPolicy{},
userID: "userID",
old: "old",
new: "new",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "no policy",
args: args{
es: GetMockManipulateUserWithPasswordAndEmailCodeGen(ctrl,
repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"},
Human: &repo_model.Human{
Password: &repo_model.Password{Secret: &crypto.CryptoValue{
CryptoType: crypto.TypeHash,
Algorithm: "hash",
Crypted: []byte("old"),
}},
},
},
),
ctx: authz.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.policy, tt.args.userID, tt.args.old, tt.args.new)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && string(result.SecretCrypto.Crypted) != tt.res.password {
t.Errorf("got wrong result crypted: expected: %v, actual: %v ", tt.res.password, result.SecretString)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v", err)
}
})
}
}
func TestRequestSetPassword(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
notifyType model.NotificationType
}
type res struct {
password *model.Password
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "create pw",
args: args{
es: GetMockManipulateUserWithPasswordCodeGen(ctrl, repo_model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID"}, Human: &repo_model.Human{}}),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
notifyType: model.NotificationTypeEmail,
},
res: res{
password: &model.Password{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, ChangeRequired: false},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
notifyType: model.NotificationTypeEmail,
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
notifyType: model.NotificationTypeEmail,
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.RequestSetPassword(tt.args.ctx, tt.args.userID, tt.args.notifyType)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestPasswordCodeSent(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "sent password code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.PasswordCodeSent(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("rshould not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestProfileByID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
profile *model.Profile
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Human: &model.Human{}},
},
res: res{
profile: &model.Profile{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, DisplayName: "DisplayName"},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
profile, err := tt.args.es.ProfileByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && profile.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && profile.DisplayName != tt.res.profile.DisplayName {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.profile.DisplayName, profile.DisplayName)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestChangeProfile(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
profile *model.Profile
}
type res struct {
profile *model.Profile
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
profile: &model.Profile{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, FirstName: "FirstName Changed", LastName: "LastName Changed"},
},
res: res{
profile: &model.Profile{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, FirstName: "FirstName Changed", LastName: "LastName Changed"},
},
},
{
name: "invalid profile",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
profile: &model.Profile{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
profile: &model.Profile{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, FirstName: "FirstName Changed", LastName: "LastName Changed"},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangeProfile(tt.args.ctx, tt.args.profile)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.FirstName != tt.res.profile.FirstName {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.profile.FirstName, result.FirstName)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestEmailByID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
email *model.Email
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddress"},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.EmailByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.EmailAddress != tt.res.email.EmailAddress {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.email.EmailAddress, result.EmailAddress)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestChangeEmail(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
email *model.Email
}
type res struct {
email *model.Email
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "change email address, verified",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: true},
},
res: res{
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: true},
},
},
{
name: "change email not verified, getting code",
args: args{
es: GetMockManipulateUserWithEmailCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"},
},
}),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: false},
},
res: res{
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: false},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: true},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
email: &model.Email{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, EmailAddress: "EmailAddressChanged", IsEmailVerified: true},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangeEmail(tt.args.ctx, tt.args.email)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.EmailAddress != tt.res.email.EmailAddress {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.email.EmailAddress, result.EmailAddress)
}
if tt.res.errFunc == nil && result.IsEmailVerified != tt.res.email.IsEmailVerified {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.email.IsEmailVerified, result.IsEmailVerified)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestVerifyEmail(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
code string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "verify email code ok",
args: args{
es: GetMockManipulateUserWithEmailCode(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "code",
},
res: res{},
},
{
name: "verify email code wrong",
args: args{
es: GetMockManipulateUserWithEmailCode(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "wrong",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
code: "code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "code",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.VerifyEmail(tt.args.ctx, tt.args.userID, tt.args.code)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not get err %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCreateEmailVerificationCode(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "create email verification code ok",
args: args{
es: GetMockManipulateUserWithEmailCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Email: &repo_model.Email{EmailAddress: "EmailAddress"},
}}),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "no email found",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "already verified",
args: args{
es: GetMockManipulateUserVerifiedEmail(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.CreateEmailVerificationCode(tt.args.ctx, tt.args.userID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not ger err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestEmailVerificationCodeSent(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "sent email verify code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.EmailVerificationCodeSent(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("rshould not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestPhoneByID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
phone *model.Phone
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "PhoneNumber"},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.PhoneByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.PhoneNumber != tt.res.phone.PhoneNumber {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.phone.PhoneNumber, result.PhoneNumber)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestChangePhone(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
phone *model.Phone
}
type res struct {
phone *model.Phone
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "change phone, verified",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "0711234567", IsPhoneVerified: true},
},
res: res{
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "+41711234567", IsPhoneVerified: true},
},
},
{
name: "change phone not verified, getting code",
args: args{
es: GetMockManipulateUserWithPhoneCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Phone: &repo_model.Phone{PhoneNumber: "PhoneNumber"}},
}),
ctx: authz.NewMockContext("orgID", "userID"),
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "+41711234567", IsPhoneVerified: false},
},
res: res{
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "+41711234567", IsPhoneVerified: false},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}, PhoneNumber: "PhoneNumberChanged", IsPhoneVerified: true},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
phone: &model.Phone{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, PhoneNumber: "+41711234567", IsPhoneVerified: true},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangePhone(tt.args.ctx, tt.args.phone)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.PhoneNumber != tt.res.phone.PhoneNumber {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.phone.PhoneNumber, result.PhoneNumber)
}
if tt.res.errFunc == nil && result.IsPhoneVerified != tt.res.phone.IsPhoneVerified {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.phone.IsPhoneVerified, result.IsPhoneVerified)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestVerifyPhone(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
code string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "verify code ok",
args: args{
es: GetMockManipulateUserWithPhoneCode(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "code",
},
res: res{},
},
{
name: "verify code wrong",
args: args{
es: GetMockManipulateUserWithPhoneCode(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "wrong",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
code: "Code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "Code",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.VerifyPhone(tt.args.ctx, tt.args.userID, tt.args.code)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not get err %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestRemovePhone(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
code string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "remove phone ok",
args: args{
es: GetMockManipulateUserVerifiedPhone(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "code",
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
code: "Code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
code: "Code",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.RemovePhone(tt.args.ctx, tt.args.userID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not get err %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCreatePhoneVerificationCode(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "create phone verification code okk",
args: args{
es: GetMockManipulateUserWithPhoneCodeGen(ctrl, repo_model.User{
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1},
UserName: "UserName",
Human: &repo_model.Human{
Profile: &repo_model.Profile{DisplayName: "DisplayName"},
Phone: &repo_model.Phone{PhoneNumber: "PhoneNumber"},
}}),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{},
},
{
name: "no userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "no phone found",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "already verified",
args: args{
es: GetMockManipulateUserVerifiedPhone(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.CreatePhoneVerificationCode(tt.args.ctx, tt.args.userID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("should not ger err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestPhoneVerificationCodeSent(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "sent phone verification code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.PhoneVerificationCodeSent(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("rshould not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestAddressByID(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
address *model.Address
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "get by id, ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
address: &model.Address{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Country: "Country"},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.AddressByID(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.Country != tt.res.address.Country {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.address.Country, result.Country)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestChangeAddress(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
address *model.Address
}
type res struct {
address *model.Address
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "change address ok",
args: args{
es: GetMockManipulateUserFull(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
address: &model.Address{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Country: "CountryChanged"},
},
res: res{
address: &model.Address{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Country: "CountryChanged"},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
address: &model.Address{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}, Country: "CountryChanged"},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
address: &model.Address{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}, Country: "CountryCountry"},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.ChangeAddress(tt.args.ctx, tt.args.address)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.Country != tt.res.address.Country {
t.Errorf("got wrong result change required: expected: %v, actual: %v ", tt.res.address.Country, result.Country)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestAddOTP(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
accountName string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "add ok",
args: args{
es: GetMockManipulateUserWithOTPGen(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
accountName: "AccountName",
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "AggregateID",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := tt.args.es.AddOTP(tt.args.ctx, tt.args.userID, tt.args.accountName)
if tt.res.errFunc == nil && result.AggregateID == "" {
t.Errorf("result has no id")
}
if tt.res.errFunc == nil && result.Url == "" {
t.Errorf("result has no url")
}
if tt.res.errFunc == nil && result.SecretString == "" {
t.Errorf("result has no url")
}
if tt.res.errFunc == nil && result == nil {
t.Errorf("got wrong result change required: actual: %v ", result)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCheckMfaOTPSetup(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
code string
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "setup ok",
args: args{
es: func() *UserEventstore {
es := GetMockManipulateUserWithOTP(ctrl, true, false)
es.validateTOTP = func(string, string) bool {
return true
}
return es
}(),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "id",
code: "code",
},
res: res{},
},
{
name: "wrong code",
args: args{
es: func() *UserEventstore {
es := GetMockManipulateUserWithOTP(ctrl, true, false)
es.validateTOTP = func(string, string) bool {
return false
}
return es
}(),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "id",
code: "code",
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
code: "code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
code: "code",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "user has no otp",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
code: "code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.CheckMfaOTPSetup(tt.args.ctx, tt.args.userID, tt.args.code)
if tt.res.errFunc == nil && err != nil {
t.Errorf("result should not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCheckMfaOTP(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
userID string
code string
authRequest *req_model.AuthRequest
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "check ok",
args: args{
es: func() *UserEventstore {
es := GetMockManipulateUserWithOTP(ctrl, true, true)
es.validateTOTP = func(string, string) bool {
return true
}
return es
}(),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "id",
code: "code",
authRequest: &req_model.AuthRequest{
ID: "id",
AgentID: "agentID",
BrowserInfo: &req_model.BrowserInfo{
UserAgent: "user agent",
AcceptLanguage: "accept langugage",
RemoteIP: net.IPv4(29, 4, 20, 19),
},
},
},
res: res{},
},
{
name: "wrong code",
args: args{
es: func() *UserEventstore {
es := GetMockManipulateUserWithOTP(ctrl, true, true)
es.validateTOTP = func(string, string) bool {
return false
}
return es
}(),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "id",
code: "code",
authRequest: &req_model.AuthRequest{
ID: "id",
AgentID: "agentID",
BrowserInfo: &req_model.BrowserInfo{
UserAgent: "user agent",
AcceptLanguage: "accept langugage",
RemoteIP: net.IPv4(29, 4, 20, 19),
},
},
},
res: res{
errFunc: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
code: "code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "empty code",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
code: "code",
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "user has no otp",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
userID: "userID",
code: "code",
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.CheckMfaOTP(tt.args.ctx, tt.args.userID, tt.args.code, tt.args.authRequest)
if tt.res.errFunc == nil && err != nil {
t.Errorf("result should not get err, got : %v", err)
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestRemoveOTP(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
ctx context.Context
user *model.User
}
type res struct {
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "remove ok",
args: args{
es: GetMockManipulateUserWithOTP(ctrl, false, true),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
},
{
name: "empty userid",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
{
name: "existing user not found",
args: args{
es: GetMockManipulateUserNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsNotFound,
},
},
{
name: "user has no otp",
args: args{
es: GetMockManipulateUser(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
user: &model.User{ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 1}},
},
res: res{
errFunc: caos_errs.IsPreconditionFailed,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.args.es.RemoveOTP(tt.args.ctx, tt.args.user.AggregateID)
if tt.res.errFunc == nil && err != nil {
t.Errorf("result should not get err")
}
if tt.res.errFunc != nil && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestChangesUser(t *testing.T) {
ctrl := gomock.NewController(t)
type args struct {
es *UserEventstore
id string
secID string
lastSequence uint64
limit uint64
}
type res struct {
changes *model.UserChanges
profile *model.Profile
wantErr bool
errFunc func(err error) bool
}
tests := []struct {
name string
args args
res res
}{
{
name: "changes from events, ok",
args: args{
es: GetMockChangesUserOK(ctrl),
id: "1",
lastSequence: 0,
limit: 0,
},
res: res{
changes: &model.UserChanges{Changes: []*model.UserChange{{EventType: "", Sequence: 1, ModifierID: ""}}, LastSequence: 1},
profile: &model.Profile{FirstName: "Hans", LastName: "Muster"},
},
},
{
name: "changes from events, no events",
args: args{
es: GetMockChangesUserNoEvents(ctrl),
id: "2",
lastSequence: 0,
limit: 0,
},
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.UserChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit, false)
profile := &model.Profile{}
if result != nil && len(result.Changes) > 0 {
b, err := json.Marshal(result.Changes[0].Data)
json.Unmarshal(b, profile)
if err != nil {
}
}
if !tt.res.wantErr && result.LastSequence != tt.res.changes.LastSequence && profile.DisplayName != tt.res.profile.DisplayName {
t.Errorf("got wrong result name: expected: %v, actual: %v ", tt.res.changes.LastSequence, result.LastSequence)
}
if tt.res.wantErr && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}