2023-04-19 08:46:02 +00:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"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/deviceauth"
|
2023-12-08 14:30:55 +00:00
|
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
2023-04-19 08:46:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestCommands_AddDeviceAuth(t *testing.T) {
|
|
|
|
ctx := authz.WithInstanceID(context.Background(), "instance1")
|
|
|
|
pushErr := errors.New("pushErr")
|
|
|
|
now := time.Now()
|
|
|
|
|
2023-12-20 12:21:08 +00:00
|
|
|
unique := deviceauth.NewAddUniqueConstraints("123", "456")
|
2023-04-19 08:46:02 +00:00
|
|
|
require.Len(t, unique, 2)
|
|
|
|
|
|
|
|
type fields struct {
|
2023-12-20 12:21:08 +00:00
|
|
|
eventstore *eventstore.Eventstore
|
2023-04-19 08:46:02 +00:00
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
clientID string
|
|
|
|
deviceCode string
|
|
|
|
userCode string
|
|
|
|
expires time.Time
|
|
|
|
scopes []string
|
2024-04-03 06:06:21 +00:00
|
|
|
audience []string
|
2023-04-19 08:46:02 +00:00
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wantDetails *domain.ObjectDetails
|
|
|
|
wantErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "success",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t, expectPush(
|
2023-10-19 10:19:10 +00:00
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-10-19 10:19:10 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-10-19 10:19:10 +00:00
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
clientID: "client_id",
|
|
|
|
deviceCode: "123",
|
|
|
|
userCode: "456",
|
|
|
|
expires: now,
|
|
|
|
scopes: []string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
audience: []string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
},
|
|
|
|
wantDetails: &domain.ObjectDetails{
|
|
|
|
ResourceOwner: "instance1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "push error",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t, expectPushFailed(pushErr,
|
2023-10-19 10:19:10 +00:00
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-10-19 10:19:10 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-10-19 10:19:10 +00:00
|
|
|
)),
|
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
|
|
|
clientID: "client_id",
|
|
|
|
deviceCode: "123",
|
|
|
|
userCode: "456",
|
|
|
|
expires: now,
|
|
|
|
scopes: []string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
audience: []string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
},
|
|
|
|
wantErr: pushErr,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2023-12-20 12:21:08 +00:00
|
|
|
eventstore: tt.fields.eventstore,
|
2023-04-19 08:46:02 +00:00
|
|
|
}
|
2024-04-03 06:06:21 +00:00
|
|
|
gotDetails, err := c.AddDeviceAuth(tt.args.ctx, tt.args.clientID, tt.args.deviceCode, tt.args.userCode, tt.args.expires, tt.args.scopes, tt.args.audience)
|
2023-04-19 08:46:02 +00:00
|
|
|
require.ErrorIs(t, err, tt.wantErr)
|
2023-10-19 10:19:10 +00:00
|
|
|
assert.Equal(t, tt.wantDetails, gotDetails)
|
2023-04-19 08:46:02 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommands_ApproveDeviceAuth(t *testing.T) {
|
|
|
|
ctx := authz.WithInstanceID(context.Background(), "instance1")
|
|
|
|
now := time.Now()
|
|
|
|
pushErr := errors.New("pushErr")
|
|
|
|
|
|
|
|
type fields struct {
|
|
|
|
eventstore *eventstore.Eventstore
|
|
|
|
}
|
|
|
|
type args struct {
|
2023-12-20 12:21:08 +00:00
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
subject string
|
|
|
|
authMethods []domain.UserAuthMethodType
|
|
|
|
authTime time.Time
|
2023-04-19 08:46:02 +00:00
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wantDetails *domain.ObjectDetails
|
|
|
|
wantErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "not found error",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
2023-12-20 12:21:08 +00:00
|
|
|
expectFilter(),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{
|
|
|
|
ctx, "123", "subj",
|
|
|
|
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
|
|
|
time.Unix(123, 456),
|
|
|
|
},
|
2023-12-08 14:30:55 +00:00
|
|
|
wantErr: zerrors.ThrowNotFound(nil, "COMMAND-Hief9", "Errors.DeviceAuth.NotFound"),
|
2023-04-19 08:46:02 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "push error",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
|
|
|
expectFilter(eventFromEventPusherWithInstanceID(
|
|
|
|
"instance1",
|
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
)),
|
|
|
|
expectPushFailed(pushErr,
|
2023-10-19 10:19:10 +00:00
|
|
|
deviceauth.NewApprovedEvent(
|
2023-12-20 12:21:08 +00:00
|
|
|
ctx, deviceauth.NewAggregate("123", "instance1"), "subj",
|
|
|
|
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
|
|
|
time.Unix(123, 456),
|
2023-10-19 10:19:10 +00:00
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{
|
|
|
|
ctx, "123", "subj",
|
|
|
|
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
|
|
|
time.Unix(123, 456),
|
|
|
|
},
|
2023-04-19 08:46:02 +00:00
|
|
|
wantErr: pushErr,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "success",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
|
|
|
expectFilter(eventFromEventPusherWithInstanceID(
|
|
|
|
"instance1",
|
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
)),
|
2023-10-19 10:19:10 +00:00
|
|
|
expectPush(
|
|
|
|
deviceauth.NewApprovedEvent(
|
2023-12-20 12:21:08 +00:00
|
|
|
ctx, deviceauth.NewAggregate("123", "instance1"), "subj",
|
|
|
|
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
|
|
|
time.Unix(123, 456),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
2023-10-19 10:19:10 +00:00
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{
|
|
|
|
ctx, "123", "subj",
|
|
|
|
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
|
|
|
time.Unix(123, 456),
|
|
|
|
},
|
2023-04-19 08:46:02 +00:00
|
|
|
wantDetails: &domain.ObjectDetails{
|
|
|
|
ResourceOwner: "instance1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
|
|
|
eventstore: tt.fields.eventstore,
|
|
|
|
}
|
2023-12-20 12:21:08 +00:00
|
|
|
gotDetails, err := c.ApproveDeviceAuth(tt.args.ctx, tt.args.id, tt.args.subject, tt.args.authMethods, tt.args.authTime)
|
2023-04-19 08:46:02 +00:00
|
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
|
|
assert.Equal(t, gotDetails, tt.wantDetails)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommands_CancelDeviceAuth(t *testing.T) {
|
|
|
|
ctx := authz.WithInstanceID(context.Background(), "instance1")
|
|
|
|
now := time.Now()
|
|
|
|
pushErr := errors.New("pushErr")
|
|
|
|
|
|
|
|
type fields struct {
|
|
|
|
eventstore *eventstore.Eventstore
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
id string
|
|
|
|
reason domain.DeviceAuthCanceled
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
wantDetails *domain.ObjectDetails
|
|
|
|
wantErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "not found error",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
2023-12-20 12:21:08 +00:00
|
|
|
expectFilter(),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{ctx, "123", domain.DeviceAuthCanceledDenied},
|
2023-12-08 14:30:55 +00:00
|
|
|
wantErr: zerrors.ThrowNotFound(nil, "COMMAND-gee5A", "Errors.DeviceAuth.NotFound"),
|
2023-04-19 08:46:02 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "push error",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
|
|
|
expectFilter(eventFromEventPusherWithInstanceID(
|
|
|
|
"instance1",
|
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
)),
|
|
|
|
expectPushFailed(pushErr,
|
2023-10-19 10:19:10 +00:00
|
|
|
deviceauth.NewCanceledEvent(
|
2023-12-20 12:21:08 +00:00
|
|
|
ctx, deviceauth.NewAggregate("123", "instance1"),
|
2023-10-19 10:19:10 +00:00
|
|
|
domain.DeviceAuthCanceledDenied,
|
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{ctx, "123", domain.DeviceAuthCanceledDenied},
|
2023-04-19 08:46:02 +00:00
|
|
|
wantErr: pushErr,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "success/denied",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
|
|
|
expectFilter(eventFromEventPusherWithInstanceID(
|
|
|
|
"instance1",
|
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
)),
|
2023-10-19 10:19:10 +00:00
|
|
|
expectPush(
|
|
|
|
deviceauth.NewCanceledEvent(
|
2023-12-20 12:21:08 +00:00
|
|
|
ctx, deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
domain.DeviceAuthCanceledDenied,
|
|
|
|
),
|
2023-10-19 10:19:10 +00:00
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{ctx, "123", domain.DeviceAuthCanceledDenied},
|
2023-04-19 08:46:02 +00:00
|
|
|
wantDetails: &domain.ObjectDetails{
|
|
|
|
ResourceOwner: "instance1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "success/expired",
|
|
|
|
fields: fields{
|
|
|
|
eventstore: eventstoreExpect(t,
|
|
|
|
expectFilter(eventFromEventPusherWithInstanceID(
|
|
|
|
"instance1",
|
|
|
|
deviceauth.NewAddedEvent(
|
|
|
|
ctx,
|
2023-12-20 12:21:08 +00:00
|
|
|
deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
"client_id", "123", "456", now,
|
|
|
|
[]string{"a", "b", "c"},
|
2024-04-03 06:06:21 +00:00
|
|
|
[]string{"projectID", "clientID"},
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
)),
|
2023-10-19 10:19:10 +00:00
|
|
|
expectPush(
|
|
|
|
deviceauth.NewCanceledEvent(
|
2023-12-20 12:21:08 +00:00
|
|
|
ctx, deviceauth.NewAggregate("123", "instance1"),
|
2023-04-19 08:46:02 +00:00
|
|
|
domain.DeviceAuthCanceledExpired,
|
|
|
|
),
|
2023-10-19 10:19:10 +00:00
|
|
|
),
|
2023-04-19 08:46:02 +00:00
|
|
|
),
|
|
|
|
},
|
2023-12-20 12:21:08 +00:00
|
|
|
args: args{ctx, "123", domain.DeviceAuthCanceledExpired},
|
2023-04-19 08:46:02 +00:00
|
|
|
wantDetails: &domain.ObjectDetails{
|
|
|
|
ResourceOwner: "instance1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
|
|
|
eventstore: tt.fields.eventstore,
|
|
|
|
}
|
|
|
|
gotDetails, err := c.CancelDeviceAuth(tt.args.ctx, tt.args.id, tt.args.reason)
|
|
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
|
|
assert.Equal(t, gotDetails, tt.wantDetails)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|