diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml index 56aa2df2b0..7083c1de61 100644 --- a/cmd/defaults.yaml +++ b/cmd/defaults.yaml @@ -241,6 +241,7 @@ DefaultInstance: DomainPolicy: UserLoginMustBeDomain: true ValidateOrgDomains: true + SMTPSenderAddressMatchesInstanceDomain: true LoginPolicy: AllowUsernamePassword: true AllowRegister: true diff --git a/docs/docs/apis/proto/admin.md b/docs/docs/apis/proto/admin.md index 6aac51ca79..ba8845d9eb 100644 --- a/docs/docs/apis/proto/admin.md +++ b/docs/docs/apis/proto/admin.md @@ -1431,6 +1431,7 @@ This is an empty request | org_id | string | - | string.min_len: 1
string.max_len: 200
| | user_login_must_be_domain | bool | the username has to end with the domain of it's organisation (uniqueness is organisation based) | | | validate_org_domains | bool | - | | +| smtp_sender_address_matches_instance_domain | bool | - | | @@ -3472,6 +3473,7 @@ This is an empty request | org_id | string | - | string.min_len: 1
string.max_len: 200
| | user_login_must_be_domain | bool | - | | | validate_org_domains | bool | - | | +| smtp_sender_address_matches_instance_domain | bool | - | | @@ -3518,6 +3520,7 @@ This is an empty request | ----- | ---- | ----------- | ----------- | | user_login_must_be_domain | bool | - | | | validate_org_domains | bool | - | | +| smtp_sender_address_matches_instance_domain | bool | - | | diff --git a/docs/docs/apis/proto/policy.md b/docs/docs/apis/proto/policy.md index 3f49b6f1c3..3031ee41cb 100644 --- a/docs/docs/apis/proto/policy.md +++ b/docs/docs/apis/proto/policy.md @@ -19,6 +19,7 @@ title: zitadel/policy.proto | user_login_must_be_domain | bool | - | | | is_default | bool | - | | | validate_org_domains | bool | - | | +| smtp_sender_address_matches_instance_domain | bool | - | | diff --git a/internal/api/grpc/admin/domain_policy.go b/internal/api/grpc/admin/domain_policy.go index 561e06c282..de3352603d 100644 --- a/internal/api/grpc/admin/domain_policy.go +++ b/internal/api/grpc/admin/domain_policy.go @@ -27,7 +27,7 @@ func (s *Server) GetCustomDomainPolicy(ctx context.Context, req *admin_pb.GetCus } func (s *Server) AddCustomDomainPolicy(ctx context.Context, req *admin_pb.AddCustomDomainPolicyRequest) (*admin_pb.AddCustomDomainPolicyResponse, error) { - policy, err := s.command.AddOrgDomainPolicy(ctx, req.OrgId, domainPolicyToDomain(req.UserLoginMustBeDomain, req.ValidateOrgDomains)) + policy, err := s.command.AddOrgDomainPolicy(ctx, req.OrgId, domainPolicyToDomain(req.UserLoginMustBeDomain, req.ValidateOrgDomains, req.SmtpSenderAddressMatchesInstanceDomain)) if err != nil { return nil, err } @@ -76,10 +76,11 @@ func (s *Server) ResetCustomDomainPolicyTo(ctx context.Context, req *admin_pb.Re return nil, nil //TOOD: return data } -func domainPolicyToDomain(userLoginMustBeDomain, validateOrgDomains bool) *domain.DomainPolicy { +func domainPolicyToDomain(userLoginMustBeDomain, validateOrgDomains, smtpSenderAddressMatchesInstanceDomain bool) *domain.DomainPolicy { return &domain.DomainPolicy{ - UserLoginMustBeDomain: userLoginMustBeDomain, - ValidateOrgDomains: validateOrgDomains, + UserLoginMustBeDomain: userLoginMustBeDomain, + ValidateOrgDomains: validateOrgDomains, + SMTPSenderAddressMatchesInstanceDomain: smtpSenderAddressMatchesInstanceDomain, } } @@ -88,8 +89,9 @@ func updateDomainPolicyToDomain(req *admin_pb.UpdateDomainPolicyRequest) *domain // ObjectRoot: models.ObjectRoot{ // // AggreagateID: //TODO: there should only be ONE default // }, - UserLoginMustBeDomain: req.UserLoginMustBeDomain, - ValidateOrgDomains: req.ValidateOrgDomains, + UserLoginMustBeDomain: req.UserLoginMustBeDomain, + ValidateOrgDomains: req.ValidateOrgDomains, + SMTPSenderAddressMatchesInstanceDomain: req.SmtpSenderAddressMatchesInstanceDomain, } } @@ -98,13 +100,14 @@ func updateCustomDomainPolicyToDomain(req *admin_pb.UpdateCustomDomainPolicyRequ ObjectRoot: models.ObjectRoot{ AggregateID: req.OrgId, }, - UserLoginMustBeDomain: req.UserLoginMustBeDomain, - ValidateOrgDomains: req.ValidateOrgDomains, + UserLoginMustBeDomain: req.UserLoginMustBeDomain, + ValidateOrgDomains: req.ValidateOrgDomains, + SMTPSenderAddressMatchesInstanceDomain: req.SmtpSenderAddressMatchesInstanceDomain, } } func (s *Server) AddCustomOrgIAMPolicy(ctx context.Context, req *admin_pb.AddCustomOrgIAMPolicyRequest) (*admin_pb.AddCustomOrgIAMPolicyResponse, error) { - policy, err := s.command.AddOrgDomainPolicy(ctx, req.OrgId, domainPolicyToDomain(req.UserLoginMustBeDomain, true)) + policy, err := s.command.AddOrgDomainPolicy(ctx, req.OrgId, domainPolicyToDomain(req.UserLoginMustBeDomain, true, true)) if err != nil { return nil, err } @@ -163,8 +166,9 @@ func (s *Server) GetCustomOrgIAMPolicy(ctx context.Context, req *admin_pb.GetCus func updateOrgIAMPolicyToDomain(req *admin_pb.UpdateOrgIAMPolicyRequest) *domain.DomainPolicy { return &domain.DomainPolicy{ - UserLoginMustBeDomain: req.UserLoginMustBeDomain, - ValidateOrgDomains: true, + UserLoginMustBeDomain: req.UserLoginMustBeDomain, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, } } @@ -173,7 +177,8 @@ func updateCustomOrgIAMPolicyToDomain(req *admin_pb.UpdateCustomOrgIAMPolicyRequ ObjectRoot: models.ObjectRoot{ AggregateID: req.OrgId, }, - UserLoginMustBeDomain: req.UserLoginMustBeDomain, - ValidateOrgDomains: true, + UserLoginMustBeDomain: req.UserLoginMustBeDomain, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, } } diff --git a/internal/api/grpc/policy/domain_policy.go b/internal/api/grpc/policy/domain_policy.go index 69a7693ccd..1aff4b25d4 100644 --- a/internal/api/grpc/policy/domain_policy.go +++ b/internal/api/grpc/policy/domain_policy.go @@ -8,9 +8,10 @@ import ( func DomainPolicyToPb(policy *query.DomainPolicy) *policy_pb.DomainPolicy { return &policy_pb.DomainPolicy{ - UserLoginMustBeDomain: policy.UserLoginMustBeDomain, - ValidateOrgDomains: policy.ValidateOrgDomains, - IsDefault: policy.IsDefault, + UserLoginMustBeDomain: policy.UserLoginMustBeDomain, + ValidateOrgDomains: policy.ValidateOrgDomains, + SmtpSenderAddressMatchesInstanceDomain: policy.SMTPSenderAddressMatchesInstanceDomain, + IsDefault: policy.IsDefault, Details: object.ToViewDetailsPb( policy.Sequence, policy.CreationDate, diff --git a/internal/command/instance.go b/internal/command/instance.go index 7bcdc6d01a..2048a3b5e6 100644 --- a/internal/command/instance.go +++ b/internal/command/instance.go @@ -59,8 +59,9 @@ type InstanceSetup struct { MaxAgeDays uint64 } DomainPolicy struct { - UserLoginMustBeDomain bool - ValidateOrgDomains bool + UserLoginMustBeDomain bool + ValidateOrgDomains bool + SMTPSenderAddressMatchesInstanceDomain bool } LoginPolicy struct { AllowUsernamePassword bool @@ -199,6 +200,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str instanceAgg, setup.DomainPolicy.UserLoginMustBeDomain, setup.DomainPolicy.ValidateOrgDomains, + setup.DomainPolicy.SMTPSenderAddressMatchesInstanceDomain, ), AddDefaultLoginPolicy( instanceAgg, diff --git a/internal/command/instance_converter.go b/internal/command/instance_converter.go index 82701fca06..428696560e 100644 --- a/internal/command/instance_converter.go +++ b/internal/command/instance_converter.go @@ -69,9 +69,10 @@ func writeModelToMailTemplate(wm *MailTemplateWriteModel) *domain.MailTemplate { func writeModelToDomainPolicy(wm *InstanceDomainPolicyWriteModel) *domain.DomainPolicy { return &domain.DomainPolicy{ - ObjectRoot: writeModelToObjectRoot(wm.PolicyDomainWriteModel.WriteModel), - UserLoginMustBeDomain: wm.UserLoginMustBeDomain, - ValidateOrgDomains: wm.ValidateOrgDomains, + ObjectRoot: writeModelToObjectRoot(wm.PolicyDomainWriteModel.WriteModel), + UserLoginMustBeDomain: wm.UserLoginMustBeDomain, + ValidateOrgDomains: wm.ValidateOrgDomains, + SMTPSenderAddressMatchesInstanceDomain: wm.SMTPSenderAddressMatchesInstanceDomain, } } diff --git a/internal/command/instance_domain_policy.go b/internal/command/instance_domain_policy.go index 480d7103a4..21489fbfab 100644 --- a/internal/command/instance_domain_policy.go +++ b/internal/command/instance_domain_policy.go @@ -11,7 +11,8 @@ import ( func AddDefaultDomainPolicy( a *instance.Aggregate, userLoginMustBeDomain, - validateOrgDomains bool, + validateOrgDomains, + smtpSenderAddressMatchesInstanceDomain bool, ) preparation.Validation { return func() (preparation.CreateCommands, error) { return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) { @@ -20,6 +21,7 @@ func AddDefaultDomainPolicy( instance.NewDomainPolicyAddedEvent(ctx, &a.Aggregate, userLoginMustBeDomain, validateOrgDomains, + smtpSenderAddressMatchesInstanceDomain, ), }, nil }, nil diff --git a/internal/command/instance_policy_domain.go b/internal/command/instance_policy_domain.go index b61050c0f1..8cb761669b 100644 --- a/internal/command/instance_policy_domain.go +++ b/internal/command/instance_policy_domain.go @@ -37,7 +37,7 @@ func (c *Commands) addDefaultDomainPolicy(ctx context.Context, instanceAgg *even if addedPolicy.State == domain.PolicyStateActive { return nil, caos_errs.ThrowAlreadyExists(nil, "INSTANCE-Lk0dS", "Errors.IAM.DomainPolicy.AlreadyExists") } - return iam_repo.NewDomainPolicyAddedEvent(ctx, instanceAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains), nil + return iam_repo.NewDomainPolicyAddedEvent(ctx, instanceAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains, policy.SMTPSenderAddressMatchesInstanceDomain), nil } func (c *Commands) ChangeDefaultDomainPolicy(ctx context.Context, policy *domain.DomainPolicy) (*domain.DomainPolicy, error) { @@ -50,7 +50,7 @@ func (c *Commands) ChangeDefaultDomainPolicy(ctx context.Context, policy *domain } instanceAgg := InstanceAggregateFromWriteModel(&existingPolicy.PolicyDomainWriteModel.WriteModel) - changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, instanceAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains) + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, instanceAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains, policy.SMTPSenderAddressMatchesInstanceDomain) if !hasChanged { return nil, caos_errs.ThrowPreconditionFailed(nil, "INSTANCE-pl9fN", "Errors.IAM.DomainPolicy.NotChanged") } diff --git a/internal/command/instance_policy_domain_model.go b/internal/command/instance_policy_domain_model.go index 2b01256d58..cb6b9ca311 100644 --- a/internal/command/instance_policy_domain_model.go +++ b/internal/command/instance_policy_domain_model.go @@ -56,7 +56,8 @@ func (wm *InstanceDomainPolicyWriteModel) NewChangedEvent( ctx context.Context, aggregate *eventstore.Aggregate, userLoginMustBeDomain, - validateOrgDomain bool) (*instance.DomainPolicyChangedEvent, bool) { + validateOrgDomain, + smtpSenderAddresssMatchesInstanceDomain bool) (*instance.DomainPolicyChangedEvent, bool) { changes := make([]policy.DomainPolicyChanges, 0) if wm.UserLoginMustBeDomain != userLoginMustBeDomain { changes = append(changes, policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain)) @@ -64,6 +65,9 @@ func (wm *InstanceDomainPolicyWriteModel) NewChangedEvent( if wm.ValidateOrgDomains != validateOrgDomain { changes = append(changes, policy.ChangeValidateOrgDomains(validateOrgDomain)) } + if wm.SMTPSenderAddressMatchesInstanceDomain != smtpSenderAddresssMatchesInstanceDomain { + changes = append(changes, policy.ChangeSMTPSenderAddressMatchesInstanceDomain(smtpSenderAddresssMatchesInstanceDomain)) + } if len(changes) == 0 { return nil, false } diff --git a/internal/command/instance_policy_domain_test.go b/internal/command/instance_policy_domain_test.go index 0b91444c0a..64e0db0db7 100644 --- a/internal/command/instance_policy_domain_test.go +++ b/internal/command/instance_policy_domain_test.go @@ -44,6 +44,7 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) { &instance.NewAggregate("INSTANCE").Aggregate, true, true, + true, ), ), ), @@ -52,8 +53,9 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) { args: args{ ctx: context.Background(), policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -74,6 +76,7 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) { &instance.NewAggregate("INSTANCE").Aggregate, true, true, + true, ), ), }, @@ -83,8 +86,9 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) { args: args{ ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -94,8 +98,9 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) { AggregateID: "INSTANCE", ResourceOwner: "INSTANCE", }, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, }, @@ -148,8 +153,9 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { args: args{ ctx: context.Background(), policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -167,6 +173,7 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { &instance.NewAggregate("INSTANCE").Aggregate, true, true, + true, ), ), ), @@ -175,8 +182,9 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { args: args{ ctx: context.Background(), policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -194,13 +202,14 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { &instance.NewAggregate("INSTANCE").Aggregate, true, true, + true, ), ), ), expectPush( []*repository.Event{ eventFromEventPusher( - newDefaultDomainPolicyChangedEvent(context.Background(), false, false), + newDefaultDomainPolicyChangedEvent(context.Background(), false, false, false), ), }, ), @@ -209,8 +218,9 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { args: args{ ctx: context.Background(), policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: false, - ValidateOrgDomains: false, + UserLoginMustBeDomain: false, + ValidateOrgDomains: false, + SMTPSenderAddressMatchesInstanceDomain: false, }, }, res: res{ @@ -219,8 +229,9 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { AggregateID: "INSTANCE", ResourceOwner: "INSTANCE", }, - UserLoginMustBeDomain: false, - ValidateOrgDomains: false, + UserLoginMustBeDomain: false, + ValidateOrgDomains: false, + SMTPSenderAddressMatchesInstanceDomain: false, }, }, }, @@ -244,12 +255,13 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) { } } -func newDefaultDomainPolicyChangedEvent(ctx context.Context, userLoginMustBeDomain, validateOrgDomains bool) *instance.DomainPolicyChangedEvent { +func newDefaultDomainPolicyChangedEvent(ctx context.Context, userLoginMustBeDomain, validateOrgDomains, smtpSenderAddressMatchesInstanceDomain bool) *instance.DomainPolicyChangedEvent { event, _ := instance.NewDomainPolicyChangedEvent(ctx, &instance.NewAggregate("INSTANCE").Aggregate, []policy.DomainPolicyChanges{ policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain), policy.ChangeValidateOrgDomains(validateOrgDomains), + policy.ChangeSMTPSenderAddressMatchesInstanceDomain(smtpSenderAddressMatchesInstanceDomain), }, ) return event diff --git a/internal/command/instance_smtp_config_model.go b/internal/command/instance_smtp_config_model.go index 71cd7b6e47..cb4377539d 100644 --- a/internal/command/instance_smtp_config_model.go +++ b/internal/command/instance_smtp_config_model.go @@ -19,14 +19,39 @@ type InstanceSMTPConfigWriteModel struct { User string Password *crypto.CryptoValue State domain.SMTPConfigState + + domain string + domainState domain.InstanceDomainState + smtpSenderAddressMatchesInstanceDomain bool } -func NewInstanceSMTPConfigWriteModel(instanceID string) *InstanceSMTPConfigWriteModel { +func NewInstanceSMTPConfigWriteModel(instanceID, domain string) *InstanceSMTPConfigWriteModel { return &InstanceSMTPConfigWriteModel{ WriteModel: eventstore.WriteModel{ AggregateID: instanceID, ResourceOwner: instanceID, }, + domain: domain, + } +} + +func (wm *InstanceSMTPConfigWriteModel) AppendEvents(events ...eventstore.Event) { + for _, event := range events { + switch e := event.(type) { + case *instance.DomainAddedEvent: + if e.Domain != wm.domain { + continue + } + wm.WriteModel.AppendEvents(e) + case *instance.DomainRemovedEvent: + if e.Domain != wm.domain { + continue + } + wm.WriteModel.AppendEvents(e) + default: + wm.WriteModel.AppendEvents(e) + } + } } @@ -57,6 +82,16 @@ func (wm *InstanceSMTPConfigWriteModel) Reduce() error { if e.User != nil { wm.User = *e.User } + case *instance.DomainAddedEvent: + wm.domainState = domain.InstanceDomainStateActive + case *instance.DomainRemovedEvent: + wm.domainState = domain.InstanceDomainStateRemoved + case *instance.DomainPolicyAddedEvent: + wm.smtpSenderAddressMatchesInstanceDomain = e.SMTPSenderAddressMatchesInstanceDomain + case *instance.DomainPolicyChangedEvent: + if e.SMTPSenderAddressMatchesInstanceDomain != nil { + wm.smtpSenderAddressMatchesInstanceDomain = *e.SMTPSenderAddressMatchesInstanceDomain + } } } return wm.WriteModel.Reduce() @@ -71,7 +106,11 @@ func (wm *InstanceSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder { EventTypes( instance.SMTPConfigAddedEventType, instance.SMTPConfigChangedEventType, - instance.SMTPConfigPasswordChangedEventType). + instance.SMTPConfigPasswordChangedEventType, + instance.InstanceDomainAddedEventType, + instance.InstanceDomainRemovedEventType, + instance.DomainPolicyAddedEventType, + instance.DomainPolicyChangedEventType). Builder() } diff --git a/internal/command/org_converter.go b/internal/command/org_converter.go index f1ed76e6aa..74672e48f3 100644 --- a/internal/command/org_converter.go +++ b/internal/command/org_converter.go @@ -15,9 +15,10 @@ func orgWriteModelToOrg(wm *OrgWriteModel) *domain.Org { func orgWriteModelToDomainPolicy(wm *OrgDomainPolicyWriteModel) *domain.DomainPolicy { return &domain.DomainPolicy{ - ObjectRoot: writeModelToObjectRoot(wm.PolicyDomainWriteModel.WriteModel), - UserLoginMustBeDomain: wm.UserLoginMustBeDomain, - ValidateOrgDomains: wm.ValidateOrgDomains, + ObjectRoot: writeModelToObjectRoot(wm.PolicyDomainWriteModel.WriteModel), + UserLoginMustBeDomain: wm.UserLoginMustBeDomain, + ValidateOrgDomains: wm.ValidateOrgDomains, + SMTPSenderAddressMatchesInstanceDomain: wm.SMTPSenderAddressMatchesInstanceDomain, } } diff --git a/internal/command/org_domain_test.go b/internal/command/org_domain_test.go index 7770061fe4..b5c041f836 100644 --- a/internal/command/org_domain_test.go +++ b/internal/command/org_domain_test.go @@ -54,7 +54,7 @@ func TestAddDomain(t *testing.T) { domain: "domain", filter: func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) { return []eventstore.Event{ - org.NewDomainPolicyAddedEvent(ctx, &agg.Aggregate, true, true), + org.NewDomainPolicyAddedEvent(ctx, &agg.Aggregate, true, true, true), }, nil }, }, @@ -71,7 +71,7 @@ func TestAddDomain(t *testing.T) { domain: "domain", filter: func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) { return []eventstore.Event{ - org.NewDomainPolicyAddedEvent(ctx, &agg.Aggregate, true, false), + org.NewDomainPolicyAddedEvent(ctx, &agg.Aggregate, true, false, false), }, nil }, }, @@ -1043,7 +1043,7 @@ func TestCommandSide_ValidateOrgDomain(t *testing.T) { eventFromEventPusher( org.NewDomainPolicyAddedEvent(context.Background(), &org.NewAggregate("org2").Aggregate, - false, false))), + false, false, false))), expectPush( []*repository.Event{ eventFromEventPusher(org.NewDomainVerifiedEvent(context.Background(), diff --git a/internal/command/org_policy_domain.go b/internal/command/org_policy_domain.go index 3e57d24985..3b1f1354a3 100644 --- a/internal/command/org_policy_domain.go +++ b/internal/command/org_policy_domain.go @@ -39,7 +39,7 @@ func (c *Commands) addOrgDomainPolicy(ctx context.Context, orgAgg *eventstore.Ag if addedPolicy.State == domain.PolicyStateActive { return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-1M8ds", "Errors.Org.DomainPolicy.AlreadyExists") } - return org.NewDomainPolicyAddedEvent(ctx, orgAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains), nil + return org.NewDomainPolicyAddedEvent(ctx, orgAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains, policy.SMTPSenderAddressMatchesInstanceDomain), nil } func (c *Commands) ChangeOrgDomainPolicy(ctx context.Context, resourceOwner string, policy *domain.DomainPolicy) (*domain.DomainPolicy, error) { @@ -55,7 +55,7 @@ func (c *Commands) ChangeOrgDomainPolicy(ctx context.Context, resourceOwner stri } orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyDomainWriteModel.WriteModel) - changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains) + changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.UserLoginMustBeDomain, policy.ValidateOrgDomains, policy.SMTPSenderAddressMatchesInstanceDomain) if !hasChanged { return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged") } diff --git a/internal/command/org_policy_domain_model.go b/internal/command/org_policy_domain_model.go index 17367a7605..921e7faa66 100644 --- a/internal/command/org_policy_domain_model.go +++ b/internal/command/org_policy_domain_model.go @@ -57,7 +57,8 @@ func (wm *OrgDomainPolicyWriteModel) NewChangedEvent( ctx context.Context, aggregate *eventstore.Aggregate, userLoginMustBeDomain, - validateOrgDomains bool) (*org.DomainPolicyChangedEvent, bool) { + validateOrgDomains, + smtpSenderAddressMatchesInstanceDomain bool) (*org.DomainPolicyChangedEvent, bool) { changes := make([]policy.DomainPolicyChanges, 0) if wm.UserLoginMustBeDomain != userLoginMustBeDomain { changes = append(changes, policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain)) @@ -65,6 +66,9 @@ func (wm *OrgDomainPolicyWriteModel) NewChangedEvent( if wm.ValidateOrgDomains != validateOrgDomains { changes = append(changes, policy.ChangeValidateOrgDomains(validateOrgDomains)) } + if wm.SMTPSenderAddressMatchesInstanceDomain != smtpSenderAddressMatchesInstanceDomain { + changes = append(changes, policy.ChangeSMTPSenderAddressMatchesInstanceDomain(smtpSenderAddressMatchesInstanceDomain)) + } if len(changes) == 0 { return nil, false } diff --git a/internal/command/org_policy_domain_test.go b/internal/command/org_policy_domain_test.go index 479f216fcc..249a0283ac 100644 --- a/internal/command/org_policy_domain_test.go +++ b/internal/command/org_policy_domain_test.go @@ -63,6 +63,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -72,8 +73,9 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) { ctx: context.Background(), orgID: "org1", policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -93,6 +95,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), }, @@ -103,8 +106,9 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) { ctx: context.Background(), orgID: "org1", policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -113,8 +117,9 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) { AggregateID: "org1", ResourceOwner: "org1", }, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, }, @@ -206,6 +211,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -215,8 +221,9 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) { ctx: context.Background(), orgID: "org1", policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, }, }, res: res{ @@ -234,13 +241,14 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), expectPush( []*repository.Event{ eventFromEventPusher( - newDomainPolicyChangedEvent(context.Background(), "org1", false, false), + newDomainPolicyChangedEvent(context.Background(), "org1", false, false, false), ), }, ), @@ -250,8 +258,9 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) { ctx: context.Background(), orgID: "org1", policy: &domain.DomainPolicy{ - UserLoginMustBeDomain: false, - ValidateOrgDomains: false, + UserLoginMustBeDomain: false, + ValidateOrgDomains: false, + SMTPSenderAddressMatchesInstanceDomain: false, }, }, res: res{ @@ -260,8 +269,9 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) { AggregateID: "org1", ResourceOwner: "org1", }, - UserLoginMustBeDomain: false, - ValidateOrgDomains: false, + UserLoginMustBeDomain: false, + ValidateOrgDomains: false, + SMTPSenderAddressMatchesInstanceDomain: false, }, }, }, @@ -344,6 +354,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -384,12 +395,13 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) { } } -func newDomainPolicyChangedEvent(ctx context.Context, orgID string, userLoginMustBeDomain, validateOrgDomains bool) *org.DomainPolicyChangedEvent { +func newDomainPolicyChangedEvent(ctx context.Context, orgID string, userLoginMustBeDomain, validateOrgDomains, smtpSenderAddressMatchesInstanceDomain bool) *org.DomainPolicyChangedEvent { event, _ := org.NewDomainPolicyChangedEvent(ctx, &org.NewAggregate(orgID).Aggregate, []policy.DomainPolicyChanges{ policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain), policy.ChangeValidateOrgDomains(validateOrgDomains), + policy.ChangeSMTPSenderAddressMatchesInstanceDomain(smtpSenderAddressMatchesInstanceDomain), }, ) return event diff --git a/internal/command/policy_org_model.go b/internal/command/policy_org_model.go index d622865903..e989dd6e2f 100644 --- a/internal/command/policy_org_model.go +++ b/internal/command/policy_org_model.go @@ -9,9 +9,10 @@ import ( type PolicyDomainWriteModel struct { eventstore.WriteModel - UserLoginMustBeDomain bool - ValidateOrgDomains bool - State domain.PolicyState + UserLoginMustBeDomain bool + ValidateOrgDomains bool + SMTPSenderAddressMatchesInstanceDomain bool + State domain.PolicyState } func (wm *PolicyDomainWriteModel) Reduce() error { @@ -20,6 +21,7 @@ func (wm *PolicyDomainWriteModel) Reduce() error { case *policy.DomainPolicyAddedEvent: wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain wm.ValidateOrgDomains = e.ValidateOrgDomains + wm.SMTPSenderAddressMatchesInstanceDomain = e.SMTPSenderAddressMatchesInstanceDomain wm.State = domain.PolicyStateActive case *policy.DomainPolicyChangedEvent: if e.UserLoginMustBeDomain != nil { @@ -28,6 +30,9 @@ func (wm *PolicyDomainWriteModel) Reduce() error { if e.ValidateOrgDomains != nil { wm.ValidateOrgDomains = *e.ValidateOrgDomains } + if e.SMTPSenderAddressMatchesInstanceDomain != nil { + wm.SMTPSenderAddressMatchesInstanceDomain = *e.SMTPSenderAddressMatchesInstanceDomain + } } } return wm.WriteModel.Reduce() diff --git a/internal/command/smtp.go b/internal/command/smtp.go index 07720d630a..720a90a1cf 100644 --- a/internal/command/smtp.go +++ b/internal/command/smtp.go @@ -53,7 +53,7 @@ func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *smtp.EmailConfi func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string) (*domain.ObjectDetails, error) { instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID()) - smtpConfigWriteModel, err := getSMTPConfigWriteModel(ctx, c.eventstore.Filter) + smtpConfigWriteModel, err := getSMTPConfigWriteModel(ctx, c.eventstore.Filter, "") if err != nil { return nil, err } @@ -90,13 +90,19 @@ func (c *Commands) prepareAddSMTPConfig(a *instance.Aggregate, from, name, host, return nil, errors.ThrowInvalidArgument(nil, "INST-SF3g1", "Errors.Invalid.Argument") } return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) { - writeModel, err := getSMTPConfigWriteModel(ctx, filter) + fromSplitted := strings.Split(from, "@") + senderDomain := fromSplitted[len(fromSplitted)-1] + writeModel, err := getSMTPConfigWriteModel(ctx, filter, senderDomain) if err != nil { return nil, err } if writeModel.State == domain.SMTPConfigStateActive { return nil, errors.ThrowAlreadyExists(nil, "INST-W3VS2", "Errors.SMTPConfig.AlreadyExists") } + err = checkSenderAddress(writeModel) + if err != nil { + return nil, err + } var smtpPassword *crypto.CryptoValue if password != nil { smtpPassword, err = crypto.Encrypt(password, c.smtpEncryption) @@ -128,14 +134,21 @@ func (c *Commands) prepareChangeSMTPConfig(a *instance.Aggregate, from, name, ho if host = strings.TrimSpace(host); host == "" { return nil, errors.ThrowInvalidArgument(nil, "INST-VDwvq", "Errors.Invalid.Argument") } + return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) { - writeModel, err := getSMTPConfigWriteModel(ctx, filter) + fromSplitted := strings.Split(from, "@") + senderDomain := fromSplitted[len(fromSplitted)-1] + writeModel, err := getSMTPConfigWriteModel(ctx, filter, senderDomain) if err != nil { return nil, err } if writeModel.State != domain.SMTPConfigStateActive { return nil, errors.ThrowNotFound(nil, "INST-Svq1a", "Errors.SMTPConfig.NotFound") } + err = checkSenderAddress(writeModel) + if err != nil { + return nil, err + } changedEvent, hasChanged, err := writeModel.NewChangedEvent( ctx, &a.Aggregate, @@ -155,8 +168,18 @@ func (c *Commands) prepareChangeSMTPConfig(a *instance.Aggregate, from, name, ho } } -func getSMTPConfigWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer) (_ *InstanceSMTPConfigWriteModel, err error) { - writeModel := NewInstanceSMTPConfigWriteModel(authz.GetInstance(ctx).InstanceID()) +func checkSenderAddress(writeModel *InstanceSMTPConfigWriteModel) error { + if !writeModel.smtpSenderAddressMatchesInstanceDomain { + return nil + } + if !writeModel.domainState.Exists() { + return errors.ThrowInvalidArgument(nil, "INST-83nl8", "Errors.SMTPConfig.SenderAdressNotCustomDomain") + } + return nil +} + +func getSMTPConfigWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer, domain string) (_ *InstanceSMTPConfigWriteModel, err error) { + writeModel := NewInstanceSMTPConfigWriteModel(authz.GetInstance(ctx).InstanceID(), domain) events, err := filter(ctx, writeModel.Query()) if err != nil { return nil, err diff --git a/internal/command/smtp_test.go b/internal/command/smtp_test.go index f0766e8cad..6158ea90ec 100644 --- a/internal/command/smtp_test.go +++ b/internal/command/smtp_test.go @@ -36,17 +36,64 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { args args res res }{ + { + name: "smtp config, custom domain not existing", + fields: fields{ + eventstore: eventstoreExpect( + t, + expectFilter( + eventFromEventPusher( + instance.NewDomainPolicyAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, + true, + true, + ), + ), + ), + ), + }, + args: args{ + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), + smtp: &smtp.EmailConfig{ + Tls: true, + From: "from@domain.ch", + FromName: "name", + SMTP: smtp.SMTP{ + Host: "host", + User: "user", + Password: "password", + }, + }, + }, + res: res{ + err: caos_errs.IsErrorInvalidArgument, + }, + }, { name: "smtp config, error already exists", fields: fields{ eventstore: eventstoreExpect( t, expectFilter( + eventFromEventPusher( + instance.NewDomainAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + "domain.ch", + false, + ), + ), + eventFromEventPusher( + instance.NewDomainPolicyAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, true, false, + ), + ), eventFromEventPusher( instance.NewSMTPConfigAddedEvent(context.Background(), &instance.NewAggregate("INSTANCE").Aggregate, true, - "from", + "from@domain.ch", "name", "host", "user", @@ -60,7 +107,7 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: true, - From: "from", + From: "from@domain.ch", FromName: "name", SMTP: smtp.SMTP{ Host: "host", @@ -78,7 +125,21 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { fields: fields{ eventstore: eventstoreExpect( t, - expectFilter(), + expectFilter( + eventFromEventPusher( + instance.NewDomainAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + "domain.ch", + false, + ), + ), + eventFromEventPusher( + instance.NewDomainPolicyAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, true, false, + ), + ), + ), expectPush( []*repository.Event{ eventFromEventPusherWithInstanceID( @@ -87,7 +148,7 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { context.Background(), &instance.NewAggregate("INSTANCE").Aggregate, true, - "from", + "from@domain.ch", "name", "host", "user", @@ -108,7 +169,7 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) { ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: true, - From: "from", + From: "from@domain.ch", FromName: "name", SMTP: smtp.SMTP{ Host: "host", @@ -189,7 +250,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: true, - From: "from", + From: "from@domain.ch", FromName: "name", SMTP: smtp.SMTP{ Host: "host", @@ -202,17 +263,30 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { }, }, { - name: "no changes, precondition error", + name: "smtp domain not matched", fields: fields{ eventstore: eventstoreExpect( t, expectFilter( + eventFromEventPusher( + instance.NewDomainAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + "domain.ch", + false, + ), + ), + eventFromEventPusher( + instance.NewDomainPolicyAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, true, true, + ), + ), eventFromEventPusher( instance.NewSMTPConfigAddedEvent( context.Background(), &instance.NewAggregate("INSTANCE").Aggregate, true, - "from", + "from@domain.ch", "name", "host", "user", @@ -226,7 +300,57 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: true, - From: "from", + From: "from@wrongdomain.ch", + FromName: "name", + SMTP: smtp.SMTP{ + Host: "host", + User: "user", + }, + }, + }, + res: res{ + err: caos_errs.IsErrorInvalidArgument, + }, + }, + { + name: "no changes, precondition error", + fields: fields{ + eventstore: eventstoreExpect( + t, + expectFilter( + eventFromEventPusher( + instance.NewDomainAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + "domain.ch", + false, + ), + ), + eventFromEventPusher( + instance.NewDomainPolicyAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, true, true, + ), + ), + eventFromEventPusher( + instance.NewSMTPConfigAddedEvent( + context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, + "from@domain.ch", + "name", + "host", + "user", + &crypto.CryptoValue{}, + ), + ), + ), + ), + }, + args: args{ + ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), + smtp: &smtp.EmailConfig{ + Tls: true, + From: "from@domain.ch", FromName: "name", SMTP: smtp.SMTP{ Host: "host", @@ -244,12 +368,25 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { eventstore: eventstoreExpect( t, expectFilter( + eventFromEventPusher( + instance.NewDomainAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + "domain.ch", + false, + ), + ), + eventFromEventPusher( + instance.NewDomainPolicyAddedEvent(context.Background(), + &instance.NewAggregate("INSTANCE").Aggregate, + true, true, true, + ), + ), eventFromEventPusher( instance.NewSMTPConfigAddedEvent( context.Background(), &instance.NewAggregate("INSTANCE").Aggregate, true, - "from", + "from@domain.ch", "name", "host", "user", @@ -264,7 +401,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { newSMTPConfigChangedEvent( context.Background(), false, - "from2", + "from2@domain.ch", "name2", "host2", "user2", @@ -278,7 +415,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) { ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), smtp: &smtp.EmailConfig{ Tls: false, - From: "from2", + From: "from2@domain.ch", FromName: "name2", SMTP: smtp.SMTP{ Host: "host2", diff --git a/internal/command/user_domain_policy_test.go b/internal/command/user_domain_policy_test.go index 18c9ba9f3b..d8f7e0cd35 100644 --- a/internal/command/user_domain_policy_test.go +++ b/internal/command/user_domain_policy_test.go @@ -54,6 +54,7 @@ func Test_customDomainPolicy(t *testing.T) { &org.NewAggregate("id").Aggregate, true, true, + true, ), }, nil }, @@ -64,9 +65,10 @@ func Test_customDomainPolicy(t *testing.T) { ResourceOwner: "id", Events: []eventstore.Event{}, }, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, - State: domain.PolicyStateActive, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, + State: domain.PolicyStateActive, }, wantErr: false, }, @@ -125,6 +127,7 @@ func Test_defaultDomainPolicy(t *testing.T) { &instance.NewAggregate("INSTANCE").Aggregate, true, true, + true, ), }, nil }, @@ -135,9 +138,10 @@ func Test_defaultDomainPolicy(t *testing.T) { ResourceOwner: "INSTANCE", Events: []eventstore.Event{}, }, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, - State: domain.PolicyStateActive, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, + State: domain.PolicyStateActive, }, wantErr: false, }, @@ -186,6 +190,7 @@ func Test_DomainPolicy(t *testing.T) { &org.NewAggregate("id").Aggregate, true, true, + true, ), }, nil }, @@ -196,9 +201,10 @@ func Test_DomainPolicy(t *testing.T) { ResourceOwner: "id", Events: []eventstore.Event{}, }, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, - State: domain.PolicyStateActive, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, + State: domain.PolicyStateActive, }, wantErr: false, }, @@ -231,6 +237,7 @@ func Test_DomainPolicy(t *testing.T) { &instance.NewAggregate("INSTANCE").Aggregate, true, true, + true, ), }, nil }). @@ -242,9 +249,10 @@ func Test_DomainPolicy(t *testing.T) { ResourceOwner: "INSTANCE", Events: []eventstore.Event{}, }, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, - State: domain.PolicyStateActive, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, + State: domain.PolicyStateActive, }, wantErr: false, }, diff --git a/internal/command/user_human_otp_test.go b/internal/command/user_human_otp_test.go index 047919083c..c894a63f6c 100644 --- a/internal/command/user_human_otp_test.go +++ b/internal/command/user_human_otp_test.go @@ -180,6 +180,7 @@ func TestCommandSide_AddHumanOTP(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), diff --git a/internal/command/user_human_test.go b/internal/command/user_human_test.go index f3cd304a9b..e3fe001947 100644 --- a/internal/command/user_human_test.go +++ b/internal/command/user_human_test.go @@ -112,6 +112,7 @@ func TestCommandSide_AddHuman(t *testing.T) { &userAgg.Aggregate, true, true, + true, ), ), ), @@ -169,6 +170,7 @@ func TestCommandSide_AddHuman(t *testing.T) { &userAgg.Aggregate, true, true, + true, ), ), ), @@ -285,6 +287,7 @@ func TestCommandSide_AddHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -402,6 +405,7 @@ func TestCommandSide_AddHuman(t *testing.T) { &userAgg.Aggregate, true, true, + true, ), ), ), @@ -499,6 +503,7 @@ func TestCommandSide_AddHuman(t *testing.T) { &userAgg.Aggregate, true, true, + true, ), ), ), @@ -583,6 +588,7 @@ func TestCommandSide_AddHuman(t *testing.T) { &userAgg.Aggregate, true, true, + true, ), ), ), @@ -800,6 +806,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -836,6 +843,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -878,6 +886,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -968,6 +977,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1052,6 +1062,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1158,6 +1169,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1268,6 +1280,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1374,6 +1387,7 @@ func TestCommandSide_ImportHuman(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1577,6 +1591,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -1616,6 +1631,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -1663,6 +1679,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -1728,6 +1745,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -1793,6 +1811,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, false, true, + true, ), ), ), @@ -1875,6 +1894,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, false, true, + true, ), ), ), @@ -2015,6 +2035,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -2123,6 +2144,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &user.NewAggregate("org1", "org1").Aggregate, true, true, + true, ), ), ), @@ -2225,6 +2247,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -2349,6 +2372,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) { &org.NewAggregate("org1").Aggregate, true, true, + true, ), ), ), @@ -2923,6 +2947,7 @@ func TestAddHumanCommand(t *testing.T) { &org.NewAggregate("id").Aggregate, true, true, + true, ), }, nil }). @@ -2967,6 +2992,7 @@ func TestAddHumanCommand(t *testing.T) { &org.NewAggregate("id").Aggregate, true, true, + true, ), }, nil }). diff --git a/internal/command/user_machine_test.go b/internal/command/user_machine_test.go index 8df767f3ee..23e15859eb 100644 --- a/internal/command/user_machine_test.go +++ b/internal/command/user_machine_test.go @@ -87,6 +87,7 @@ func TestCommandSide_AddMachine(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, false, true, + true, ), ), ), @@ -115,6 +116,7 @@ func TestCommandSide_AddMachine(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), diff --git a/internal/command/user_test.go b/internal/command/user_test.go index b31974597f..b92f52facd 100644 --- a/internal/command/user_test.go +++ b/internal/command/user_test.go @@ -209,6 +209,7 @@ func TestCommandSide_UsernameChange(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -252,6 +253,7 @@ func TestCommandSide_UsernameChange(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1036,6 +1038,7 @@ func TestCommandSide_RemoveUser(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1101,6 +1104,7 @@ func TestCommandSide_RemoveUser(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), @@ -1159,6 +1163,7 @@ func TestCommandSide_RemoveUser(t *testing.T) { &user.NewAggregate("user1", "org1").Aggregate, true, true, + true, ), ), ), diff --git a/internal/domain/policy_domain.go b/internal/domain/policy_domain.go index cba2e50514..742908248f 100644 --- a/internal/domain/policy_domain.go +++ b/internal/domain/policy_domain.go @@ -7,7 +7,8 @@ import ( type DomainPolicy struct { models.ObjectRoot - UserLoginMustBeDomain bool - ValidateOrgDomains bool - Default bool + UserLoginMustBeDomain bool + ValidateOrgDomains bool + SMTPSenderAddressMatchesInstanceDomain bool + Default bool } diff --git a/internal/query/org_iam_policy.go b/internal/query/org_iam_policy.go index 6c9ec877ea..0a6e4c3bd9 100644 --- a/internal/query/org_iam_policy.go +++ b/internal/query/org_iam_policy.go @@ -23,8 +23,9 @@ type DomainPolicy struct { ResourceOwner string State domain.PolicyState - UserLoginMustBeDomain bool - ValidateOrgDomains bool + UserLoginMustBeDomain bool + ValidateOrgDomains bool + SMTPSenderAddressMatchesInstanceDomain bool IsDefault bool } @@ -65,6 +66,10 @@ var ( name: projection.DomainPolicyValidateOrgDomainsCol, table: domainPolicyTable, } + DomainPolicyColSMTPSenderAddressMatchesInstanceDomain = Column{ + name: projection.DomainPolicySMTPSenderAddressMatchesInstanceDomainCol, + table: domainPolicyTable, + } DomainPolicyColIsDefault = Column{ name: projection.DomainPolicyIsDefaultCol, table: domainPolicyTable, @@ -126,6 +131,7 @@ func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy DomainPolicyColResourceOwner.identifier(), DomainPolicyColUserLoginMustBeDomain.identifier(), DomainPolicyColValidateOrgDomains.identifier(), + DomainPolicyColSMTPSenderAddressMatchesInstanceDomain.identifier(), DomainPolicyColIsDefault.identifier(), DomainPolicyColState.identifier(), ). @@ -140,6 +146,7 @@ func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy &policy.ResourceOwner, &policy.UserLoginMustBeDomain, &policy.ValidateOrgDomains, + &policy.SMTPSenderAddressMatchesInstanceDomain, &policy.IsDefault, &policy.State, ) diff --git a/internal/query/org_iam_policy_test.go b/internal/query/org_iam_policy_test.go index 1b2a8d24d1..c396536383 100644 --- a/internal/query/org_iam_policy_test.go +++ b/internal/query/org_iam_policy_test.go @@ -35,6 +35,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { ` projections.domain_policies.resource_owner,`+ ` projections.domain_policies.user_login_must_be_domain,`+ ` projections.domain_policies.validate_org_domains,`+ + ` projections.domain_policies.smtp_sender_address_matches_instance_domain,`+ ` projections.domain_policies.is_default,`+ ` projections.domain_policies.state`+ ` FROM projections.domain_policies`), @@ -62,6 +63,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { ` projections.domain_policies.resource_owner,`+ ` projections.domain_policies.user_login_must_be_domain,`+ ` projections.domain_policies.validate_org_domains,`+ + ` projections.domain_policies.smtp_sender_address_matches_instance_domain,`+ ` projections.domain_policies.is_default,`+ ` projections.domain_policies.state`+ ` FROM projections.domain_policies`), @@ -73,6 +75,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { "resource_owner", "user_login_must_be_domain", "validate_org_domains", + "smtp_sender_address_matches_instance_domain", "is_default", "state", }, @@ -85,20 +88,22 @@ func Test_DomainPolicyPrepares(t *testing.T) { true, true, true, + true, domain.PolicyStateActive, }, ), }, object: &DomainPolicy{ - ID: "pol-id", - CreationDate: testNow, - ChangeDate: testNow, - Sequence: 20211109, - ResourceOwner: "ro", - State: domain.PolicyStateActive, - UserLoginMustBeDomain: true, - ValidateOrgDomains: true, - IsDefault: true, + ID: "pol-id", + CreationDate: testNow, + ChangeDate: testNow, + Sequence: 20211109, + ResourceOwner: "ro", + State: domain.PolicyStateActive, + UserLoginMustBeDomain: true, + ValidateOrgDomains: true, + SMTPSenderAddressMatchesInstanceDomain: true, + IsDefault: true, }, }, { @@ -113,6 +118,7 @@ func Test_DomainPolicyPrepares(t *testing.T) { ` projections.domain_policies.resource_owner,`+ ` projections.domain_policies.user_login_must_be_domain,`+ ` projections.domain_policies.validate_org_domains,`+ + ` projections.domain_policies.smtp_sender_address_matches_instance_domain,`+ ` projections.domain_policies.is_default,`+ ` projections.domain_policies.state`+ ` FROM projections.domain_policies`), diff --git a/internal/query/projection/domain_policy.go b/internal/query/projection/domain_policy.go index b9a6930826..86c954bf4f 100644 --- a/internal/query/projection/domain_policy.go +++ b/internal/query/projection/domain_policy.go @@ -16,16 +16,17 @@ import ( const ( DomainPolicyTable = "projections.domain_policies" - DomainPolicyIDCol = "id" - DomainPolicyCreationDateCol = "creation_date" - DomainPolicyChangeDateCol = "change_date" - DomainPolicySequenceCol = "sequence" - DomainPolicyStateCol = "state" - DomainPolicyUserLoginMustBeDomainCol = "user_login_must_be_domain" - DomainPolicyValidateOrgDomainsCol = "validate_org_domains" - DomainPolicyIsDefaultCol = "is_default" - DomainPolicyResourceOwnerCol = "resource_owner" - DomainPolicyInstanceIDCol = "instance_id" + DomainPolicyIDCol = "id" + DomainPolicyCreationDateCol = "creation_date" + DomainPolicyChangeDateCol = "change_date" + DomainPolicySequenceCol = "sequence" + DomainPolicyStateCol = "state" + DomainPolicyUserLoginMustBeDomainCol = "user_login_must_be_domain" + DomainPolicyValidateOrgDomainsCol = "validate_org_domains" + DomainPolicySMTPSenderAddressMatchesInstanceDomainCol = "smtp_sender_address_matches_instance_domain" + DomainPolicyIsDefaultCol = "is_default" + DomainPolicyResourceOwnerCol = "resource_owner" + DomainPolicyInstanceIDCol = "instance_id" ) type DomainPolicyProjection struct { @@ -45,6 +46,7 @@ func NewDomainPolicyProjection(ctx context.Context, config crdb.StatementHandler crdb.NewColumn(DomainPolicyStateCol, crdb.ColumnTypeEnum), crdb.NewColumn(DomainPolicyUserLoginMustBeDomainCol, crdb.ColumnTypeBool), crdb.NewColumn(DomainPolicyValidateOrgDomainsCol, crdb.ColumnTypeBool), + crdb.NewColumn(DomainPolicySMTPSenderAddressMatchesInstanceDomainCol, crdb.ColumnTypeBool), crdb.NewColumn(DomainPolicyIsDefaultCol, crdb.ColumnTypeBool, crdb.Default(false)), crdb.NewColumn(DomainPolicyResourceOwnerCol, crdb.ColumnTypeText), crdb.NewColumn(DomainPolicyInstanceIDCol, crdb.ColumnTypeText), @@ -114,6 +116,7 @@ func (p *DomainPolicyProjection) reduceAdded(event eventstore.Event) (*handler.S handler.NewCol(DomainPolicyStateCol, domain.PolicyStateActive), handler.NewCol(DomainPolicyUserLoginMustBeDomainCol, policyEvent.UserLoginMustBeDomain), handler.NewCol(DomainPolicyValidateOrgDomainsCol, policyEvent.ValidateOrgDomains), + handler.NewCol(DomainPolicySMTPSenderAddressMatchesInstanceDomainCol, policyEvent.SMTPSenderAddressMatchesInstanceDomain), handler.NewCol(DomainPolicyIsDefaultCol, isDefault), handler.NewCol(DomainPolicyResourceOwnerCol, policyEvent.Aggregate().ResourceOwner), handler.NewCol(DomainPolicyInstanceIDCol, policyEvent.Aggregate().InstanceID), @@ -140,6 +143,9 @@ func (p *DomainPolicyProjection) reduceChanged(event eventstore.Event) (*handler if policyEvent.ValidateOrgDomains != nil { cols = append(cols, handler.NewCol(DomainPolicyValidateOrgDomainsCol, *policyEvent.ValidateOrgDomains)) } + if policyEvent.SMTPSenderAddressMatchesInstanceDomain != nil { + cols = append(cols, handler.NewCol(DomainPolicySMTPSenderAddressMatchesInstanceDomainCol, *policyEvent.SMTPSenderAddressMatchesInstanceDomain)) + } return crdb.NewUpdateStatement( &policyEvent, cols, diff --git a/internal/query/projection/domain_policy_test.go b/internal/query/projection/domain_policy_test.go index 2ca4df4448..83774c4ee9 100644 --- a/internal/query/projection/domain_policy_test.go +++ b/internal/query/projection/domain_policy_test.go @@ -30,7 +30,8 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { org.AggregateType, []byte(`{ "userLoginMustBeDomain": true, - "validateOrgDomains": true + "validateOrgDomains": true, + "smtpSenderAddressMatchesInstanceDomain": true }`), ), org.DomainPolicyAddedEventMapper), }, @@ -43,7 +44,7 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.domain_policies (creation_date, change_date, sequence, id, state, user_login_must_be_domain, validate_org_domains, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.domain_policies (creation_date, change_date, sequence, id, state, user_login_must_be_domain, validate_org_domains, smtp_sender_address_matches_instance_domain, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", expectedArgs: []interface{}{ anyArg{}, anyArg{}, @@ -52,6 +53,7 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { domain.PolicyStateActive, true, true, + true, false, "ro-id", "instance-id", @@ -70,7 +72,8 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { org.AggregateType, []byte(`{ "userLoginMustBeDomain": true, - "validateOrgDomains": true + "validateOrgDomains": true, + "smtpSenderAddressMatchesInstanceDomain": true }`), ), org.DomainPolicyChangedEventMapper), }, @@ -82,12 +85,13 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.domain_policies SET (change_date, sequence, user_login_must_be_domain, validate_org_domains) = ($1, $2, $3, $4) WHERE (id = $5)", + expectedStmt: "UPDATE projections.domain_policies SET (change_date, sequence, user_login_must_be_domain, validate_org_domains, smtp_sender_address_matches_instance_domain) = ($1, $2, $3, $4, $5) WHERE (id = $6)", expectedArgs: []interface{}{ anyArg{}, uint64(15), true, true, + true, "agg-id", }, }, @@ -131,7 +135,8 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { instance.AggregateType, []byte(`{ "userLoginMustBeDomain": true, - "validateOrgDomains": true + "validateOrgDomains": true, + "smtpSenderAddressMatchesInstanceDomain": true }`), ), instance.DomainPolicyAddedEventMapper), }, @@ -143,7 +148,7 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "INSERT INTO projections.domain_policies (creation_date, change_date, sequence, id, state, user_login_must_be_domain, validate_org_domains, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", + expectedStmt: "INSERT INTO projections.domain_policies (creation_date, change_date, sequence, id, state, user_login_must_be_domain, validate_org_domains, smtp_sender_address_matches_instance_domain, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", expectedArgs: []interface{}{ anyArg{}, anyArg{}, @@ -153,6 +158,7 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { true, true, true, + true, "ro-id", "instance-id", }, @@ -170,7 +176,8 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { instance.AggregateType, []byte(`{ "userLoginMustBeDomain": true, - "validateOrgDomains": true + "validateOrgDomains": true, + "smtpSenderAddressMatchesInstanceDomain": true }`), ), instance.DomainPolicyChangedEventMapper), }, @@ -182,12 +189,13 @@ func TestDomainPolicyProjection_reduces(t *testing.T) { executer: &testExecuter{ executions: []execution{ { - expectedStmt: "UPDATE projections.domain_policies SET (change_date, sequence, user_login_must_be_domain, validate_org_domains) = ($1, $2, $3, $4) WHERE (id = $5)", + expectedStmt: "UPDATE projections.domain_policies SET (change_date, sequence, user_login_must_be_domain, validate_org_domains, smtp_sender_address_matches_instance_domain) = ($1, $2, $3, $4, $5) WHERE (id = $6)", expectedArgs: []interface{}{ anyArg{}, uint64(15), true, true, + true, "agg-id", }, }, diff --git a/internal/repository/instance/domain.go b/internal/repository/instance/domain.go index 807ed5b925..b1a4fa01bd 100644 --- a/internal/repository/instance/domain.go +++ b/internal/repository/instance/domain.go @@ -18,17 +18,17 @@ const ( InstanceDomainRemovedEventType = domainEventPrefix + "removed" ) -func NewAddInstanceDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint { +func NewAddInstanceDomainUniqueConstraint(domain string) *eventstore.EventUniqueConstraint { return eventstore.NewAddGlobalEventUniqueConstraint( UniqueInstanceDomain, - orgDomain, + domain, "Errors.Instance.Domain.AlreadyExists") } -func NewRemoveInstanceDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint { +func NewRemoveInstanceDomainUniqueConstraint(domain string) *eventstore.EventUniqueConstraint { return eventstore.NewRemoveGlobalEventUniqueConstraint( UniqueInstanceDomain, - orgDomain) + domain) } type DomainAddedEvent struct { @@ -59,15 +59,15 @@ func NewDomainAddedEvent(ctx context.Context, aggregate *eventstore.Aggregate, d } func DomainAddedEventMapper(event *repository.Event) (eventstore.Event, error) { - orgDomainAdded := &DomainAddedEvent{ + domainAdded := &DomainAddedEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), } - err := json.Unmarshal(event.Data, orgDomainAdded) + err := json.Unmarshal(event.Data, domainAdded) if err != nil { return nil, errors.ThrowInternal(err, "INSTANCE-3noij", "unable to unmarshal instance domain added") } - return orgDomainAdded, nil + return domainAdded, nil } type DomainPrimarySetEvent struct { @@ -96,15 +96,15 @@ func NewDomainPrimarySetEvent(ctx context.Context, aggregate *eventstore.Aggrega } func DomainPrimarySetEventMapper(event *repository.Event) (eventstore.Event, error) { - orgDomainAdded := &DomainPrimarySetEvent{ + domainAdded := &DomainPrimarySetEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), } - err := json.Unmarshal(event.Data, orgDomainAdded) + err := json.Unmarshal(event.Data, domainAdded) if err != nil { return nil, errors.ThrowInternal(err, "INSTANCE-29jöF", "unable to unmarshal instance domain added") } - return orgDomainAdded, nil + return domainAdded, nil } type DomainRemovedEvent struct { @@ -133,13 +133,13 @@ func NewDomainRemovedEvent(ctx context.Context, aggregate *eventstore.Aggregate, } func DomainRemovedEventMapper(event *repository.Event) (eventstore.Event, error) { - orgDomainRemoved := &DomainRemovedEvent{ + domainRemoved := &DomainRemovedEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), } - err := json.Unmarshal(event.Data, orgDomainRemoved) + err := json.Unmarshal(event.Data, domainRemoved) if err != nil { return nil, errors.ThrowInternal(err, "INSTANCE-BngB2", "unable to unmarshal instance domain removed") } - return orgDomainRemoved, nil + return domainRemoved, nil } diff --git a/internal/repository/instance/policy_domain.go b/internal/repository/instance/policy_domain.go index 861c840128..b4d6bb36c2 100644 --- a/internal/repository/instance/policy_domain.go +++ b/internal/repository/instance/policy_domain.go @@ -22,7 +22,8 @@ func NewDomainPolicyAddedEvent( ctx context.Context, aggregate *eventstore.Aggregate, userLoginMustBeDomain, - validateOrgDomain bool, + validateOrgDomain, + smtpSenderAddressMatchesInstanceDomain bool, ) *DomainPolicyAddedEvent { return &DomainPolicyAddedEvent{ DomainPolicyAddedEvent: *policy.NewDomainPolicyAddedEvent( @@ -32,6 +33,7 @@ func NewDomainPolicyAddedEvent( DomainPolicyAddedEventType), userLoginMustBeDomain, validateOrgDomain, + smtpSenderAddressMatchesInstanceDomain, ), } } diff --git a/internal/repository/org/policy_domain.go b/internal/repository/org/policy_domain.go index b560b97c3f..18191533c2 100644 --- a/internal/repository/org/policy_domain.go +++ b/internal/repository/org/policy_domain.go @@ -23,7 +23,8 @@ func NewDomainPolicyAddedEvent( ctx context.Context, aggregate *eventstore.Aggregate, userLoginMustBeDomain, - validateOrgDomains bool, + validateOrgDomains, + smtpSenderAddressMatchesInstanceDomain bool, ) *DomainPolicyAddedEvent { return &DomainPolicyAddedEvent{ DomainPolicyAddedEvent: *policy.NewDomainPolicyAddedEvent( @@ -33,6 +34,7 @@ func NewDomainPolicyAddedEvent( DomainPolicyAddedEventType), userLoginMustBeDomain, validateOrgDomains, + smtpSenderAddressMatchesInstanceDomain, ), } } diff --git a/internal/repository/policy/policy_domain.go b/internal/repository/policy/policy_domain.go index b855bfdc1f..6802cd1c39 100644 --- a/internal/repository/policy/policy_domain.go +++ b/internal/repository/policy/policy_domain.go @@ -19,8 +19,9 @@ const ( type DomainPolicyAddedEvent struct { eventstore.BaseEvent `json:"-"` - UserLoginMustBeDomain bool `json:"userLoginMustBeDomain,omitempty"` - ValidateOrgDomains bool `json:"validateOrgDomains,omitempty"` + UserLoginMustBeDomain bool `json:"userLoginMustBeDomain,omitempty"` + ValidateOrgDomains bool `json:"validateOrgDomains,omitempty"` + SMTPSenderAddressMatchesInstanceDomain bool `json:"smtpSenderAddressMatchesInstanceDomain,omitempty"` } func (e *DomainPolicyAddedEvent) Data() interface{} { @@ -34,13 +35,15 @@ func (e *DomainPolicyAddedEvent) UniqueConstraints() []*eventstore.EventUniqueCo func NewDomainPolicyAddedEvent( base *eventstore.BaseEvent, userLoginMustBeDomain, - validateOrgDomains bool, + validateOrgDomains, + smtpSenderAddressMatchesInstanceDomain bool, ) *DomainPolicyAddedEvent { return &DomainPolicyAddedEvent{ - BaseEvent: *base, - UserLoginMustBeDomain: userLoginMustBeDomain, - ValidateOrgDomains: validateOrgDomains, + BaseEvent: *base, + UserLoginMustBeDomain: userLoginMustBeDomain, + ValidateOrgDomains: validateOrgDomains, + SMTPSenderAddressMatchesInstanceDomain: smtpSenderAddressMatchesInstanceDomain, } } @@ -60,8 +63,9 @@ func DomainPolicyAddedEventMapper(event *repository.Event) (eventstore.Event, er type DomainPolicyChangedEvent struct { eventstore.BaseEvent `json:"-"` - UserLoginMustBeDomain *bool `json:"userLoginMustBeDomain,omitempty"` - ValidateOrgDomains *bool `json:"validateOrgDomains,omitempty"` + UserLoginMustBeDomain *bool `json:"userLoginMustBeDomain,omitempty"` + ValidateOrgDomains *bool `json:"validateOrgDomains,omitempty"` + SMTPSenderAddressMatchesInstanceDomain *bool `json:"smtpSenderAddressMatchesInstanceDomain,omitempty"` } func (e *DomainPolicyChangedEvent) Data() interface{} { @@ -102,6 +106,12 @@ func ChangeValidateOrgDomains(validateOrgDomain bool) func(*DomainPolicyChangedE } } +func ChangeSMTPSenderAddressMatchesInstanceDomain(smtpSenderAddressMatchesInstanceDomain bool) func(*DomainPolicyChangedEvent) { + return func(e *DomainPolicyChangedEvent) { + e.SMTPSenderAddressMatchesInstanceDomain = &smtpSenderAddressMatchesInstanceDomain + } +} + func DomainPolicyChangedEventMapper(event *repository.Event) (eventstore.Event, error) { e := &DomainPolicyChangedEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), diff --git a/internal/static/i18n/de.yaml b/internal/static/i18n/de.yaml index c4db709909..81264ed6fe 100644 --- a/internal/static/i18n/de.yaml +++ b/internal/static/i18n/de.yaml @@ -44,6 +44,7 @@ Errors: SMTPConfig: NotFound: SMTP Konfiguration nicht gefunden AlreadyExists: SMTP Konfiguration existiert bereits + SenderAdressNotCustomDomain: Die Sender Adresse muss als Custom Domain auf der Instanz registriert sein. Notification: NoDomain: Keine Domäne für Nachricht gefunden User: diff --git a/internal/static/i18n/en.yaml b/internal/static/i18n/en.yaml index e5033029bf..1202a59bb8 100644 --- a/internal/static/i18n/en.yaml +++ b/internal/static/i18n/en.yaml @@ -44,6 +44,7 @@ Errors: SMTPConfig: NotFound: SMTP configuration not found AlreadyExists: SMTP configuration already exists + SenderAdressNotCustomDomain: The sender adress must be configured as custom domain on the instance. Notification: NoDomain: No Domain found for message User: diff --git a/internal/static/i18n/it.yaml b/internal/static/i18n/it.yaml index c55375a74e..ce3ef52e93 100644 --- a/internal/static/i18n/it.yaml +++ b/internal/static/i18n/it.yaml @@ -44,6 +44,7 @@ Errors: SMTPConfig: NotFound: Configurazione SMTP non trovata AlreadyExists: La configurazione SMTP esiste già + SenderAdressNotCustomDomain: L'indirizzo del mittente deve essere configurato come dominio personalizzato sull'istanza. Notification: NoDomain: Nessun dominio trovato per il messaggio User: diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto index d21084016d..0302905bc5 100644 --- a/proto/zitadel/admin.proto +++ b/proto/zitadel/admin.proto @@ -3444,6 +3444,7 @@ message GetDomainPolicyResponse { message UpdateDomainPolicyRequest { bool user_login_must_be_domain = 1; bool validate_org_domains = 2; + bool smtp_sender_address_matches_instance_domain = 3; } message UpdateDomainPolicyResponse { @@ -3497,6 +3498,11 @@ message AddCustomDomainPolicyRequest { description: "defines if organisation domains should be validated org count as validated automatically" } ]; + bool smtp_sender_address_matches_instance_domain = 4 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "defines if the smtp sender address domain should match an existing domain on the instance" + } + ]; } message AddCustomDomainPolicyResponse { @@ -3528,6 +3534,11 @@ message UpdateCustomDomainPolicyRequest { description: "defines if organisation domains should be validated org count as validated automatically" } ]; + bool smtp_sender_address_matches_instance_domain = 4 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "defines if the smtp sender address domain should match an existing domain on the instance" + } + ]; } message UpdateCustomDomainPolicyResponse { diff --git a/proto/zitadel/policy.proto b/proto/zitadel/policy.proto index a8029a35cb..2d6f887676 100644 --- a/proto/zitadel/policy.proto +++ b/proto/zitadel/policy.proto @@ -40,6 +40,12 @@ message DomainPolicy { description: "defines if organisation domains should be validated org count as validated automatically" } ]; + bool smtp_sender_address_matches_instance_domain = 5 [ + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "defines if the smtp sender address domain should match an existing domain on the instance" + } + ]; + } message LabelPolicy {