mirror of
https://github.com/zitadel/zitadel.git
synced 2026-10-25 15:40:09 -05:00
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:
1 parent
eb76977a29
commit
a1748b2f03
6 files changed
+125
-197
No files matched your search
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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 == "" {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user