mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:17:32 +00:00
feat: patch user scim v2 endpoint (#9219)
# Which Problems Are Solved * Adds support for the patch user SCIM v2 endpoint # How the Problems Are Solved * Adds support for the patch user SCIM v2 endpoint under `PATCH /scim/v2/{orgID}/Users/{id}` # Additional Context Part of #8140
This commit is contained in:
@@ -6,16 +6,32 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type Phone struct {
|
||||
Number domain.PhoneNumber
|
||||
Remove bool
|
||||
Verified bool
|
||||
|
||||
// ReturnCode is used if the Verified field is false
|
||||
ReturnCode bool
|
||||
}
|
||||
|
||||
func (p *Phone) Validate() (err error) {
|
||||
if p.Remove && p.Number != "" {
|
||||
return zerrors.ThrowInvalidArgumentf(nil, "USRP2-12881", "Cannot update and remove the phone number at the same time")
|
||||
}
|
||||
|
||||
if p.Number != "" {
|
||||
if p.Number, err = p.Number.Normalize(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// newPhoneCode generates a new code to be sent out to via SMS or
|
||||
// returns the ID of the external code provider (e.g. when using Twilio verification API)
|
||||
func (c *Commands) newPhoneCode(ctx context.Context, filter preparation.FilterToQueryReducer, secretGeneratorType domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm, defaultConfig *crypto.GeneratorConfig) (*EncryptedCode, string, error) {
|
||||
|
@@ -14,12 +14,13 @@ import (
|
||||
)
|
||||
|
||||
type ChangeHuman struct {
|
||||
ID string
|
||||
State *domain.UserState
|
||||
Username *string
|
||||
Profile *Profile
|
||||
Email *Email
|
||||
Phone *Phone
|
||||
ID string
|
||||
State *domain.UserState
|
||||
Username *string
|
||||
Profile *Profile
|
||||
Email *Email
|
||||
Phone *Phone
|
||||
|
||||
Metadata []*domain.Metadata
|
||||
MetadataKeysToRemove []string
|
||||
|
||||
@@ -61,8 +62,8 @@ func (h *ChangeHuman) Validate(hasher *crypto.Hasher) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if h.Phone != nil && h.Phone.Number != "" {
|
||||
if h.Phone.Number, err = h.Phone.Number.Normalize(); err != nil {
|
||||
if h.Phone != nil {
|
||||
if err := h.Phone.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -263,7 +264,7 @@ func (c *Commands) ChangeUserHuman(ctx context.Context, human *ChangeHuman, alg
|
||||
return err
|
||||
}
|
||||
|
||||
existingHuman, err := c.userHumanWriteModel(
|
||||
existingHuman, err := c.UserHumanWriteModel(
|
||||
ctx,
|
||||
human.ID,
|
||||
human.Profile != nil,
|
||||
@@ -272,13 +273,11 @@ func (c *Commands) ChangeUserHuman(ctx context.Context, human *ChangeHuman, alg
|
||||
human.Password != nil,
|
||||
false, // avatar not updateable
|
||||
false, // IDPLinks not updateable
|
||||
len(human.Metadata) > 0 || len(human.MetadataKeysToRemove) > 0,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isUserStateExists(existingHuman.UserState) {
|
||||
return zerrors.ThrowNotFound(nil, "COMMAND-ugjs0upun6", "Errors.User.NotFound")
|
||||
}
|
||||
|
||||
if human.Changed() {
|
||||
if err := c.checkPermissionUpdateUser(ctx, existingHuman.ResourceOwner, existingHuman.AggregateID); err != nil {
|
||||
@@ -415,6 +414,10 @@ func (c *Commands) changeUserPhone(ctx context.Context, cmds []eventstore.Comman
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.End() }()
|
||||
|
||||
if phone.Remove {
|
||||
return append(cmds, user.NewHumanPhoneRemovedEvent(ctx, &wm.Aggregate().Aggregate)), nil, nil
|
||||
}
|
||||
|
||||
if phone.Number != "" && phone.Number != wm.Phone {
|
||||
cmds = append(cmds, user.NewHumanPhoneChangedEvent(ctx, &wm.Aggregate().Aggregate, phone.Number))
|
||||
|
||||
@@ -432,6 +435,7 @@ func (c *Commands) changeUserPhone(ctx context.Context, cmds []eventstore.Comman
|
||||
return cmds, code, nil
|
||||
}
|
||||
}
|
||||
|
||||
// only create separate event of verified if email was not changed
|
||||
if phone.Verified && wm.IsPhoneVerified != phone.Verified {
|
||||
return append(cmds, user.NewHumanPhoneVerifiedEvent(ctx, &wm.Aggregate().Aggregate)), code, nil
|
||||
@@ -499,14 +503,19 @@ func (c *Commands) userExistsWriteModel(ctx context.Context, userID string) (wri
|
||||
return writeModel, nil
|
||||
}
|
||||
|
||||
func (c *Commands) userHumanWriteModel(ctx context.Context, userID string, profileWM, emailWM, phoneWM, passwordWM, avatarWM, idpLinksWM bool) (writeModel *UserV2WriteModel, err error) {
|
||||
func (c *Commands) UserHumanWriteModel(ctx context.Context, userID string, profileWM, emailWM, phoneWM, passwordWM, avatarWM, idpLinksWM, metadataWM bool) (writeModel *UserV2WriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel = NewUserHumanWriteModel(userID, "", profileWM, emailWM, phoneWM, passwordWM, avatarWM, idpLinksWM)
|
||||
writeModel = NewUserHumanWriteModel(userID, "", profileWM, emailWM, phoneWM, passwordWM, avatarWM, idpLinksWM, metadataWM)
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !isUserStateExists(writeModel.UserState) {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-ugjs0upun6", "Errors.User.NotFound")
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
||||
|
@@ -15,6 +15,8 @@ import (
|
||||
type UserV2WriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
CreationDate time.Time
|
||||
|
||||
UserName string
|
||||
|
||||
MachineWriteModel bool
|
||||
@@ -73,6 +75,9 @@ type UserV2WriteModel struct {
|
||||
|
||||
IDPLinkWriteModel bool
|
||||
IDPLinks []*domain.UserIDPLink
|
||||
|
||||
MetadataWriteModel bool
|
||||
Metadata map[string][]byte
|
||||
}
|
||||
|
||||
func NewUserExistsWriteModel(userID, resourceOwner string) *UserV2WriteModel {
|
||||
@@ -87,7 +92,7 @@ func NewUserRemoveWriteModel(userID, resourceOwner string) *UserV2WriteModel {
|
||||
return newUserV2WriteModel(userID, resourceOwner, WithHuman(), WithMachine(), WithState(), WithIDPLinks())
|
||||
}
|
||||
|
||||
func NewUserHumanWriteModel(userID, resourceOwner string, profileWM, emailWM, phoneWM, passwordWM, avatarWM, idpLinks bool) *UserV2WriteModel {
|
||||
func NewUserHumanWriteModel(userID, resourceOwner string, profileWM, emailWM, phoneWM, passwordWM, avatarWM, idpLinks, metadataListWM bool) *UserV2WriteModel {
|
||||
opts := []UserV2WMOption{WithHuman(), WithState()}
|
||||
if profileWM {
|
||||
opts = append(opts, WithProfile())
|
||||
@@ -107,6 +112,9 @@ func NewUserHumanWriteModel(userID, resourceOwner string, profileWM, emailWM, ph
|
||||
if idpLinks {
|
||||
opts = append(opts, WithIDPLinks())
|
||||
}
|
||||
if metadataListWM {
|
||||
opts = append(opts, WithMetadata())
|
||||
}
|
||||
return newUserV2WriteModel(userID, resourceOwner, opts...)
|
||||
}
|
||||
|
||||
@@ -172,6 +180,12 @@ func WithIDPLinks() UserV2WMOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithMetadata() UserV2WMOption {
|
||||
return func(o *UserV2WriteModel) {
|
||||
o.MetadataWriteModel = true
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *UserV2WriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
@@ -281,6 +295,17 @@ func (wm *UserV2WriteModel) Reduce() error {
|
||||
wm.RemoveIDPLink(e.IDPConfigID, e.ExternalUserID)
|
||||
case *user.UserIDPLinkCascadeRemovedEvent:
|
||||
wm.RemoveIDPLink(e.IDPConfigID, e.ExternalUserID)
|
||||
case *user.MetadataSetEvent:
|
||||
if wm.Metadata == nil {
|
||||
wm.Metadata = make(map[string][]byte)
|
||||
}
|
||||
|
||||
wm.Metadata[e.Key] = e.Value
|
||||
case *user.MetadataRemovedEvent:
|
||||
wm.Metadata[e.Key] = nil
|
||||
delete(wm.Metadata, e.Key)
|
||||
case *user.MetadataRemovedAllEvent:
|
||||
wm.Metadata = nil
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
@@ -457,6 +482,13 @@ func (wm *UserV2WriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if wm.MetadataWriteModel {
|
||||
eventTypes = append(eventTypes,
|
||||
user.MetadataSetType,
|
||||
user.MetadataRemovedType,
|
||||
user.MetadataRemovedAllType)
|
||||
}
|
||||
|
||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
AddQuery().
|
||||
AggregateTypes(user.AggregateType).
|
||||
@@ -482,6 +514,7 @@ func (wm *UserV2WriteModel) reduceHumanAddedEvent(e *user.HumanAddedEvent) {
|
||||
wm.UserState = domain.UserStateActive
|
||||
wm.PasswordEncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
|
||||
wm.PasswordChangeRequired = e.ChangeRequired
|
||||
wm.CreationDate = e.Creation
|
||||
}
|
||||
|
||||
func (wm *UserV2WriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEvent) {
|
||||
|
@@ -567,7 +567,7 @@ func TestCommandSide_userHumanWriteModel_profile(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
wm, err := r.userHumanWriteModel(tt.args.ctx, tt.args.userID, true, false, false, false, false, false)
|
||||
wm, err := r.UserHumanWriteModel(tt.args.ctx, tt.args.userID, true, false, false, false, false, false, false)
|
||||
if tt.res.err == nil {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
@@ -912,7 +912,7 @@ func TestCommandSide_userHumanWriteModel_email(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
wm, err := r.userHumanWriteModel(tt.args.ctx, tt.args.userID, false, true, false, false, false, false)
|
||||
wm, err := r.UserHumanWriteModel(tt.args.ctx, tt.args.userID, false, true, false, false, false, false, false)
|
||||
if tt.res.err == nil {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
@@ -1344,7 +1344,7 @@ func TestCommandSide_userHumanWriteModel_phone(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
wm, err := r.userHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, true, false, false, false)
|
||||
wm, err := r.UserHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, true, false, false, false, false)
|
||||
if tt.res.err == nil {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
@@ -1605,7 +1605,7 @@ func TestCommandSide_userHumanWriteModel_password(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
wm, err := r.userHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, false, true, false, false)
|
||||
wm, err := r.UserHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, false, true, false, false, false)
|
||||
if tt.res.err == nil {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
@@ -2132,7 +2132,7 @@ func TestCommandSide_userHumanWriteModel_avatar(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
wm, err := r.userHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, false, false, true, false)
|
||||
wm, err := r.UserHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, false, false, true, false, false)
|
||||
if tt.res.err == nil {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
@@ -2456,3 +2456,306 @@ func TestCommandSide_userHumanWriteModel_idpLinks(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_userHumanWriteModel_metadata(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
}
|
||||
type res struct {
|
||||
want *UserV2WriteModel
|
||||
err func(error) bool
|
||||
}
|
||||
|
||||
userAgg := user.NewAggregate("user1", "org1")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "user added with metadata",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("$plain$x$password", true, true, "", language.English),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key",
|
||||
[]byte("value"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
},
|
||||
res: res{
|
||||
want: &UserV2WriteModel{
|
||||
HumanWriteModel: true,
|
||||
StateWriteModel: true,
|
||||
MetadataWriteModel: true,
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: "user1",
|
||||
Events: []eventstore.Event{},
|
||||
ProcessedSequence: 0,
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
UserName: "username",
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.English,
|
||||
PasswordEncodedHash: "$plain$x$password",
|
||||
PasswordChangeRequired: true,
|
||||
Email: "email@test.ch",
|
||||
IsEmailVerified: false,
|
||||
UserState: domain.UserStateActive,
|
||||
Metadata: map[string][]byte{
|
||||
"key": []byte("value"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user added with multiple metadata",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("$plain$x$password", true, true, "", language.English),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key1",
|
||||
[]byte("value1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key2",
|
||||
[]byte("value2"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key3",
|
||||
[]byte("value3"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
},
|
||||
res: res{
|
||||
want: &UserV2WriteModel{
|
||||
HumanWriteModel: true,
|
||||
StateWriteModel: true,
|
||||
MetadataWriteModel: true,
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: "user1",
|
||||
Events: []eventstore.Event{},
|
||||
ProcessedSequence: 0,
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
UserName: "username",
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.English,
|
||||
PasswordEncodedHash: "$plain$x$password",
|
||||
PasswordChangeRequired: true,
|
||||
Email: "email@test.ch",
|
||||
IsEmailVerified: false,
|
||||
UserState: domain.UserStateActive,
|
||||
Metadata: map[string][]byte{
|
||||
"key1": []byte("value1"),
|
||||
"key2": []byte("value2"),
|
||||
"key3": []byte("value3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user added with metadata add and remove",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("$plain$x$password", true, true, "", language.English),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key1",
|
||||
[]byte("value1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key2",
|
||||
[]byte("name2"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key3",
|
||||
[]byte("value3"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataRemovedEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key2",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataRemovedEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key3",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
},
|
||||
res: res{
|
||||
want: &UserV2WriteModel{
|
||||
HumanWriteModel: true,
|
||||
StateWriteModel: true,
|
||||
MetadataWriteModel: true,
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: "user1",
|
||||
Events: []eventstore.Event{},
|
||||
ProcessedSequence: 0,
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
UserName: "username",
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.English,
|
||||
PasswordEncodedHash: "$plain$x$password",
|
||||
PasswordChangeRequired: true,
|
||||
Email: "email@test.ch",
|
||||
IsEmailVerified: false,
|
||||
UserState: domain.UserStateActive,
|
||||
Metadata: map[string][]byte{
|
||||
"key1": []byte("value1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user added with added metadata and removed all",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
newAddHumanEvent("$plain$x$password", true, true, "", language.English),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key1",
|
||||
[]byte("value1"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataSetEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
"key2",
|
||||
[]byte("value2"),
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewMetadataRemovedAllEvent(
|
||||
context.Background(),
|
||||
&userAgg.Aggregate,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
},
|
||||
res: res{
|
||||
want: &UserV2WriteModel{
|
||||
HumanWriteModel: true,
|
||||
StateWriteModel: true,
|
||||
MetadataWriteModel: true,
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: "user1",
|
||||
Events: []eventstore.Event{},
|
||||
ProcessedSequence: 0,
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
UserName: "username",
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: language.English,
|
||||
PasswordEncodedHash: "$plain$x$password",
|
||||
PasswordChangeRequired: true,
|
||||
Email: "email@test.ch",
|
||||
IsEmailVerified: false,
|
||||
UserState: domain.UserStateActive,
|
||||
Metadata: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
wm, err := r.UserHumanWriteModel(tt.args.ctx, tt.args.userID, false, false, false, false, false, false, true)
|
||||
if tt.res.err == nil {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
} else if !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, wm)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user