fix(api): check permission based on provided data on user updates

# Which Problems Are Solved

Users were allowed to self-request verification codes for email and phone through the API.

# How the Problems Are Solved

Return codes can only be requested with the according permission.

(cherry picked from commit ed09b3df7f)
This commit is contained in:
Marco A. authored and Livio Spring committed 2026-06-08 16:51:22 +02:00
1 parent eb76977a29
commit a1748b2f03
6 files changed
+125 -197

No files matched your search

+4 -2
View File
@@ -148,7 +148,8 @@ func (c *Commands) changeUserEmailWithGeneratorEvents(ctx context.Context, userI
if err != nil {
return nil, err
}
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, true); err != nil {
allowSelfManagement := !returnCode
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, allowSelfManagement); err != nil {
return nil, err
}
if err = cmd.Change(ctx, domain.EmailAddress(email)); err != nil {
@@ -170,7 +171,8 @@ func (c *Commands) sendUserEmailCodeWithGeneratorEvents(ctx context.Context, use
if err != nil {
return nil, err
}
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, true); err != nil {
allowSelfManagement := !returnCode
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, allowSelfManagement); err != nil {
return nil, err
}
if existingCheck && cmd.model.Code == nil {
+31 -57
View File
@@ -5,12 +5,12 @@ import (
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
@@ -1165,6 +1165,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths func(*testing.T) LoginPaths
}
type args struct {
ctx context.Context
userID string
email string
returnCode bool
@@ -1184,6 +1185,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "",
email: "email@test.ch",
returnCode: false,
@@ -1216,6 +1218,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
email: "email@test.ch",
returnCode: false,
@@ -1248,6 +1251,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
email: "",
returnCode: false,
@@ -1280,6 +1284,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
email: "email@test.ch",
returnCode: false,
@@ -1330,6 +1335,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths: expectLoginPathsDefaultEmailCodeURLTemplate("http://example.com/{{.user}}/email/{{.code}}"),
},
args: args{
ctx: t.Context(),
userID: "user1",
email: "email-changed@test.ch",
returnCode: false,
@@ -1345,7 +1351,9 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
},
},
{
name: "email changed, return code",
// returnCode=true returns the plaintext code to the caller, bypassing email delivery.
// Self-management must not be sufficient — explicit write permission is required.
name: "email change not allowed when return code=true for self-management",
fields: fields{
eventstore: expectEventstore(
expectFilter(
@@ -1364,42 +1372,18 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
),
),
),
expectPush(
user.NewHumanEmailChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"email-changed@test.ch",
),
user.NewHumanEmailCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
"http://example.com/{{.user}}/email/{{.code2}}", true, "",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
loginPaths: expectLoginPathsDefaultEmailCodeURLTemplate("http://example.com/{{.user}}/email/{{.code2}}"),
checkPermission: newMockPermissionCheckNotAllowed(),
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: authz.SetCtxData(t.Context(), authz.CtxData{UserID: "user1"}),
userID: "user1",
email: "email-changed@test.ch",
returnCode: true,
urlTmpl: "",
},
want: &domain.Email{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
ResourceOwner: "org1",
},
EmailAddress: "email-changed@test.ch",
IsEmailVerified: false,
PlainCode: gu.Ptr("a"),
},
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
},
{
name: "email changed, URL template",
@@ -1443,6 +1427,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
email: "email-changed@test.ch",
returnCode: false,
@@ -1465,7 +1450,7 @@ func TestCommands_changeUserEmailWithGenerator(t *testing.T) {
checkPermission: tt.fields.checkPermission,
loginPaths: tt.fields.loginPaths(t),
}
got, err := c.changeUserEmailWithGenerator(context.Background(), tt.args.userID, tt.args.email, GetMockSecretGenerator(t), tt.args.returnCode, tt.args.urlTmpl)
got, err := c.changeUserEmailWithGenerator(tt.args.ctx, tt.args.userID, tt.args.email, GetMockSecretGenerator(t), tt.args.returnCode, tt.args.urlTmpl)
require.ErrorIs(t, tt.wantErr, err)
assert.Equal(t, tt.want, got)
})
@@ -1479,6 +1464,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths func(*testing.T) LoginPaths
}
type args struct {
ctx context.Context
userID string
returnCode bool
urlTmpl string
@@ -1498,6 +1484,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "",
returnCode: false,
urlTmpl: "",
@@ -1543,6 +1530,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
urlTmpl: "",
@@ -1588,6 +1576,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths: expectLoginPathsDefaultEmailCodeURLTemplate("http://example.com/{{.user}}/email/{{.code}}"),
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
urlTmpl: "",
@@ -1654,6 +1643,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths: expectLoginPathsDefaultEmailCodeURLTemplate("http://example.com/{{.user}}/email/{{.code2}}"),
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
urlTmpl: "",
@@ -1694,6 +1684,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
urlTmpl: "",
@@ -1702,7 +1693,9 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
wantErr: zerrors.ThrowPreconditionFailed(nil, "EMAIL-5w5ilin4yt", "Errors.User.Code.Empty"),
},
{
name: "send code, return code",
// returnCode=true returns the plaintext code to the caller, bypassing email delivery.
// Self-management must not be sufficient — explicit write permission is required.
name: "send code not allowed when return code=true for self-management",
fields: fields{
eventstore: eventstoreExpect(
t,
@@ -1722,38 +1715,18 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
),
),
),
expectPush(
user.NewHumanEmailCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
"http://example.com/{{.user}}/email/{{.code}}", true, "",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
loginPaths: expectLoginPathsDefaultEmailCodeURLTemplate("http://example.com/{{.user}}/email/{{.code}}"),
checkPermission: newMockPermissionCheckNotAllowed(),
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: authz.SetCtxData(t.Context(), authz.CtxData{UserID: "user1"}),
userID: "user1",
returnCode: true,
urlTmpl: "",
checkExisting: false,
},
want: &domain.Email{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
ResourceOwner: "org1",
},
EmailAddress: "email@test.ch",
IsEmailVerified: false,
PlainCode: gu.Ptr("a"),
},
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
},
{
name: "send code, URL template",
@@ -1794,6 +1767,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
loginPaths: expectLoginPathsNoCall,
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
urlTmpl: "https://example.com/email/verify?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}",
@@ -1816,7 +1790,7 @@ func TestCommands_sendUserEmailCodeWithGeneratorEvents(t *testing.T) {
checkPermission: tt.fields.checkPermission,
loginPaths: tt.fields.loginPaths(t),
}
got, err := c.sendUserEmailCodeWithGenerator(context.Background(), tt.args.userID, GetMockSecretGenerator(t), tt.args.returnCode, tt.args.urlTmpl, tt.args.checkExisting)
got, err := c.sendUserEmailCodeWithGenerator(tt.args.ctx, tt.args.userID, GetMockSecretGenerator(t), tt.args.returnCode, tt.args.urlTmpl, tt.args.checkExisting)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, tt.want, got)
})
+3 -1
View File
@@ -297,7 +297,9 @@ func (c *Commands) ChangeUserHuman(ctx context.Context, human *ChangeHuman, alg
if human.Changed() {
// Changing metadata or setting email, resp. phone to verified is only allowed with user write permissions, but not for self-management.
requireWritePermission := metadataChanged || (human.Email != nil && human.Email.Verified) || (human.Phone != nil && human.Phone.Verified)
requireWritePermission := metadataChanged ||
(human.Email != nil && (human.Email.Verified || human.Email.ReturnCode)) ||
(human.Phone != nil && (human.Phone.Verified || human.Phone.ReturnCode))
if err := c.checkPermissionUpdateUser(ctx, existingHuman.ResourceOwner, existingHuman.AggregateID, !requireWritePermission); err != nil {
return err
}
+60
View File
@@ -2823,6 +2823,36 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
},
},
},
{
name: "change human email return-code (self-management), not allowed",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
newAddHumanEvent("$plain$x$password", true, true, "", language.English),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
loginPaths: expectLoginPathsNoCall,
tarpit: expectTarpit(0),
},
args: args{
ctx: authz.NewMockContext("instance1", "org1", "user1"),
orgID: "org1",
human: &ChangeHuman{
Email: &Email{
Address: "changed@example.com",
ReturnCode: true,
},
},
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
},
},
},
{
name: "change human email verified, ok",
fields: fields{
@@ -3173,6 +3203,36 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
},
},
},
{
name: "change human phone return-code (self-management), not allowed",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
newAddHumanEvent("$plain$x$password", true, true, "", language.English),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
loginPaths: expectLoginPathsNoCall,
tarpit: expectTarpit(0),
},
args: args{
ctx: authz.NewMockContext("instance1", "org1", "user1"),
orgID: "org1",
human: &ChangeHuman{
Phone: &Phone{
Number: "+41791234567",
ReturnCode: true,
},
},
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
},
},
},
{
name: "change human phone verified, ok",
fields: fields{
+4 -2
View File
@@ -82,7 +82,8 @@ func (c *Commands) changeUserPhoneWithGenerator(ctx context.Context, userID, pho
if err != nil {
return nil, err
}
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, true); err != nil {
allowSelfManagement := !returnCode
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, allowSelfManagement); err != nil {
return nil, err
}
if err = cmd.Change(ctx, domain.PhoneNumber(phone)); err != nil {
@@ -102,7 +103,8 @@ func (c *Commands) resendUserPhoneCodeWithGenerator(ctx context.Context, userID
if err != nil {
return nil, err
}
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, true); err != nil {
allowSelfManagement := !returnCode
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID, allowSelfManagement); err != nil {
return nil, err
}
if cmd.model.Code == nil && cmd.model.GeneratorID == "" {
+23 -135
View File
@@ -5,12 +5,12 @@ import (
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
@@ -684,6 +684,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
defaultSecretGenerators *SecretGenerators
}
type args struct {
ctx context.Context
userID string
phone string
returnCode bool
@@ -701,6 +702,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
eventstore: expectEventstore(),
},
args: args{
ctx: t.Context(),
userID: "",
phone: "+41791234567",
returnCode: false,
@@ -735,6 +737,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: t.Context(),
userID: "user1",
phone: "+41791234567",
returnCode: false,
@@ -769,6 +772,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: t.Context(),
userID: "user1",
phone: "",
returnCode: false,
@@ -803,6 +807,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: t.Context(),
userID: "user1",
phone: "+41791234567",
returnCode: false,
@@ -887,6 +892,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: t.Context(),
userID: "user1",
phone: "+41791234568",
returnCode: false,
@@ -901,7 +907,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
},
},
{
name: "phone changed, return code",
name: "phone change not allowed when return code=true for self-management",
fields: fields{
eventstore: expectEventstore(
expectFilter(
@@ -924,73 +930,16 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
}(),
),
),
expectFilter(
eventFromEventPusher(
instance.NewSMSConfigActivatedEvent(
context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
"id",
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewSMSConfigTwilioAddedEvent(
context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
"id",
"",
"sid",
"senderNumber",
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "id", Crypted: []byte("crypted")},
"",
),
),
eventFromEventPusher(
instance.NewSMSConfigActivatedEvent(
context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
"id",
),
),
),
expectPush(
user.NewHumanPhoneChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"+41791234568",
),
user.NewHumanPhoneCodeAddedEventV2(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
true,
"",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
newEncryptedCodeWithDefault: mockEncryptedCodeWithDefault("a", time.Hour),
defaultSecretGenerators: defaultGenerators,
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: authz.SetCtxData(t.Context(), authz.CtxData{UserID: "user1"}),
userID: "user1",
phone: "+41791234568",
returnCode: true,
},
want: &domain.Phone{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
ResourceOwner: "org1",
},
PhoneNumber: "+41791234568",
IsPhoneVerified: false,
PlainCode: gu.Ptr("a"),
},
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
},
}
for _, tt := range tests {
@@ -1002,7 +951,7 @@ func TestCommands_changeUserPhoneWithGenerator(t *testing.T) {
userEncryption: tt.fields.userEncryption,
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
}
got, err := c.changeUserPhoneWithGenerator(context.Background(), tt.args.userID, tt.args.phone, GetMockSecretGenerator(t), tt.args.returnCode)
got, err := c.changeUserPhoneWithGenerator(tt.args.ctx, tt.args.userID, tt.args.phone, GetMockSecretGenerator(t), tt.args.returnCode)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, got, tt.want)
})
@@ -1027,6 +976,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
defaultSecretGenerators *SecretGenerators
}
type args struct {
ctx context.Context
userID string
returnCode bool
}
@@ -1043,6 +993,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
eventstore: expectEventstore(),
},
args: args{
ctx: t.Context(),
userID: "",
returnCode: false,
},
@@ -1076,6 +1027,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
},
@@ -1109,6 +1061,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
},
@@ -1202,6 +1155,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
},
@@ -1292,6 +1246,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: t.Context(),
userID: "user1",
returnCode: false,
},
@@ -1305,7 +1260,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
},
},
{
name: "return code",
name: "resend code not allowed when return code=true for self-management",
fields: fields{
eventstore: expectEventstore(
expectFilter(
@@ -1327,83 +1282,16 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
return event
}(),
),
eventFromEventPusher(
user.NewHumanPhoneCodeAddedEventV2(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
true,
"",
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewSMSConfigActivatedEvent(
context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
"id",
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewSMSConfigTwilioAddedEvent(
context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
"id",
"",
"sid",
"senderNumber",
&crypto.CryptoValue{CryptoType: crypto.TypeEncryption, Algorithm: "enc", KeyID: "id", Crypted: []byte("crypted")},
"",
),
),
eventFromEventPusher(
instance.NewSMSConfigActivatedEvent(
context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
"id",
),
),
),
expectPush(
user.NewHumanPhoneCodeAddedEventV2(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
true,
"",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
newEncryptedCodeWithDefault: mockEncryptedCodeWithDefault("a", time.Hour),
defaultSecretGenerators: defaultGenerators,
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: authz.SetCtxData(t.Context(), authz.CtxData{UserID: "user1"}),
userID: "user1",
returnCode: true,
},
want: &domain.Phone{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
ResourceOwner: "org1",
},
PhoneNumber: "+41791234567",
IsPhoneVerified: false,
PlainCode: gu.Ptr("a"),
},
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
},
}
for _, tt := range tests {
@@ -1414,7 +1302,7 @@ func TestCommands_resendUserPhoneCodeWithGenerator(t *testing.T) {
newEncryptedCodeWithDefault: tt.fields.newEncryptedCodeWithDefault,
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
}
got, err := c.resendUserPhoneCodeWithGenerator(context.Background(), tt.args.userID, GetMockSecretGenerator(t), tt.args.returnCode)
got, err := c.resendUserPhoneCodeWithGenerator(tt.args.ctx, tt.args.userID, GetMockSecretGenerator(t), tt.args.returnCode)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, got, tt.want)
})