mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:07:31 +00:00
feat: jwt as idp (#2363)
* feat: jwt idp * feat: command side * feat: add tests * fill idp views with jwt idps and return apis * add jwtEndpoint to jwt idp * begin jwt request handling * merge * handle jwt idp * cleanup * fixes * autoregister * get token from specific header name * error handling * fix texts * handle renderExternalNotFoundOption Co-authored-by: fabi <fabienne.gerschwiler@gmail.com>
This commit is contained in:
@@ -153,6 +153,17 @@ func writeModelToIDPOIDCConfig(wm *OIDCConfigWriteModel) *domain.OIDCIDPConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToIDPJWTConfig(wm *JWTConfigWriteModel) *domain.JWTIDPConfig {
|
||||
return &domain.JWTIDPConfig{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
IDPConfigID: wm.IDPConfigID,
|
||||
JWTEndpoint: wm.JWTEndpoint,
|
||||
Issuer: wm.Issuer,
|
||||
KeysEndpoint: wm.KeysEndpoint,
|
||||
HeaderName: wm.HeaderName,
|
||||
}
|
||||
}
|
||||
|
||||
func writeModelToIDPProvider(wm *IdentityProviderWriteModel) *domain.IDPProvider {
|
||||
return &domain.IDPProvider{
|
||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||
|
@@ -2,6 +2,7 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
@@ -13,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func (c *Commands) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
|
||||
if config.OIDCConfig == nil {
|
||||
if config.OIDCConfig == nil && config.JWTConfig == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
|
||||
}
|
||||
|
||||
@@ -23,11 +24,6 @@ func (c *Commands) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPCo
|
||||
}
|
||||
addedConfig := NewIAMIDPConfigWriteModel(idpConfigID)
|
||||
|
||||
clientSecret, err := crypto.Encrypt([]byte(config.OIDCConfig.ClientSecretString), c.idpConfigSecretCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&addedConfig.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
iam_repo.NewIDPConfigAddedEvent(
|
||||
@@ -39,7 +35,14 @@ func (c *Commands) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPCo
|
||||
config.StylingType,
|
||||
config.AutoRegister,
|
||||
),
|
||||
iam_repo.NewIDPOIDCConfigAddedEvent(
|
||||
}
|
||||
if config.OIDCConfig != nil {
|
||||
clientSecret, err := crypto.Encrypt([]byte(config.OIDCConfig.ClientSecretString), c.idpConfigSecretCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
events = append(events, iam_repo.NewIDPOIDCConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
config.OIDCConfig.ClientID,
|
||||
@@ -51,9 +54,18 @@ func (c *Commands) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPCo
|
||||
config.OIDCConfig.IDPDisplayNameMapping,
|
||||
config.OIDCConfig.UsernameMapping,
|
||||
config.OIDCConfig.Scopes...,
|
||||
),
|
||||
))
|
||||
} else if config.JWTConfig != nil {
|
||||
events = append(events, iam_repo.NewIDPJWTConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
idpConfigID,
|
||||
config.JWTConfig.JWTEndpoint,
|
||||
config.JWTConfig.Issuer,
|
||||
config.JWTConfig.KeysEndpoint,
|
||||
config.JWTConfig.HeaderName,
|
||||
))
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -129,6 +129,65 @@ func TestCommandSide_AddDefaultIDPConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config jwt add, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(idpconfig.NewAddIDPConfigNameUniqueConstraint("name1", "IAM")),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "config1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.IDPConfig{
|
||||
Name: "name1",
|
||||
StylingType: domain.IDPConfigStylingTypeGoogle,
|
||||
JWTConfig: &domain.JWTIDPConfig{
|
||||
JWTEndpoint: "jwt-endpoint",
|
||||
Issuer: "issuer",
|
||||
KeysEndpoint: "keys-endpoint",
|
||||
HeaderName: "auth",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.IDPConfig{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "IAM",
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
Name: "name1",
|
||||
StylingType: domain.IDPConfigStylingTypeGoogle,
|
||||
State: domain.IDPConfigStateActive,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
49
internal/command/iam_idp_jwt_config.go
Normal file
49
internal/command/iam_idp_jwt_config.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
func (c *Commands) ChangeDefaultIDPJWTConfig(ctx context.Context, config *domain.JWTIDPConfig) (*domain.JWTIDPConfig, error) {
|
||||
if config.IDPConfigID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-m9322", "Errors.IDMissing")
|
||||
}
|
||||
existingConfig := NewIAMIDPJWTConfigWriteModel(config.IDPConfigID)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingConfig.State == domain.IDPConfigStateRemoved || existingConfig.State == domain.IDPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-2m00d", "Errors.IAM.IDPConfig.AlreadyExists")
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingConfig.WriteModel)
|
||||
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
config.IDPConfigID,
|
||||
config.JWTEndpoint,
|
||||
config.Issuer,
|
||||
config.KeysEndpoint,
|
||||
config.HeaderName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-3n9gg", "Errors.IAM.IDPConfig.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingConfig, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToIDPJWTConfig(&existingConfig.JWTConfigWriteModel), nil
|
||||
}
|
116
internal/command/iam_idp_jwt_config_model.go
Normal file
116
internal/command/iam_idp_jwt_config_model.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/repository/idpconfig"
|
||||
)
|
||||
|
||||
type IAMIDPJWTConfigWriteModel struct {
|
||||
JWTConfigWriteModel
|
||||
}
|
||||
|
||||
func NewIAMIDPJWTConfigWriteModel(idpConfigID string) *IAMIDPJWTConfigWriteModel {
|
||||
return &IAMIDPJWTConfigWriteModel{
|
||||
JWTConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
IDPConfigID: idpConfigID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIDPJWTConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.IDPJWTConfigAddedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.JWTConfigAddedEvent)
|
||||
case *iam.IDPJWTConfigChangedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.JWTConfigChangedEvent)
|
||||
case *iam.IDPConfigReactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
|
||||
case *iam.IDPConfigDeactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
|
||||
case *iam.IDPConfigRemovedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
|
||||
default:
|
||||
wm.JWTConfigWriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMIDPJWTConfigWriteModel) Reduce() error {
|
||||
if err := wm.JWTConfigWriteModel.Reduce(); err != nil {
|
||||
return err
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMIDPJWTConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
iam.IDPJWTConfigAddedEventType,
|
||||
iam.IDPJWTConfigChangedEventType,
|
||||
iam.IDPConfigReactivatedEventType,
|
||||
iam.IDPConfigDeactivatedEventType,
|
||||
iam.IDPConfigRemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMIDPJWTConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
idpConfigID,
|
||||
jwtEndpoint,
|
||||
issuer,
|
||||
keysEndpoint,
|
||||
headerName string,
|
||||
) (*iam.IDPJWTConfigChangedEvent, bool, error) {
|
||||
|
||||
changes := make([]idpconfig.JWTConfigChanges, 0)
|
||||
if wm.JWTEndpoint != jwtEndpoint {
|
||||
changes = append(changes, idpconfig.ChangeJWTEndpoint(jwtEndpoint))
|
||||
}
|
||||
if wm.Issuer != issuer {
|
||||
changes = append(changes, idpconfig.ChangeJWTIssuer(issuer))
|
||||
}
|
||||
if wm.KeysEndpoint != keysEndpoint {
|
||||
changes = append(changes, idpconfig.ChangeKeysEndpoint(keysEndpoint))
|
||||
}
|
||||
if wm.HeaderName != headerName {
|
||||
changes = append(changes, idpconfig.ChangeHeaderName(headerName))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := iam.NewIDPJWTConfigChangedEvent(ctx, aggregate, idpConfigID, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
264
internal/command/iam_idp_jwt_config_test.go
Normal file
264
internal/command/iam_idp_jwt_config_test.go
Normal file
@@ -0,0 +1,264 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/repository/idpconfig"
|
||||
)
|
||||
|
||||
func TestCommandSide_ChangeDefaultIDPJWTConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
type (
|
||||
args struct {
|
||||
ctx context.Context
|
||||
config *domain.JWTIDPConfig
|
||||
}
|
||||
)
|
||||
type res struct {
|
||||
want *domain.JWTIDPConfig
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "invalid config, error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config removed, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPConfigRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
JWTEndpoint: "jwt-endpoint",
|
||||
Issuer: "issuer",
|
||||
KeysEndpoint: "keys-endpoint",
|
||||
HeaderName: "auth",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config jwt add, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newDefaultIDPJWTConfigChangedEvent(context.Background(),
|
||||
"config1",
|
||||
"jwt-endpoint-changed",
|
||||
"issuer-changed",
|
||||
"keys-endpoint-changed",
|
||||
"auth-changed",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
JWTEndpoint: "jwt-endpoint-changed",
|
||||
Issuer: "issuer-changed",
|
||||
KeysEndpoint: "keys-endpoint-changed",
|
||||
HeaderName: "auth-changed",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.JWTIDPConfig{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "IAM",
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
JWTEndpoint: "jwt-endpoint-changed",
|
||||
Issuer: "issuer-changed",
|
||||
KeysEndpoint: "keys-endpoint-changed",
|
||||
HeaderName: "auth-changed",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idpConfigSecretCrypto: tt.fields.secretCrypto,
|
||||
}
|
||||
got, err := r.ChangeDefaultIDPJWTConfig(tt.args.ctx, tt.args.config)
|
||||
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.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newDefaultIDPJWTConfigChangedEvent(ctx context.Context, configID, jwtEndpoint, issuer, keysEndpoint, headerName string) *iam.IDPJWTConfigChangedEvent {
|
||||
event, _ := iam.NewIDPJWTConfigChangedEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
configID,
|
||||
[]idpconfig.JWTConfigChanges{
|
||||
idpconfig.ChangeJWTEndpoint(jwtEndpoint),
|
||||
idpconfig.ChangeJWTIssuer(issuer),
|
||||
idpconfig.ChangeKeysEndpoint(keysEndpoint),
|
||||
idpconfig.ChangeHeaderName(headerName),
|
||||
},
|
||||
)
|
||||
return event
|
||||
}
|
61
internal/command/jwt_config_model.go
Normal file
61
internal/command/jwt_config_model.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/idpconfig"
|
||||
)
|
||||
|
||||
type JWTConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
IDPConfigID string
|
||||
JWTEndpoint string
|
||||
Issuer string
|
||||
KeysEndpoint string
|
||||
HeaderName string
|
||||
State domain.IDPConfigState
|
||||
}
|
||||
|
||||
func (wm *JWTConfigWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *idpconfig.JWTConfigAddedEvent:
|
||||
wm.reduceConfigAddedEvent(e)
|
||||
case *idpconfig.JWTConfigChangedEvent:
|
||||
wm.reduceConfigChangedEvent(e)
|
||||
case *idpconfig.IDPConfigDeactivatedEvent:
|
||||
wm.State = domain.IDPConfigStateInactive
|
||||
case *idpconfig.IDPConfigReactivatedEvent:
|
||||
wm.State = domain.IDPConfigStateActive
|
||||
case *idpconfig.IDPConfigRemovedEvent:
|
||||
wm.State = domain.IDPConfigStateRemoved
|
||||
}
|
||||
}
|
||||
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *JWTConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.JWTConfigAddedEvent) {
|
||||
wm.IDPConfigID = e.IDPConfigID
|
||||
wm.JWTEndpoint = e.JWTEndpoint
|
||||
wm.Issuer = e.Issuer
|
||||
wm.KeysEndpoint = e.KeysEndpoint
|
||||
wm.HeaderName = e.HeaderName
|
||||
wm.State = domain.IDPConfigStateActive
|
||||
}
|
||||
|
||||
func (wm *JWTConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.JWTConfigChangedEvent) {
|
||||
if e.JWTEndpoint != nil {
|
||||
wm.JWTEndpoint = *e.JWTEndpoint
|
||||
}
|
||||
if e.Issuer != nil {
|
||||
wm.Issuer = *e.Issuer
|
||||
}
|
||||
if e.KeysEndpoint != nil {
|
||||
wm.KeysEndpoint = *e.KeysEndpoint
|
||||
}
|
||||
if e.HeaderName != nil {
|
||||
wm.HeaderName = *e.HeaderName
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
@@ -16,7 +17,7 @@ func (c *Commands) AddIDPConfig(ctx context.Context, config *domain.IDPConfig, r
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-0j8gs", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if config.OIDCConfig == nil {
|
||||
if config.OIDCConfig == nil && config.JWTConfig == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "Org-eUpQU", "Errors.idp.config.notset")
|
||||
}
|
||||
|
||||
@@ -26,11 +27,6 @@ func (c *Commands) AddIDPConfig(ctx context.Context, config *domain.IDPConfig, r
|
||||
}
|
||||
addedConfig := NewOrgIDPConfigWriteModel(idpConfigID, resourceOwner)
|
||||
|
||||
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), c.idpConfigSecretCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedConfig.WriteModel)
|
||||
events := []eventstore.EventPusher{
|
||||
org_repo.NewIDPConfigAddedEvent(
|
||||
@@ -42,7 +38,13 @@ func (c *Commands) AddIDPConfig(ctx context.Context, config *domain.IDPConfig, r
|
||||
config.StylingType,
|
||||
config.AutoRegister,
|
||||
),
|
||||
org_repo.NewIDPOIDCConfigAddedEvent(
|
||||
}
|
||||
if config.OIDCConfig != nil {
|
||||
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), c.idpConfigSecretCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events = append(events, org_repo.NewIDPOIDCConfigAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
config.OIDCConfig.ClientID,
|
||||
@@ -53,7 +55,17 @@ func (c *Commands) AddIDPConfig(ctx context.Context, config *domain.IDPConfig, r
|
||||
clientSecret,
|
||||
config.OIDCConfig.IDPDisplayNameMapping,
|
||||
config.OIDCConfig.UsernameMapping,
|
||||
config.OIDCConfig.Scopes...),
|
||||
config.OIDCConfig.Scopes...))
|
||||
} else if config.JWTConfig != nil {
|
||||
events = append(events, org_repo.NewIDPJWTConfigAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
idpConfigID,
|
||||
config.JWTConfig.JWTEndpoint,
|
||||
config.JWTConfig.Issuer,
|
||||
config.JWTConfig.KeysEndpoint,
|
||||
config.JWTConfig.HeaderName,
|
||||
))
|
||||
}
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, events...)
|
||||
if err != nil {
|
||||
|
@@ -159,6 +159,66 @@ func TestCommandSide_AddIDPConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config jwt add, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(idpconfig.NewAddIDPConfigNameUniqueConstraint("name1", "org1")),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "config1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
config: &domain.IDPConfig{
|
||||
Name: "name1",
|
||||
StylingType: domain.IDPConfigStylingTypeGoogle,
|
||||
JWTConfig: &domain.JWTIDPConfig{
|
||||
JWTEndpoint: "jwt-endpoint",
|
||||
Issuer: "issuer",
|
||||
KeysEndpoint: "keys-endpoint",
|
||||
HeaderName: "auth",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.IDPConfig{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
Name: "name1",
|
||||
StylingType: domain.IDPConfigStylingTypeGoogle,
|
||||
State: domain.IDPConfigStateActive,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
53
internal/command/org_idp_jwt_config.go
Normal file
53
internal/command/org_idp_jwt_config.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
func (c *Commands) ChangeIDPJWTConfig(ctx context.Context, config *domain.JWTIDPConfig, resourceOwner string) (*domain.JWTIDPConfig, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-ff8NF", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if config.IDPConfigID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-2n99f", "Errors.IDMissing")
|
||||
}
|
||||
existingConfig := NewOrgIDPJWTConfigWriteModel(config.IDPConfigID, resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existingConfig.State == domain.IDPConfigStateRemoved || existingConfig.State == domain.IDPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-67J9d", "Errors.Org.IDPConfig.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingConfig.WriteModel)
|
||||
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
config.IDPConfigID,
|
||||
config.JWTEndpoint,
|
||||
config.Issuer,
|
||||
config.KeysEndpoint,
|
||||
config.HeaderName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-2k9fs", "Errors.Org.IDPConfig.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingConfig, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModelToIDPJWTConfig(&existingConfig.JWTConfigWriteModel), nil
|
||||
}
|
115
internal/command/org_idp_jwt_config_model.go
Normal file
115
internal/command/org_idp_jwt_config_model.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
|
||||
"github.com/caos/zitadel/internal/repository/idpconfig"
|
||||
"github.com/caos/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
type IDPJWTConfigWriteModel struct {
|
||||
JWTConfigWriteModel
|
||||
}
|
||||
|
||||
func NewOrgIDPJWTConfigWriteModel(idpConfigID, orgID string) *IDPJWTConfigWriteModel {
|
||||
return &IDPJWTConfigWriteModel{
|
||||
JWTConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: orgID,
|
||||
ResourceOwner: orgID,
|
||||
},
|
||||
IDPConfigID: idpConfigID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IDPJWTConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *org.IDPJWTConfigAddedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.JWTConfigAddedEvent)
|
||||
case *org.IDPJWTConfigChangedEvent:
|
||||
if wm.IDPConfigID != e.IDPConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.JWTConfigChangedEvent)
|
||||
case *org.IDPConfigReactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
|
||||
case *org.IDPConfigDeactivatedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
|
||||
case *org.IDPConfigRemovedEvent:
|
||||
if wm.IDPConfigID != e.ConfigID {
|
||||
continue
|
||||
}
|
||||
wm.JWTConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
|
||||
default:
|
||||
wm.JWTConfigWriteModel.AppendEvents(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IDPJWTConfigWriteModel) Reduce() error {
|
||||
if err := wm.JWTConfigWriteModel.Reduce(); err != nil {
|
||||
return err
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IDPJWTConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(org.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
org.IDPJWTConfigAddedEventType,
|
||||
org.IDPJWTConfigChangedEventType,
|
||||
org.IDPConfigReactivatedEventType,
|
||||
org.IDPConfigDeactivatedEventType,
|
||||
org.IDPConfigRemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IDPJWTConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
idpConfigID,
|
||||
jwtEndpoint,
|
||||
issuer,
|
||||
keysEndpoint,
|
||||
headerName string,
|
||||
) (*org.IDPJWTConfigChangedEvent, bool, error) {
|
||||
|
||||
changes := make([]idpconfig.JWTConfigChanges, 0)
|
||||
if wm.JWTEndpoint != jwtEndpoint {
|
||||
changes = append(changes, idpconfig.ChangeJWTEndpoint(jwtEndpoint))
|
||||
}
|
||||
if wm.Issuer != issuer {
|
||||
changes = append(changes, idpconfig.ChangeJWTIssuer(issuer))
|
||||
}
|
||||
if wm.KeysEndpoint != keysEndpoint {
|
||||
changes = append(changes, idpconfig.ChangeKeysEndpoint(keysEndpoint))
|
||||
}
|
||||
if wm.HeaderName != headerName {
|
||||
changes = append(changes, idpconfig.ChangeHeaderName(headerName))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := org.NewIDPJWTConfigChangedEvent(ctx, aggregate, idpConfigID, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
288
internal/command/org_idp_jwt_config_test.go
Normal file
288
internal/command/org_idp_jwt_config_test.go
Normal file
@@ -0,0 +1,288 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/caos/zitadel/internal/repository/idpconfig"
|
||||
"github.com/caos/zitadel/internal/repository/org"
|
||||
)
|
||||
|
||||
func TestCommandSide_ChangeIDPJWTConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
type (
|
||||
args struct {
|
||||
ctx context.Context
|
||||
config *domain.JWTIDPConfig
|
||||
resourceOwner string
|
||||
}
|
||||
)
|
||||
type res struct {
|
||||
want *domain.JWTIDPConfig
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "resourceowner missing, error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid config, error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config removed, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
JWTEndpoint: "jwt-endpoint",
|
||||
Issuer: "issuer",
|
||||
KeysEndpoint: "keys-endpoint",
|
||||
HeaderName: "auth",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "idp config jwt add, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name1",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPConfigStylingTypeGoogle,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPJWTConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate,
|
||||
"config1",
|
||||
"jwt-endpoint",
|
||||
"issuer",
|
||||
"keys-endpoint",
|
||||
"auth",
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newIDPJWTConfigChangedEvent(context.Background(),
|
||||
"org1",
|
||||
"config1",
|
||||
"jwt-endpoint-changed",
|
||||
"issuer-changed",
|
||||
"keys-endpoint-changed",
|
||||
"auth-changed",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.JWTIDPConfig{
|
||||
IDPConfigID: "config1",
|
||||
JWTEndpoint: "jwt-endpoint-changed",
|
||||
Issuer: "issuer-changed",
|
||||
KeysEndpoint: "keys-endpoint-changed",
|
||||
HeaderName: "auth-changed",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.JWTIDPConfig{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
JWTEndpoint: "jwt-endpoint-changed",
|
||||
Issuer: "issuer-changed",
|
||||
KeysEndpoint: "keys-endpoint-changed",
|
||||
HeaderName: "auth-changed",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idpConfigSecretCrypto: tt.fields.secretCrypto,
|
||||
}
|
||||
got, err := r.ChangeIDPJWTConfig(tt.args.ctx, tt.args.config, tt.args.resourceOwner)
|
||||
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.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newIDPJWTConfigChangedEvent(ctx context.Context, orgID, configID, jwtEndpoint, issuer, keysEndpoint, headerName string) *org.IDPJWTConfigChangedEvent {
|
||||
event, _ := org.NewIDPJWTConfigChangedEvent(ctx,
|
||||
&org.NewAggregate(orgID, orgID).Aggregate,
|
||||
configID,
|
||||
[]idpconfig.JWTConfigChanges{
|
||||
idpconfig.ChangeJWTEndpoint(jwtEndpoint),
|
||||
idpconfig.ChangeJWTIssuer(issuer),
|
||||
idpconfig.ChangeKeysEndpoint(keysEndpoint),
|
||||
idpconfig.ChangeHeaderName(headerName),
|
||||
},
|
||||
)
|
||||
return event
|
||||
}
|
Reference in New Issue
Block a user