Files
zitadel/internal/command/user_v2_test.go
Gayathri Vijayan ad8e8bf61f feat(group): manage users in user groups (#10940)
# Which Problems Are Solved

1. Adding users to user groups and removing users from user groups.
2. Searching for users in user groups by group IDs or user IDs

# How the Problems Are Solved

By adding:
1. The API definitions to manage users in users groups
3. The command-layer implementation of adding users/removing users
to/from user groups.
4. The projection table group_users1
5. Query-side implementation to search for users in user groups

# Additional Changes

1. Remove debug statements from unit tests.
2. Fix removal of groups when orgs are removed
3. Add unit tests for groups projection

# Additional Context

* Related to #9702 
* Follow-up for PRs 
  * https://github.com/zitadel/zitadel/pull/10455
  * https://github.com/zitadel/zitadel/pull/10758
  * https://github.com/zitadel/zitadel/pull/10853
2025-10-28 13:23:54 +00:00

1482 lines
33 KiB
Go

package command
import (
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/group"
"github.com/zitadel/zitadel/internal/repository/org"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors"
)
func TestCommandSide_LockUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type (
args struct {
ctx context.Context
userID string
}
)
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-agz3eczifm", "Errors.User.UserIDMissing"))
},
},
},
{
name: "user not existing, not found error",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-450yxuqrh1", "Errors.User.NotFound"))
},
},
},
{
name: "user already locked, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
userAgg,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-lgws8wtsqf", "Errors.User.ShouldBeActiveOrInitial"))
},
},
},
{
name: "user already locked, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
userAgg,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-lgws8wtsqf", "Errors.User.ShouldBeActiveOrInitial"))
},
},
},
{
name: "lock user, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
),
expectPush(
user.NewUserLockedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "lock user, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
},
},
},
{
name: "lock user machine, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
),
expectPush(
user.NewUserLockedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.LockUserV2(tt.args.ctx, tt.args.userID)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assertObjectDetails(t, tt.res.want, got)
}
})
}
}
func TestCommandSide_UnlockUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type (
args struct {
ctx context.Context
userID string
}
)
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-a9ld4xckax", "Errors.User.UserIDMissing"))
},
},
},
{
name: "user not existing, not found error",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-x377t913pw", "Errors.User.NotFound"))
},
},
},
{
name: "user already active, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-olb9vb0oca", "Errors.User.NotLocked"))
},
},
},
{
name: "user already active, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-olb9vb0oca", "Errors.User.NotLocked"))
},
},
},
{
name: "unlock user, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
userAgg),
),
),
expectPush(
user.NewUserUnlockedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "unlock user, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
userAgg),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
},
},
},
{
name: "unlock user machine, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
userAgg),
),
),
expectPush(
user.NewUserUnlockedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.UnlockUserV2(tt.args.ctx, tt.args.userID)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assertObjectDetails(t, tt.res.want, got)
}
})
}
}
func TestCommandSide_DeactivateUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type (
args struct {
ctx context.Context
userID string
}
)
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-78iiirat8y", "Errors.User.UserIDMissing"))
},
},
},
{
name: "user not existing, not found error",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-5gp2p62iin", "Errors.User.NotFound"))
},
},
},
{
name: "user initial, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
userAgg,
nil, time.Hour*1,
"",
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-gvx4kct9r2", "Errors.User.CantDeactivateInitial"))
},
},
},
{
name: "user already inactive, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
userAgg,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-5gunjw0cd7", "Errors.User.AlreadyInactive"))
},
},
},
{
name: "deactivate user, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanInitializedCheckSucceededEvent(context.Background(),
userAgg,
),
),
),
expectPush(
user.NewUserDeactivatedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "deactivate user, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanInitializedCheckSucceededEvent(context.Background(),
userAgg,
),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
},
},
},
{
name: "user machine already inactive, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
userAgg,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-5gunjw0cd7", "Errors.User.AlreadyInactive"))
},
},
},
{
name: "deactivate user machine, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
),
expectPush(
user.NewUserDeactivatedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.DeactivateUserV2(tt.args.ctx, tt.args.userID)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assertObjectDetails(t, tt.res.want, got)
}
})
}
}
func TestCommandSide_ReactivateUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type (
args struct {
ctx context.Context
userID string
}
)
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-0nx1ie38fw", "Errors.User.UserIDMissing"))
},
},
},
{
name: "user not existing, not found error",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-9hy5kzbuk6", "Errors.User.NotFound"))
},
},
},
{
name: "user already active, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-s5qqcz97hf", "Errors.User.NotInactive"))
},
},
},
{
name: "user machine already active, precondition error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "COMMAND-s5qqcz97hf", "Errors.User.NotInactive"))
},
},
},
{
name: "reactivate user, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
userAgg),
),
),
expectPush(
user.NewUserReactivatedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "reactivate user, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
userAgg),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
},
},
},
{
name: "reactivate user machine, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
userAgg),
),
),
expectPush(
user.NewUserReactivatedEvent(context.Background(),
userAgg,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.ReactivateUserV2(tt.args.ctx, tt.args.userID)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assertObjectDetails(t, tt.res.want, got)
}
})
}
}
func TestCommandSide_RemoveUserV2(t *testing.T) {
ctxUserID := "ctxUserID"
ctx := authz.SetCtxData(context.Background(), authz.CtxData{UserID: ctxUserID})
userAgg := &user.NewAggregate("user1", "org1").Aggregate
orgAgg := &org.NewAggregate("org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type (
args struct {
userID string
cascadingMemberships []*CascadingMembership
grantIDs []string
groupIDs []string
}
)
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
userID: "",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "COMMAND-vaipl7s13l", "Errors.User.UserIDMissing"))
},
},
},
{
name: "user not existing, not found error",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-bd4ir1mblj", "Errors.User.NotFound"))
},
},
},
{
name: "user removed, notfound error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewUserRemovedEvent(ctx,
userAgg,
"username",
nil,
true,
),
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-bd4ir1mblj", "Errors.User.NotFound"))
},
},
},
{
name: "remove user, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
orgAgg,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(ctx,
userAgg,
"username",
nil,
true,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove user, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
user.NewHumanInitializedCheckSucceededEvent(ctx,
userAgg,
),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
userID: "user1",
},
res: res{
err: zerrors.IsPermissionDenied,
},
},
{
name: "user machine already removed, notfound error",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(ctx,
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
eventFromEventPusher(
user.NewUserRemovedEvent(ctx,
userAgg,
"username",
nil,
true,
),
),
),
),
},
args: args{
userID: "user1",
},
res: res{
err: func(err error) bool {
return errors.Is(err, zerrors.ThrowNotFound(nil, "COMMAND-bd4ir1mblj", "Errors.User.NotFound"))
},
},
},
{
name: "remove user machine, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(ctx,
userAgg,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
orgAgg,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(ctx,
userAgg,
"username",
nil,
true,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove user with user groups, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
userAgg,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
eventFromEventPusher(
group.NewGroupUsersAddedEvent(context.Background(),
&group.NewAggregate("group1", "org1").Aggregate,
[]string{"user1"},
),
),
eventFromEventPusher(
group.NewGroupUsersAddedEvent(context.Background(),
&group.NewAggregate("group2", "org1").Aggregate,
[]string{"user1"},
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
orgAgg,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(ctx,
userAgg,
"username",
nil,
true,
),
group.NewGroupUsersRemovedEvent(ctx,
&group.NewAggregate("group1", "").Aggregate,
[]string{"user1"},
),
group.NewGroupUsersRemovedEvent(ctx,
&group.NewAggregate("group2", "").Aggregate,
[]string{"user1"},
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
userID: "user1",
groupIDs: []string{
"group1",
"group2",
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove self, permission denied",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
&user.NewAggregate(ctxUserID, "org1").Aggregate,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email@test.ch",
true,
),
),
),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
userID: ctxUserID,
},
res: res{
err: zerrors.IsPermissionDenied,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.RemoveUserV2(ctx, tt.args.userID, "", tt.args.cascadingMemberships, tt.args.grantIDs, tt.args.groupIDs)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assertObjectDetails(t, tt.res.want, got)
}
})
}
}