mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 21:37:24 +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:
parent
7d6c933485
commit
7899a0b851
@ -152,6 +152,10 @@ protoc \
|
|||||||
-I=/proto/include \
|
-I=/proto/include \
|
||||||
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,user.md \
|
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,user.md \
|
||||||
${PROTO_PATH}/user.proto
|
${PROTO_PATH}/user.proto
|
||||||
|
protoc \
|
||||||
|
-I=/proto/include \
|
||||||
|
--doc_out=${DOCS_PATH} --doc_opt=${PROTO_PATH}/docs/zitadel-md.tmpl,settings.md \
|
||||||
|
${PROTO_PATH}/settings.proto
|
||||||
|
|
||||||
|
|
||||||
echo "done generating grpc"
|
echo "done generating grpc"
|
@ -171,7 +171,7 @@ func startZitadel(config *startConfig) error {
|
|||||||
return fmt.Errorf("cannot start commands: %w", err)
|
return fmt.Errorf("cannot start commands: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Start(config.Notification, config.SystemDefaults, commands, queries, dbClient, assets.HandlerPrefix, smtpPasswordCrypto)
|
notification.Start(config.Notification, config.SystemDefaults, commands, queries, dbClient, assets.HandlerPrefix, smtpPasswordCrypto, smsCrypto)
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, keyChan, config, storage, authZRepo)
|
err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, keyChan, config, storage, authZRepo)
|
||||||
|
@ -188,6 +188,30 @@ Update twilio sms provider token
|
|||||||
PUT: /sms/twilio/{id}/token
|
PUT: /sms/twilio/{id}/token
|
||||||
|
|
||||||
|
|
||||||
|
### GetFileSystemNotificationProvider
|
||||||
|
|
||||||
|
> **rpc** GetFileSystemNotificationProvider([GetFileSystemNotificationProviderRequest](#getfilesystemnotificationproviderrequest))
|
||||||
|
[GetFileSystemNotificationProviderResponse](#getfilesystemnotificationproviderresponse)
|
||||||
|
|
||||||
|
Get file system notification provider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GET: /notification/provider/file
|
||||||
|
|
||||||
|
|
||||||
|
### GetLogNotificationProvider
|
||||||
|
|
||||||
|
> **rpc** GetLogNotificationProvider([GetLogNotificationProviderRequest](#getlognotificationproviderrequest))
|
||||||
|
[GetLogNotificationProviderResponse](#getlognotificationproviderresponse)
|
||||||
|
|
||||||
|
Get log notification provider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GET: /notification/provider/log
|
||||||
|
|
||||||
|
|
||||||
### GetOIDCSettings
|
### GetOIDCSettings
|
||||||
|
|
||||||
> **rpc** GetOIDCSettings([GetOIDCSettingsRequest](#getoidcsettingsrequest))
|
> **rpc** GetOIDCSettings([GetOIDCSettingsRequest](#getoidcsettingsrequest))
|
||||||
@ -1997,6 +2021,23 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetFileSystemNotificationProviderRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetFileSystemNotificationProviderResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| provider | zitadel.settings.v1.DebugNotificationProvider | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetIDPByIDRequest
|
### GetIDPByIDRequest
|
||||||
|
|
||||||
|
|
||||||
@ -2053,6 +2094,23 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetLogNotificationProviderRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetLogNotificationProviderResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| provider | zitadel.settings.v1.DebugNotificationProvider | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetLoginPolicyRequest
|
### GetLoginPolicyRequest
|
||||||
This is an empty request
|
This is an empty request
|
||||||
|
|
||||||
|
31
internal/api/grpc/admin/notification_provider.go
Normal file
31
internal/api/grpc/admin/notification_provider.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/grpc/settings"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) GetFileSystemNotificationProvider(ctx context.Context, req *admin_pb.GetFileSystemNotificationProviderRequest) (*admin_pb.GetFileSystemNotificationProviderResponse, error) {
|
||||||
|
result, err := s.query.NotificationProviderByIDAndType(ctx, domain.IAMID, domain.NotificationProviderTypeFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
|
||||||
|
}
|
||||||
|
return &admin_pb.GetFileSystemNotificationProviderResponse{
|
||||||
|
Provider: settings.NotificationProviderToPb(result),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetLogNotificationProvider(ctx context.Context, req *admin_pb.GetLogNotificationProviderRequest) (*admin_pb.GetLogNotificationProviderResponse, error) {
|
||||||
|
result, err := s.query.NotificationProviderByIDAndType(ctx, domain.IAMID, domain.NotificationProviderTypeLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
|
||||||
|
}
|
||||||
|
return &admin_pb.GetLogNotificationProviderResponse{
|
||||||
|
Provider: settings.NotificationProviderToPb(result),
|
||||||
|
}, nil
|
||||||
|
}
|
15
internal/api/grpc/settings/converter.go
Normal file
15
internal/api/grpc/settings/converter.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
obj_pb "github.com/caos/zitadel/internal/api/grpc/object"
|
||||||
|
"github.com/caos/zitadel/internal/query"
|
||||||
|
settings_pb "github.com/caos/zitadel/pkg/grpc/settings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NotificationProviderToPb(provider *query.DebugNotificationProvider) *settings_pb.DebugNotificationProvider {
|
||||||
|
mapped := &settings_pb.DebugNotificationProvider{
|
||||||
|
Compact: provider.Compact,
|
||||||
|
Details: obj_pb.ToViewDetailsPb(provider.Sequence, provider.CreationDate, provider.ChangeDate, provider.AggregateID),
|
||||||
|
}
|
||||||
|
return mapped
|
||||||
|
}
|
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
|
||||||
|
}
|
@ -6,7 +6,6 @@ import (
|
|||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/chat"
|
|
||||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||||
@ -56,7 +55,8 @@ type DomainVerification struct {
|
|||||||
type Notifications struct {
|
type Notifications struct {
|
||||||
DebugMode bool
|
DebugMode bool
|
||||||
Endpoints Endpoints
|
Endpoints Endpoints
|
||||||
Providers Channels
|
FileSystemPath string
|
||||||
|
//Providers Channels
|
||||||
}
|
}
|
||||||
|
|
||||||
type Endpoints struct {
|
type Endpoints struct {
|
||||||
@ -68,7 +68,6 @@ type Endpoints struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Channels struct {
|
type Channels struct {
|
||||||
Chat chat.ChatConfig
|
|
||||||
Twilio twilio.TwilioConfig
|
Twilio twilio.TwilioConfig
|
||||||
FileSystem fs.FSConfig
|
FileSystem fs.FSConfig
|
||||||
Log log.LogConfig
|
Log log.LogConfig
|
||||||
|
@ -12,3 +12,26 @@ const (
|
|||||||
func (f NotificationType) Valid() bool {
|
func (f NotificationType) Valid() bool {
|
||||||
return f >= 0 && f < notificationCount
|
return f >= 0 && f < notificationCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NotificationProviderState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
NotificationProviderStateUnspecified NotificationProviderState = iota
|
||||||
|
NotificationProviderStateActive
|
||||||
|
NotificationProviderStateRemoved
|
||||||
|
|
||||||
|
notificationProviderCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s NotificationProviderState) Exists() bool {
|
||||||
|
return s == NotificationProviderStateActive
|
||||||
|
}
|
||||||
|
|
||||||
|
type NotificationProviderType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
NotificationProviderTypeFile NotificationProviderType = iota
|
||||||
|
NotificationProviderTypeLog
|
||||||
|
|
||||||
|
notificationProviderTypeCount
|
||||||
|
)
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
package chat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/k3a/html2text"
|
|
||||||
|
|
||||||
"github.com/caos/logging"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/notification/channels"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitChatChannel(config ChatConfig) (channels.NotificationChannel, error) {
|
|
||||||
|
|
||||||
url, err := url.Parse(config.Url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
logging.Log("NOTIF-kSvPp").Debug("successfully initialized chat email and sms channel")
|
|
||||||
|
|
||||||
return channels.HandleMessageFunc(func(message channels.Message) error {
|
|
||||||
contentText := message.GetContent()
|
|
||||||
if config.Compact {
|
|
||||||
contentText = html2text.HTML2Text(contentText)
|
|
||||||
}
|
|
||||||
for _, splittedMsg := range splitMessage(contentText, config.SplitCount) {
|
|
||||||
if err := sendMessage(splittedMsg, url); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendMessage(message string, chatUrl *url.URL) error {
|
|
||||||
chatMsg := &struct {
|
|
||||||
Text string `json:"text"`
|
|
||||||
}{Text: message}
|
|
||||||
req, err := json.Marshal(chatMsg)
|
|
||||||
if err != nil {
|
|
||||||
return caos_errs.ThrowInternal(err, "PROVI-s8uie", "Could not unmarshal content")
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.Post(chatUrl.String(), "application/json; charset=UTF-8", bytes.NewReader(req))
|
|
||||||
if err != nil {
|
|
||||||
return caos_errs.ThrowInternal(err, "PROVI-si93s", "unable to send message")
|
|
||||||
}
|
|
||||||
if response.StatusCode != 200 {
|
|
||||||
defer response.Body.Close()
|
|
||||||
bodyBytes, err := ioutil.ReadAll(response.Body)
|
|
||||||
if err != nil {
|
|
||||||
return caos_errs.ThrowInternal(err, "PROVI-PSLd3", "unable to read response message")
|
|
||||||
}
|
|
||||||
logging.LogWithFields("PROVI-PS0kx", "Body", string(bodyBytes)).Warn("Chat Message post didnt get 200 OK")
|
|
||||||
return caos_errs.ThrowInternal(nil, "PROVI-LSopw", string(bodyBytes))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitMessage(message string, count int) []string {
|
|
||||||
if count == 0 {
|
|
||||||
return []string{message}
|
|
||||||
}
|
|
||||||
var splits []string
|
|
||||||
var l, r int
|
|
||||||
for l, r = 0, count; r < len(message); l, r = r, r+count {
|
|
||||||
for !utf8.RuneStart(message[r]) {
|
|
||||||
r--
|
|
||||||
}
|
|
||||||
splits = append(splits, message[l:r])
|
|
||||||
}
|
|
||||||
splits = append(splits, message[l:])
|
|
||||||
return splits
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package chat
|
|
||||||
|
|
||||||
type ChatConfig struct {
|
|
||||||
// Defaults to true if DebugMode is set to true
|
|
||||||
Enabled *bool
|
|
||||||
Url string
|
|
||||||
SplitCount int
|
|
||||||
Compact bool
|
|
||||||
}
|
|
@ -19,9 +19,11 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/notification/messages"
|
"github.com/caos/zitadel/internal/notification/messages"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitFSChannel(config FSConfig) (channels.NotificationChannel, error) {
|
func InitFSChannel(path string, config FSConfig) (channels.NotificationChannel, error) {
|
||||||
|
if path == "" {
|
||||||
if err := os.MkdirAll(config.Path, os.ModePerm); err != nil {
|
return nil, nil
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(path, os.ModePerm); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +48,6 @@ func InitFSChannel(config FSConfig) (channels.NotificationChannel, error) {
|
|||||||
return caos_errors.ThrowUnimplementedf(nil, "NOTIF-6f9a1", "filesystem provider doesn't support message type %T", message)
|
return caos_errors.ThrowUnimplementedf(nil, "NOTIF-6f9a1", "filesystem provider doesn't support message type %T", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(filepath.Join(config.Path, fileName), []byte(content), 0666)
|
return ioutil.WriteFile(filepath.Join(path, fileName), []byte(content), 0666)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,5 @@ package fs
|
|||||||
|
|
||||||
type FSConfig struct {
|
type FSConfig struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Path string
|
|
||||||
Compact bool
|
Compact bool
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,15 @@ type Email struct {
|
|||||||
|
|
||||||
func InitSMTPChannel(ctx context.Context, getSMTPConfig func(ctx context.Context) (*EmailConfig, error)) (*Email, error) {
|
func InitSMTPChannel(ctx context.Context, getSMTPConfig func(ctx context.Context) (*EmailConfig, error)) (*Email, error) {
|
||||||
smtpConfig, err := getSMTPConfig(ctx)
|
smtpConfig, err := getSMTPConfig(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
client, err := smtpConfig.SMTP.connectToSMTP(smtpConfig.Tls)
|
client, err := smtpConfig.SMTP.connectToSMTP(smtpConfig.Tls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logging.Log("NOTIF-4n4Ih").Debug("successfully initialized smtp email channel")
|
logging.New().Debug("successfully initialized smtp email channel")
|
||||||
|
|
||||||
return &Email{
|
return &Email{
|
||||||
smtpClient: client,
|
smtpClient: client,
|
||||||
|
@ -18,10 +18,10 @@ type Config struct {
|
|||||||
Repository eventsourcing.Config
|
Repository eventsourcing.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(config Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) {
|
func Start(config Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) {
|
||||||
statikFS, err := fs.NewWithNamespace("notification")
|
statikFS, err := fs.NewWithNamespace("notification")
|
||||||
logging.OnError(err).Panic("unable to start listener")
|
logging.OnError(err).Panic("unable to start listener")
|
||||||
|
|
||||||
_, err = eventsourcing.Start(config.Repository, statikFS, systemDefaults, command, queries, dbClient, assetsPrefix, smtpPasswordEncAlg)
|
_, err = eventsourcing.Start(config.Repository, statikFS, systemDefaults, command, queries, dbClient, assetsPrefix, smtpPasswordEncAlg, smsCrypto)
|
||||||
logging.OnError(err).Panic("unable to start app")
|
logging.OnError(err).Panic("unable to start app")
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ func (h *handler) Eventstore() v1.Eventstore {
|
|||||||
return h.es
|
return h.es
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) []queryv1.Handler {
|
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) []queryv1.Handler {
|
||||||
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.UserVerificationKey)
|
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.UserVerificationKey)
|
||||||
logging.OnError(err).Fatal("error create new aes crypto")
|
logging.OnError(err).Fatal("error create new aes crypto")
|
||||||
|
|
||||||
@ -52,6 +52,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
|||||||
dir,
|
dir,
|
||||||
assetsPrefix,
|
assetsPrefix,
|
||||||
smtpPasswordEncAlg,
|
smtpPasswordEncAlg,
|
||||||
|
smsCrypto,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
"github.com/caos/zitadel/internal/command"
|
"github.com/caos/zitadel/internal/command"
|
||||||
@ -43,18 +46,10 @@ type Notification struct {
|
|||||||
assetsPrefix string
|
assetsPrefix string
|
||||||
queries *query.Queries
|
queries *query.Queries
|
||||||
smtpPasswordCrypto crypto.EncryptionAlgorithm
|
smtpPasswordCrypto crypto.EncryptionAlgorithm
|
||||||
|
smsTokenCrypto crypto.EncryptionAlgorithm
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNotification(
|
func newNotification(handler handler, command *command.Commands, query *query.Queries, defaults sd.SystemDefaults, aesCrypto crypto.EncryptionAlgorithm, statikDir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) *Notification {
|
||||||
handler handler,
|
|
||||||
command *command.Commands,
|
|
||||||
query *query.Queries,
|
|
||||||
defaults sd.SystemDefaults,
|
|
||||||
aesCrypto crypto.EncryptionAlgorithm,
|
|
||||||
statikDir http.FileSystem,
|
|
||||||
assetsPrefix string,
|
|
||||||
smtpPasswordEncAlg crypto.EncryptionAlgorithm,
|
|
||||||
) *Notification {
|
|
||||||
h := &Notification{
|
h := &Notification{
|
||||||
handler: handler,
|
handler: handler,
|
||||||
command: command,
|
command: command,
|
||||||
@ -64,6 +59,7 @@ func newNotification(
|
|||||||
assetsPrefix: assetsPrefix,
|
assetsPrefix: assetsPrefix,
|
||||||
queries: query,
|
queries: query,
|
||||||
smtpPasswordCrypto: smtpPasswordEncAlg,
|
smtpPasswordCrypto: smtpPasswordEncAlg,
|
||||||
|
smsTokenCrypto: smsCrypto,
|
||||||
}
|
}
|
||||||
|
|
||||||
h.subscribe()
|
h.subscribe()
|
||||||
@ -165,7 +161,7 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = types.SendUserInitCode(ctx, string(template.Template), translator, user, initCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
err = types.SendUserInitCode(ctx, string(template.Template), translator, user, initCode, n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -203,7 +199,7 @@ func (n *Notification) handlePasswordCode(event *models.Event) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = types.SendPasswordCode(ctx, string(template.Template), translator, user, pwCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
err = types.SendPasswordCode(ctx, string(template.Template), translator, user, pwCode, n.systemDefaults, n.getSMTPConfig, n.getTwilioConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -242,7 +238,7 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = types.SendEmailVerificationCode(ctx, string(template.Template), translator, user, emailCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
err = types.SendEmailVerificationCode(ctx, string(template.Template), translator, user, emailCode, n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -268,7 +264,7 @@ func (n *Notification) handlePhoneVerificationCode(event *models.Event) (err err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = types.SendPhoneVerificationCode(translator, user, phoneCode, n.systemDefaults, n.AesCrypto)
|
err = types.SendPhoneVerificationCode(context.Background(), translator, user, phoneCode, n.systemDefaults, n.getTwilioConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -308,7 +304,7 @@ func (n *Notification) handleDomainClaimed(event *models.Event) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = types.SendDomainClaimed(ctx, string(template.Template), translator, user, data["userName"], n.systemDefaults, n.getSMTPConfig, colors, n.assetsPrefix)
|
err = types.SendDomainClaimed(ctx, string(template.Template), translator, user, data["userName"], n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, colors, n.assetsPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -355,7 +351,7 @@ func (n *Notification) handlePasswordlessRegistrationLink(event *models.Event) (
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = types.SendPasswordlessRegistrationLink(ctx, string(template.Template), translator, user, addedEvent, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
err = types.SendPasswordlessRegistrationLink(ctx, string(template.Template), translator, user, addedEvent, n.systemDefaults, n.getSMTPConfig, n.getFileSystemProvider, n.getLogProvider, n.AesCrypto, colors, n.assetsPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -394,7 +390,7 @@ func (n *Notification) getUserEvents(userID string, sequence uint64) ([]*models.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) OnError(event *models.Event, err error) error {
|
func (n *Notification) OnError(event *models.Event, err error) error {
|
||||||
logging.LogWithFields("SPOOL-s9opc", "id", event.AggregateID, "sequence", event.Sequence).WithError(err).Warn("something went wrong in notification handler")
|
logging.WithFields("id", event.AggregateID, "sequence", event.Sequence).WithError(err).Warn("something went wrong in notification handler")
|
||||||
return spooler.HandleError(event, err, n.view.GetLatestNotificationFailedEvent, n.view.ProcessedNotificationFailedEvent, n.view.ProcessedNotificationSequence, n.errorCountUntilSkip)
|
return spooler.HandleError(event, err, n.view.GetLatestNotificationFailedEvent, n.view.ProcessedNotificationFailedEvent, n.view.ProcessedNotificationSequence, n.errorCountUntilSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,6 +433,48 @@ func (n *Notification) getSMTPConfig(ctx context.Context) (*smtp.EmailConfig, er
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read iam twilio config
|
||||||
|
func (n *Notification) getTwilioConfig(ctx context.Context) (*twilio.TwilioConfig, error) {
|
||||||
|
config, err := n.queries.SMSProviderConfigByID(ctx, domain.IAMID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if config.TwilioConfig == nil {
|
||||||
|
return nil, errors.ThrowNotFound(nil, "HANDLER-8nfow", "Errors.SMS.Twilio.NotFound")
|
||||||
|
}
|
||||||
|
token, err := crypto.Decrypt(config.TwilioConfig.Token, n.smtpPasswordCrypto)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &twilio.TwilioConfig{
|
||||||
|
SID: config.TwilioConfig.SID,
|
||||||
|
Token: string(token),
|
||||||
|
SenderNumber: config.TwilioConfig.SenderNumber,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read iam filesystem provider config
|
||||||
|
func (n *Notification) getFileSystemProvider(ctx context.Context) (*fs.FSConfig, error) {
|
||||||
|
config, err := n.queries.NotificationProviderByIDAndType(ctx, domain.IAMID, domain.NotificationProviderTypeFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &fs.FSConfig{
|
||||||
|
Compact: config.Compact,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read iam log provider config
|
||||||
|
func (n *Notification) getLogProvider(ctx context.Context) (*log.LogConfig, error) {
|
||||||
|
config, err := n.queries.NotificationProviderByIDAndType(ctx, domain.IAMID, domain.NotificationProviderTypeLog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &log.LogConfig{
|
||||||
|
Compact: config.Compact,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Notification) getTranslatorWithOrgTexts(orgID, textType string) (*i18n.Translator, error) {
|
func (n *Notification) getTranslatorWithOrgTexts(orgID, textType string) (*i18n.Translator, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
translator, err := i18n.NewTranslator(n.statikDir, i18n.TranslatorConfig{DefaultLanguage: n.queries.GetDefaultLanguage(ctx)})
|
translator, err := i18n.NewTranslator(n.statikDir, i18n.TranslatorConfig{DefaultLanguage: n.queries.GetDefaultLanguage(ctx)})
|
||||||
|
@ -22,7 +22,7 @@ type EsRepository struct {
|
|||||||
spooler *es_spol.Spooler
|
spooler *es_spol.Spooler
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) (*EsRepository, error) {
|
func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) (*EsRepository, error) {
|
||||||
es, err := v1.Start(dbClient)
|
es, err := v1.Start(dbClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -33,7 +33,7 @@ func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, c
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
spool := spooler.StartSpooler(conf.Spooler, es, view, dbClient, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg)
|
spool := spooler.StartSpooler(conf.Spooler, es, view, dbClient, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg, smsCrypto)
|
||||||
|
|
||||||
return &EsRepository{
|
return &EsRepository{
|
||||||
spool,
|
spool,
|
||||||
|
@ -21,12 +21,12 @@ type SpoolerConfig struct {
|
|||||||
Handlers handler.Configs
|
Handlers handler.Configs
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) *spooler.Spooler {
|
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm, smsCrypto *crypto.AESCrypto) *spooler.Spooler {
|
||||||
spoolerConfig := spooler.Config{
|
spoolerConfig := spooler.Config{
|
||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
Locker: &locker{dbClient: sql},
|
Locker: &locker{dbClient: sql},
|
||||||
ConcurrentWorkers: c.ConcurrentWorkers,
|
ConcurrentWorkers: c.ConcurrentWorkers,
|
||||||
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg),
|
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg, smsCrypto),
|
||||||
}
|
}
|
||||||
spool := spoolerConfig.New()
|
spool := spoolerConfig.New()
|
||||||
spool.Start()
|
spool.Start()
|
||||||
|
@ -22,3 +22,7 @@ func (c *Chain) HandleMessage(message channels.Message) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Chain) Len() int {
|
||||||
|
return len(c.channels)
|
||||||
|
}
|
||||||
|
@ -1,45 +1,28 @@
|
|||||||
package senders
|
package senders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/notification/channels"
|
"github.com/caos/zitadel/internal/notification/channels"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/chat"
|
|
||||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func debugChannels(config systemdefaults.Notifications) (channels.NotificationChannel, error) {
|
func debugChannels(ctx context.Context, config systemdefaults.Notifications, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (*Chain, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
providers []channels.NotificationChannel
|
providers []channels.NotificationChannel
|
||||||
enableChat bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if config.Providers.Chat.Enabled != nil {
|
if fsProvider, err := getFileSystemProvider(ctx); err == nil {
|
||||||
enableChat = *config.Providers.Chat.Enabled
|
p, err := fs.InitFSChannel(config.FileSystemPath, *fsProvider)
|
||||||
} else {
|
if err == nil {
|
||||||
// ensures backward compatible configuration
|
|
||||||
enableChat = config.DebugMode
|
|
||||||
}
|
|
||||||
|
|
||||||
if enableChat {
|
|
||||||
p, err := chat.InitChatChannel(config.Providers.Chat)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
providers = append(providers, p)
|
providers = append(providers, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Providers.FileSystem.Enabled {
|
|
||||||
p, err := fs.InitFSChannel(config.Providers.FileSystem)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
providers = append(providers, p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Providers.Log.Enabled {
|
if logProvider, err := getLogProvider(ctx); err == nil {
|
||||||
providers = append(providers, log.InitStdoutChannel(config.Providers.Log))
|
providers = append(providers, log.InitStdoutChannel(*logProvider))
|
||||||
}
|
}
|
||||||
|
|
||||||
return chainChannels(providers...), nil
|
return chainChannels(providers...), nil
|
||||||
|
@ -3,25 +3,21 @@ package senders
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/notification/channels"
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EmailChannels(ctx context.Context, config systemdefaults.Notifications, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error)) (channels.NotificationChannel, error) {
|
func EmailChannels(ctx context.Context, config systemdefaults.Notifications, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (chain *Chain, err error) {
|
||||||
|
|
||||||
debug, err := debugChannels(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !config.DebugMode {
|
|
||||||
p, err := smtp.InitSMTPChannel(ctx, emailConfig)
|
p, err := smtp.InitSMTPChannel(ctx, emailConfig)
|
||||||
|
if err == nil {
|
||||||
|
chain.channels = append(chain.channels, p)
|
||||||
|
}
|
||||||
|
chain, err = debugChannels(ctx, config, getFileSystemProvider, getLogProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
logging.New().Info("Error in creating debug channels")
|
||||||
}
|
}
|
||||||
return chainChannels(debug, p), nil
|
return chain, nil
|
||||||
}
|
|
||||||
|
|
||||||
return debug, nil
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
package senders
|
package senders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/notification/channels"
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SMSChannels(config systemdefaults.Notifications) (channels.NotificationChannel, error) {
|
func SMSChannels(ctx context.Context, config systemdefaults.Notifications, twilioConfig *twilio.TwilioConfig, getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error)) (chain *Chain, err error) {
|
||||||
|
if twilioConfig != nil {
|
||||||
debug, err := debugChannels(config)
|
chain.channels = append(chain.channels, twilio.InitTwilioChannel(*twilioConfig))
|
||||||
|
}
|
||||||
|
chain, err = debugChannels(ctx, config, getFileSystemProvider, getLogProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return chain, nil
|
||||||
if !config.DebugMode {
|
|
||||||
return chainChannels(debug, twilio.InitTwilioChannel(config.Providers.Twilio)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return debug, nil
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
@ -18,7 +20,7 @@ type DomainClaimedData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), colors *query.LabelPolicy, assetsPrefix string) error {
|
func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), colors *query.LabelPolicy, assetsPrefix string) error {
|
||||||
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -35,5 +37,5 @@ func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Tr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return generateEmail(ctx, user, domainClaimedData.Subject, template, systemDefaults.Notifications, emailConfig, true)
|
return generateEmail(ctx, user, domainClaimedData.Subject, template, systemDefaults.Notifications, emailConfig, getFileSystemProvider, getLogProvider, true)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
@ -19,7 +21,7 @@ type EmailVerificationCodeData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -41,5 +43,5 @@ func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
@ -25,7 +27,7 @@ type UrlData struct {
|
|||||||
PasswordSet bool
|
PasswordSet bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -45,5 +47,5 @@ func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Tra
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return generateEmail(ctx, user, initCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
return generateEmail(ctx, user, initCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||||
@ -21,7 +24,7 @@ type PasswordCodeData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getTwilioConfig func(ctx context.Context) (*twilio.TwilioConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -44,8 +47,8 @@ func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Tra
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if code.NotificationType == int32(domain.NotificationTypeSms) {
|
if code.NotificationType == int32(domain.NotificationTypeSms) {
|
||||||
return generateSms(user, passwordResetData.Text, systemDefaults.Notifications, false)
|
return generateSms(ctx, user, passwordResetData.Text, systemDefaults.Notifications, getTwilioConfig, getFileSystemProvider, getLogProvider, false)
|
||||||
}
|
}
|
||||||
return generateEmail(ctx, user, passwordResetData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
return generateEmail(ctx, user, passwordResetData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
@ -19,7 +21,7 @@ type PasswordlessRegistrationLinkData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *user.HumanPasswordlessInitCodeRequestedEvent, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *user.HumanPasswordlessInitCodeRequestedEvent, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -36,5 +38,5 @@ func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, tran
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, getFileSystemProvider, getLogProvider, true)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
"github.com/caos/zitadel/internal/i18n"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||||
@ -16,7 +20,7 @@ type PhoneVerificationCodeData struct {
|
|||||||
UserID string
|
UserID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendPhoneVerificationCode(translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PhoneCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
|
func SendPhoneVerificationCode(ctx context.Context, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PhoneCode, systemDefaults systemdefaults.SystemDefaults, getTwilioConfig func(ctx context.Context) (*twilio.TwilioConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), alg crypto.EncryptionAlgorithm) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -31,5 +35,5 @@ func SendPhoneVerificationCode(translator *i18n.Translator, user *view_model.Not
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return generateSms(user, template, systemDefaults.Notifications, true)
|
return generateSms(ctx, user, template, systemDefaults.Notifications, getTwilioConfig, getFileSystemProvider, getLogProvider, true)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"html"
|
"html"
|
||||||
|
|
||||||
|
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||||
"github.com/caos/zitadel/internal/notification/messages"
|
"github.com/caos/zitadel/internal/notification/messages"
|
||||||
"github.com/caos/zitadel/internal/notification/senders"
|
"github.com/caos/zitadel/internal/notification/senders"
|
||||||
@ -12,7 +15,7 @@ import (
|
|||||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, content string, config systemdefaults.Notifications, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), lastEmail bool) error {
|
func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, content string, config systemdefaults.Notifications, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), lastEmail bool) error {
|
||||||
content = html.UnescapeString(content)
|
content = html.UnescapeString(content)
|
||||||
message := &messages.Email{
|
message := &messages.Email{
|
||||||
Recipients: []string{user.VerifiedEmail},
|
Recipients: []string{user.VerifiedEmail},
|
||||||
@ -23,12 +26,15 @@ func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, co
|
|||||||
message.Recipients = []string{user.LastEmail}
|
message.Recipients = []string{user.LastEmail}
|
||||||
}
|
}
|
||||||
|
|
||||||
channels, err := senders.EmailChannels(ctx, config, smtpConfig)
|
channelChain, err := senders.EmailChannels(ctx, config, smtpConfig, getFileSystemProvider, getLogProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return channels.HandleMessage(message)
|
if channelChain.Len() == 0 {
|
||||||
|
return caos_errors.ThrowPreconditionFailed(nil, "MAIL-83nof", "Errors.Notification.Channels.NotPresent")
|
||||||
|
}
|
||||||
|
return channelChain.HandleMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapNotifyUserToArgs(user *view_model.NotifyUser) map[string]interface{} {
|
func mapNotifyUserToArgs(user *view_model.NotifyUser) map[string]interface{} {
|
||||||
|
@ -1,15 +1,26 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
|
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||||
|
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||||
"github.com/caos/zitadel/internal/notification/messages"
|
"github.com/caos/zitadel/internal/notification/messages"
|
||||||
"github.com/caos/zitadel/internal/notification/senders"
|
"github.com/caos/zitadel/internal/notification/senders"
|
||||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateSms(user *view_model.NotifyUser, content string, config systemdefaults.Notifications, lastPhone bool) error {
|
func generateSms(ctx context.Context, user *view_model.NotifyUser, content string, config systemdefaults.Notifications, getTwilioProvider func(ctx context.Context) (*twilio.TwilioConfig, error), getFileSystemProvider func(ctx context.Context) (*fs.FSConfig, error), getLogProvider func(ctx context.Context) (*log.LogConfig, error), lastPhone bool) error {
|
||||||
|
number := ""
|
||||||
|
twilio, err := getTwilioProvider(ctx)
|
||||||
|
if err == nil {
|
||||||
|
number = twilio.SenderNumber
|
||||||
|
}
|
||||||
message := &messages.SMS{
|
message := &messages.SMS{
|
||||||
SenderPhoneNumber: config.Providers.Twilio.SenderNumber,
|
SenderPhoneNumber: number,
|
||||||
RecipientPhoneNumber: user.VerifiedPhone,
|
RecipientPhoneNumber: user.VerifiedPhone,
|
||||||
Content: content,
|
Content: content,
|
||||||
}
|
}
|
||||||
@ -17,9 +28,10 @@ func generateSms(user *view_model.NotifyUser, content string, config systemdefau
|
|||||||
message.RecipientPhoneNumber = user.LastPhone
|
message.RecipientPhoneNumber = user.LastPhone
|
||||||
}
|
}
|
||||||
|
|
||||||
channels, err := senders.SMSChannels(config)
|
channelChain, err := senders.SMSChannels(ctx, config, twilio, getFileSystemProvider, getLogProvider)
|
||||||
if err != nil {
|
|
||||||
return err
|
if channelChain.Len() == 0 {
|
||||||
|
return caos_errors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
|
||||||
}
|
}
|
||||||
return channels.HandleMessage(message)
|
return channelChain.HandleMessage(message)
|
||||||
}
|
}
|
||||||
|
112
internal/query/notification_provider.go
Normal file
112
internal/query/notification_provider.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
errs "errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/query/projection"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DebugNotificationProvider struct {
|
||||||
|
AggregateID string
|
||||||
|
CreationDate time.Time
|
||||||
|
ChangeDate time.Time
|
||||||
|
Sequence uint64
|
||||||
|
ResourceOwner string
|
||||||
|
State domain.NotificationProviderState
|
||||||
|
Type domain.NotificationProviderType
|
||||||
|
Compact bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
notificationProviderTable = table{
|
||||||
|
name: projection.DebugNotificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnAggID = Column{
|
||||||
|
name: projection.DebugNotificationProviderAggIDCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnCreationDate = Column{
|
||||||
|
name: projection.DebugNotificationProviderCreationDateCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnChangeDate = Column{
|
||||||
|
name: projection.DebugNotificationProviderChangeDateCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnSequence = Column{
|
||||||
|
name: projection.DebugNotificationProviderSequenceCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnResourceOwner = Column{
|
||||||
|
name: projection.DebugNotificationProviderResourceOwnerCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnState = Column{
|
||||||
|
name: projection.DebugNotificationProviderStateCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnType = Column{
|
||||||
|
name: projection.DebugNotificationProviderTypeCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
NotificationProviderColumnCompact = Column{
|
||||||
|
name: projection.DebugNotificationProviderCompactCol,
|
||||||
|
table: notificationProviderTable,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (q *Queries) NotificationProviderByIDAndType(ctx context.Context, aggID string, providerType domain.NotificationProviderType) (*DebugNotificationProvider, error) {
|
||||||
|
query, scan := prepareDebugNotificationProviderQuery()
|
||||||
|
stmt, args, err := query.Where(
|
||||||
|
sq.Or{
|
||||||
|
sq.Eq{
|
||||||
|
LoginPolicyColumnOrgID.identifier(): aggID,
|
||||||
|
},
|
||||||
|
}).
|
||||||
|
Limit(1).ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "QUERY-f9jSf", "Errors.Query.SQLStatement")
|
||||||
|
}
|
||||||
|
|
||||||
|
row := q.client.QueryRowContext(ctx, stmt, args...)
|
||||||
|
return scan(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareDebugNotificationProviderQuery() (sq.SelectBuilder, func(*sql.Row) (*DebugNotificationProvider, error)) {
|
||||||
|
return sq.Select(
|
||||||
|
NotificationProviderColumnAggID.identifier(),
|
||||||
|
NotificationProviderColumnCreationDate.identifier(),
|
||||||
|
NotificationProviderColumnChangeDate.identifier(),
|
||||||
|
NotificationProviderColumnSequence.identifier(),
|
||||||
|
NotificationProviderColumnResourceOwner.identifier(),
|
||||||
|
NotificationProviderColumnState.identifier(),
|
||||||
|
NotificationProviderColumnType.identifier(),
|
||||||
|
NotificationProviderColumnCompact.identifier(),
|
||||||
|
).From(notificationProviderTable.identifier()).PlaceholderFormat(sq.Dollar),
|
||||||
|
func(row *sql.Row) (*DebugNotificationProvider, error) {
|
||||||
|
p := new(DebugNotificationProvider)
|
||||||
|
err := row.Scan(
|
||||||
|
&p.AggregateID,
|
||||||
|
&p.CreationDate,
|
||||||
|
&p.ChangeDate,
|
||||||
|
&p.Sequence,
|
||||||
|
&p.ResourceOwner,
|
||||||
|
&p.State,
|
||||||
|
&p.Type,
|
||||||
|
&p.Compact,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
if errs.Is(err, sql.ErrNoRows) {
|
||||||
|
return nil, errors.ThrowNotFound(err, "QUERY-s9ujf", "Errors.NotificationProvider.NotFound")
|
||||||
|
}
|
||||||
|
return nil, errors.ThrowInternal(err, "QUERY-2liu0", "Errors.Internal")
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
130
internal/query/notification_provider_test.go
Normal file
130
internal/query/notification_provider_test.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_NotificationProviderPrepares(t *testing.T) {
|
||||||
|
type want struct {
|
||||||
|
sqlExpectations sqlExpectation
|
||||||
|
err checkErr
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
prepare interface{}
|
||||||
|
want want
|
||||||
|
object interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "prepareNotificationProviderQuery no result",
|
||||||
|
prepare: prepareDebugNotificationProviderQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQueries(
|
||||||
|
regexp.QuoteMeta(`SELECT zitadel.projections.notification_providers.aggregate_id,`+
|
||||||
|
` zitadel.projections.notification_providers.creation_date,`+
|
||||||
|
` zitadel.projections.notification_providers.change_date,`+
|
||||||
|
` zitadel.projections.notification_providers.sequence,`+
|
||||||
|
` zitadel.projections.notification_providers.resource_owner,`+
|
||||||
|
` zitadel.projections.notification_providers.state,`+
|
||||||
|
` zitadel.projections.notification_providers.provider_type,`+
|
||||||
|
` zitadel.projections.notification_providers.compact`+
|
||||||
|
` FROM zitadel.projections.notification_providers`),
|
||||||
|
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: (*DebugNotificationProvider)(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prepareNotificationProviderQuery found",
|
||||||
|
prepare: prepareDebugNotificationProviderQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQuery(
|
||||||
|
regexp.QuoteMeta(`SELECT zitadel.projections.notification_providers.aggregate_id,`+
|
||||||
|
` zitadel.projections.notification_providers.creation_date,`+
|
||||||
|
` zitadel.projections.notification_providers.change_date,`+
|
||||||
|
` zitadel.projections.notification_providers.sequence,`+
|
||||||
|
` zitadel.projections.notification_providers.resource_owner,`+
|
||||||
|
` zitadel.projections.notification_providers.state,`+
|
||||||
|
` zitadel.projections.notification_providers.provider_type,`+
|
||||||
|
` zitadel.projections.notification_providers.compact`+
|
||||||
|
` FROM zitadel.projections.notification_providers`),
|
||||||
|
[]string{
|
||||||
|
"aggregate_id",
|
||||||
|
"creation_date",
|
||||||
|
"change_date",
|
||||||
|
"sequence",
|
||||||
|
"resource_owner",
|
||||||
|
"state",
|
||||||
|
"provider_type",
|
||||||
|
"compact",
|
||||||
|
},
|
||||||
|
[]driver.Value{
|
||||||
|
"agg-id",
|
||||||
|
testNow,
|
||||||
|
testNow,
|
||||||
|
uint64(20211109),
|
||||||
|
"ro-id",
|
||||||
|
domain.NotificationProviderStateActive,
|
||||||
|
domain.NotificationProviderTypeFile,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
object: &DebugNotificationProvider{
|
||||||
|
AggregateID: "agg-id",
|
||||||
|
CreationDate: testNow,
|
||||||
|
ChangeDate: testNow,
|
||||||
|
Sequence: 20211109,
|
||||||
|
ResourceOwner: "ro-id",
|
||||||
|
State: domain.NotificationProviderStateActive,
|
||||||
|
Type: domain.NotificationProviderTypeFile,
|
||||||
|
Compact: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prepareNotificationProviderQuery sql err",
|
||||||
|
prepare: prepareDebugNotificationProviderQuery,
|
||||||
|
want: want{
|
||||||
|
sqlExpectations: mockQueryErr(
|
||||||
|
regexp.QuoteMeta(`SELECT zitadel.projections.notification_providers.aggregate_id,`+
|
||||||
|
` zitadel.projections.notification_providers.creation_date,`+
|
||||||
|
` zitadel.projections.notification_providers.change_date,`+
|
||||||
|
` zitadel.projections.notification_providers.sequence,`+
|
||||||
|
` zitadel.projections.notification_providers.resource_owner,`+
|
||||||
|
` zitadel.projections.notification_providers.state,`+
|
||||||
|
` zitadel.projections.notification_providers.provider_type,`+
|
||||||
|
` zitadel.projections.notification_providers.compact`+
|
||||||
|
` FROM zitadel.projections.notification_providers`),
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
160
internal/query/projection/debug_notification.go
Normal file
160
internal/query/projection/debug_notification.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package projection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/repository/settings"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DebugNotificationProviderProjection struct {
|
||||||
|
crdb.StatementHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
DebugNotificationProviderTable = "zitadel.projections.notification_providers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderProjection(ctx context.Context, config crdb.StatementHandlerConfig) *DebugNotificationProviderProjection {
|
||||||
|
p := &DebugNotificationProviderProjection{}
|
||||||
|
config.ProjectionName = DebugNotificationProviderTable
|
||||||
|
config.Reducers = p.reducers()
|
||||||
|
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebugNotificationProviderProjection) reducers() []handler.AggregateReducer {
|
||||||
|
return []handler.AggregateReducer{
|
||||||
|
{
|
||||||
|
Aggregate: iam.AggregateType,
|
||||||
|
EventRedusers: []handler.EventReducer{
|
||||||
|
{
|
||||||
|
Event: iam.DebugNotificationProviderFileAddedEventType,
|
||||||
|
Reduce: p.reduceDebugNotificationProviderAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.DebugNotificationProviderFileChangedEventType,
|
||||||
|
Reduce: p.reduceDebugNotificationProviderChanged,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.DebugNotificationProviderFileRemovedEventType,
|
||||||
|
Reduce: p.reduceDebugNotificationProviderRemoved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.DebugNotificationProviderLogAddedEventType,
|
||||||
|
Reduce: p.reduceDebugNotificationProviderAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.DebugNotificationProviderLogChangedEventType,
|
||||||
|
Reduce: p.reduceDebugNotificationProviderChanged,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: iam.DebugNotificationProviderLogRemovedEventType,
|
||||||
|
Reduce: p.reduceDebugNotificationProviderRemoved,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
DebugNotificationProviderAggIDCol = "aggregate_id"
|
||||||
|
DebugNotificationProviderCreationDateCol = "creation_date"
|
||||||
|
DebugNotificationProviderChangeDateCol = "change_date"
|
||||||
|
DebugNotificationProviderSequenceCol = "sequence"
|
||||||
|
DebugNotificationProviderResourceOwnerCol = "resource_owner"
|
||||||
|
DebugNotificationProviderStateCol = "state"
|
||||||
|
DebugNotificationProviderTypeCol = "provider_type"
|
||||||
|
DebugNotificationProviderCompactCol = "compact"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *DebugNotificationProviderProjection) reduceDebugNotificationProviderAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
var providerEvent settings.DebugNotificationProviderAddedEvent
|
||||||
|
var providerType domain.NotificationProviderType
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *iam.DebugNotificationProviderFileAddedEvent:
|
||||||
|
providerEvent = e.DebugNotificationProviderAddedEvent
|
||||||
|
providerType = domain.NotificationProviderTypeFile
|
||||||
|
case *iam.DebugNotificationProviderLogAddedEvent:
|
||||||
|
providerEvent = e.DebugNotificationProviderAddedEvent
|
||||||
|
providerType = domain.NotificationProviderTypeLog
|
||||||
|
default:
|
||||||
|
logging.WithFields("seq", event.Sequence(), "expectedTypes", []eventstore.EventType{iam.DebugNotificationProviderFileAddedEventType, iam.DebugNotificationProviderLogAddedEventType}).Error("wrong event type")
|
||||||
|
return nil, errors.ThrowInvalidArgument(nil, "HANDL-pYPxS", "reduce.wrong.event.type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return crdb.NewCreateStatement(&providerEvent, []handler.Column{
|
||||||
|
handler.NewCol(DebugNotificationProviderAggIDCol, providerEvent.Aggregate().ID),
|
||||||
|
handler.NewCol(DebugNotificationProviderCreationDateCol, providerEvent.CreationDate()),
|
||||||
|
handler.NewCol(DebugNotificationProviderChangeDateCol, providerEvent.CreationDate()),
|
||||||
|
handler.NewCol(DebugNotificationProviderSequenceCol, providerEvent.Sequence()),
|
||||||
|
handler.NewCol(DebugNotificationProviderResourceOwnerCol, providerEvent.Aggregate().ResourceOwner),
|
||||||
|
handler.NewCol(DebugNotificationProviderStateCol, domain.NotificationProviderStateActive),
|
||||||
|
handler.NewCol(DebugNotificationProviderTypeCol, providerType),
|
||||||
|
handler.NewCol(DebugNotificationProviderCompactCol, providerEvent.Compact),
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebugNotificationProviderProjection) reduceDebugNotificationProviderChanged(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
var providerEvent settings.DebugNotificationProviderChangedEvent
|
||||||
|
var providerType domain.NotificationProviderType
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *iam.DebugNotificationProviderFileChangedEvent:
|
||||||
|
providerEvent = e.DebugNotificationProviderChangedEvent
|
||||||
|
providerType = domain.NotificationProviderTypeFile
|
||||||
|
case *iam.DebugNotificationProviderLogChangedEvent:
|
||||||
|
providerEvent = e.DebugNotificationProviderChangedEvent
|
||||||
|
providerType = domain.NotificationProviderTypeLog
|
||||||
|
default:
|
||||||
|
logging.WithFields("seq", event.Sequence(), "expectedTypes", []eventstore.EventType{iam.DebugNotificationProviderFileChangedEventType, iam.DebugNotificationProviderLogChangedEventType}).Error("wrong event type")
|
||||||
|
return nil, errors.ThrowInvalidArgument(nil, "HANDL-pYPxS", "reduce.wrong.event.type")
|
||||||
|
}
|
||||||
|
|
||||||
|
cols := []handler.Column{
|
||||||
|
handler.NewCol(DebugNotificationProviderChangeDateCol, providerEvent.CreationDate()),
|
||||||
|
handler.NewCol(DebugNotificationProviderSequenceCol, providerEvent.Sequence()),
|
||||||
|
}
|
||||||
|
if providerEvent.Compact != nil {
|
||||||
|
cols = append(cols, handler.NewCol(DebugNotificationProviderCompactCol, *providerEvent.Compact))
|
||||||
|
}
|
||||||
|
|
||||||
|
return crdb.NewUpdateStatement(
|
||||||
|
&providerEvent,
|
||||||
|
cols,
|
||||||
|
[]handler.Condition{
|
||||||
|
handler.NewCond(DebugNotificationProviderAggIDCol, providerEvent.Aggregate().ID),
|
||||||
|
handler.NewCond(DebugNotificationProviderTypeCol, providerType),
|
||||||
|
},
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DebugNotificationProviderProjection) reduceDebugNotificationProviderRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
var providerEvent settings.DebugNotificationProviderRemovedEvent
|
||||||
|
var providerType domain.NotificationProviderType
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *iam.DebugNotificationProviderFileRemovedEvent:
|
||||||
|
providerEvent = e.DebugNotificationProviderRemovedEvent
|
||||||
|
providerType = domain.NotificationProviderTypeFile
|
||||||
|
case *iam.DebugNotificationProviderLogRemovedEvent:
|
||||||
|
providerEvent = e.DebugNotificationProviderRemovedEvent
|
||||||
|
providerType = domain.NotificationProviderTypeLog
|
||||||
|
default:
|
||||||
|
logging.WithFields("seq", event.Sequence(), "expectedTypes", []eventstore.EventType{iam.DebugNotificationProviderFileRemovedEventType, iam.DebugNotificationProviderLogRemovedEventType}).Error("wrong event type")
|
||||||
|
return nil, errors.ThrowInvalidArgument(nil, "HANDL-dow9f", "reduce.wrong.event.type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return crdb.NewDeleteStatement(
|
||||||
|
&providerEvent,
|
||||||
|
[]handler.Condition{
|
||||||
|
handler.NewCond(DebugNotificationProviderAggIDCol, providerEvent.Aggregate().ID),
|
||||||
|
handler.NewCond(DebugNotificationProviderTypeCol, providerType),
|
||||||
|
},
|
||||||
|
), nil
|
||||||
|
}
|
232
internal/query/projection/debug_notification_provider_test.go
Normal file
232
internal/query/projection/debug_notification_provider_test.go
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
package projection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"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 TestDebugNotificationProviderProjection_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: "iam.reduceNotificationProviderFileAdded",
|
||||||
|
reduce: (&DebugNotificationProviderProjection{}).reduceDebugNotificationProviderAdded,
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.DebugNotificationProviderFileAddedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"compact": true
|
||||||
|
}`),
|
||||||
|
), iam.DebugNotificationProviderFileAddedEventMapper),
|
||||||
|
},
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("iam"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: DebugNotificationProviderTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO zitadel.projections.notification_providers (aggregate_id, creation_date, change_date, sequence, resource_owner, state, provider_type, compact) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"agg-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
domain.NotificationProviderStateActive,
|
||||||
|
domain.NotificationProviderTypeFile,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceNotificationProviderFileChanged",
|
||||||
|
reduce: (&DebugNotificationProviderProjection{}).reduceDebugNotificationProviderChanged,
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.DebugNotificationProviderFileChangedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"compact": true
|
||||||
|
}`),
|
||||||
|
), iam.DebugNotificationProviderFileChangedEventMapper),
|
||||||
|
},
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("iam"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: DebugNotificationProviderTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "UPDATE zitadel.projections.notification_providers SET (change_date, sequence, compact) = ($1, $2, $3) WHERE (aggregate_id = $4) AND (provider_type = $5)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
true,
|
||||||
|
"agg-id",
|
||||||
|
domain.NotificationProviderTypeFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceNotificationProviderFileRemoved",
|
||||||
|
reduce: (&DebugNotificationProviderProjection{}).reduceDebugNotificationProviderRemoved,
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.DebugNotificationProviderFileRemovedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
nil,
|
||||||
|
), iam.DebugNotificationProviderFileRemovedEventMapper),
|
||||||
|
},
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("iam"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: DebugNotificationProviderTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "DELETE FROM zitadel.projections.notification_providers WHERE (aggregate_id = $1) AND (provider_type = $2)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"agg-id",
|
||||||
|
domain.NotificationProviderTypeFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceNotificationProviderLogAdded",
|
||||||
|
reduce: (&DebugNotificationProviderProjection{}).reduceDebugNotificationProviderAdded,
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.DebugNotificationProviderLogAddedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"compact": true
|
||||||
|
}`),
|
||||||
|
), iam.DebugNotificationProviderLogAddedEventMapper),
|
||||||
|
},
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("iam"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: DebugNotificationProviderTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO zitadel.projections.notification_providers (aggregate_id, creation_date, change_date, sequence, resource_owner, state, provider_type, compact) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"agg-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
domain.NotificationProviderStateActive,
|
||||||
|
domain.NotificationProviderTypeLog,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceNotificationProviderLogChanged",
|
||||||
|
reduce: (&DebugNotificationProviderProjection{}).reduceDebugNotificationProviderChanged,
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.DebugNotificationProviderLogChangedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"compact": true
|
||||||
|
}`),
|
||||||
|
), iam.DebugNotificationProviderLogChangedEventMapper),
|
||||||
|
},
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("iam"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: DebugNotificationProviderTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "UPDATE zitadel.projections.notification_providers SET (change_date, sequence, compact) = ($1, $2, $3) WHERE (aggregate_id = $4) AND (provider_type = $5)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
true,
|
||||||
|
"agg-id",
|
||||||
|
domain.NotificationProviderTypeLog,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iam.reduceNotificationProviderLogRemoved",
|
||||||
|
reduce: (&DebugNotificationProviderProjection{}).reduceDebugNotificationProviderRemoved,
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(iam.DebugNotificationProviderLogRemovedEventType),
|
||||||
|
iam.AggregateType,
|
||||||
|
nil,
|
||||||
|
), iam.DebugNotificationProviderLogRemovedEventMapper),
|
||||||
|
},
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("iam"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
projection: DebugNotificationProviderTable,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: "DELETE FROM zitadel.projections.notification_providers WHERE (aggregate_id = $1) AND (provider_type = $2)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"agg-id",
|
||||||
|
domain.NotificationProviderTypeLog,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -74,6 +74,7 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
|
|||||||
NewSMSConfigProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["sms_config"]))
|
NewSMSConfigProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["sms_config"]))
|
||||||
NewOIDCSettingsProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["oidc_settings"]))
|
NewOIDCSettingsProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["oidc_settings"]))
|
||||||
_, err := NewKeyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["keys"]), keyConfig, keyChan)
|
_, err := NewKeyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["keys"]), keyConfig, keyChan)
|
||||||
|
NewDebugNotificationProviderProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["debug_notification_provider"]))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
106
internal/repository/iam/debug_notification_file.go
Normal file
106
internal/repository/iam/debug_notification_file.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package iam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/repository/settings"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
fileType = ".file"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DebugNotificationProviderFileAddedEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + fileType + settings.DebugNotificationProviderAdded
|
||||||
|
DebugNotificationProviderFileChangedEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + fileType + settings.DebugNotificationProviderChanged
|
||||||
|
DebugNotificationProviderFileRemovedEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + fileType + settings.DebugNotificationProviderRemoved
|
||||||
|
)
|
||||||
|
|
||||||
|
type DebugNotificationProviderFileAddedEvent struct {
|
||||||
|
settings.DebugNotificationProviderAddedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderFileAddedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
compact bool,
|
||||||
|
) *DebugNotificationProviderFileAddedEvent {
|
||||||
|
return &DebugNotificationProviderFileAddedEvent{
|
||||||
|
DebugNotificationProviderAddedEvent: *settings.NewDebugNotificationProviderAddedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
DebugNotificationProviderFileAddedEventType),
|
||||||
|
compact),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderFileAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := settings.DebugNotificationProviderAddedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DebugNotificationProviderFileAddedEvent{DebugNotificationProviderAddedEvent: *e.(*settings.DebugNotificationProviderAddedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderFileChangedEvent struct {
|
||||||
|
settings.DebugNotificationProviderChangedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderFileChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
changes []settings.DebugNotificationProviderChanges,
|
||||||
|
) (*DebugNotificationProviderFileChangedEvent, error) {
|
||||||
|
changedEvent, err := settings.NewDebugNotificationProviderChangedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
DebugNotificationProviderFileChangedEventType),
|
||||||
|
changes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &DebugNotificationProviderFileChangedEvent{DebugNotificationProviderChangedEvent: *changedEvent}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderFileChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := settings.DebugNotificationProviderChangedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DebugNotificationProviderFileChangedEvent{DebugNotificationProviderChangedEvent: *e.(*settings.DebugNotificationProviderChangedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderFileRemovedEvent struct {
|
||||||
|
settings.DebugNotificationProviderRemovedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderFileRemovedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
) *DebugNotificationProviderFileRemovedEvent {
|
||||||
|
return &DebugNotificationProviderFileRemovedEvent{
|
||||||
|
DebugNotificationProviderRemovedEvent: *settings.NewDebugNotificationProviderRemovedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
DebugNotificationProviderFileRemovedEventType),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderFileRemovedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := settings.DebugNotificationProviderRemovedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DebugNotificationProviderFileRemovedEvent{DebugNotificationProviderRemovedEvent: *e.(*settings.DebugNotificationProviderRemovedEvent)}, nil
|
||||||
|
}
|
108
internal/repository/iam/debug_notification_log.go
Normal file
108
internal/repository/iam/debug_notification_log.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package iam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/repository/settings"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
logType = ".log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DebugNotificationProviderLogAddedEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + logType + settings.DebugNotificationProviderAdded
|
||||||
|
DebugNotificationProviderLogChangedEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + logType + settings.DebugNotificationProviderChanged
|
||||||
|
DebugNotificationProviderLogEnabledEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + logType + settings.DebugNotificationProviderEnabled
|
||||||
|
DebugNotificationProviderLogDisabledEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + logType + settings.DebugNotificationProviderDisabled
|
||||||
|
DebugNotificationProviderLogRemovedEventType = iamEventTypePrefix + settings.DebugNotificationPrefix + logType + settings.DebugNotificationProviderRemoved
|
||||||
|
)
|
||||||
|
|
||||||
|
type DebugNotificationProviderLogAddedEvent struct {
|
||||||
|
settings.DebugNotificationProviderAddedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderLogAddedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
compact bool,
|
||||||
|
) *DebugNotificationProviderLogAddedEvent {
|
||||||
|
return &DebugNotificationProviderLogAddedEvent{
|
||||||
|
DebugNotificationProviderAddedEvent: *settings.NewDebugNotificationProviderAddedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
DebugNotificationProviderLogAddedEventType),
|
||||||
|
compact),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderLogAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := settings.DebugNotificationProviderAddedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DebugNotificationProviderLogAddedEvent{DebugNotificationProviderAddedEvent: *e.(*settings.DebugNotificationProviderAddedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderLogChangedEvent struct {
|
||||||
|
settings.DebugNotificationProviderChangedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderLogChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
changes []settings.DebugNotificationProviderChanges,
|
||||||
|
) (*DebugNotificationProviderLogChangedEvent, error) {
|
||||||
|
changedEvent, err := settings.NewDebugNotificationProviderChangedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
DebugNotificationProviderLogChangedEventType),
|
||||||
|
changes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &DebugNotificationProviderLogChangedEvent{DebugNotificationProviderChangedEvent: *changedEvent}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderLogChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := settings.DebugNotificationProviderChangedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DebugNotificationProviderLogChangedEvent{DebugNotificationProviderChangedEvent: *e.(*settings.DebugNotificationProviderChangedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderLogRemovedEvent struct {
|
||||||
|
settings.DebugNotificationProviderRemovedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderLogRemovedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
) *DebugNotificationProviderLogRemovedEvent {
|
||||||
|
return &DebugNotificationProviderLogRemovedEvent{
|
||||||
|
DebugNotificationProviderRemovedEvent: *settings.NewDebugNotificationProviderRemovedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
DebugNotificationProviderLogRemovedEventType),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderLogRemovedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := settings.DebugNotificationProviderRemovedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DebugNotificationProviderLogRemovedEvent{DebugNotificationProviderRemovedEvent: *e.(*settings.DebugNotificationProviderRemovedEvent)}, nil
|
||||||
|
}
|
@ -23,6 +23,12 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
|||||||
RegisterFilterEventMapper(SMSConfigActivatedEventType, SMSConfigActivatedEventMapper).
|
RegisterFilterEventMapper(SMSConfigActivatedEventType, SMSConfigActivatedEventMapper).
|
||||||
RegisterFilterEventMapper(SMSConfigDeactivatedEventType, SMSConfigDeactivatedEventMapper).
|
RegisterFilterEventMapper(SMSConfigDeactivatedEventType, SMSConfigDeactivatedEventMapper).
|
||||||
RegisterFilterEventMapper(SMSConfigRemovedEventType, SMSConfigRemovedEventMapper).
|
RegisterFilterEventMapper(SMSConfigRemovedEventType, SMSConfigRemovedEventMapper).
|
||||||
|
RegisterFilterEventMapper(DebugNotificationProviderFileAddedEventType, DebugNotificationProviderFileAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(DebugNotificationProviderFileChangedEventType, DebugNotificationProviderFileChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(DebugNotificationProviderFileRemovedEventType, DebugNotificationProviderFileRemovedEventMapper).
|
||||||
|
RegisterFilterEventMapper(DebugNotificationProviderLogAddedEventType, DebugNotificationProviderLogAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(DebugNotificationProviderLogChangedEventType, DebugNotificationProviderLogChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(DebugNotificationProviderLogRemovedEventType, DebugNotificationProviderLogRemovedEventMapper).
|
||||||
RegisterFilterEventMapper(OIDCSettingsAddedEventType, OIDCSettingsAddedEventMapper).
|
RegisterFilterEventMapper(OIDCSettingsAddedEventType, OIDCSettingsAddedEventMapper).
|
||||||
RegisterFilterEventMapper(OIDCSettingsChangedEventType, OIDCSettingsChangedEventMapper).
|
RegisterFilterEventMapper(OIDCSettingsChangedEventType, OIDCSettingsChangedEventMapper).
|
||||||
RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper).
|
RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper).
|
||||||
|
130
internal/repository/settings/debug_notification.go
Normal file
130
internal/repository/settings/debug_notification.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DebugNotificationPrefix = "notification.provider.debug"
|
||||||
|
DebugNotificationProviderAdded = "added"
|
||||||
|
DebugNotificationProviderChanged = "changed"
|
||||||
|
DebugNotificationProviderEnabled = "enabled"
|
||||||
|
DebugNotificationProviderDisabled = "disabled"
|
||||||
|
DebugNotificationProviderRemoved = "removed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DebugNotificationProviderAddedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Compact bool `json:"compact,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DebugNotificationProviderAddedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DebugNotificationProviderAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderAddedEvent(
|
||||||
|
base *eventstore.BaseEvent,
|
||||||
|
compact bool,
|
||||||
|
) *DebugNotificationProviderAddedEvent {
|
||||||
|
return &DebugNotificationProviderAddedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
Compact: compact,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e := &DebugNotificationProviderAddedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "SET-f93ns", "unable to unmarshal debug notification added")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderChangedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Compact *bool `json:"compact,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DebugNotificationProviderChangedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DebugNotificationProviderChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderChangedEvent(
|
||||||
|
base *eventstore.BaseEvent,
|
||||||
|
changes []DebugNotificationProviderChanges,
|
||||||
|
) (*DebugNotificationProviderChangedEvent, error) {
|
||||||
|
if len(changes) == 0 {
|
||||||
|
return nil, errors.ThrowPreconditionFailed(nil, "SET-hj90s", "Errors.NoChangesFound")
|
||||||
|
}
|
||||||
|
changeEvent := &DebugNotificationProviderChangedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
}
|
||||||
|
for _, change := range changes {
|
||||||
|
change(changeEvent)
|
||||||
|
}
|
||||||
|
return changeEvent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderChanges func(*DebugNotificationProviderChangedEvent)
|
||||||
|
|
||||||
|
func ChangeCompact(compact bool) func(*DebugNotificationProviderChangedEvent) {
|
||||||
|
return func(e *DebugNotificationProviderChangedEvent) {
|
||||||
|
e.Compact = &compact
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e := &DebugNotificationProviderChangedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "POLIC-ehssl", "unable to unmarshal policy")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DebugNotificationProviderRemovedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DebugNotificationProviderRemovedEvent) Data() interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *DebugNotificationProviderRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugNotificationProviderRemovedEvent(base *eventstore.BaseEvent) *DebugNotificationProviderRemovedEvent {
|
||||||
|
return &DebugNotificationProviderRemovedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DebugNotificationProviderRemovedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
return &DebugNotificationProviderRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}, nil
|
||||||
|
}
|
@ -2,11 +2,11 @@ syntax = "proto3";
|
|||||||
|
|
||||||
import "zitadel/idp.proto";
|
import "zitadel/idp.proto";
|
||||||
import "zitadel/user.proto";
|
import "zitadel/user.proto";
|
||||||
import "zitadel/settings.proto";
|
|
||||||
import "zitadel/object.proto";
|
import "zitadel/object.proto";
|
||||||
import "zitadel/options.proto";
|
import "zitadel/options.proto";
|
||||||
import "zitadel/org.proto";
|
import "zitadel/org.proto";
|
||||||
import "zitadel/policy.proto";
|
import "zitadel/policy.proto";
|
||||||
|
import "zitadel/settings.proto";
|
||||||
import "zitadel/text.proto";
|
import "zitadel/text.proto";
|
||||||
import "zitadel/member.proto";
|
import "zitadel/member.proto";
|
||||||
import "zitadel/features.proto";
|
import "zitadel/features.proto";
|
||||||
@ -336,6 +336,28 @@ service AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get file system notification provider
|
||||||
|
rpc GetFileSystemNotificationProvider(GetFileSystemNotificationProviderRequest) returns (GetFileSystemNotificationProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/notification/provider/file";
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.read";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get log notification provider
|
||||||
|
rpc GetLogNotificationProvider(GetLogNotificationProviderRequest) returns (GetLogNotificationProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/notification/provider/log";
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.read";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an organisation by id
|
// Returns an organisation by id
|
||||||
rpc GetOrgByID(GetOrgByIDRequest) returns (GetOrgByIDResponse) {
|
rpc GetOrgByID(GetOrgByIDRequest) returns (GetOrgByIDResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -2561,6 +2583,20 @@ message UpdateSMSProviderTwilioTokenResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This is an empty request
|
||||||
|
message GetFileSystemNotificationProviderRequest {}
|
||||||
|
|
||||||
|
message GetFileSystemNotificationProviderResponse {
|
||||||
|
zitadel.settings.v1.DebugNotificationProvider provider = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//This is an empty request
|
||||||
|
message GetLogNotificationProviderRequest {}
|
||||||
|
|
||||||
|
message GetLogNotificationProviderResponse {
|
||||||
|
zitadel.settings.v1.DebugNotificationProvider provider = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// This is an empty request
|
// This is an empty request
|
||||||
message GetOIDCSettingsRequest {}
|
message GetOIDCSettingsRequest {}
|
||||||
|
|
||||||
|
@ -72,6 +72,11 @@ enum SMSProviderConfigState {
|
|||||||
SMS_PROVIDER_CONFIG_INACTIVE = 2;
|
SMS_PROVIDER_CONFIG_INACTIVE = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message DebugNotificationProvider {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
bool compact = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message OIDCSettings {
|
message OIDCSettings {
|
||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
google.protobuf.Duration access_token_lifetime = 2;
|
google.protobuf.Duration access_token_lifetime = 2;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user