2023-02-15 09:14:59 +01:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-03-13 17:34:29 +01:00
|
|
|
"errors"
|
2023-02-15 09:14:59 +01:00
|
|
|
"testing"
|
2023-03-24 16:18:56 +01:00
|
|
|
"time"
|
2023-02-15 09:14:59 +01:00
|
|
|
|
2024-05-23 07:04:07 +02:00
|
|
|
"github.com/muhlemmer/gu"
|
2023-02-15 09:14:59 +01:00
|
|
|
"github.com/stretchr/testify/assert"
|
2023-10-19 12:34:00 +02:00
|
|
|
openid "github.com/zitadel/oidc/v3/pkg/oidc"
|
2023-11-22 12:56:43 +02:00
|
|
|
"go.uber.org/mock/gomock"
|
2023-02-15 09:14:59 +01:00
|
|
|
|
|
|
|
"github.com/zitadel/zitadel/internal/crypto"
|
|
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
|
|
"github.com/zitadel/zitadel/internal/id"
|
|
|
|
id_mock "github.com/zitadel/zitadel/internal/id/mock"
|
|
|
|
"github.com/zitadel/zitadel/internal/repository/idp"
|
|
|
|
"github.com/zitadel/zitadel/internal/repository/org"
|
2023-12-08 16:30:55 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
2023-02-15 09:14:59 +01:00
|
|
|
)
|
|
|
|
|
2024-09-06 15:47:57 +03:00
|
|
|
func TestCommandSide_AddOrgGenericOAuthProvider(t *testing.T) {
|
2023-02-24 15:16:06 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider GenericOAuthProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D32ef", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dbgzf", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-DF4ga", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-B23bs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D2gj8", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Fb8jk", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
{
|
|
|
|
"invalid id attribute",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-03 11:38:49 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sadf3d", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
},
|
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
"idAttribute",
|
|
|
|
nil,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-02-24 15:16:06 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
"idAttribute",
|
|
|
|
[]string{"user"},
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-02-24 15:16:06 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
Scopes: []string{"user"},
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-02-24 15:16:06 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-24 15:16:06 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgGenericOAuthProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-24 15:16:06 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-24 15:16:06 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GenericOAuthProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOAuthProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-asfsa", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D32ef", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dbgzf", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
2023-03-13 17:34:29 +01:00
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-B23bs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D2gj8", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Fb8jk", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
{
|
|
|
|
"invalid id attribute",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-03 11:38:49 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAe4gh", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-03 11:38:49 +01:00
|
|
|
},
|
|
|
|
},
|
2023-02-24 15:16:06 +01:00
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
2023-03-03 11:38:49 +01:00
|
|
|
"idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
nil,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-02-24 15:16:06 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "idAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: false,
|
2023-02-24 15:16:06 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-24 15:16:06 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOAuthIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
2023-03-03 11:38:49 +01:00
|
|
|
"idAttribute",
|
2023-02-24 15:16:06 +01:00
|
|
|
nil,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-02-24 15:16:06 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewOAuthIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.OAuthIDPChanges{
|
|
|
|
idp.ChangeOAuthName("new name"),
|
|
|
|
idp.ChangeOAuthClientID("clientID2"),
|
|
|
|
idp.ChangeOAuthClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeOAuthAuthorizationEndpoint("new auth"),
|
|
|
|
idp.ChangeOAuthTokenEndpoint("new token"),
|
|
|
|
idp.ChangeOAuthUserEndpoint("new user"),
|
|
|
|
idp.ChangeOAuthScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeOAuthIDAttribute("newAttribute"),
|
2025-02-26 13:20:47 +01:00
|
|
|
idp.ChangeOAuthUsePKCE(true),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeOAuthOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-02-24 15:16:06 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOAuthProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
AuthorizationEndpoint: "new auth",
|
|
|
|
TokenEndpoint: "new token",
|
|
|
|
UserEndpoint: "new user",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
2023-03-03 11:38:49 +01:00
|
|
|
IDAttribute: "newAttribute",
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-02-24 15:16:06 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-24 15:16:06 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgGenericOAuthProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-15 07:48:37 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-16 16:47:22 +01:00
|
|
|
func TestCommandSide_AddOrgGenericOIDCIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider GenericOIDCProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Sgtj5", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid issuer",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Hz6zj", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-fb5jm", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Sfdf4", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-16 16:47:22 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{openid.ScopeOpenID},
|
|
|
|
true,
|
2025-02-26 13:20:47 +01:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-16 16:47:22 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{openid.ScopeOpenID},
|
|
|
|
IsIDTokenMapping: true,
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-03-16 16:47:22 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-16 16:47:22 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgGenericOIDCProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-16 16:47:22 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgGenericOIDCIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-16 16:47:22 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GenericOIDCProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GenericOIDCProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAfd3", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dvf4f", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid issuer",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-BDfr3", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Db3bs", ""))
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-16 16:47:22 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-03-16 16:47:22 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-16 16:47:22 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-03-16 16:47:22 +01:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewOIDCIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.OIDCIDPChanges{
|
|
|
|
idp.ChangeOIDCName("new name"),
|
|
|
|
idp.ChangeOIDCIssuer("new issuer"),
|
|
|
|
idp.ChangeOIDCClientID("clientID2"),
|
|
|
|
idp.ChangeOIDCClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeOIDCScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeOIDCIsIDTokenMapping(true),
|
2025-02-26 13:20:47 +01:00
|
|
|
idp.ChangeOIDCUsePKCE(true),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeOIDCOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-16 16:47:22 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GenericOIDCProvider{
|
|
|
|
Name: "new name",
|
|
|
|
Issuer: "new issuer",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IsIDTokenMapping: true,
|
2025-02-26 13:20:47 +01:00
|
|
|
UsePKCE: true,
|
2023-03-16 16:47:22 +01:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-16 16:47:22 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgGenericOIDCProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-16 16:47:22 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-08 00:50:53 +02:00
|
|
|
func TestCommandSide_MigrateOrgGenericOIDCToAzureADProvider(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-06-08 00:50:53 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider AzureADProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sdf3g", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Fhbr2", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client secret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dzh3g", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "ro",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
event := org.NewOIDCIDPMigratedAzureADEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate full ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOIDCIDPMigratedAzureADEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
"tenant",
|
|
|
|
true,
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
Tenant: "tenant",
|
|
|
|
EmailVerified: true,
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-06-08 00:50:53 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.MigrateOrgGenericOIDCToAzureADProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-06-08 00:50:53 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_MigrateOrgOIDCToGoogleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-06-08 00:50:53 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GoogleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D3fvs", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-W2vqs", ""))
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"not found",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-06-08 00:50:53 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOIDCIDPMigratedGoogleEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "migrate full ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-06-08 00:50:53 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewOIDCIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
false,
|
2025-02-26 13:20:47 +01:00
|
|
|
false,
|
2023-06-08 00:50:53 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewOIDCIDPMigratedGoogleEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-06-08 00:50:53 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-06-08 00:50:53 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.MigrateOrgGenericOIDCToGoogleProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-06-08 00:50:53 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-15 07:48:37 +01:00
|
|
|
func TestCommandSide_AddOrgAzureADIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider AzureADProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sdf3g", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Fhbr2", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client secret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dzh3g", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-15 07:48:37 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
"tenant",
|
|
|
|
true,
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-15 07:48:37 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
Tenant: "tenant",
|
|
|
|
EmailVerified: true,
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-15 07:48:37 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgAzureADProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-15 07:48:37 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgAzureADIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-15 07:48:37 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider AzureADProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAgh2", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-fh3h1", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-dmitg", ""))
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-15 07:48:37 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-15 07:48:37 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewAzureADIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.AzureADIDPChanges{
|
|
|
|
idp.ChangeAzureADName("new name"),
|
|
|
|
idp.ChangeAzureADClientID("new clientID"),
|
|
|
|
idp.ChangeAzureADClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new clientSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeAzureADScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeAzureADTenant("new tenant"),
|
|
|
|
idp.ChangeAzureADIsEmailVerified(true),
|
|
|
|
idp.ChangeAzureADOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-15 07:48:37 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AzureADProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "new clientID",
|
|
|
|
ClientSecret: "new clientSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
Tenant: "new tenant",
|
|
|
|
EmailVerified: true,
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-15 07:48:37 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgAzureADProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-24 15:16:06 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-08 11:17:28 +01:00
|
|
|
func TestCommandSide_AddOrgGitHubIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider GitHubProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Jdsgf", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client secret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-dsgz3", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitHubIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitHubIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgGitHubProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgGitHubIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GitHubProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sdf4h", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid client id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-fdh5z", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGitHubIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGitHubIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewGitHubIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitHubIDPChanges{
|
|
|
|
idp.ChangeGitHubName("new name"),
|
|
|
|
idp.ChangeGitHubClientID("new clientID"),
|
|
|
|
idp.ChangeGitHubClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new clientSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitHubScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitHubOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "new clientID",
|
|
|
|
ClientSecret: "new clientSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgGitHubProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddOrgGitHubEnterpriseIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider GitHubEnterpriseProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dg4td", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-dgj53", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Ghjjs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sani2", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-agj42", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sd5hn", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
[]string{"user"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
Scopes: []string{"user"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgGitHubEnterpriseProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgGitHubEnterpriseIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-08 11:17:28 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GitHubEnterpriseProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitHubEnterpriseProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sdfh3", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-shj42", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sdh73", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid auth endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
2023-03-13 17:34:29 +01:00
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-acx2w", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid token endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-dgj6q", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid user endpoint",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-ybj62", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-08 11:17:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "name",
|
|
|
|
ClientID: "clientID",
|
|
|
|
AuthorizationEndpoint: "auth",
|
|
|
|
TokenEndpoint: "token",
|
|
|
|
UserEndpoint: "user",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-08 11:17:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGitHubEnterpriseIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
"auth",
|
|
|
|
"token",
|
|
|
|
"user",
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewGitHubEnterpriseIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitHubEnterpriseIDPChanges{
|
|
|
|
idp.ChangeGitHubEnterpriseName("new name"),
|
|
|
|
idp.ChangeGitHubEnterpriseClientID("clientID2"),
|
|
|
|
idp.ChangeGitHubEnterpriseClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitHubEnterpriseAuthorizationEndpoint("new auth"),
|
|
|
|
idp.ChangeGitHubEnterpriseTokenEndpoint("new token"),
|
|
|
|
idp.ChangeGitHubEnterpriseUserEndpoint("new user"),
|
|
|
|
idp.ChangeGitHubEnterpriseScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitHubEnterpriseOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-08 11:17:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitHubEnterpriseProvider{
|
|
|
|
Name: "new name",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
AuthorizationEndpoint: "new auth",
|
|
|
|
TokenEndpoint: "new token",
|
|
|
|
UserEndpoint: "new user",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-08 11:17:28 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgGitHubEnterpriseProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-08 11:17:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_AddOrgGitLabIDP(t *testing.T) {
|
2023-02-21 18:18:28 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabProvider
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-adsg2", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-GD1j2", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-02-21 18:18:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-02-21 18:18:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-21 18:18:28 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
2023-03-13 17:34:29 +01:00
|
|
|
id, got, err := c.AddOrgGitLabProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
2023-02-21 18:18:28 +01:00
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_UpdateOrgGitLabIDP(t *testing.T) {
|
2023-02-21 18:18:28 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-21 18:18:28 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabProvider
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-HJK91", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D12t6", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
2023-03-13 17:34:29 +01:00
|
|
|
org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
2023-02-21 18:18:28 +01:00
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-02-24 15:16:06 +01:00
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
2023-02-21 18:18:28 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-21 18:18:28 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
2023-03-13 17:34:29 +01:00
|
|
|
org.NewGitLabIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
2023-02-21 18:18:28 +01:00
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewGitLabIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitLabIDPChanges{
|
|
|
|
idp.ChangeGitLabClientID("clientID2"),
|
|
|
|
idp.ChangeGitLabClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitLabScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitLabOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-02-21 18:18:28 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabProvider{
|
2023-02-21 18:18:28 +01:00
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-21 18:18:28 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
2023-03-13 17:34:29 +01:00
|
|
|
got, err := c.UpdateOrgGitLabProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
2023-02-21 18:18:28 +01:00
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-21 18:18:28 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 17:34:29 +01:00
|
|
|
func TestCommandSide_AddOrgGitLabSelfHostedIDP(t *testing.T) {
|
2023-02-15 09:14:59 +01:00
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
2023-03-13 17:34:29 +01:00
|
|
|
provider GitLabSelfHostedProvider
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-jw4ZT", ""))
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid issuer",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
2023-02-15 09:14:59 +01:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-AST4S", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid clientID",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
2023-02-15 09:14:59 +01:00
|
|
|
Name: "name",
|
2023-03-13 17:34:29 +01:00
|
|
|
Issuer: "issuer",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-DBZHJ", ""))
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-13 17:34:29 +01:00
|
|
|
"invalid clientSecret",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SDGJ4", ""))
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-02-15 09:14:59 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2023-03-13 17:34:29 +01:00
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgGitLabSelfHostedProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgGitLabSelfHostedIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GitLabSelfHostedProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GitLabSelfHostedProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAFG4", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-DG4H", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid issuer",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SD4eb", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-GHWE3", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Name: "name",
|
|
|
|
Issuer: "issuer",
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGitLabSelfHostedIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
"issuer",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewGitLabSelfHostedIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GitLabSelfHostedIDPChanges{
|
|
|
|
idp.ChangeGitLabSelfHostedClientID("clientID2"),
|
|
|
|
idp.ChangeGitLabSelfHostedIssuer("newIssuer"),
|
|
|
|
idp.ChangeGitLabSelfHostedName("newName"),
|
|
|
|
idp.ChangeGitLabSelfHostedClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGitLabSelfHostedScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGitLabSelfHostedOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GitLabSelfHostedProvider{
|
|
|
|
Issuer: "newIssuer",
|
|
|
|
Name: "newName",
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgGitLabSelfHostedProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddOrgGoogleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider GoogleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-D3fvs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientSecret",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-W2vqs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGoogleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewGoogleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
[]string{"openid"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "clientSecret",
|
|
|
|
Scopes: []string{"openid"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgGoogleProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgGoogleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider GoogleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-S32t1", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-ds432", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGoogleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewGoogleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("clientSecret"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewGoogleIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.GoogleIDPChanges{
|
|
|
|
idp.ChangeGoogleClientID("clientID2"),
|
|
|
|
idp.ChangeGoogleClientSecret(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newSecret"),
|
|
|
|
}),
|
|
|
|
idp.ChangeGoogleScopes([]string{"openid", "profile"}),
|
|
|
|
idp.ChangeGoogleOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: GoogleProvider{
|
|
|
|
ClientID: "clientID2",
|
|
|
|
ClientSecret: "newSecret",
|
|
|
|
Scopes: []string{"openid", "profile"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-03-13 17:34:29 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgGoogleProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-03-13 17:34:29 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_AddOrgLDAPIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider LDAPProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAfdd", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid baseDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sv31s", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid binddn",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-sdgf4", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid password",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
2023-03-24 16:18:56 +01:00
|
|
|
BindDN: "binddn",
|
2023-03-13 17:34:29 +01:00
|
|
|
BaseDN: "baseDN",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-AEG2w", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userbase",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAD5n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid servers",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SAy945n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userObjectClasses",
|
2023-03-13 17:34:29 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-13 17:34:29 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-S1x705n", ""))
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid userFilters",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-24 16:18:56 +01:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BindDN: "binddn",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-aAx9x1n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2025-03-18 15:23:12 +00:00
|
|
|
{
|
|
|
|
"invalid rootCA",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "dn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
|
|
|
RootCA: []byte("certificate"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-cwqVVdBwKt", "Errors.Invalid.Argument"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-03-13 17:34:29 +01:00
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewLDAPIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]string{"server"},
|
|
|
|
false,
|
|
|
|
"baseDN",
|
|
|
|
"dn",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-02-18 10:06:50 +00:00
|
|
|
nil,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.LDAPAttributes{},
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-03-13 17:34:29 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "dn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-03-13 17:34:29 +01:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewLDAPIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]string{"server"},
|
|
|
|
false,
|
|
|
|
"baseDN",
|
|
|
|
"dn",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
validLDAPRootCA,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.LDAPAttributes{
|
|
|
|
IDAttribute: "id",
|
|
|
|
FirstNameAttribute: "firstName",
|
|
|
|
LastNameAttribute: "lastName",
|
|
|
|
DisplayNameAttribute: "displayName",
|
|
|
|
NickNameAttribute: "nickName",
|
|
|
|
PreferredUsernameAttribute: "preferredUsername",
|
|
|
|
EmailAttribute: "email",
|
|
|
|
EmailVerifiedAttribute: "emailVerified",
|
|
|
|
PhoneAttribute: "phone",
|
|
|
|
PhoneVerifiedAttribute: "phoneVerified",
|
|
|
|
PreferredLanguageAttribute: "preferredLanguage",
|
|
|
|
AvatarURLAttribute: "avatarURL",
|
|
|
|
ProfileAttribute: "profile",
|
|
|
|
},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-02-15 09:14:59 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
StartTLS: false,
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "dn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
Timeout: time.Second * 30,
|
2025-03-18 15:23:12 +00:00
|
|
|
RootCA: validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
LDAPAttributes: idp.LDAPAttributes{
|
|
|
|
IDAttribute: "id",
|
|
|
|
FirstNameAttribute: "firstName",
|
|
|
|
LastNameAttribute: "lastName",
|
|
|
|
DisplayNameAttribute: "displayName",
|
|
|
|
NickNameAttribute: "nickName",
|
|
|
|
PreferredUsernameAttribute: "preferredUsername",
|
|
|
|
EmailAttribute: "email",
|
|
|
|
EmailVerifiedAttribute: "emailVerified",
|
|
|
|
PhoneAttribute: "phone",
|
|
|
|
PhoneVerifiedAttribute: "phoneVerified",
|
|
|
|
PreferredLanguageAttribute: "preferredLanguage",
|
|
|
|
AvatarURLAttribute: "avatarURL",
|
|
|
|
ProfileAttribute: "profile",
|
|
|
|
},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-15 09:14:59 +01:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgLDAPProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgLDAPIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-02-15 09:14:59 +01:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider LDAPProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: LDAPProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Dgdbs", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Sffgd", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid baseDN",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-vb3ss", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid binddn",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-hbere", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userbase",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
2023-03-24 16:18:56 +01:00
|
|
|
BindDN: "bindDN",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-DG45z", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid servers",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Sxx945n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-03-24 16:18:56 +01:00
|
|
|
"invalid userObjectClasses",
|
2023-02-15 09:14:59 +01:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
2023-03-13 17:34:29 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-S1p605n", ""))
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid userFilters",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-aBx901n", ""))
|
2023-03-13 17:34:29 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
2025-03-18 15:23:12 +00:00
|
|
|
{
|
|
|
|
"invalid rootCA",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "bindDN",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
RootCA: []byte("certificate"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-aBx901n", ""))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "baseDN",
|
|
|
|
BindDN: "binddn",
|
|
|
|
BindPassword: "password",
|
|
|
|
UserBase: "user",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-03-24 16:18:56 +01:00
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowNotFound(nil, "ORG-ASF3F", ""))
|
2023-03-24 16:18:56 +01:00
|
|
|
},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewLDAPIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2023-03-24 16:18:56 +01:00
|
|
|
[]string{"server"},
|
2023-02-15 09:14:59 +01:00
|
|
|
false,
|
2023-03-24 16:18:56 +01:00
|
|
|
"basedn",
|
|
|
|
"binddn",
|
2023-02-15 09:14:59 +01:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
2023-03-24 16:18:56 +01:00
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
idp.LDAPAttributes{},
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "name",
|
|
|
|
Servers: []string{"server"},
|
|
|
|
BaseDN: "basedn",
|
|
|
|
BindDN: "binddn",
|
|
|
|
UserObjectClasses: []string{"object"},
|
|
|
|
UserFilters: []string{"filter"},
|
|
|
|
UserBase: "user",
|
|
|
|
Timeout: time.Second * 30,
|
2025-03-18 15:23:12 +00:00
|
|
|
RootCA: validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-02-24 15:16:06 +01:00
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
2023-02-15 09:14:59 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-02-15 09:14:59 +01:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewLDAPIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2023-03-24 16:18:56 +01:00
|
|
|
[]string{"server"},
|
2023-02-15 09:14:59 +01:00
|
|
|
false,
|
2023-03-24 16:18:56 +01:00
|
|
|
"basedn",
|
|
|
|
"binddn",
|
2023-02-15 09:14:59 +01:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("password"),
|
|
|
|
},
|
2023-03-24 16:18:56 +01:00
|
|
|
"user",
|
|
|
|
[]string{"object"},
|
|
|
|
[]string{"filter"},
|
|
|
|
time.Second*30,
|
2025-03-18 15:23:12 +00:00
|
|
|
nil,
|
2023-02-15 09:14:59 +01:00
|
|
|
idp.LDAPAttributes{},
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewLDAPIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.LDAPIDPChanges{
|
|
|
|
idp.ChangeLDAPName("new name"),
|
|
|
|
idp.ChangeLDAPServers([]string{"new server"}),
|
|
|
|
idp.ChangeLDAPStartTLS(true),
|
|
|
|
idp.ChangeLDAPBaseDN("new basedn"),
|
|
|
|
idp.ChangeLDAPBindDN("new binddn"),
|
|
|
|
idp.ChangeLDAPBindPassword(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new password"),
|
|
|
|
}),
|
|
|
|
idp.ChangeLDAPUserBase("new user"),
|
|
|
|
idp.ChangeLDAPUserObjectClasses([]string{"new object"}),
|
|
|
|
idp.ChangeLDAPUserFilters([]string{"new filter"}),
|
|
|
|
idp.ChangeLDAPTimeout(time.Second * 20),
|
|
|
|
idp.ChangeLDAPAttributes(idp.LDAPAttributeChanges{
|
|
|
|
IDAttribute: stringPointer("new id"),
|
|
|
|
FirstNameAttribute: stringPointer("new firstName"),
|
|
|
|
LastNameAttribute: stringPointer("new lastName"),
|
|
|
|
DisplayNameAttribute: stringPointer("new displayName"),
|
|
|
|
NickNameAttribute: stringPointer("new nickName"),
|
|
|
|
PreferredUsernameAttribute: stringPointer("new preferredUsername"),
|
|
|
|
EmailAttribute: stringPointer("new email"),
|
|
|
|
EmailVerifiedAttribute: stringPointer("new emailVerified"),
|
|
|
|
PhoneAttribute: stringPointer("new phone"),
|
|
|
|
PhoneVerifiedAttribute: stringPointer("new phoneVerified"),
|
|
|
|
PreferredLanguageAttribute: stringPointer("new preferredLanguage"),
|
|
|
|
AvatarURLAttribute: stringPointer("new avatarURL"),
|
|
|
|
ProfileAttribute: stringPointer("new profile"),
|
|
|
|
}),
|
|
|
|
idp.ChangeLDAPOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
2025-03-18 15:23:12 +00:00
|
|
|
idp.ChangeLDAPRootCA(validLDAPRootCA),
|
2023-10-19 12:19:10 +02:00
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-02-15 09:14:59 +01:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: LDAPProvider{
|
2023-03-24 16:18:56 +01:00
|
|
|
Name: "new name",
|
|
|
|
Servers: []string{"new server"},
|
|
|
|
StartTLS: true,
|
|
|
|
BaseDN: "new basedn",
|
|
|
|
BindDN: "new binddn",
|
|
|
|
BindPassword: "new password",
|
|
|
|
UserBase: "new user",
|
|
|
|
UserObjectClasses: []string{"new object"},
|
|
|
|
UserFilters: []string{"new filter"},
|
|
|
|
Timeout: time.Second * 20,
|
2025-03-18 15:23:12 +00:00
|
|
|
RootCA: validLDAPRootCA,
|
2023-02-15 09:14:59 +01:00
|
|
|
LDAPAttributes: idp.LDAPAttributes{
|
|
|
|
IDAttribute: "new id",
|
|
|
|
FirstNameAttribute: "new firstName",
|
|
|
|
LastNameAttribute: "new lastName",
|
|
|
|
DisplayNameAttribute: "new displayName",
|
|
|
|
NickNameAttribute: "new nickName",
|
|
|
|
PreferredUsernameAttribute: "new preferredUsername",
|
|
|
|
EmailAttribute: "new email",
|
|
|
|
EmailVerifiedAttribute: "new emailVerified",
|
|
|
|
PhoneAttribute: "new phone",
|
|
|
|
PhoneVerifiedAttribute: "new phoneVerified",
|
|
|
|
PreferredLanguageAttribute: "new preferredLanguage",
|
|
|
|
AvatarURLAttribute: "new avatarURL",
|
|
|
|
ProfileAttribute: "new profile",
|
|
|
|
},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-02-15 09:14:59 +01:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgLDAPProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-02-15 09:14:59 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 08:39:16 +02:00
|
|
|
func TestCommandSide_AddOrgAppleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
provider AppleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-jkn3w", "Errors.IDP.ClientIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid teamID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Ffg32", "Errors.IDP.TeamIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid keyID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-GDjm5", "Errors.IDP.KeyIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid privateKey",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-GVD4n", "Errors.IDP.PrivateKeyMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewAppleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-08-31 08:39:16 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
PrivateKey: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewAppleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
[]string{"name", "email"},
|
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-08-31 08:39:16 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
PrivateKey: []byte("privateKey"),
|
|
|
|
Scopes: []string{"name", "email"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-08-31 08:39:16 +02:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgAppleProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-08-31 08:39:16 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgAppleIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-08-31 08:39:16 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
provider AppleProvider
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: AppleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-FRHBH", "Errors.IDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid clientID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SFm4l", "Errors.IDP.ClientIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid teamID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SG34t", "Errors.IDP.TeamIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid keyID",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-Gh4z2", "Errors.IDP.KeyIDMissing"))
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
2023-12-08 16:30:55 +02:00
|
|
|
err: zerrors.IsNotFound,
|
2023-08-31 08:39:16 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewAppleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID",
|
|
|
|
TeamID: "teamID",
|
|
|
|
KeyID: "keyID",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-08-31 08:39:16 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewAppleIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"",
|
|
|
|
"clientID",
|
|
|
|
"teamID",
|
|
|
|
"keyID",
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("privateKey"),
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewAppleIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.AppleIDPChanges{
|
|
|
|
idp.ChangeAppleClientID("clientID2"),
|
|
|
|
idp.ChangeAppleTeamID("teamID2"),
|
|
|
|
idp.ChangeAppleKeyID("keyID2"),
|
|
|
|
idp.ChangeApplePrivateKey(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("newPrivateKey"),
|
|
|
|
}),
|
|
|
|
idp.ChangeAppleScopes([]string{"name", "email"}),
|
|
|
|
idp.ChangeAppleOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-08-31 08:39:16 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: AppleProvider{
|
|
|
|
ClientID: "clientID2",
|
|
|
|
TeamID: "teamID2",
|
|
|
|
KeyID: "keyID2",
|
|
|
|
PrivateKey: []byte("newPrivateKey"),
|
|
|
|
Scopes: []string{"name", "email"},
|
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-08-31 08:39:16 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgAppleProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-08-31 08:39:16 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-15 09:14:59 +01:00
|
|
|
func stringPointer(s string) *string {
|
|
|
|
return &s
|
|
|
|
}
|
2023-09-29 11:26:14 +02:00
|
|
|
|
|
|
|
func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator id.Generator
|
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
certificateAndKeyGenerator func(id string) ([]byte, []byte, error)
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
2024-12-03 11:38:28 +01:00
|
|
|
provider *SAMLProvider
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
id string
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{},
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-957lr0f8u3", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-12-03 11:38:28 +01:00
|
|
|
"no metadata",
|
2023-09-29 11:26:14 +02:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-78isv6m53a", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-12-03 11:38:28 +01:00
|
|
|
{
|
|
|
|
"invalid metadata, fail on error",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
provider: &SAMLProvider{
|
|
|
|
Name: "name",
|
|
|
|
Metadata: []byte("metadata"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-09-29 11:26:14 +02:00
|
|
|
{
|
|
|
|
name: "ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2024-12-03 11:38:28 +01:00
|
|
|
validSAMLMetadata,
|
2023-10-19 12:19:10 +02:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
nil,
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{},
|
|
|
|
),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)), certificateAndKeyGenerator: func(id string) ([]byte, []byte, error) { return []byte("key"), []byte("certificate"), nil },
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ok all set",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2024-12-03 11:38:28 +01:00
|
|
|
validSAMLMetadata,
|
2023-10-19 12:19:10 +02:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"binding",
|
|
|
|
true,
|
2024-05-23 07:04:07 +02:00
|
|
|
gu.Ptr(domain.SAMLNameIDFormatTransient),
|
|
|
|
"customAttribute",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
true,
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
certificateAndKeyGenerator: func(id string) ([]byte, []byte, error) { return []byte("key"), []byte("certificate"), nil },
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2024-05-23 07:04:07 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2024-05-23 07:04:07 +02:00
|
|
|
Binding: "binding",
|
|
|
|
WithSignedRequest: true,
|
|
|
|
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
|
|
|
TransientMappingAttributeName: "customAttribute",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
FederatedLogoutEnabled: true,
|
2023-09-29 11:26:14 +02:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
id: "id1",
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-09-29 11:26:14 +02:00
|
|
|
idGenerator: tt.fields.idGenerator,
|
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
samlCertificateAndKeyGenerator: tt.fields.certificateAndKeyGenerator,
|
|
|
|
}
|
|
|
|
id, got, err := c.AddOrgSAMLProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
|
|
|
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 {
|
|
|
|
assert.Equal(t, tt.res.id, id)
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-09-29 11:26:14 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
2024-12-03 11:38:28 +01:00
|
|
|
provider *SAMLProvider
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{},
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-wwdwdlaya0", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid name",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{},
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-egixaofgyl", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-12-03 11:38:28 +01:00
|
|
|
"no metadata",
|
2023-09-29 11:26:14 +02:00
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-j6spncd74m", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-12-03 11:38:28 +01:00
|
|
|
{
|
|
|
|
"invalid metadata, error",
|
|
|
|
fields{
|
|
|
|
eventstore: expectEventstore(),
|
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
provider: &SAMLProvider{
|
|
|
|
Name: "name",
|
|
|
|
Metadata: []byte("metadata"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SFqqh42", "Errors.Project.App.SAMLMetadataFormat"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-09-29 11:26:14 +02:00
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowNotFound(nil, "ORG-z82dddndql", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no changes",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
2024-12-03 11:38:28 +01:00
|
|
|
validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
nil,
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-09-29 11:26:14 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2023-09-29 11:26:14 +02:00
|
|
|
Name: "name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]byte("metadata"),
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"binding",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
gu.Ptr(domain.SAMLNameIDFormatUnspecified),
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-09-29 11:26:14 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
t := true
|
|
|
|
event, _ := org.NewSAMLIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.SAMLIDPChanges{
|
|
|
|
idp.ChangeSAMLName("new name"),
|
2024-12-03 11:38:28 +01:00
|
|
|
idp.ChangeSAMLMetadata(validSAMLMetadata),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeSAMLBinding("new binding"),
|
|
|
|
idp.ChangeSAMLWithSignedRequest(true),
|
2024-05-23 07:04:07 +02:00
|
|
|
idp.ChangeSAMLNameIDFormat(gu.Ptr(domain.SAMLNameIDFormatTransient)),
|
|
|
|
idp.ChangeSAMLTransientMappingAttributeName("customAttribute"),
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
idp.ChangeSAMLFederatedLogoutEnabled(true),
|
2023-10-19 12:19:10 +02:00
|
|
|
idp.ChangeSAMLOptions(idp.OptionChanges{
|
|
|
|
IsCreationAllowed: &t,
|
|
|
|
IsLinkingAllowed: &t,
|
|
|
|
IsAutoCreation: &t,
|
|
|
|
IsAutoUpdate: &t,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
2024-12-03 11:38:28 +01:00
|
|
|
provider: &SAMLProvider{
|
2024-05-23 07:04:07 +02:00
|
|
|
Name: "new name",
|
2024-12-03 11:38:28 +01:00
|
|
|
Metadata: validSAMLMetadata,
|
2024-05-23 07:04:07 +02:00
|
|
|
Binding: "new binding",
|
|
|
|
WithSignedRequest: true,
|
|
|
|
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
|
|
|
TransientMappingAttributeName: "customAttribute",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
FederatedLogoutEnabled: true,
|
2023-09-29 11:26:14 +02:00
|
|
|
IDPOptions: idp.Options{
|
|
|
|
IsCreationAllowed: true,
|
|
|
|
IsLinkingAllowed: true,
|
|
|
|
IsAutoCreation: true,
|
|
|
|
IsAutoUpdate: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-09-29 11:26:14 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
}
|
|
|
|
got, err := c.UpdateOrgSAMLProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandSide_RegenerateOrgSAMLProviderCertificate(t *testing.T) {
|
|
|
|
type fields struct {
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore func(*testing.T) *eventstore.Eventstore
|
2023-09-29 11:26:14 +02:00
|
|
|
secretCrypto crypto.EncryptionAlgorithm
|
|
|
|
certificateAndKeyGenerator func(id string) ([]byte, []byte, error)
|
|
|
|
}
|
|
|
|
type args struct {
|
|
|
|
ctx context.Context
|
|
|
|
resourceOwner string
|
|
|
|
id string
|
|
|
|
}
|
|
|
|
type res struct {
|
|
|
|
want *domain.ObjectDetails
|
|
|
|
err func(error) bool
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
fields fields
|
|
|
|
args args
|
|
|
|
res res
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"invalid id",
|
|
|
|
fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(),
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
},
|
|
|
|
res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-arv4vdrb6c", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
err: func(err error) bool {
|
2023-12-08 16:30:55 +02:00
|
|
|
return errors.Is(err, zerrors.ThrowNotFound(nil, "ORG-4dw21ch9o9", ""))
|
2023-09-29 11:26:14 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change ok",
|
|
|
|
fields: fields{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: expectEventstore(
|
2023-09-29 11:26:14 +02:00
|
|
|
expectFilter(
|
|
|
|
eventFromEventPusher(
|
|
|
|
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
"name",
|
|
|
|
[]byte("metadata"),
|
|
|
|
&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("key"),
|
|
|
|
},
|
|
|
|
[]byte("certificate"),
|
|
|
|
"binding",
|
|
|
|
false,
|
2024-05-23 07:04:07 +02:00
|
|
|
gu.Ptr(domain.SAMLNameIDFormatUnspecified),
|
|
|
|
"",
|
feat: federated logout for SAML IdPs (#9931)
# Which Problems Are Solved
Currently if a user signs in using an IdP, once they sign out of
Zitadel, the corresponding IdP session is not terminated. This can be
the desired behavior. In some cases, e.g. when using a shared computer
it results in a potential security risk, since a follower user might be
able to sign in as the previous using the still open IdP session.
# How the Problems Are Solved
- Admins can enabled a federated logout option on SAML IdPs through the
Admin and Management APIs.
- During the termination of a login V1 session using OIDC end_session
endpoint, Zitadel will check if an IdP was used to authenticate that
session.
- In case there was a SAML IdP used with Federated Logout enabled, it
will intercept the logout process, store the information into the shared
cache and redirect to the federated logout endpoint in the V1 login.
- The V1 login federated logout endpoint checks every request on an
existing cache entry. On success it will create a SAML logout request
for the used IdP and either redirect or POST to the configured SLO
endpoint. The cache entry is updated with a `redirected` state.
- A SLO endpoint is added to the `/idp` handlers, which will handle the
SAML logout responses. At the moment it will check again for an existing
federated logout entry (with state `redirected`) in the cache. On
success, the user is redirected to the initially provided
`post_logout_redirect_uri` from the end_session request.
# Additional Changes
None
# Additional Context
- This PR merges the https://github.com/zitadel/zitadel/pull/9841 and
https://github.com/zitadel/zitadel/pull/9854 to main, additionally
updating the docs on Entra ID SAML.
- closes #9228
- backport to 3.x
---------
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Zach Hirschtritt <zachary.hirschtritt@klaviyo.com>
(cherry picked from commit 2cf3ef4de4ef993367daec6ff3974bdbdf70d2f3)
2025-05-23 13:52:25 +02:00
|
|
|
false,
|
2023-09-29 11:26:14 +02:00
|
|
|
idp.Options{},
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
expectPush(
|
2023-10-19 12:19:10 +02:00
|
|
|
func() eventstore.Command {
|
|
|
|
event, _ := org.NewSAMLIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
|
|
|
"id1",
|
|
|
|
[]idp.SAMLIDPChanges{
|
|
|
|
idp.ChangeSAMLKey(&crypto.CryptoValue{
|
|
|
|
CryptoType: crypto.TypeEncryption,
|
|
|
|
Algorithm: "enc",
|
|
|
|
KeyID: "id",
|
|
|
|
Crypted: []byte("new key"),
|
|
|
|
}),
|
|
|
|
idp.ChangeSAMLCertificate([]byte("new certificate")),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return event
|
|
|
|
}(),
|
2023-09-29 11:26:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
|
|
certificateAndKeyGenerator: func(id string) ([]byte, []byte, error) {
|
|
|
|
return []byte("new key"), []byte("new certificate"), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
args: args{
|
|
|
|
ctx: context.Background(),
|
|
|
|
resourceOwner: "org1",
|
|
|
|
id: "id1",
|
|
|
|
},
|
|
|
|
res: res{
|
|
|
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
c := &Commands{
|
2024-05-23 07:04:07 +02:00
|
|
|
eventstore: tt.fields.eventstore(t),
|
2023-09-29 11:26:14 +02:00
|
|
|
idpConfigEncryption: tt.fields.secretCrypto,
|
|
|
|
samlCertificateAndKeyGenerator: tt.fields.certificateAndKeyGenerator,
|
|
|
|
}
|
|
|
|
got, err := c.RegenerateOrgSAMLProviderCertificate(tt.args.ctx, tt.args.resourceOwner, tt.args.id)
|
|
|
|
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 {
|
2024-08-12 22:32:01 +02:00
|
|
|
assertObjectDetails(t, tt.res.want, got)
|
2023-09-29 11:26:14 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|