mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:27:31 +00:00
feat: Notification providers config (#3212)
* feat: add login check lifetimes to login policy * feat: org features test * feat: debug notificatiaon events * feat: debug notification file/log commands * feat: add requests to proto * feat: add api for debug notification providers file/log * feat: add projection for debug notifiication providers * feat: requests * feat: merge v2 * feat: add settings proto to generate * feat: notifiaction providers * fix: remove unused code * Update iam_converter.go Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
31
internal/command/debug_notification_model.go
Normal file
31
internal/command/debug_notification_model.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/settings"
|
||||
)
|
||||
|
||||
type DebugNotificationWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Compact bool
|
||||
State domain.NotificationProviderState
|
||||
}
|
||||
|
||||
func (wm *DebugNotificationWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *settings.DebugNotificationProviderAddedEvent:
|
||||
wm.Compact = e.Compact
|
||||
wm.State = domain.NotificationProviderStateActive
|
||||
case *settings.DebugNotificationProviderChangedEvent:
|
||||
if e.Compact != nil {
|
||||
wm.Compact = *e.Compact
|
||||
}
|
||||
case *settings.DebugNotificationProviderRemovedEvent:
|
||||
wm.State = domain.NotificationProviderStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
120
internal/command/iam_debug_notification_file.go
Normal file
120
internal/command/iam_debug_notification_file.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/notification/channels/fs"
|
||||
iam_repo "github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddDebugNotificationProviderFile(ctx context.Context, fileSystemProvider *fs.FSConfig) (*domain.ObjectDetails, error) {
|
||||
writeModel := NewIAMDebugNotificationFileWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&writeModel.WriteModel)
|
||||
events, err := c.addDefaultDebugNotificationFile(ctx, iamAgg, writeModel, fileSystemProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(writeModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&writeModel.DebugNotificationWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) addDefaultDebugNotificationFile(ctx context.Context, iamAgg *eventstore.Aggregate, addedWriteModel *IAMDebugNotificationFileWriteModel, fileSystemProvider *fs.FSConfig) ([]eventstore.Command, error) {
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, addedWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedWriteModel.State.Exists() {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-d93nfs", "Errors.IAM.DebugNotificationProvider.AlreadyExists")
|
||||
}
|
||||
|
||||
events := []eventstore.Command{
|
||||
iam_repo.NewDebugNotificationProviderFileAddedEvent(ctx,
|
||||
iamAgg,
|
||||
fileSystemProvider.Compact),
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeDefaultNotificationFile(ctx context.Context, fileSystemProvider *fs.FSConfig) (*domain.ObjectDetails, error) {
|
||||
writeModel := NewIAMDebugNotificationFileWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&writeModel.WriteModel)
|
||||
events, err := c.changeDefaultDebugNotificationProviderFile(ctx, iamAgg, writeModel, fileSystemProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(writeModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&writeModel.DebugNotificationWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) changeDefaultDebugNotificationProviderFile(ctx context.Context, iamAgg *eventstore.Aggregate, existingProvider *IAMDebugNotificationFileWriteModel, fileSystemProvider *fs.FSConfig) ([]eventstore.Command, error) {
|
||||
err := c.defaultDebugNotificationProviderFileWriteModelByID(ctx, existingProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingProvider.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-fm9wl", "Errors.IAM.DebugNotificationProvider.NotFound")
|
||||
}
|
||||
events := make([]eventstore.Command, 0)
|
||||
changedEvent, hasChanged := existingProvider.NewChangedEvent(ctx,
|
||||
iamAgg,
|
||||
fileSystemProvider.Compact)
|
||||
if hasChanged {
|
||||
events = append(events, changedEvent)
|
||||
}
|
||||
if len(events) == 0 {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
|
||||
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveDefaultNotificationFile(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||
existingProvider := NewIAMDebugNotificationFileWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingProvider.WriteModel)
|
||||
err := c.defaultDebugNotificationProviderFileWriteModelByID(ctx, existingProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingProvider.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-dj9ew", "Errors.IAM.DebugNotificationProvider.NotFound")
|
||||
}
|
||||
|
||||
events, err := c.eventstore.Push(ctx, iam_repo.NewDebugNotificationProviderFileRemovedEvent(ctx, iamAgg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingProvider, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&existingProvider.DebugNotificationWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) defaultDebugNotificationProviderFileWriteModelByID(ctx context.Context, writeModel *IAMDebugNotificationFileWriteModel) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
79
internal/command/iam_debug_notification_file_model.go
Normal file
79
internal/command/iam_debug_notification_file_model.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/settings"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
type IAMDebugNotificationFileWriteModel struct {
|
||||
DebugNotificationWriteModel
|
||||
}
|
||||
|
||||
func NewIAMDebugNotificationFileWriteModel() *IAMDebugNotificationFileWriteModel {
|
||||
return &IAMDebugNotificationFileWriteModel{
|
||||
DebugNotificationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationFileWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.DebugNotificationProviderFileAddedEvent:
|
||||
wm.DebugNotificationWriteModel.AppendEvents(&e.DebugNotificationProviderAddedEvent)
|
||||
case *iam.DebugNotificationProviderFileChangedEvent:
|
||||
wm.DebugNotificationWriteModel.AppendEvents(&e.DebugNotificationProviderChangedEvent)
|
||||
case *iam.DebugNotificationProviderFileRemovedEvent:
|
||||
wm.DebugNotificationWriteModel.AppendEvents(&e.DebugNotificationProviderRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationFileWriteModel) IsValid() bool {
|
||||
return wm.AggregateID != ""
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationFileWriteModel) Reduce() error {
|
||||
return wm.DebugNotificationWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationFileWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(iam.AggregateType).
|
||||
AggregateIDs(wm.DebugNotificationWriteModel.AggregateID).
|
||||
EventTypes(
|
||||
iam.DebugNotificationProviderFileAddedEventType,
|
||||
iam.DebugNotificationProviderFileChangedEventType,
|
||||
iam.DebugNotificationProviderFileRemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationFileWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
compact bool) (*iam.DebugNotificationProviderFileChangedEvent, bool) {
|
||||
|
||||
changes := make([]settings.DebugNotificationProviderChanges, 0)
|
||||
if wm.Compact != compact {
|
||||
changes = append(changes, settings.ChangeCompact(compact))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewDebugNotificationProviderFileChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
348
internal/command/iam_debug_notification_file_test.go
Normal file
348
internal/command/iam_debug_notification_file_test.go
Normal file
@@ -0,0 +1,348 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/repository/settings"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddDefaultDebugNotificationProviderFile(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider *fs.FSConfig
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "provider already existing, already exists error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add provider,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddDebugNotificationProviderFile(tt.args.ctx, tt.args.provider)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeDebugNotificationProviderFile(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider *fs.FSConfig
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "provider not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes enabled, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newDefaultDebugNotificationFileChangedEvent(context.Background(),
|
||||
false),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: false,
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
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.ChangeDefaultNotificationFile(tt.args.ctx, tt.args.provider)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_RemoveDebugNotificationProviderFile(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "provider not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderFileRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
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.RemoveDefaultNotificationFile(tt.args.ctx)
|
||||
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 newDefaultDebugNotificationFileChangedEvent(ctx context.Context, compact bool) *iam.DebugNotificationProviderFileChangedEvent {
|
||||
event, _ := iam.NewDebugNotificationProviderFileChangedEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
[]settings.DebugNotificationProviderChanges{
|
||||
settings.ChangeCompact(compact),
|
||||
},
|
||||
)
|
||||
return event
|
||||
}
|
115
internal/command/iam_debug_notification_log.go
Normal file
115
internal/command/iam_debug_notification_log.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/notification/channels/fs"
|
||||
iam_repo "github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddDebugNotificationProviderLog(ctx context.Context, fileSystemProvider *fs.FSConfig) (*domain.ObjectDetails, error) {
|
||||
writeModel := NewIAMDebugNotificationLogWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&writeModel.WriteModel)
|
||||
events, err := c.addDefaultDebugNotificationLog(ctx, iamAgg, writeModel, fileSystemProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(writeModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&writeModel.DebugNotificationWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) addDefaultDebugNotificationLog(ctx context.Context, iamAgg *eventstore.Aggregate, addedWriteModel *IAMDebugNotificationLogWriteModel, fileSystemProvider *fs.FSConfig) ([]eventstore.Command, error) {
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, addedWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedWriteModel.State.Exists() {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-3h0fs", "Errors.IAM.DebugNotificationProvider.AlreadyExists")
|
||||
}
|
||||
|
||||
events := []eventstore.Command{
|
||||
iam_repo.NewDebugNotificationProviderLogAddedEvent(ctx,
|
||||
iamAgg,
|
||||
fileSystemProvider.Compact),
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeDefaultNotificationLog(ctx context.Context, fileSystemProvider *fs.FSConfig) (*domain.ObjectDetails, error) {
|
||||
writeModel := NewIAMDebugNotificationLogWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&writeModel.WriteModel)
|
||||
event, err := c.changeDefaultDebugNotificationProviderLog(ctx, iamAgg, writeModel, fileSystemProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(writeModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&writeModel.DebugNotificationWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) changeDefaultDebugNotificationProviderLog(ctx context.Context, iamAgg *eventstore.Aggregate, existingProvider *IAMDebugNotificationLogWriteModel, fileSystemProvider *fs.FSConfig) (eventstore.Command, error) {
|
||||
err := c.defaultDebugNotificationProviderLogWriteModelByID(ctx, existingProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingProvider.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-2h0s3", "Errors.IAM.DebugNotificationProvider.NotFound")
|
||||
}
|
||||
changedEvent, hasChanged := existingProvider.NewChangedEvent(ctx,
|
||||
iamAgg,
|
||||
fileSystemProvider.Compact)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-fn9p3", "Errors.IAM.LoginPolicy.NotChanged")
|
||||
}
|
||||
return changedEvent, nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveDefaultNotificationLog(ctx context.Context) (*domain.ObjectDetails, error) {
|
||||
existingProvider := NewIAMDebugNotificationLogWriteModel()
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingProvider.WriteModel)
|
||||
err := c.defaultDebugNotificationProviderLogWriteModelByID(ctx, existingProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingProvider.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-39lse", "Errors.IAM.DebugNotificationProvider.NotFound")
|
||||
}
|
||||
|
||||
events, err := c.eventstore.Push(ctx, iam_repo.NewDebugNotificationProviderLogRemovedEvent(ctx, iamAgg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingProvider, events...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&existingProvider.DebugNotificationWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) defaultDebugNotificationProviderLogWriteModelByID(ctx context.Context, writeModel *IAMDebugNotificationLogWriteModel) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
81
internal/command/iam_debug_notification_log_model.go
Normal file
81
internal/command/iam_debug_notification_log_model.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/settings"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
type IAMDebugNotificationLogWriteModel struct {
|
||||
DebugNotificationWriteModel
|
||||
}
|
||||
|
||||
func NewIAMDebugNotificationLogWriteModel() *IAMDebugNotificationLogWriteModel {
|
||||
return &IAMDebugNotificationLogWriteModel{
|
||||
DebugNotificationWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationLogWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||
for _, event := range events {
|
||||
switch e := event.(type) {
|
||||
case *iam.DebugNotificationProviderLogAddedEvent:
|
||||
wm.DebugNotificationWriteModel.AppendEvents(&e.DebugNotificationProviderAddedEvent)
|
||||
case *iam.DebugNotificationProviderLogChangedEvent:
|
||||
wm.DebugNotificationWriteModel.AppendEvents(&e.DebugNotificationProviderChangedEvent)
|
||||
case *iam.DebugNotificationProviderLogRemovedEvent:
|
||||
wm.DebugNotificationWriteModel.AppendEvents(&e.DebugNotificationProviderRemovedEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationLogWriteModel) IsValid() bool {
|
||||
return wm.AggregateID != ""
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationLogWriteModel) Reduce() error {
|
||||
return wm.DebugNotificationWriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationLogWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(iam.AggregateType).
|
||||
AggregateIDs(wm.DebugNotificationWriteModel.AggregateID).
|
||||
EventTypes(
|
||||
iam.DebugNotificationProviderLogAddedEventType,
|
||||
iam.DebugNotificationProviderLogChangedEventType,
|
||||
iam.DebugNotificationProviderLogEnabledEventType,
|
||||
iam.DebugNotificationProviderLogDisabledEventType,
|
||||
iam.DebugNotificationProviderLogRemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMDebugNotificationLogWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
compact bool) (*iam.DebugNotificationProviderLogChangedEvent, bool) {
|
||||
|
||||
changes := make([]settings.DebugNotificationProviderChanges, 0)
|
||||
if wm.Compact != compact {
|
||||
changes = append(changes, settings.ChangeCompact(compact))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changedEvent, err := iam.NewDebugNotificationProviderLogChangedEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return changedEvent, true
|
||||
}
|
389
internal/command/iam_debug_notification_log_test.go
Normal file
389
internal/command/iam_debug_notification_log_test.go
Normal file
@@ -0,0 +1,389 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/repository/settings"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddDefaultDebugNotificationProviderLog(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider *fs.FSConfig
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "provider already existing, already exists error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add disabled provider,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add provider,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddDebugNotificationProviderLog(tt.args.ctx, tt.args.provider)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeDebugNotificationProviderLog(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider *fs.FSConfig
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "provider not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: true,
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newDefaultDebugNotificationLogChangedEvent(context.Background(),
|
||||
false),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: false,
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newDefaultDebugNotificationLogChangedEvent(context.Background(),
|
||||
false),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
provider: &fs.FSConfig{
|
||||
Compact: false,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
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.ChangeDefaultNotificationLog(tt.args.ctx, tt.args.provider)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_RemoveDebugNotificationProviderLog(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "provider not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewDebugNotificationProviderLogRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
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.RemoveDefaultNotificationLog(tt.args.ctx)
|
||||
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 newDefaultDebugNotificationLogChangedEvent(ctx context.Context, compact bool) *iam.DebugNotificationProviderLogChangedEvent {
|
||||
event, _ := iam.NewDebugNotificationProviderLogChangedEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
[]settings.DebugNotificationProviderChanges{
|
||||
settings.ChangeCompact(compact),
|
||||
},
|
||||
)
|
||||
return event
|
||||
}
|
Reference in New Issue
Block a user