mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 16:07:24 +00:00
feat: OIDC setting (#3245)
* feat: add oidc config struct * feat: oidc config command side * feat: oidc configuration query side * feat: add translations * feat: add tests * feat: add translations * feat: rename oidc config to oidc settings * feat: rename oidc config to oidc settings
This commit is contained in:
parent
f05d4063bf
commit
7d6c933485
@ -188,6 +188,30 @@ Update twilio sms provider token
|
||||
PUT: /sms/twilio/{id}/token
|
||||
|
||||
|
||||
### GetOIDCSettings
|
||||
|
||||
> **rpc** GetOIDCSettings([GetOIDCSettingsRequest](#getoidcsettingsrequest))
|
||||
[GetOIDCSettingsResponse](#getoidcsettingsresponse)
|
||||
|
||||
Get OIDC settings (e.g token lifetimes, etc.)
|
||||
|
||||
|
||||
|
||||
GET: /settings/oidc
|
||||
|
||||
|
||||
### UpdateOIDCSettings
|
||||
|
||||
> **rpc** UpdateOIDCSettings([UpdateOIDCSettingsRequest](#updateoidcsettingsrequest))
|
||||
[UpdateOIDCSettingsResponse](#updateoidcsettingsresponse)
|
||||
|
||||
Update oidc settings (e.g token lifetimes, etc)
|
||||
|
||||
|
||||
|
||||
PUT: /settings/oidc
|
||||
|
||||
|
||||
### GetOrgByID
|
||||
|
||||
> **rpc** GetOrgByID([GetOrgByIDRequest](#getorgbyidrequest))
|
||||
@ -2046,6 +2070,23 @@ This is an empty request
|
||||
|
||||
|
||||
|
||||
### GetOIDCSettingsRequest
|
||||
This is an empty request
|
||||
|
||||
|
||||
|
||||
|
||||
### GetOIDCSettingsResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| settings | zitadel.settings.v1.OIDCSettings | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### GetOrgByIDRequest
|
||||
|
||||
|
||||
@ -3613,6 +3654,31 @@ This is an empty request
|
||||
|
||||
|
||||
|
||||
### UpdateOIDCSettingsRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| access_token_lifetime | google.protobuf.Duration | - | |
|
||||
| id_token_lifetime | google.protobuf.Duration | - | |
|
||||
| refresh_token_idle_expiration | google.protobuf.Duration | - | |
|
||||
| refresh_token_expiration | google.protobuf.Duration | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateOIDCSettingsResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| details | zitadel.v1.ObjectDetails | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateOrgIAMPolicyRequest
|
||||
|
||||
|
||||
|
29
internal/api/grpc/admin/oidc_settings.go
Normal file
29
internal/api/grpc/admin/oidc_settings.go
Normal file
@ -0,0 +1,29 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func (s *Server) GetOIDCSettings(ctx context.Context, _ *admin_pb.GetOIDCSettingsRequest) (*admin_pb.GetOIDCSettingsResponse, error) {
|
||||
result, err := s.query.OIDCSettingsByAggID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetOIDCSettingsResponse{
|
||||
Settings: OIDCSettingsToPb(result),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateOIDCSettings(ctx context.Context, req *admin_pb.UpdateOIDCSettingsRequest) (*admin_pb.UpdateOIDCSettingsResponse, error) {
|
||||
result, err := s.command.ChangeOIDCSettings(ctx, UpdateOIDCConfigToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateOIDCSettingsResponse{
|
||||
Details: object.DomainToChangeDetailsPb(result),
|
||||
}, nil
|
||||
}
|
29
internal/api/grpc/admin/oidc_settings_converter.go
Normal file
29
internal/api/grpc/admin/oidc_settings_converter.go
Normal file
@ -0,0 +1,29 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
obj_grpc "github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
settings_pb "github.com/caos/zitadel/pkg/grpc/settings"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
)
|
||||
|
||||
func OIDCSettingsToPb(config *query.OIDCSettings) *settings_pb.OIDCSettings {
|
||||
return &settings_pb.OIDCSettings{
|
||||
Details: obj_grpc.ToViewDetailsPb(config.Sequence, config.CreationDate, config.ChangeDate, config.AggregateID),
|
||||
AccessTokenLifetime: durationpb.New(config.AccessTokenLifetime),
|
||||
IdTokenLifetime: durationpb.New(config.IdTokenLifetime),
|
||||
RefreshTokenIdleExpiration: durationpb.New(config.RefreshTokenIdleExpiration),
|
||||
RefreshTokenExpiration: durationpb.New(config.RefreshTokenExpiration),
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateOIDCConfigToConfig(req *admin_pb.UpdateOIDCSettingsRequest) *domain.OIDCSettings {
|
||||
return &domain.OIDCSettings{
|
||||
AccessTokenLifetime: req.AccessTokenLifetime.AsDuration(),
|
||||
IdTokenLifetime: req.IdTokenLifetime.AsDuration(),
|
||||
RefreshTokenIdleExpiration: req.RefreshTokenIdleExpiration.AsDuration(),
|
||||
RefreshTokenExpiration: req.RefreshTokenExpiration.AsDuration(),
|
||||
}
|
||||
}
|
79
internal/command/iam_oidc_settings.go
Normal file
79
internal/command/iam_oidc_settings.go
Normal file
@ -0,0 +1,79 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func (c *Commands) AddOIDCSettings(ctx context.Context, settings *domain.OIDCSettings) (*domain.ObjectDetails, error) {
|
||||
oidcSettingWriteModel, err := c.getOIDCSettings(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if oidcSettingWriteModel.State.Exists() {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-d9nlw", "Errors.OIDCSettings.AlreadyExists")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&oidcSettingWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, iam.NewOIDCSettingsAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
settings.AccessTokenLifetime,
|
||||
settings.IdTokenLifetime,
|
||||
settings.RefreshTokenIdleExpiration,
|
||||
settings.RefreshTokenExpiration))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(oidcSettingWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&oidcSettingWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeOIDCSettings(ctx context.Context, settings *domain.OIDCSettings) (*domain.ObjectDetails, error) {
|
||||
oidcSettingWriteModel, err := c.getOIDCSettings(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !oidcSettingWriteModel.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-8snEr", "Errors.OIDCSettings.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&oidcSettingWriteModel.WriteModel)
|
||||
|
||||
changedEvent, hasChanged, err := oidcSettingWriteModel.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
settings.AccessTokenLifetime,
|
||||
settings.IdTokenLifetime,
|
||||
settings.RefreshTokenIdleExpiration,
|
||||
settings.RefreshTokenExpiration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-398uF", "Errors.NoChangesFound")
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(oidcSettingWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&oidcSettingWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) getOIDCSettings(ctx context.Context) (_ *IAMOIDCSettingsWriteModel, err error) {
|
||||
writeModel := NewIAMOIDCSettingsWriteModel()
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
101
internal/command/iam_oidc_settings_model.go
Normal file
101
internal/command/iam_oidc_settings_model.go
Normal file
@ -0,0 +1,101 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
type IAMOIDCSettingsWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
AccessTokenLifetime time.Duration
|
||||
IdTokenLifetime time.Duration
|
||||
RefreshTokenIdleExpiration time.Duration
|
||||
RefreshTokenExpiration time.Duration
|
||||
State domain.OIDCSettingsState
|
||||
}
|
||||
|
||||
func NewIAMOIDCSettingsWriteModel() *IAMOIDCSettingsWriteModel {
|
||||
return &IAMOIDCSettingsWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMOIDCSettingsWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *iam.OIDCSettingsAddedEvent:
|
||||
wm.AccessTokenLifetime = e.AccessTokenLifetime
|
||||
wm.IdTokenLifetime = e.IdTokenLifetime
|
||||
wm.RefreshTokenIdleExpiration = e.RefreshTokenIdleExpiration
|
||||
wm.RefreshTokenExpiration = e.RefreshTokenExpiration
|
||||
wm.State = domain.OIDCSettingsStateActive
|
||||
case *iam.OIDCSettingsChangedEvent:
|
||||
if e.AccessTokenLifetime != nil {
|
||||
wm.AccessTokenLifetime = *e.AccessTokenLifetime
|
||||
}
|
||||
if e.IdTokenLifetime != nil {
|
||||
wm.IdTokenLifetime = *e.IdTokenLifetime
|
||||
}
|
||||
if e.RefreshTokenIdleExpiration != nil {
|
||||
wm.RefreshTokenIdleExpiration = *e.RefreshTokenIdleExpiration
|
||||
}
|
||||
if e.RefreshTokenExpiration != nil {
|
||||
wm.RefreshTokenExpiration = *e.RefreshTokenExpiration
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMOIDCSettingsWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
iam.OIDCSettingsAddedEventType,
|
||||
iam.OIDCSettingsChangedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMOIDCSettingsWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
accessTokenLifetime,
|
||||
idTokenLifetime,
|
||||
refreshTokenIdleExpiration,
|
||||
refreshTokenExpiration time.Duration,
|
||||
) (*iam.OIDCSettingsChangedEvent, bool, error) {
|
||||
changes := make([]iam.OIDCSettingsChanges, 0, 4)
|
||||
var err error
|
||||
|
||||
if wm.AccessTokenLifetime != accessTokenLifetime {
|
||||
changes = append(changes, iam.ChangeOIDCSettingsAccessTokenLifetime(accessTokenLifetime))
|
||||
}
|
||||
if wm.IdTokenLifetime != idTokenLifetime {
|
||||
changes = append(changes, iam.ChangeOIDCSettingsIdTokenLifetime(idTokenLifetime))
|
||||
}
|
||||
if wm.RefreshTokenIdleExpiration != refreshTokenIdleExpiration {
|
||||
changes = append(changes, iam.ChangeOIDCSettingsRefreshTokenIdleExpiration(refreshTokenIdleExpiration))
|
||||
}
|
||||
if wm.RefreshTokenExpiration != refreshTokenExpiration {
|
||||
changes = append(changes, iam.ChangeOIDCSettingsRefreshTokenExpiration(refreshTokenExpiration))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := iam.NewOIDCSettingsChangeEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
264
internal/command/iam_oidc_settings_test.go
Normal file
264
internal/command/iam_oidc_settings_test.go
Normal file
@ -0,0 +1,264 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"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/repository/iam"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddOIDCConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
oidcConfig *domain.OIDCSettings
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "oidc config, error already exists",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewOIDCSettingsAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
oidcConfig: &domain.OIDCSettings{
|
||||
AccessTokenLifetime: 1 * time.Hour,
|
||||
IdTokenLifetime: 1 * time.Hour,
|
||||
RefreshTokenIdleExpiration: 1 * time.Hour,
|
||||
RefreshTokenExpiration: 1 * time.Hour,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add secret generator, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(iam.NewOIDCSettingsAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
oidcConfig: &domain.OIDCSettings{
|
||||
AccessTokenLifetime: 1 * time.Hour,
|
||||
IdTokenLifetime: 1 * time.Hour,
|
||||
RefreshTokenIdleExpiration: 1 * time.Hour,
|
||||
RefreshTokenExpiration: 1 * time.Hour,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddOIDCSettings(tt.args.ctx, tt.args.oidcConfig)
|
||||
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 TestCommandSide_ChangeOIDCConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
oidcConfig *domain.OIDCSettings
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "oidc config not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewOIDCSettingsAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
oidcConfig: &domain.OIDCSettings{
|
||||
AccessTokenLifetime: 1 * time.Hour,
|
||||
IdTokenLifetime: 1 * time.Hour,
|
||||
RefreshTokenIdleExpiration: 1 * time.Hour,
|
||||
RefreshTokenExpiration: 1 * time.Hour,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "secret generator change, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewOIDCSettingsAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newOIDCConfigChangedEvent(context.Background(),
|
||||
time.Hour*2,
|
||||
time.Hour*2,
|
||||
time.Hour*2,
|
||||
time.Hour*2),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
oidcConfig: &domain.OIDCSettings{
|
||||
AccessTokenLifetime: 2 * time.Hour,
|
||||
IdTokenLifetime: 2 * time.Hour,
|
||||
RefreshTokenIdleExpiration: 2 * time.Hour,
|
||||
RefreshTokenExpiration: 2 * time.Hour,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeOIDCSettings(tt.args.ctx, tt.args.oidcConfig)
|
||||
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 newOIDCConfigChangedEvent(ctx context.Context, accessTokenLifetime, idTokenLifetime, refreshTokenIdleExpiration, refreshTokenExpiration time.Duration) *iam.OIDCSettingsChangedEvent {
|
||||
changes := []iam.OIDCSettingsChanges{
|
||||
iam.ChangeOIDCSettingsAccessTokenLifetime(accessTokenLifetime),
|
||||
iam.ChangeOIDCSettingsIdTokenLifetime(idTokenLifetime),
|
||||
iam.ChangeOIDCSettingsRefreshTokenIdleExpiration(refreshTokenIdleExpiration),
|
||||
iam.ChangeOIDCSettingsRefreshTokenExpiration(refreshTokenExpiration),
|
||||
}
|
||||
event, _ := iam.NewOIDCSettingsChangeEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
changes,
|
||||
)
|
||||
return event
|
||||
}
|
37
internal/domain/oidc_settings.go
Normal file
37
internal/domain/oidc_settings.go
Normal file
@ -0,0 +1,37 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
)
|
||||
|
||||
type OIDCSettings struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State OIDCSettingsState
|
||||
Default bool
|
||||
|
||||
AccessTokenLifetime time.Duration
|
||||
IdTokenLifetime time.Duration
|
||||
RefreshTokenIdleExpiration time.Duration
|
||||
RefreshTokenExpiration time.Duration
|
||||
}
|
||||
|
||||
type OIDCSettingsState int32
|
||||
|
||||
const (
|
||||
OIDCSettingsStateUnspecified OIDCSettingsState = iota
|
||||
OIDCSettingsStateActive
|
||||
OIDCSettingsStateRemoved
|
||||
|
||||
oidcSettingsStateCount
|
||||
)
|
||||
|
||||
func (c OIDCSettingsState) Valid() bool {
|
||||
return c >= 0 && c < oidcSettingsStateCount
|
||||
}
|
||||
|
||||
func (s OIDCSettingsState) Exists() bool {
|
||||
return s != OIDCSettingsStateUnspecified && s != OIDCSettingsStateRemoved
|
||||
}
|
115
internal/query/oidc_settings.go
Normal file
115
internal/query/oidc_settings.go
Normal file
@ -0,0 +1,115 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
errs "errors"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/query/projection"
|
||||
)
|
||||
|
||||
var (
|
||||
oidcSettingsTable = table{
|
||||
name: projection.OIDCSettingsProjectionTable,
|
||||
}
|
||||
OIDCSettingsColumnAggregateID = Column{
|
||||
name: projection.OIDCSettingsColumnAggregateID,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnCreationDate = Column{
|
||||
name: projection.OIDCSettingsColumnCreationDate,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnChangeDate = Column{
|
||||
name: projection.OIDCSettingsColumnChangeDate,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnResourceOwner = Column{
|
||||
name: projection.OIDCSettingsColumnResourceOwner,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnSequence = Column{
|
||||
name: projection.OIDCSettingsColumnSequence,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnAccessTokenLifetime = Column{
|
||||
name: projection.OIDCSettingsColumnAccessTokenLifetime,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnIdTokenLifetime = Column{
|
||||
name: projection.OIDCSettingsColumnIdTokenLifetime,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnRefreshTokenIdleExpiration = Column{
|
||||
name: projection.OIDCSettingsColumnRefreshTokenIdleExpiration,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
OIDCSettingsColumnRefreshTokenExpiration = Column{
|
||||
name: projection.OIDCSettingsColumnRefreshTokenExpiration,
|
||||
table: oidcSettingsTable,
|
||||
}
|
||||
)
|
||||
|
||||
type OIDCSettings struct {
|
||||
AggregateID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
|
||||
AccessTokenLifetime time.Duration
|
||||
IdTokenLifetime time.Duration
|
||||
RefreshTokenIdleExpiration time.Duration
|
||||
RefreshTokenExpiration time.Duration
|
||||
}
|
||||
|
||||
func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) (*OIDCSettings, error) {
|
||||
stmt, scan := prepareOIDCSettingsQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
OIDCSettingsColumnAggregateID.identifier(): aggregateID,
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-s9nle", "Errors.Query.SQLStatment")
|
||||
}
|
||||
|
||||
row := q.client.QueryRowContext(ctx, query, args...)
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func prepareOIDCSettingsQuery() (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings, error)) {
|
||||
return sq.Select(
|
||||
OIDCSettingsColumnAggregateID.identifier(),
|
||||
OIDCSettingsColumnCreationDate.identifier(),
|
||||
OIDCSettingsColumnChangeDate.identifier(),
|
||||
OIDCSettingsColumnResourceOwner.identifier(),
|
||||
OIDCSettingsColumnSequence.identifier(),
|
||||
OIDCSettingsColumnAccessTokenLifetime.identifier(),
|
||||
OIDCSettingsColumnIdTokenLifetime.identifier(),
|
||||
OIDCSettingsColumnRefreshTokenIdleExpiration.identifier(),
|
||||
OIDCSettingsColumnRefreshTokenExpiration.identifier()).
|
||||
From(oidcSettingsTable.identifier()).PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*OIDCSettings, error) {
|
||||
oidcSettings := new(OIDCSettings)
|
||||
err := row.Scan(
|
||||
&oidcSettings.AggregateID,
|
||||
&oidcSettings.CreationDate,
|
||||
&oidcSettings.ChangeDate,
|
||||
&oidcSettings.ResourceOwner,
|
||||
&oidcSettings.Sequence,
|
||||
&oidcSettings.AccessTokenLifetime,
|
||||
&oidcSettings.IdTokenLifetime,
|
||||
&oidcSettings.RefreshTokenIdleExpiration,
|
||||
&oidcSettings.RefreshTokenExpiration,
|
||||
)
|
||||
if err != nil {
|
||||
if errs.Is(err, sql.ErrNoRows) {
|
||||
return nil, errors.ThrowNotFound(err, "QUERY-s9nlw", "Errors.OIDCSettings.NotFound")
|
||||
}
|
||||
return nil, errors.ThrowInternal(err, "QUERY-9bf8s", "Errors.Internal")
|
||||
}
|
||||
return oidcSettings, nil
|
||||
}
|
||||
}
|
136
internal/query/oidc_settings_test.go
Normal file
136
internal/query/oidc_settings_test.go
Normal file
@ -0,0 +1,136 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
errs "github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
func Test_OIDCConfigsPrepares(t *testing.T) {
|
||||
type want struct {
|
||||
sqlExpectations sqlExpectation
|
||||
err checkErr
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare interface{}
|
||||
want want
|
||||
object interface{}
|
||||
}{
|
||||
{
|
||||
name: "prepareOIDCSettingsQuery no result",
|
||||
prepare: prepareOIDCSettingsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
`SELECT zitadel.projections.oidc_settings.aggregate_id,`+
|
||||
` zitadel.projections.oidc_settings.creation_date,`+
|
||||
` zitadel.projections.oidc_settings.change_date,`+
|
||||
` zitadel.projections.oidc_settings.resource_owner,`+
|
||||
` zitadel.projections.oidc_settings.sequence,`+
|
||||
` zitadel.projections.oidc_settings.access_token_lifetime,`+
|
||||
` zitadel.projections.oidc_settings.id_token_lifetime,`+
|
||||
` zitadel.projections.oidc_settings.refresh_token_idle_expiration,`+
|
||||
` zitadel.projections.oidc_settings.refresh_token_expiration`+
|
||||
` FROM zitadel.projections.oidc_settings`,
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
if !errs.IsNotFound(err) {
|
||||
return fmt.Errorf("err should be zitadel.NotFoundError got: %w", err), false
|
||||
}
|
||||
return nil, true
|
||||
},
|
||||
},
|
||||
object: (*OIDCSettings)(nil),
|
||||
},
|
||||
{
|
||||
name: "prepareOIDCSettingsQuery found",
|
||||
prepare: prepareOIDCSettingsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT zitadel.projections.oidc_settings.aggregate_id,`+
|
||||
` zitadel.projections.oidc_settings.creation_date,`+
|
||||
` zitadel.projections.oidc_settings.change_date,`+
|
||||
` zitadel.projections.oidc_settings.resource_owner,`+
|
||||
` zitadel.projections.oidc_settings.sequence,`+
|
||||
` zitadel.projections.oidc_settings.access_token_lifetime,`+
|
||||
` zitadel.projections.oidc_settings.id_token_lifetime,`+
|
||||
` zitadel.projections.oidc_settings.refresh_token_idle_expiration,`+
|
||||
` zitadel.projections.oidc_settings.refresh_token_expiration`+
|
||||
` FROM zitadel.projections.oidc_settings`),
|
||||
[]string{
|
||||
"aggregate_id",
|
||||
"creation_date",
|
||||
"change_date",
|
||||
"resource_owner",
|
||||
"sequence",
|
||||
"access_token_lifetime",
|
||||
"id_token_lifetime",
|
||||
"refresh_token_idle_expiration",
|
||||
"refresh_token_expiration",
|
||||
},
|
||||
[]driver.Value{
|
||||
"agg-id",
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
time.Minute * 1,
|
||||
time.Minute * 2,
|
||||
time.Minute * 3,
|
||||
time.Minute * 4,
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &OIDCSettings{
|
||||
AggregateID: "agg-id",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
AccessTokenLifetime: time.Minute * 1,
|
||||
IdTokenLifetime: time.Minute * 2,
|
||||
RefreshTokenIdleExpiration: time.Minute * 3,
|
||||
RefreshTokenExpiration: time.Minute * 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareOIDCSettingsQuery sql err",
|
||||
prepare: prepareOIDCSettingsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT zitadel.projections.oidc_settings.aggregate_id,`+
|
||||
` zitadel.projections.oidc_settings.creation_date,`+
|
||||
` zitadel.projections.oidc_settings.change_date,`+
|
||||
` zitadel.projections.oidc_settings.resource_owner,`+
|
||||
` zitadel.projections.oidc_settings.sequence,`+
|
||||
` zitadel.projections.oidc_settings.access_token_lifetime,`+
|
||||
` zitadel.projections.oidc_settings.id_token_lifetime,`+
|
||||
` zitadel.projections.oidc_settings.refresh_token_idle_expiration,`+
|
||||
` zitadel.projections.oidc_settings.refresh_token_expiration`+
|
||||
` FROM zitadel.projections.oidc_settings`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
if !errors.Is(err, sql.ErrConnDone) {
|
||||
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
|
||||
}
|
||||
return nil, true
|
||||
},
|
||||
},
|
||||
object: nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
||||
})
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ type ActionProjection struct {
|
||||
}
|
||||
|
||||
func NewActionProjection(ctx context.Context, config crdb.StatementHandlerConfig) *ActionProjection {
|
||||
p := &ActionProjection{}
|
||||
p := new(ActionProjection)
|
||||
config.ProjectionName = ActionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
func NewAppProjection(ctx context.Context, config crdb.StatementHandlerConfig) *AppProjection {
|
||||
p := &AppProjection{}
|
||||
p := new(AppProjection)
|
||||
config.ProjectionName = AppProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -35,7 +35,7 @@ type AuthNKeyProjection struct {
|
||||
}
|
||||
|
||||
func NewAuthNKeyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *AuthNKeyProjection {
|
||||
p := &AuthNKeyProjection{}
|
||||
p := new(AuthNKeyProjection)
|
||||
config.ProjectionName = AuthNKeyTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -33,7 +33,7 @@ const (
|
||||
)
|
||||
|
||||
func NewCustomTextProjection(ctx context.Context, config crdb.StatementHandlerConfig) *CustomTextProjection {
|
||||
p := &CustomTextProjection{}
|
||||
p := new(CustomTextProjection)
|
||||
config.ProjectionName = CustomTextTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
func NewFeatureProjection(ctx context.Context, config crdb.StatementHandlerConfig) *FeatureProjection {
|
||||
p := &FeatureProjection{}
|
||||
p := new(FeatureProjection)
|
||||
config.ProjectionName = FeatureTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -26,7 +26,7 @@ type FlowProjection struct {
|
||||
}
|
||||
|
||||
func NewFlowProjection(ctx context.Context, config crdb.StatementHandlerConfig) *FlowProjection {
|
||||
p := &FlowProjection{}
|
||||
p := new(FlowProjection)
|
||||
config.ProjectionName = FlowTriggerTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -20,7 +20,7 @@ const (
|
||||
)
|
||||
|
||||
func NewIAMProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IAMProjection {
|
||||
p := &IAMProjection{}
|
||||
p := new(IAMProjection)
|
||||
config.ProjectionName = IAMProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
func NewIAMMemberProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IAMMemberProjection {
|
||||
p := &IAMMemberProjection{}
|
||||
p := new(IAMMemberProjection)
|
||||
config.ProjectionName = IAMMemberProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -26,7 +26,7 @@ const (
|
||||
)
|
||||
|
||||
func NewIDPProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IDPProjection {
|
||||
p := &IDPProjection{}
|
||||
p := new(IDPProjection)
|
||||
config.ProjectionName = IDPTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func NewIDPLoginPolicyLinkProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IDPLoginPolicyLinkProjection {
|
||||
p := &IDPLoginPolicyLinkProjection{}
|
||||
p := new(IDPLoginPolicyLinkProjection)
|
||||
config.ProjectionName = IDPLoginPolicyLinkTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -18,7 +18,7 @@ type IDPUserLinkProjection struct {
|
||||
}
|
||||
|
||||
func NewIDPUserLinkProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IDPUserLinkProjection {
|
||||
p := &IDPUserLinkProjection{}
|
||||
p := new(IDPUserLinkProjection)
|
||||
config.ProjectionName = IDPUserLinkTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -27,7 +27,7 @@ const (
|
||||
)
|
||||
|
||||
func NewKeyProjection(ctx context.Context, config crdb.StatementHandlerConfig, keyConfig *crypto.KeyConfig, keyChan chan<- interface{}) (_ *KeyProjection, err error) {
|
||||
p := &KeyProjection{}
|
||||
p := new(KeyProjection)
|
||||
config.ProjectionName = KeyProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func NewLabelPolicyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *LabelPolicyProjection {
|
||||
p := &LabelPolicyProjection{}
|
||||
p := new(LabelPolicyProjection)
|
||||
config.ProjectionName = LabelPolicyTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -33,7 +33,7 @@ const (
|
||||
)
|
||||
|
||||
func NewLockoutPolicyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *LockoutPolicyProjection {
|
||||
p := &LockoutPolicyProjection{}
|
||||
p := new(LockoutPolicyProjection)
|
||||
config.ProjectionName = LockoutPolicyTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -26,7 +26,7 @@ const (
|
||||
)
|
||||
|
||||
func NewLoginNameProjection(ctx context.Context, config crdb.StatementHandlerConfig) *LoginNameProjection {
|
||||
p := &LoginNameProjection{}
|
||||
p := new(LoginNameProjection)
|
||||
config.ProjectionName = LoginNameProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func NewLoginPolicyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *LoginPolicyProjection {
|
||||
p := &LoginPolicyProjection{}
|
||||
p := new(LoginPolicyProjection)
|
||||
config.ProjectionName = LoginPolicyTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -31,7 +31,7 @@ const (
|
||||
)
|
||||
|
||||
func NewMailTemplateProjection(ctx context.Context, config crdb.StatementHandlerConfig) *MailTemplateProjection {
|
||||
p := &MailTemplateProjection{}
|
||||
p := new(MailTemplateProjection)
|
||||
config.ProjectionName = MailTemplateTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -39,7 +39,7 @@ const (
|
||||
)
|
||||
|
||||
func NewMessageTextProjection(ctx context.Context, config crdb.StatementHandlerConfig) *MessageTextProjection {
|
||||
p := &MessageTextProjection{}
|
||||
p := new(MessageTextProjection)
|
||||
config.ProjectionName = MessageTextTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
114
internal/query/projection/oidc_settings.go
Normal file
114
internal/query/projection/oidc_settings.go
Normal file
@ -0,0 +1,114 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/handler"
|
||||
"github.com/caos/zitadel/internal/eventstore/handler/crdb"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/repository/project"
|
||||
)
|
||||
|
||||
type OIDCSettingsProjection struct {
|
||||
crdb.StatementHandler
|
||||
}
|
||||
|
||||
const (
|
||||
OIDCSettingsProjectionTable = "zitadel.projections.oidc_settings"
|
||||
)
|
||||
|
||||
func NewOIDCSettingsProjection(ctx context.Context, config crdb.StatementHandlerConfig) *OIDCSettingsProjection {
|
||||
p := new(OIDCSettingsProjection)
|
||||
config.ProjectionName = OIDCSettingsProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *OIDCSettingsProjection) reducers() []handler.AggregateReducer {
|
||||
return []handler.AggregateReducer{
|
||||
{
|
||||
Aggregate: project.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
{
|
||||
Event: iam.OIDCSettingsAddedEventType,
|
||||
Reduce: p.reduceOIDCSettingsAdded,
|
||||
},
|
||||
{
|
||||
Event: iam.OIDCSettingsChangedEventType,
|
||||
Reduce: p.reduceOIDCSettingsChanged,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
OIDCSettingsColumnAggregateID = "aggregate_id"
|
||||
OIDCSettingsColumnCreationDate = "creation_date"
|
||||
OIDCSettingsColumnChangeDate = "change_date"
|
||||
OIDCSettingsColumnResourceOwner = "resource_owner"
|
||||
OIDCSettingsColumnSequence = "sequence"
|
||||
OIDCSettingsColumnAccessTokenLifetime = "access_token_lifetime"
|
||||
OIDCSettingsColumnIdTokenLifetime = "id_token_lifetime"
|
||||
OIDCSettingsColumnRefreshTokenIdleExpiration = "refresh_token_idle_expiration"
|
||||
OIDCSettingsColumnRefreshTokenExpiration = "refresh_token_expiration"
|
||||
)
|
||||
|
||||
func (p *OIDCSettingsProjection) reduceOIDCSettingsAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.OIDCSettingsAddedEvent)
|
||||
if !ok {
|
||||
logging.WithFields("seq", event.Sequence(), "expectedType", iam.OIDCSettingsAddedEventType).Error("wrong event type")
|
||||
return nil, errors.ThrowInvalidArgument(nil, "HANDL-f9nwf", "reduce.wrong.event.type")
|
||||
}
|
||||
return crdb.NewCreateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(OIDCSettingsColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCol(OIDCSettingsColumnCreationDate, e.CreationDate()),
|
||||
handler.NewCol(OIDCSettingsColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(OIDCSettingsColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCol(OIDCSettingsColumnSequence, e.Sequence()),
|
||||
handler.NewCol(OIDCSettingsColumnAccessTokenLifetime, e.AccessTokenLifetime),
|
||||
handler.NewCol(OIDCSettingsColumnIdTokenLifetime, e.IdTokenLifetime),
|
||||
handler.NewCol(OIDCSettingsColumnRefreshTokenIdleExpiration, e.RefreshTokenIdleExpiration),
|
||||
handler.NewCol(OIDCSettingsColumnRefreshTokenExpiration, e.RefreshTokenExpiration),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *OIDCSettingsProjection) reduceOIDCSettingsChanged(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.OIDCSettingsChangedEvent)
|
||||
if !ok {
|
||||
logging.WithFields("seq", event.Sequence(), "expected", iam.OIDCSettingsChangedEventType).Error("wrong event type")
|
||||
return nil, errors.ThrowInvalidArgument(nil, "HANDL-8JJ2d", "reduce.wrong.event.type")
|
||||
}
|
||||
|
||||
columns := make([]handler.Column, 0, 6)
|
||||
columns = append(columns,
|
||||
handler.NewCol(OIDCSettingsColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(OIDCSettingsColumnSequence, e.Sequence()),
|
||||
)
|
||||
if e.AccessTokenLifetime != nil {
|
||||
columns = append(columns, handler.NewCol(OIDCSettingsColumnAccessTokenLifetime, *e.AccessTokenLifetime))
|
||||
}
|
||||
if e.IdTokenLifetime != nil {
|
||||
columns = append(columns, handler.NewCol(OIDCSettingsColumnIdTokenLifetime, *e.IdTokenLifetime))
|
||||
}
|
||||
if e.RefreshTokenIdleExpiration != nil {
|
||||
columns = append(columns, handler.NewCol(OIDCSettingsColumnRefreshTokenIdleExpiration, *e.RefreshTokenIdleExpiration))
|
||||
}
|
||||
if e.RefreshTokenExpiration != nil {
|
||||
columns = append(columns, handler.NewCol(OIDCSettingsColumnRefreshTokenExpiration, *e.RefreshTokenExpiration))
|
||||
}
|
||||
return crdb.NewUpdateStatement(
|
||||
e,
|
||||
columns,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(OIDCSettingsColumnAggregateID, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
}
|
106
internal/query/projection/oidc_settings_test.go
Normal file
106
internal/query/projection/oidc_settings_test.go
Normal file
@ -0,0 +1,106 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/handler"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func TestOIDCSettingsProjection_reduces(t *testing.T) {
|
||||
type args struct {
|
||||
event func(t *testing.T) eventstore.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
reduce func(event eventstore.Event) (*handler.Statement, error)
|
||||
want wantReduce
|
||||
}{
|
||||
{
|
||||
name: "reduceOIDCSettingsChanged",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.OIDCSettingsChangedEventType),
|
||||
iam.AggregateType,
|
||||
[]byte(`{"accessTokenLifetime": 10000000, "idTokenLifetime": 10000000, "refreshTokenIdleExpiration": 10000000, "refreshTokenExpiration": 10000000}`),
|
||||
), iam.OIDCSettingsChangedEventMapper),
|
||||
},
|
||||
reduce: (&OIDCSettingsProjection{}).reduceOIDCSettingsChanged,
|
||||
want: wantReduce{
|
||||
projection: OIDCSettingsProjectionTable,
|
||||
aggregateType: eventstore.AggregateType("iam"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE zitadel.projections.oidc_settings SET (change_date, sequence, access_token_lifetime, id_token_lifetime, refresh_token_idle_expiration, refresh_token_expiration) = ($1, $2, $3, $4, $5, $6) WHERE (aggregate_id = $7)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
"agg-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceOIDCSettingsAdded",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.OIDCSettingsAddedEventType),
|
||||
iam.AggregateType,
|
||||
[]byte(`{"accessTokenLifetime": 10000000, "idTokenLifetime": 10000000, "refreshTokenIdleExpiration": 10000000, "refreshTokenExpiration": 10000000}`),
|
||||
), iam.OIDCSettingsAddedEventMapper),
|
||||
},
|
||||
reduce: (&OIDCSettingsProjection{}).reduceOIDCSettingsAdded,
|
||||
want: wantReduce{
|
||||
projection: OIDCSettingsProjectionTable,
|
||||
aggregateType: eventstore.AggregateType("iam"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO zitadel.projections.oidc_settings (aggregate_id, creation_date, change_date, resource_owner, sequence, access_token_lifetime, id_token_lifetime, refresh_token_idle_expiration, refresh_token_expiration) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
"ro-id",
|
||||
uint64(15),
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
event := baseEvent(t)
|
||||
got, err := tt.reduce(event)
|
||||
if _, ok := err.(errors.InvalidArgument); !ok {
|
||||
t.Errorf("no wrong event mapping: %v, got: %v", err, got)
|
||||
}
|
||||
|
||||
event = tt.args.event(t)
|
||||
got, err = tt.reduce(event)
|
||||
assertReduce(t, got, err, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
func NewOrgProjection(ctx context.Context, config crdb.StatementHandlerConfig) *OrgProjection {
|
||||
p := &OrgProjection{}
|
||||
p := new(OrgProjection)
|
||||
config.ProjectionName = OrgProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
func NewOrgDomainProjection(ctx context.Context, config crdb.StatementHandlerConfig) *OrgDomainProjection {
|
||||
p := &OrgDomainProjection{}
|
||||
p := new(OrgDomainProjection)
|
||||
config.ProjectionName = OrgDomainTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -32,7 +32,7 @@ const (
|
||||
)
|
||||
|
||||
func NewOrgIAMPolicyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *OrgIAMPolicyProjection {
|
||||
p := &OrgIAMPolicyProjection{}
|
||||
p := new(OrgIAMPolicyProjection)
|
||||
config.ProjectionName = OrgIAMPolicyTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
func NewOrgMemberProjection(ctx context.Context, config crdb.StatementHandlerConfig) *OrgMemberProjection {
|
||||
p := &OrgMemberProjection{}
|
||||
p := new(OrgMemberProjection)
|
||||
config.ProjectionName = OrgMemberProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func NewPasswordAgeProjection(ctx context.Context, config crdb.StatementHandlerConfig) *PasswordAgeProjection {
|
||||
p := &PasswordAgeProjection{}
|
||||
p := new(PasswordAgeProjection)
|
||||
config.ProjectionName = PasswordAgeTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func NewPasswordComplexityProjection(ctx context.Context, config crdb.StatementHandlerConfig) *PasswordComplexityProjection {
|
||||
p := &PasswordComplexityProjection{}
|
||||
p := new(PasswordComplexityProjection)
|
||||
config.ProjectionName = PasswordComplexityTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -33,7 +33,7 @@ const (
|
||||
)
|
||||
|
||||
func NewPrivacyPolicyProjection(ctx context.Context, config crdb.StatementHandlerConfig) *PrivacyPolicyProjection {
|
||||
p := &PrivacyPolicyProjection{}
|
||||
p := new(PrivacyPolicyProjection)
|
||||
config.ProjectionName = PrivacyPolicyTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -21,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
func NewProjectProjection(ctx context.Context, config crdb.StatementHandlerConfig) *ProjectProjection {
|
||||
p := &ProjectProjection{}
|
||||
p := new(ProjectProjection)
|
||||
config.ProjectionName = ProjectProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -20,7 +20,7 @@ type ProjectGrantProjection struct {
|
||||
const ProjectGrantProjectionTable = "zitadel.projections.project_grants"
|
||||
|
||||
func NewProjectGrantProjection(ctx context.Context, config crdb.StatementHandlerConfig) *ProjectGrantProjection {
|
||||
p := &ProjectGrantProjection{}
|
||||
p := new(ProjectGrantProjection)
|
||||
config.ProjectionName = ProjectGrantProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -24,7 +24,7 @@ const (
|
||||
)
|
||||
|
||||
func NewProjectGrantMemberProjection(ctx context.Context, config crdb.StatementHandlerConfig) *ProjectGrantMemberProjection {
|
||||
p := &ProjectGrantMemberProjection{}
|
||||
p := new(ProjectGrantMemberProjection)
|
||||
config.ProjectionName = ProjectGrantMemberProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -24,7 +24,7 @@ const (
|
||||
)
|
||||
|
||||
func NewProjectMemberProjection(ctx context.Context, config crdb.StatementHandlerConfig) *ProjectMemberProjection {
|
||||
p := &ProjectMemberProjection{}
|
||||
p := new(ProjectMemberProjection)
|
||||
config.ProjectionName = ProjectMemberProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -18,7 +18,7 @@ type ProjectRoleProjection struct {
|
||||
const ProjectRoleProjectionTable = "zitadel.projections.project_roles"
|
||||
|
||||
func NewProjectRoleProjection(ctx context.Context, config crdb.StatementHandlerConfig) *ProjectRoleProjection {
|
||||
p := &ProjectRoleProjection{}
|
||||
p := new(ProjectRoleProjection)
|
||||
config.ProjectionName = ProjectRoleProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -72,6 +72,7 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
|
||||
NewSecretGeneratorProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["secret_generators"]))
|
||||
NewSMTPConfigProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["smtp_configs"]))
|
||||
NewSMSConfigProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["sms_config"]))
|
||||
NewOIDCSettingsProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["oidc_settings"]))
|
||||
_, err := NewKeyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["keys"]), keyConfig, keyChan)
|
||||
|
||||
return err
|
||||
|
@ -21,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
func NewSecretGeneratorProjection(ctx context.Context, config crdb.StatementHandlerConfig) *SecretGeneratorProjection {
|
||||
p := &SecretGeneratorProjection{}
|
||||
p := new(SecretGeneratorProjection)
|
||||
config.ProjectionName = SecretGeneratorProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
func NewSMSConfigProjection(ctx context.Context, config crdb.StatementHandlerConfig) *SMSConfigProjection {
|
||||
p := &SMSConfigProjection{}
|
||||
p := new(SMSConfigProjection)
|
||||
config.ProjectionName = SMSConfigProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -21,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
func NewSMTPConfigProjection(ctx context.Context, config crdb.StatementHandlerConfig) *SMTPConfigProjection {
|
||||
p := &SMTPConfigProjection{}
|
||||
p := new(SMTPConfigProjection)
|
||||
config.ProjectionName = SMTPConfigProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
func NewUserProjection(ctx context.Context, config crdb.StatementHandlerConfig) *UserProjection {
|
||||
p := &UserProjection{}
|
||||
p := new(UserProjection)
|
||||
config.ProjectionName = UserTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -21,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
func NewUserAuthMethodProjection(ctx context.Context, config crdb.StatementHandlerConfig) *UserAuthMethodProjection {
|
||||
p := &UserAuthMethodProjection{}
|
||||
p := new(UserAuthMethodProjection)
|
||||
config.ProjectionName = UserAuthMethodTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
func NewUserGrantProjection(ctx context.Context, config crdb.StatementHandlerConfig) *UserGrantProjection {
|
||||
p := &UserGrantProjection{}
|
||||
p := new(UserGrantProjection)
|
||||
config.ProjectionName = UserGrantProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -19,7 +19,7 @@ type UserMetadataProjection struct {
|
||||
const UserMetadataProjectionTable = "zitadel.projections.user_metadata"
|
||||
|
||||
func NewUserMetadataProjection(ctx context.Context, config crdb.StatementHandlerConfig) *UserMetadataProjection {
|
||||
p := &UserMetadataProjection{}
|
||||
p := new(UserMetadataProjection)
|
||||
config.ProjectionName = UserMetadataProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
)
|
||||
|
||||
func NewPersonalAccessTokenProjection(ctx context.Context, config crdb.StatementHandlerConfig) *PersonalAccessTokenProjection {
|
||||
p := &PersonalAccessTokenProjection{}
|
||||
p := new(PersonalAccessTokenProjection)
|
||||
config.ProjectionName = PersonalAccessTokenProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
|
@ -23,6 +23,8 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(SMSConfigActivatedEventType, SMSConfigActivatedEventMapper).
|
||||
RegisterFilterEventMapper(SMSConfigDeactivatedEventType, SMSConfigDeactivatedEventMapper).
|
||||
RegisterFilterEventMapper(SMSConfigRemovedEventType, SMSConfigRemovedEventMapper).
|
||||
RegisterFilterEventMapper(OIDCSettingsAddedEventType, OIDCSettingsAddedEventMapper).
|
||||
RegisterFilterEventMapper(OIDCSettingsChangedEventType, OIDCSettingsChangedEventMapper).
|
||||
RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper).
|
||||
RegisterFilterEventMapper(LabelPolicyChangedEventType, LabelPolicyChangedEventMapper).
|
||||
RegisterFilterEventMapper(LabelPolicyActivatedEventType, LabelPolicyActivatedEventMapper).
|
||||
|
145
internal/repository/iam/oidc_settings.go
Normal file
145
internal/repository/iam/oidc_settings.go
Normal file
@ -0,0 +1,145 @@
|
||||
package iam
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
oidcSettingsPrefix = "oidc.settings."
|
||||
OIDCSettingsAddedEventType = iamEventTypePrefix + oidcSettingsPrefix + "added"
|
||||
OIDCSettingsChangedEventType = iamEventTypePrefix + oidcSettingsPrefix + "changed"
|
||||
OIDCSettingsRemovedEventType = iamEventTypePrefix + oidcSettingsPrefix + "removed"
|
||||
)
|
||||
|
||||
type OIDCSettingsAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
AccessTokenLifetime time.Duration `json:"accessTokenLifetime,omitempty"`
|
||||
IdTokenLifetime time.Duration `json:"idTokenLifetime,omitempty"`
|
||||
RefreshTokenIdleExpiration time.Duration `json:"refreshTokenIdleExpiration,omitempty"`
|
||||
RefreshTokenExpiration time.Duration `json:"refreshTokenExpiration,omitempty"`
|
||||
}
|
||||
|
||||
func NewOIDCSettingsAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
accessTokenLifetime,
|
||||
idTokenLifetime,
|
||||
refreshTokenIdleExpiration,
|
||||
refreshTokenExpiration time.Duration,
|
||||
) *OIDCSettingsAddedEvent {
|
||||
return &OIDCSettingsAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OIDCSettingsAddedEventType,
|
||||
),
|
||||
AccessTokenLifetime: accessTokenLifetime,
|
||||
IdTokenLifetime: idTokenLifetime,
|
||||
RefreshTokenIdleExpiration: refreshTokenIdleExpiration,
|
||||
RefreshTokenExpiration: refreshTokenExpiration,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *OIDCSettingsAddedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *OIDCSettingsAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func OIDCSettingsAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
oidcSettingsAdded := &OIDCSettingsAddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
err := json.Unmarshal(event.Data, oidcSettingsAdded)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "IAM-soiwj", "unable to unmarshal oidc config added")
|
||||
}
|
||||
|
||||
return oidcSettingsAdded, nil
|
||||
}
|
||||
|
||||
type OIDCSettingsChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
AccessTokenLifetime *time.Duration `json:"accessTokenLifetime,omitempty"`
|
||||
IdTokenLifetime *time.Duration `json:"idTokenLifetime,omitempty"`
|
||||
RefreshTokenIdleExpiration *time.Duration `json:"refreshTokenIdleExpiration,omitempty"`
|
||||
RefreshTokenExpiration *time.Duration `json:"refreshTokenExpiration,omitempty"`
|
||||
}
|
||||
|
||||
func (e *OIDCSettingsChangedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *OIDCSettingsChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewOIDCSettingsChangeEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
changes []OIDCSettingsChanges,
|
||||
) (*OIDCSettingsChangedEvent, error) {
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "IAM-dnlwe", "Errors.NoChangesFound")
|
||||
}
|
||||
changeEvent := &OIDCSettingsChangedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OIDCSettingsChangedEventType,
|
||||
),
|
||||
}
|
||||
for _, change := range changes {
|
||||
change(changeEvent)
|
||||
}
|
||||
return changeEvent, nil
|
||||
}
|
||||
|
||||
type OIDCSettingsChanges func(event *OIDCSettingsChangedEvent)
|
||||
|
||||
func ChangeOIDCSettingsAccessTokenLifetime(accessTokenLifetime time.Duration) func(event *OIDCSettingsChangedEvent) {
|
||||
return func(e *OIDCSettingsChangedEvent) {
|
||||
e.AccessTokenLifetime = &accessTokenLifetime
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOIDCSettingsIdTokenLifetime(idTokenLifetime time.Duration) func(event *OIDCSettingsChangedEvent) {
|
||||
return func(e *OIDCSettingsChangedEvent) {
|
||||
e.IdTokenLifetime = &idTokenLifetime
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOIDCSettingsRefreshTokenIdleExpiration(refreshTokenIdleExpiration time.Duration) func(event *OIDCSettingsChangedEvent) {
|
||||
return func(e *OIDCSettingsChangedEvent) {
|
||||
e.RefreshTokenIdleExpiration = &refreshTokenIdleExpiration
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeOIDCSettingsRefreshTokenExpiration(refreshTokenExpiration time.Duration) func(event *OIDCSettingsChangedEvent) {
|
||||
return func(e *OIDCSettingsChangedEvent) {
|
||||
e.RefreshTokenExpiration = &refreshTokenExpiration
|
||||
}
|
||||
}
|
||||
|
||||
func OIDCSettingsChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e := &OIDCSettingsChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(event.Data, e)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "IAM-f98uf", "unable to unmarshal oidc settings changed")
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
@ -29,6 +29,20 @@ Errors:
|
||||
ExceedsDefault: Limit überschreitet default Limit
|
||||
Language:
|
||||
NotParsed: Sprache konnte nicht gemapped werde
|
||||
OIDCSettings:
|
||||
NotFound: OIDC Konfiguration konnte nicht gefunden werden
|
||||
AlreadyExists: OIDC Konfiguration existiert bereits
|
||||
SecretGenerator:
|
||||
AlreadyExists: Passwort Generator exisiter bereits
|
||||
TypeMissing: Passwort Generator Typ fehlt
|
||||
NotFound: Passwort Generator nicht gefunden
|
||||
SMSConfig:
|
||||
NotFound: SMS Konfiguration nicht gefunden
|
||||
AlreadyActive: SMS Konfiguration ist bereits aktiviert
|
||||
AlreadyDeactivated: SMS Konfiguration ist bereits deaktiviert
|
||||
SMTPConfig:
|
||||
NotFound: SMTP Konfiguration nicht gefunden
|
||||
AlreadyExists: SMTP Konfiguration existiert bereits
|
||||
User:
|
||||
NotFound: Benutzer konnte nicht gefunden werden
|
||||
AlreadyExists: Benutzer existierts bereits
|
||||
@ -816,6 +830,35 @@ EventTypes:
|
||||
removed: Schrift von Label Richtlinie entfernt
|
||||
assets:
|
||||
removed: Bilder und Schrift von Label Richtlinie entfernt
|
||||
default:
|
||||
language:
|
||||
set: Standard Sprache gesetzt
|
||||
oidc:
|
||||
settings:
|
||||
added: OIDC Konfiguration hinzugefügt
|
||||
changed: OIDC Konfiguration geändert
|
||||
removed: OIDC Konfiguration gelöscht
|
||||
secret:
|
||||
generator:
|
||||
added: Passwort Generator hinzugefügt
|
||||
changed: Passwort Generator geändert
|
||||
removed: Passwort Generator gelöscht
|
||||
smtp:
|
||||
config:
|
||||
added: SMTP Konfiguration hinzugefügt
|
||||
changed: SMTP Konfiguration geändert
|
||||
password:
|
||||
changed: SMTP Konfigurations Passwort geändert
|
||||
sms:
|
||||
config:
|
||||
twilio:
|
||||
added: Twilio SMS Provider hinzugefügt
|
||||
changed: Twilio SMS Provider geändert
|
||||
token:
|
||||
changed: Twilio SMS Provider Token geändert
|
||||
removed: Twilio SMS Provider entfernt
|
||||
activated: Twilio SMS Provider aktiviert
|
||||
deactivated: Twilio SMS Provider deaktiviert
|
||||
key_pair:
|
||||
added: Schlüsselpaar hinzugefügt
|
||||
action:
|
||||
|
@ -29,6 +29,20 @@ Errors:
|
||||
ExceedsDefault: Limit exceeds default limit
|
||||
Language:
|
||||
NotParsed: Could not parse languge
|
||||
OIDCSettings:
|
||||
NotFound: OIDC Configuration not found
|
||||
AlreadyExists: OIDC configuration already exists
|
||||
SecretGenerator:
|
||||
AlreadyExists: Secret generator already exists
|
||||
TypeMissing: Secret generator type missing
|
||||
NotFound: Secret generator not found
|
||||
SMSConfig:
|
||||
NotFound: SMS configuration not found
|
||||
AlreadyActive: SMS configuration already active
|
||||
AlreadyDeactivated: SMS configuration already deactived
|
||||
SMTPConfig:
|
||||
NotFound: SMTP configuration not found
|
||||
AlreadyExists: SMTP configuration already exists
|
||||
User:
|
||||
NotFound: User could not be found
|
||||
AlreadyExists: User already exists
|
||||
@ -813,6 +827,35 @@ EventTypes:
|
||||
removed: Font removed from Label Policy
|
||||
assets:
|
||||
removed: Assets removed from Label Policy
|
||||
default:
|
||||
language:
|
||||
set: Default language set
|
||||
oidc:
|
||||
settings:
|
||||
added: OIDC configuration added
|
||||
changed: OIDC configuration changed
|
||||
removed: OIDC configuration removed
|
||||
secret:
|
||||
generator:
|
||||
added: Secret generator added
|
||||
changed: Secret generator changed
|
||||
removed: Secret generator removed
|
||||
smtp:
|
||||
config:
|
||||
added: SMTP configuration added
|
||||
changed: SMTP configuration changed
|
||||
password:
|
||||
changed: SMTP configuration secret changed
|
||||
sms:
|
||||
config:
|
||||
twilio:
|
||||
added: Twilio SMS provider added
|
||||
changed: Twilio SMS provider changed
|
||||
token:
|
||||
changed: Twilio SMS provider token changed
|
||||
removed: Twilio SMS provider removed
|
||||
activated: Twilio SMS provider activated
|
||||
deactivated: Twilio SMS provider deactivated
|
||||
key_pair:
|
||||
added: Key pair added
|
||||
action:
|
||||
@ -821,6 +864,7 @@ EventTypes:
|
||||
deactivated: Action deactivated
|
||||
reactivated: Action reactivated
|
||||
removed: Action removed
|
||||
|
||||
Application:
|
||||
OIDC:
|
||||
UnsupportedVersion: Your OIDC version is not supported
|
||||
|
@ -29,6 +29,20 @@ Errors:
|
||||
ExceedsDefault: Il limite supera quello predefinito
|
||||
Language:
|
||||
NotParsed: Impossibile analizzare la lingua
|
||||
OIDCSettings:
|
||||
NotFound: Impossibile trovare la configurazione OIDC
|
||||
AlreadyExists: La configurazione OIDC esiste già
|
||||
SecretGenerator:
|
||||
AlreadyExists: Il generatore di segreti esiste già
|
||||
TypeMissing: Manca il tipo di generatore segreto
|
||||
NotFound: Generatore segreto non trovato
|
||||
SMSConfig:
|
||||
NotFound: Configurazione SMS non trovata
|
||||
AlreadyActive: Configurazione SMS già attiva
|
||||
AlreadyDeactivated: Configurazione SMS già disattivata
|
||||
SMTPConfig:
|
||||
NotFound: Configurazione SMTP non trovata
|
||||
AlreadyExists: La configurazione SMTP esiste già
|
||||
User:
|
||||
NotFound: L'utente non è stato trovato
|
||||
AlreadyExists: L'utente già esistente
|
||||
@ -811,6 +825,35 @@ EventTypes:
|
||||
removed: Font rimosso
|
||||
assets:
|
||||
removed: Asset rimosse
|
||||
default:
|
||||
language:
|
||||
set: lingua predefinita impostata
|
||||
oidc:
|
||||
settings:
|
||||
added: Configurazione OIDC aggiunta
|
||||
changed: Configurazione OIDC cambiata
|
||||
removed: Configurazione OIDC rimossa
|
||||
secret:
|
||||
generator:
|
||||
added: Generatore di segreti aggiunto
|
||||
changed: Generatore di segreti cambiato
|
||||
removed: Generatore di segreti cambiato
|
||||
smtp:
|
||||
config:
|
||||
added: SMTP configuration added
|
||||
changed: SMTP configuration changed
|
||||
password:
|
||||
changed: SMTP configuration secret changed
|
||||
sms:
|
||||
config:
|
||||
twilio:
|
||||
added: Aggiunto il fornitore di SMS Twilio
|
||||
changed: Twilio SMS Provider cambiato
|
||||
token:
|
||||
changed: Twilio SMS Provider token cambiato
|
||||
removed: Provider SMS Twilio rimosso
|
||||
activated: Provider SMS Twilio attivato
|
||||
deactivated: Provider SMS Twilio disattivato
|
||||
key_pair:
|
||||
added: Keypair aggiunto
|
||||
action:
|
||||
|
@ -313,6 +313,28 @@ service AdminService {
|
||||
};
|
||||
}
|
||||
|
||||
// Get OIDC settings (e.g token lifetimes, etc.)
|
||||
rpc GetOIDCSettings(GetOIDCSettingsRequest) returns (GetOIDCSettingsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/settings/oidc";
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.read";
|
||||
};
|
||||
}
|
||||
|
||||
// Update oidc settings (e.g token lifetimes, etc)
|
||||
rpc UpdateOIDCSettings(UpdateOIDCSettingsRequest) returns (UpdateOIDCSettingsResponse) {
|
||||
option (google.api.http) = {
|
||||
put: "/settings/oidc";
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (zitadel.v1.auth_option) = {
|
||||
permission: "iam.write";
|
||||
};
|
||||
}
|
||||
|
||||
// Returns an organisation by id
|
||||
rpc GetOrgByID(GetOrgByIDRequest) returns (GetOrgByIDResponse) {
|
||||
@ -2539,6 +2561,24 @@ message UpdateSMSProviderTwilioTokenResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
// This is an empty request
|
||||
message GetOIDCSettingsRequest {}
|
||||
|
||||
message GetOIDCSettingsResponse {
|
||||
zitadel.settings.v1.OIDCSettings settings = 1;
|
||||
}
|
||||
|
||||
message UpdateOIDCSettingsRequest {
|
||||
google.protobuf.Duration access_token_lifetime = 1;
|
||||
google.protobuf.Duration id_token_lifetime = 2;
|
||||
google.protobuf.Duration refresh_token_idle_expiration = 3;
|
||||
google.protobuf.Duration refresh_token_expiration = 4;
|
||||
}
|
||||
|
||||
message UpdateOIDCSettingsResponse {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
}
|
||||
|
||||
// if name or domain is already in use, org is not unique
|
||||
message IsOrgUniqueRequest {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
|
||||
|
@ -20,7 +20,6 @@ message SecretGenerator {
|
||||
bool include_symbols = 8;
|
||||
}
|
||||
|
||||
|
||||
message SecretGeneratorQuery {
|
||||
oneof query {
|
||||
option (validate.required) = true;
|
||||
@ -67,9 +66,16 @@ message TwilioConfig {
|
||||
string sender_number = 2;
|
||||
}
|
||||
|
||||
|
||||
enum SMSProviderConfigState {
|
||||
SMS_PROVIDER_CONFIG_STATE_UNSPECIFIED = 0;
|
||||
SMS_PROVIDER_CONFIG_ACTIVE = 1;
|
||||
SMS_PROVIDER_CONFIG_INACTIVE = 2;
|
||||
}
|
||||
|
||||
message OIDCSettings {
|
||||
zitadel.v1.ObjectDetails details = 1;
|
||||
google.protobuf.Duration access_token_lifetime = 2;
|
||||
google.protobuf.Duration id_token_lifetime = 3;
|
||||
google.protobuf.Duration refresh_token_idle_expiration = 4;
|
||||
google.protobuf.Duration refresh_token_expiration = 5;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user