mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 20:57:24 +00:00
feat: e-mail templates (#1158)
* View definition added * Get templates and texts from the database. * Fill in texts in templates * Fill in texts in templates * Client API added * Weekly backup * Weekly backup * Daily backup * Weekly backup * Tests added * Corrections from merge branch * Fixes from pull request review
This commit is contained in:
parent
e7540e5e05
commit
f2a32871a7
File diff suppressed because one or more lines are too long
1
go.mod
1
go.mod
@ -30,6 +30,7 @@ require (
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/gorilla/securecookie v1.1.1
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
|
3
go.sum
3
go.sum
@ -333,6 +333,7 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1/go.mod h1:oVMjMN64nzEcepv1kdZKgx1qNYt4Ro0Gqefiq2JWdis=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -1065,6 +1066,7 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201103154000-415bd0cd5df6 h1:rMoZiLTOobSD3eg30lPMcFkBFNSyKUQQIQlw/hsAXME=
|
||||
google.golang.org/genproto v0.0.0-20201103154000-415bd0cd5df6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
@ -1096,6 +1098,7 @@ google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -176,66 +176,6 @@ func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
|
||||
policy, viewErr := repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
if viewErr != nil && !caos_errs.IsNotFound(viewErr) {
|
||||
return nil, viewErr
|
||||
}
|
||||
if caos_errs.IsNotFound(viewErr) {
|
||||
policy = new(iam_es_model.LabelPolicyView)
|
||||
}
|
||||
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
|
||||
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "EVENT-4bM0s", "Errors.IAM.LabelPolicy.NotFound")
|
||||
}
|
||||
if esErr != nil {
|
||||
logging.Log("EVENT-3M0xs").WithError(esErr).Debug("error retrieving new events")
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), nil
|
||||
}
|
||||
policyCopy := *policy
|
||||
for _, event := range events {
|
||||
if err := policyCopy.AppendEvent(event); err != nil {
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), nil
|
||||
}
|
||||
}
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), nil
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
|
||||
policy.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.AddLabelPolicy(ctx, policy)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
|
||||
policy.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
|
||||
policy, viewErr := repo.View.LoginPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
if viewErr != nil && !caos_errs.IsNotFound(viewErr) {
|
||||
return nil, viewErr
|
||||
}
|
||||
if caos_errs.IsNotFound(viewErr) {
|
||||
policy = new(iam_es_model.LoginPolicyView)
|
||||
}
|
||||
events, esErr := repo.IAMEventstore.IAMEventsByID(ctx, repo.SystemDefaults.IamID, policy.Sequence)
|
||||
if caos_errs.IsNotFound(viewErr) && len(events) == 0 {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "EVENT-cmO9s", "Errors.IAM.LoginPolicy.NotFound")
|
||||
}
|
||||
if esErr != nil {
|
||||
logging.Log("EVENT-2Mi8s").WithError(esErr).Debug("error retrieving new events")
|
||||
return iam_es_model.LoginPolicyViewToModel(policy), nil
|
||||
}
|
||||
policyCopy := *policy
|
||||
for _, event := range events {
|
||||
if err := policyCopy.AppendEvent(event); err != nil {
|
||||
return iam_es_model.LoginPolicyViewToModel(policy), nil
|
||||
}
|
||||
}
|
||||
return iam_es_model.LoginPolicyViewToModel(policy), nil
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) AddDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
|
||||
policy.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.AddLoginPolicy(ctx, policy)
|
||||
@ -475,3 +415,95 @@ func (repo *IAMRepository) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy
|
||||
policy.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.ChangeOrgIAMPolicy(ctx, policy)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) {
|
||||
policy, err := repo.View.LabelPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), err
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
|
||||
policy.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.AddLabelPolicy(ctx, policy)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
|
||||
policy.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) {
|
||||
template, err := repo.View.MailTemplateByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTemplateViewToModel(template), err
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) AddDefaultMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
template.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.AddMailTemplate(ctx, template)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) ChangeDefaultMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
template.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.ChangeMailTemplate(ctx, template)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) SearchIAMMembersx(ctx context.Context, request *iam_model.IAMMemberSearchRequest) (*iam_model.IAMMemberSearchResponse, error) {
|
||||
request.EnsureLimit(repo.SearchLimit)
|
||||
sequence, err := repo.View.GetLatestIAMMemberSequence("")
|
||||
logging.Log("EVENT-Slkci").OnError(err).Warn("could not read latest iam sequence")
|
||||
members, count, err := repo.View.SearchIAMMembers(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := &iam_model.IAMMemberSearchResponse{
|
||||
Offset: request.Offset,
|
||||
Limit: request.Limit,
|
||||
TotalResult: count,
|
||||
Result: iam_es_model.IAMMembersToModel(members),
|
||||
}
|
||||
if err == nil {
|
||||
result.Sequence = sequence.CurrentSequence
|
||||
result.Timestamp = result.Timestamp
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error) {
|
||||
text, err := repo.View.MailTexts(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTextsViewToModel(text, true), err
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultMailText(ctx context.Context, textType string, language string) (*iam_model.MailTextView, error) {
|
||||
text, err := repo.View.MailTextByIDs(repo.SystemDefaults.IamID, textType, language)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
text.Default = true
|
||||
return iam_es_model.MailTextViewToModel(text), err
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) AddDefaultMailText(ctx context.Context, text *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
text.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.AddMailText(ctx, text)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) ChangeDefaultMailText(ctx context.Context, text *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
text.AggregateID = repo.SystemDefaults.IamID
|
||||
return repo.IAMEventstore.ChangeMailText(ctx, text)
|
||||
}
|
||||
|
||||
func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
|
||||
policy, err := repo.View.LoginPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.LoginPolicyViewToModel(policy), err
|
||||
}
|
||||
|
@ -74,6 +74,10 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
||||
defaults,
|
||||
repos.IamEvents,
|
||||
repos.OrgEvents),
|
||||
newMailTemplate(
|
||||
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
|
||||
newMailText(
|
||||
handler{view, bulkLimit, configs.cycleDuration("MailText"), errorCount, es}),
|
||||
}
|
||||
}
|
||||
|
||||
|
105
internal/admin/repository/eventsourcing/handler/mail_template.go
Normal file
105
internal/admin/repository/eventsourcing/handler/mail_template.go
Normal file
@ -0,0 +1,105 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/query"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
)
|
||||
|
||||
type MailTemplate struct {
|
||||
handler
|
||||
subscription *eventstore.Subscription
|
||||
}
|
||||
|
||||
func newMailTemplate(handler handler) *MailTemplate {
|
||||
h := &MailTemplate{
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *MailTemplate) subscribe() {
|
||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||
go func() {
|
||||
for event := range m.subscription.Events {
|
||||
query.ReduceEvent(m, event)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
const (
|
||||
mailTemplateTable = "adminapi.mail_templates"
|
||||
)
|
||||
|
||||
func (m *MailTemplate) ViewModel() string {
|
||||
return mailTemplateTable
|
||||
}
|
||||
|
||||
func (_ *MailTemplate) AggregateTypes() []es_models.AggregateType {
|
||||
return []es_models.AggregateType{iam_es_model.IAMAggregate}
|
||||
}
|
||||
|
||||
func (p *MailTemplate) CurrentSequence(event *models.Event) (uint64, error) {
|
||||
sequence, err := p.view.GetLatestMailTemplateSequence(string(event.AggregateType))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return sequence.CurrentSequence, nil
|
||||
}
|
||||
|
||||
func (m *MailTemplate) EventQuery() (*models.SearchQuery, error) {
|
||||
sequence, err := m.view.GetLatestMailTemplateSequence("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(m.AggregateTypes()...).
|
||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||
}
|
||||
|
||||
func (m *MailTemplate) Reduce(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case model.IAMAggregate:
|
||||
err = m.processMailTemplate(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *MailTemplate) processMailTemplate(event *models.Event) (err error) {
|
||||
template := new(iam_model.MailTemplateView)
|
||||
switch event.Type {
|
||||
case model.MailTemplateAdded:
|
||||
err = template.AppendEvent(event)
|
||||
case model.MailTemplateChanged:
|
||||
template, err = m.view.MailTemplateByAggregateID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = template.AppendEvent(event)
|
||||
default:
|
||||
return m.view.ProcessedMailTemplateSequence(event)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutMailTemplate(template, event)
|
||||
}
|
||||
|
||||
func (m *MailTemplate) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-Wj8sf", "id", event.AggregateID).WithError(err).Warn("something went wrong in label template handler")
|
||||
return spooler.HandleError(event, err, m.view.GetLatestMailTemplateFailedEvent, m.view.ProcessedMailTemplateFailedEvent, m.view.ProcessedMailTemplateSequence, m.errorCountUntilSkip)
|
||||
}
|
||||
|
||||
func (o *MailTemplate) OnSuccess() error {
|
||||
return spooler.HandleSuccess(o.view.UpdateMailTemplateSpoolerRunTimestamp)
|
||||
}
|
109
internal/admin/repository/eventsourcing/handler/mail_text.go
Normal file
109
internal/admin/repository/eventsourcing/handler/mail_text.go
Normal file
@ -0,0 +1,109 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/query"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
)
|
||||
|
||||
type MailText struct {
|
||||
handler
|
||||
subscription *eventstore.Subscription
|
||||
}
|
||||
|
||||
func newMailText(handler handler) *MailText {
|
||||
h := &MailText{
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *MailText) subscribe() {
|
||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||
go func() {
|
||||
for event := range m.subscription.Events {
|
||||
query.ReduceEvent(m, event)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
const (
|
||||
mailTextTable = "adminapi.mail_texts"
|
||||
)
|
||||
|
||||
func (m *MailText) ViewModel() string {
|
||||
return mailTextTable
|
||||
}
|
||||
|
||||
func (_ *MailText) AggregateTypes() []es_models.AggregateType {
|
||||
return []es_models.AggregateType{iam_es_model.IAMAggregate}
|
||||
}
|
||||
|
||||
func (p *MailText) CurrentSequence(event *models.Event) (uint64, error) {
|
||||
sequence, err := p.view.GetLatestMailTextSequence(string(event.AggregateType))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return sequence.CurrentSequence, nil
|
||||
}
|
||||
|
||||
func (m *MailText) EventQuery() (*models.SearchQuery, error) {
|
||||
sequence, err := m.view.GetLatestMailTextSequence("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(m.AggregateTypes()...).
|
||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||
}
|
||||
|
||||
func (m *MailText) Reduce(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case model.IAMAggregate:
|
||||
err = m.processMailText(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *MailText) processMailText(event *models.Event) (err error) {
|
||||
mailText := new(iam_model.MailTextView)
|
||||
switch event.Type {
|
||||
case model.MailTextAdded:
|
||||
err = mailText.AppendEvent(event)
|
||||
case model.MailTextChanged:
|
||||
err = mailText.SetData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mailText, err = m.view.MailTextByIDs(event.AggregateID, mailText.MailTextType, mailText.Language)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = mailText.AppendEvent(event)
|
||||
default:
|
||||
return m.view.ProcessedMailTextSequence(event)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutMailText(mailText, event)
|
||||
}
|
||||
|
||||
func (m *MailText) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("HANDL-5jk84", "id", event.AggregateID).WithError(err).Warn("something went wrong in label mailText handler")
|
||||
return spooler.HandleError(event, err, m.view.GetLatestMailTextFailedEvent, m.view.ProcessedMailTextFailedEvent, m.view.ProcessedMailTextSequence, m.errorCountUntilSkip)
|
||||
}
|
||||
|
||||
func (o *MailText) OnSuccess() error {
|
||||
return spooler.HandleSuccess(o.view.UpdateMailTextSpoolerRunTimestamp)
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
mailTemplateTable = "adminapi.mail_templates"
|
||||
)
|
||||
|
||||
func (v *View) MailTemplateByAggregateID(aggregateID string) (*model.MailTemplateView, error) {
|
||||
return view.GetMailTemplateByAggregateID(v.Db, mailTemplateTable, aggregateID)
|
||||
}
|
||||
|
||||
func (v *View) PutMailTemplate(template *model.MailTemplateView, event *models.Event) error {
|
||||
err := view.PutMailTemplate(v.Db, mailTemplateTable, template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedMailTemplateSequence(event)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTemplateSequence(aggregateType string) (*global_view.CurrentSequence, error) {
|
||||
return v.latestSequence(mailTemplateTable, aggregateType)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTemplateSequence(event *models.Event) error {
|
||||
return v.saveCurrentSequence(mailTemplateTable, event)
|
||||
}
|
||||
|
||||
func (v *View) UpdateMailTemplateSpoolerRunTimestamp() error {
|
||||
return v.updateSpoolerRunSequence(mailTemplateTable)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTemplateFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||
return v.latestFailedEvent(mailTemplateTable, sequence)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTemplateFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||
return v.saveFailedEvent(failedEvent)
|
||||
}
|
48
internal/admin/repository/eventsourcing/view/mail_texts.go
Normal file
48
internal/admin/repository/eventsourcing/view/mail_texts.go
Normal file
@ -0,0 +1,48 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
mailTextTable = "adminapi.mail_texts"
|
||||
)
|
||||
|
||||
func (v *View) MailTexts(aggregateID string) ([]*model.MailTextView, error) {
|
||||
return view.GetMailTexts(v.Db, mailTextTable, aggregateID)
|
||||
}
|
||||
|
||||
func (v *View) MailTextByIDs(aggregateID string, textType string, language string) (*model.MailTextView, error) {
|
||||
return view.GetMailTextByIDs(v.Db, mailTextTable, aggregateID, textType, language)
|
||||
}
|
||||
|
||||
func (v *View) PutMailText(template *model.MailTextView, event *models.Event) error {
|
||||
err := view.PutMailText(v.Db, mailTextTable, template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedMailTextSequence(event)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTextSequence(aggregateType string) (*global_view.CurrentSequence, error) {
|
||||
return v.latestSequence(mailTextTable, aggregateType)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTextSequence(event *models.Event) error {
|
||||
return v.saveCurrentSequence(mailTextTable, event)
|
||||
}
|
||||
|
||||
func (v *View) UpdateMailTextSpoolerRunTimestamp() error {
|
||||
return v.updateSpoolerRunSequence(mailTextTable)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTextFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||
return v.latestFailedEvent(mailTextTable, sequence)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTextFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||
return v.saveFailedEvent(failedEvent)
|
||||
}
|
@ -40,6 +40,15 @@ type IAMRepository interface {
|
||||
AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
|
||||
ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error)
|
||||
|
||||
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||
AddDefaultMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error)
|
||||
ChangeDefaultMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error)
|
||||
|
||||
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
||||
GetDefaultMailText(ctx context.Context, textType string, language string) (*iam_model.MailTextView, error)
|
||||
AddDefaultMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
||||
ChangeDefaultMailText(ctx context.Context, policy *iam_model.MailText) (*iam_model.MailText, error)
|
||||
|
||||
GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
|
||||
AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error)
|
||||
ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error)
|
||||
|
24
internal/api/grpc/admin/template.go
Normal file
24
internal/api/grpc/admin/template.go
Normal file
@ -0,0 +1,24 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetDefaultMailTemplate(ctx context.Context, _ *empty.Empty) (*admin.DefaultMailTemplateView, error) {
|
||||
result, err := s.iam.GetDefaultMailTemplate(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return templateViewFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateDefaultMailTemplate(ctx context.Context, policy *admin.DefaultMailTemplateUpdate) (*admin.DefaultMailTemplate, error) {
|
||||
result, err := s.iam.ChangeDefaultMailTemplate(ctx, templateToModel(policy))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return templateFromModel(result), nil
|
||||
}
|
42
internal/api/grpc/admin/template_converter.go
Normal file
42
internal/api/grpc/admin/template_converter.go
Normal file
@ -0,0 +1,42 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
func templateToModel(policy *admin.DefaultMailTemplateUpdate) *iam_model.MailTemplate {
|
||||
return &iam_model.MailTemplate{
|
||||
Template: policy.Template,
|
||||
}
|
||||
}
|
||||
|
||||
func templateFromModel(policy *iam_model.MailTemplate) *admin.DefaultMailTemplate {
|
||||
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
|
||||
logging.Log("ADMIN-CAA7T").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
|
||||
logging.Log("ADMIN-H52Zx").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &admin.DefaultMailTemplate{
|
||||
Template: policy.Template,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
||||
|
||||
func templateViewFromModel(policy *iam_model.MailTemplateView) *admin.DefaultMailTemplateView {
|
||||
creationDate, err := ptypes.TimestampProto(policy.CreationDate)
|
||||
logging.Log("ADMIN-yWFs5").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(policy.ChangeDate)
|
||||
logging.Log("ADMIN-JRpIO").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &admin.DefaultMailTemplateView{
|
||||
Template: policy.Template,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
32
internal/api/grpc/admin/text.go
Normal file
32
internal/api/grpc/admin/text.go
Normal file
@ -0,0 +1,32 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetDefaultMailTexts(ctx context.Context, _ *empty.Empty) (*admin.DefaultMailTextsView, error) {
|
||||
result, err := s.iam.GetDefaultMailTexts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return textsViewFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultMailText(ctx context.Context, textType string, language string) (*admin.DefaultMailTextView, error) {
|
||||
result, err := s.iam.GetDefaultMailText(ctx, textType, language)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return textViewFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateDefaultMailText(ctx context.Context, text *admin.DefaultMailTextUpdate) (*admin.DefaultMailText, error) {
|
||||
result, err := s.iam.ChangeDefaultMailText(ctx, textToModel(text))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return textFromModel(result), nil
|
||||
}
|
78
internal/api/grpc/admin/text_converter.go
Normal file
78
internal/api/grpc/admin/text_converter.go
Normal file
@ -0,0 +1,78 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/pkg/grpc/admin"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
func textToModel(text *admin.DefaultMailTextUpdate) *iam_model.MailText {
|
||||
return &iam_model.MailText{
|
||||
MailTextType: text.MailTextType,
|
||||
Language: text.Language,
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: text.Text,
|
||||
ButtonText: text.ButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
func textFromModel(text *iam_model.MailText) *admin.DefaultMailText {
|
||||
creationDate, err := ptypes.TimestampProto(text.CreationDate)
|
||||
logging.Log("ADMIN-Jlzsj").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(text.ChangeDate)
|
||||
logging.Log("ADMIN-mw5b8").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &admin.DefaultMailText{
|
||||
MailTextType: text.MailTextType,
|
||||
Language: text.Language,
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: text.Text,
|
||||
ButtonText: text.ButtonText,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
||||
|
||||
func textsViewFromModel(textsin *iam_model.MailTextsView) *admin.DefaultMailTextsView {
|
||||
return &admin.DefaultMailTextsView{
|
||||
Texts: textsViewToModel(textsin.Texts),
|
||||
}
|
||||
}
|
||||
|
||||
func textsViewToModel(queries []*iam_model.MailTextView) []*admin.DefaultMailTextView {
|
||||
modelQueries := make([]*admin.DefaultMailTextView, len(queries))
|
||||
for i, query := range queries {
|
||||
modelQueries[i] = textViewFromModel(query)
|
||||
}
|
||||
|
||||
return modelQueries
|
||||
}
|
||||
|
||||
func textViewFromModel(text *iam_model.MailTextView) *admin.DefaultMailTextView {
|
||||
creationDate, err := ptypes.TimestampProto(text.CreationDate)
|
||||
logging.Log("ADMIN-7RyJc").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(text.ChangeDate)
|
||||
logging.Log("ADMIN-fTFgY").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &admin.DefaultMailTextView{
|
||||
MailTextType: text.MailTextType,
|
||||
Language: text.Language,
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: text.Text,
|
||||
ButtonText: text.ButtonText,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
45
internal/api/grpc/management/mail_template.go
Normal file
45
internal/api/grpc/management/mail_template.go
Normal file
@ -0,0 +1,45 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/pkg/grpc/management"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetMailTemplate(ctx context.Context, _ *empty.Empty) (*management.MailTemplateView, error) {
|
||||
result, err := s.org.GetMailTemplate(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTemplateViewFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultMailTemplate(ctx context.Context, _ *empty.Empty) (*management.MailTemplateView, error) {
|
||||
result, err := s.org.GetDefaultMailTemplate(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTemplateViewFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) CreateMailTemplate(ctx context.Context, template *management.MailTemplateUpdate) (*management.MailTemplate, error) {
|
||||
result, err := s.org.AddMailTemplate(ctx, mailTemplateRequestToModel(template))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTemplateFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateMailTemplate(ctx context.Context, template *management.MailTemplateUpdate) (*management.MailTemplate, error) {
|
||||
result, err := s.org.ChangeMailTemplate(ctx, mailTemplateRequestToModel(template))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTemplateFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveMailTemplate(ctx context.Context, _ *empty.Empty) (*empty.Empty, error) {
|
||||
err := s.org.RemoveMailTemplate(ctx)
|
||||
return &empty.Empty{}, err
|
||||
}
|
42
internal/api/grpc/management/mail_template_converter.go
Normal file
42
internal/api/grpc/management/mail_template_converter.go
Normal file
@ -0,0 +1,42 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/pkg/grpc/management"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
func mailTemplateRequestToModel(mailTemplate *management.MailTemplateUpdate) *iam_model.MailTemplate {
|
||||
return &iam_model.MailTemplate{
|
||||
Template: mailTemplate.Template,
|
||||
}
|
||||
}
|
||||
|
||||
func mailTemplateFromModel(mailTemplate *iam_model.MailTemplate) *management.MailTemplate {
|
||||
creationDate, err := ptypes.TimestampProto(mailTemplate.CreationDate)
|
||||
logging.Log("MANAG-ULKZ6").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(mailTemplate.ChangeDate)
|
||||
logging.Log("MANAG-451rI").OnError(err).Debug("date parse failed")
|
||||
return &management.MailTemplate{
|
||||
Template: mailTemplate.Template,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
||||
|
||||
func mailTemplateViewFromModel(mailTemplate *iam_model.MailTemplateView) *management.MailTemplateView {
|
||||
creationDate, err := ptypes.TimestampProto(mailTemplate.CreationDate)
|
||||
logging.Log("MANAG-koQnB").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(mailTemplate.ChangeDate)
|
||||
logging.Log("MANAG-ToDhD").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &management.MailTemplateView{
|
||||
Default: mailTemplate.Default,
|
||||
Template: mailTemplate.Template,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
45
internal/api/grpc/management/mail_text.go
Normal file
45
internal/api/grpc/management/mail_text.go
Normal file
@ -0,0 +1,45 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/pkg/grpc/management"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetMailTexts(ctx context.Context, _ *empty.Empty) (*management.MailTextsView, error) {
|
||||
result, err := s.org.GetMailTexts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTextsViewFromModel(result.Texts), nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultMailTexts(ctx context.Context, _ *empty.Empty) (*management.MailTextsView, error) {
|
||||
result, err := s.org.GetDefaultMailTexts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTextsViewFromModel(result.Texts), nil
|
||||
}
|
||||
|
||||
func (s *Server) CreateMailText(ctx context.Context, mailText *management.MailTextUpdate) (*management.MailText, error) {
|
||||
result, err := s.org.AddMailText(ctx, mailTextRequestToModel(mailText))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTextFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateMailText(ctx context.Context, mailText *management.MailTextUpdate) (*management.MailText, error) {
|
||||
result, err := s.org.ChangeMailText(ctx, mailTextRequestToModel(mailText))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mailTextFromModel(result), nil
|
||||
}
|
||||
|
||||
func (s *Server) RemoveMailText(ctx context.Context, mailText *management.MailTextRemove) (*empty.Empty, error) {
|
||||
err := s.org.RemoveMailText(ctx, mailTextRemoveToModel(mailText))
|
||||
return &empty.Empty{}, err
|
||||
}
|
82
internal/api/grpc/management/mail_text_converter.go
Normal file
82
internal/api/grpc/management/mail_text_converter.go
Normal file
@ -0,0 +1,82 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/pkg/grpc/management"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
func mailTextRequestToModel(mailText *management.MailTextUpdate) *iam_model.MailText {
|
||||
return &iam_model.MailText{
|
||||
MailTextType: mailText.MailTextType,
|
||||
Language: mailText.Language,
|
||||
Title: mailText.Title,
|
||||
PreHeader: mailText.PreHeader,
|
||||
Subject: mailText.Subject,
|
||||
Greeting: mailText.Greeting,
|
||||
Text: mailText.Text,
|
||||
ButtonText: mailText.ButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
func mailTextRemoveToModel(mailText *management.MailTextRemove) *iam_model.MailText {
|
||||
return &iam_model.MailText{
|
||||
MailTextType: mailText.MailTextType,
|
||||
Language: mailText.Language,
|
||||
}
|
||||
}
|
||||
|
||||
func mailTextFromModel(mailText *iam_model.MailText) *management.MailText {
|
||||
creationDate, err := ptypes.TimestampProto(mailText.CreationDate)
|
||||
logging.Log("MANAG-ULKZ6").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(mailText.ChangeDate)
|
||||
logging.Log("MANAG-451rI").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &management.MailText{
|
||||
MailTextType: mailText.MailTextType,
|
||||
Language: mailText.Language,
|
||||
Title: mailText.Title,
|
||||
PreHeader: mailText.PreHeader,
|
||||
Subject: mailText.Subject,
|
||||
Greeting: mailText.Greeting,
|
||||
Text: mailText.Text,
|
||||
ButtonText: mailText.ButtonText,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
||||
|
||||
func mailTextsViewFromModel(queries []*iam_model.MailTextView) *management.MailTextsView {
|
||||
modelQueries := make([]*management.MailTextView, len(queries))
|
||||
for i, query := range queries {
|
||||
modelQueries[i] = mailTextViewFromModel(query)
|
||||
}
|
||||
|
||||
return &management.MailTextsView{
|
||||
Texts: modelQueries,
|
||||
}
|
||||
}
|
||||
|
||||
func mailTextViewFromModel(mailText *iam_model.MailTextView) *management.MailTextView {
|
||||
creationDate, err := ptypes.TimestampProto(mailText.CreationDate)
|
||||
logging.Log("MANAG-koQnB").OnError(err).Debug("date parse failed")
|
||||
|
||||
changeDate, err := ptypes.TimestampProto(mailText.ChangeDate)
|
||||
logging.Log("MANAG-ToDhD").OnError(err).Debug("date parse failed")
|
||||
|
||||
return &management.MailTextView{
|
||||
Default: mailText.Default,
|
||||
MailTextType: mailText.MailTextType,
|
||||
Language: mailText.Language,
|
||||
Title: mailText.Title,
|
||||
PreHeader: mailText.PreHeader,
|
||||
Subject: mailText.Subject,
|
||||
Greeting: mailText.Greeting,
|
||||
Text: mailText.Text,
|
||||
ButtonText: mailText.ButtonText,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
}
|
||||
}
|
@ -99,10 +99,13 @@ func projectRoleViewsFromModel(roles []*proj_model.ProjectRoleView) []*managemen
|
||||
func projectRoleViewFromModel(role *proj_model.ProjectRoleView) *management.ProjectRoleView {
|
||||
creationDate, err := ptypes.TimestampProto(role.CreationDate)
|
||||
logging.Log("GRPC-dlso3").OnError(err).Debug("unable to parse timestamp")
|
||||
changeDate, err := ptypes.TimestampProto(role.ChangeDate)
|
||||
logging.Log("MANAG-BRr8Y").OnError(err).Debug("unable to parse timestamp")
|
||||
|
||||
return &management.ProjectRoleView{
|
||||
ProjectId: role.ProjectID,
|
||||
CreationDate: creationDate,
|
||||
ChangeDate: changeDate,
|
||||
Key: role.Key,
|
||||
Group: role.Group,
|
||||
DisplayName: role.DisplayName,
|
||||
|
@ -84,6 +84,7 @@ func (p *ProjectRole) Reduce(event *es_models.Event) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
role.ChangeDate = event.CreationDate
|
||||
err = role.AppendEvent(event)
|
||||
case model.ProjectRoleRemoved:
|
||||
err = role.SetData(event)
|
||||
|
@ -16,6 +16,7 @@ const (
|
||||
Step7
|
||||
Step8
|
||||
Step9
|
||||
Step10
|
||||
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
|
||||
StepCount
|
||||
)
|
||||
@ -34,6 +35,8 @@ type IAM struct {
|
||||
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy
|
||||
DefaultPasswordAgePolicy *PasswordAgePolicy
|
||||
DefaultPasswordLockoutPolicy *PasswordLockoutPolicy
|
||||
DefaultMailTemplate *MailTemplate
|
||||
DefaultMailTexts []*MailText
|
||||
}
|
||||
|
||||
func (iam *IAM) GetMember(userID string) (int, *IAMMember) {
|
||||
@ -53,3 +56,12 @@ func (iam *IAM) GetIDP(idpID string) (int, *IDPConfig) {
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (iam *IAM) GetDefaultMailText(mailTextType string, language string) (int, *MailText) {
|
||||
for i, m := range iam.DefaultMailTexts {
|
||||
if m.MailTextType == mailTextType && m.Language == language {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
17
internal/iam/model/mail_template.go
Normal file
17
internal/iam/model/mail_template.go
Normal file
@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type MailTemplate struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
Template []byte
|
||||
}
|
||||
|
||||
func (p *MailTemplate) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != ""
|
||||
}
|
47
internal/iam/model/mail_template_view.go
Normal file
47
internal/iam/model/mail_template_view.go
Normal file
@ -0,0 +1,47 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/model"
|
||||
)
|
||||
|
||||
type MailTemplateView struct {
|
||||
AggregateID string
|
||||
Template []byte
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type MailTemplateSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn MailTemplateSearchKey
|
||||
Asc bool
|
||||
Queries []*MailTemplateSearchQuery
|
||||
}
|
||||
|
||||
type MailTemplateSearchKey int32
|
||||
|
||||
const (
|
||||
MailTemplateSearchKeyUnspecified MailTemplateSearchKey = iota
|
||||
MailTemplateSearchKeyAggregateID
|
||||
)
|
||||
|
||||
type MailTemplateSearchQuery struct {
|
||||
Key MailTemplateSearchKey
|
||||
Method model.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type MailTemplateSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*MailTemplateView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
28
internal/iam/model/mail_text.go
Normal file
28
internal/iam/model/mail_text.go
Normal file
@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
type MailTexts struct {
|
||||
Texts []*MailText
|
||||
Default bool
|
||||
}
|
||||
type MailText struct {
|
||||
models.ObjectRoot
|
||||
|
||||
State PolicyState
|
||||
Default bool
|
||||
MailTextType string
|
||||
Language string
|
||||
Title string
|
||||
PreHeader string
|
||||
Subject string
|
||||
Greeting string
|
||||
Text string
|
||||
ButtonText string
|
||||
}
|
||||
|
||||
func (p *MailText) IsValid() bool {
|
||||
return p.ObjectRoot.AggregateID != ""
|
||||
}
|
60
internal/iam/model/mail_text_view.go
Normal file
60
internal/iam/model/mail_text_view.go
Normal file
@ -0,0 +1,60 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/model"
|
||||
)
|
||||
|
||||
type MailTextsView struct {
|
||||
Texts []*MailTextView
|
||||
Default bool
|
||||
}
|
||||
type MailTextView struct {
|
||||
AggregateID string
|
||||
MailTextType string
|
||||
Language string
|
||||
Title string
|
||||
PreHeader string
|
||||
Subject string
|
||||
Greeting string
|
||||
Text string
|
||||
ButtonText string
|
||||
Default bool
|
||||
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type MailTextSearchRequest struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
SortingColumn MailTextSearchKey
|
||||
Asc bool
|
||||
Queries []*MailTextSearchQuery
|
||||
}
|
||||
|
||||
type MailTextSearchKey int32
|
||||
|
||||
const (
|
||||
MailTextSearchKeyUnspecified MailTextSearchKey = iota
|
||||
MailTextSearchKeyAggregateID
|
||||
MailTextSearchKeyMailTextType
|
||||
MailTextSearchKeyLanguage
|
||||
)
|
||||
|
||||
type MailTextSearchQuery struct {
|
||||
Key MailTextSearchKey
|
||||
Method model.SearchMethod
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type MailTextSearchResponse struct {
|
||||
Offset uint64
|
||||
Limit uint64
|
||||
TotalResult uint64
|
||||
Result []*MailTextView
|
||||
Sequence uint64
|
||||
Timestamp time.Time
|
||||
}
|
@ -964,3 +964,118 @@ func (es *IAMEventstore) ChangeOrgIAMPolicy(ctx context.Context, policy *iam_mod
|
||||
es.iamCache.cacheIAM(repoIam)
|
||||
return model.OrgIAMPolicyToModel(repoIam.DefaultOrgIAMPolicy), nil
|
||||
}
|
||||
|
||||
func (es *IAMEventstore) PrepareAddMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*model.IAM, *models.Aggregate, error) {
|
||||
if template == nil || !template.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-j9l18", "Errors.IAM.MailTemplate.Empty")
|
||||
}
|
||||
iam, err := es.IAMByID(ctx, template.AggregateID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repoIam := model.IAMFromModel(iam)
|
||||
mailTemplate := model.MailTemplateFromModel(template)
|
||||
|
||||
addAggregate := MailTemplateAddedAggregate(es.Eventstore.AggregateCreator(), repoIam, mailTemplate)
|
||||
aggregate, err := addAggregate(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return repoIam, aggregate, nil
|
||||
}
|
||||
|
||||
func (es *IAMEventstore) AddMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
repoIam, addAggregate, err := es.PrepareAddMailTemplate(ctx, template)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoIam.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
es.iamCache.cacheIAM(repoIam)
|
||||
return model.MailTemplateToModel(repoIam.DefaultMailTemplate), nil
|
||||
}
|
||||
|
||||
func (es *IAMEventstore) ChangeMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
if template == nil || !template.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-gCnCs", "Errors.IAM.MailTemplateInvalid")
|
||||
}
|
||||
iam, err := es.IAMByID(ctx, template.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoIam := model.IAMFromModel(iam)
|
||||
repoMailTemplate := model.MailTemplateFromModel(template)
|
||||
|
||||
addAggregate := MailTemplateChangedAggregate(es.Eventstore.AggregateCreator(), repoIam, repoMailTemplate)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
es.iamCache.cacheIAM(repoIam)
|
||||
return model.MailTemplateToModel(repoIam.DefaultMailTemplate), nil
|
||||
}
|
||||
|
||||
func (es *IAMEventstore) PrepareAddMailText(ctx context.Context, text *iam_model.MailText) (*model.IAM, *models.Aggregate, error) {
|
||||
if text == nil || !text.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-j9l18", "Errors.IAM.MailText.Empty")
|
||||
}
|
||||
iam, err := es.IAMByID(ctx, text.AggregateID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repoIam := model.IAMFromModel(iam)
|
||||
mailText := model.MailTextFromModel(text)
|
||||
|
||||
addAggregate := MailTextAddedAggregate(es.Eventstore.AggregateCreator(), repoIam, mailText)
|
||||
aggregate, err := addAggregate(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return repoIam, aggregate, nil
|
||||
}
|
||||
|
||||
func (es *IAMEventstore) AddMailText(ctx context.Context, text *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
repoIam, addAggregate, err := es.PrepareAddMailText(ctx, text)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = es_sdk.PushAggregates(ctx, es.PushAggregates, repoIam.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
es.iamCache.cacheIAM(repoIam)
|
||||
|
||||
if _, m := model.GetMailText(repoIam.DefaultMailTexts, text.MailTextType, text.Language); m != nil {
|
||||
return model.MailTextToModel(m), nil
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-9AwUm", "Errors.Internal")
|
||||
}
|
||||
|
||||
func (es *IAMEventstore) ChangeMailText(ctx context.Context, text *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
if !text.IsValid() {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-J5xbB", "Errors.IAM.MailTextInvalid")
|
||||
}
|
||||
existing, err := es.IAMByID(ctx, text.AggregateID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, m := existing.GetDefaultMailText(text.MailTextType, text.Language); m == nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-0CTV3", "Errors.IAM.MailTextNotExisting")
|
||||
}
|
||||
repoIam := model.IAMFromModel(existing)
|
||||
repoMember := model.MailTextFromModel(text)
|
||||
|
||||
projectAggregate := MailTextChangedAggregate(es.Eventstore.AggregateCreator(), repoIam, repoMember)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, projectAggregate)
|
||||
es.iamCache.cacheIAM(repoIam)
|
||||
|
||||
if _, m := model.GetMailText(repoIam.DefaultMailTexts, text.MailTextType, text.Language); m != nil {
|
||||
return model.MailTextToModel(m), nil
|
||||
}
|
||||
return nil, caos_errs.ThrowInternal(nil, "EVENT-HawVx", "Errors.Internal")
|
||||
}
|
||||
|
@ -216,3 +216,29 @@ func GetMockManipulateIAMWithLabelPolicy(ctrl *gomock.Controller) *IAMEventstore
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateIAMWithMailTemplate(ctrl *gomock.Controller) *IAMEventstore {
|
||||
mailTemplate, _ := json.Marshal(model.MailTemplate{Template: []byte("<!doctype htm>")})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.IAMSetupStarted},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.MailTemplateAdded, Data: mailTemplate},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockManipulateIAMWithMailText(ctrl *gomock.Controller) *IAMEventstore {
|
||||
mailText, _ := json.Marshal(model.MailText{MailTextType: "Type", Language: "DE"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.IAMSetupStarted},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.MailTextAdded, Data: mailText},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
@ -2815,3 +2815,321 @@ func TestChangeOrgIAMPolicy(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestAddMailTemplate(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *IAMEventstore
|
||||
ctx context.Context
|
||||
policy *iam_model.MailTemplate
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailTemplate
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add mailtemplate, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateIAM(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid policy",
|
||||
args: args{
|
||||
es: GetMockManipulateIAM(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing iam not found",
|
||||
args: args{
|
||||
es: GetMockManipulateIAMNotExisting(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.AddMailTemplate(tt.args.ctx, tt.args.policy)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.Template) != string(tt.res.result.Template) {
|
||||
t.Errorf("got wrong result Template: expected: %v, actual: %v ", tt.res.result.Template, result.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeMailTemplate(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *IAMEventstore
|
||||
ctx context.Context
|
||||
template *iam_model.MailTemplate
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailTemplate
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add mail template, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateIAMWithMailTemplate(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid mail template",
|
||||
args: args{
|
||||
es: GetMockManipulateIAM(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing iam not found",
|
||||
args: args{
|
||||
es: GetMockManipulateIAMNotExisting(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ChangeMailTemplate(tt.args.ctx, tt.args.template)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.Template) != string(tt.res.result.Template) {
|
||||
t.Errorf("got wrong result Template: expected: %v, actual: %v ", tt.res.result.Template, result.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestAddMailText(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *IAMEventstore
|
||||
ctx context.Context
|
||||
policy *iam_model.MailText
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailText
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add mailtemplate, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateIAM(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type", Language: "DE",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type", Language: "DE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid policy",
|
||||
args: args{
|
||||
es: GetMockManipulateIAM(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing iam not found",
|
||||
args: args{
|
||||
es: GetMockManipulateIAMNotExisting(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.AddMailText(tt.args.ctx, tt.args.policy)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.MailTextType) != string(tt.res.result.MailTextType) {
|
||||
t.Errorf("got wrong result MailTextType: expected: %v, actual: %v ", tt.res.result.MailTextType, result.MailTextType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeMailText(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *IAMEventstore
|
||||
ctx context.Context
|
||||
policy *iam_model.MailText
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailText
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "change mailtemplate, ok",
|
||||
args: args{
|
||||
es: GetMockManipulateIAMWithMailText(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type", Language: "DE",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type", Language: "DE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid policy",
|
||||
args: args{
|
||||
es: GetMockManipulateIAM(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing iam not found",
|
||||
args: args{
|
||||
es: GetMockManipulateIAMNotExisting(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
policy: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ChangeMailText(tt.args.ctx, tt.args.policy)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.MailTextType) != string(tt.res.result.MailTextType) {
|
||||
t.Errorf("got wrong result MailTextType: expected: %v, actual: %v ", tt.res.result.MailTextType, result.MailTextType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -232,6 +232,7 @@ func OIDCIDPConfigChangedAggregate(aggCreator *es_models.AggregateCreator, exist
|
||||
return agg.AppendEvent(model.OIDCIDPConfigChanged, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func LabelPolicyAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.IAM, policy *model.LabelPolicy) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
@ -678,6 +679,101 @@ func checkExistingLoginPolicyIDPProviderValidation(idpConfigID string) func(...*
|
||||
}
|
||||
}
|
||||
|
||||
func MailTemplateAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.IAM, template *model.MailTemplate) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if template == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-ZCfDS", "Errors.Internal")
|
||||
}
|
||||
agg, err := IAMAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validationQuery := es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.IAMAggregate).
|
||||
EventTypesFilter(model.MailTemplateAdded).
|
||||
AggregateIDFilter(existing.AggregateID)
|
||||
|
||||
validation := checkExistingMailTemplateValidation()
|
||||
agg.SetPrecondition(validationQuery, validation)
|
||||
return agg.AppendEvent(model.MailTemplateAdded, template)
|
||||
}
|
||||
}
|
||||
|
||||
func checkExistingMailTemplateValidation() func(...*es_models.Event) error {
|
||||
return func(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
switch event.Type {
|
||||
case model.MailTemplateAdded:
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-uKPiJ", "Errors.IAM.MailTemplate.AlreadyExists")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func MailTemplateChangedAggregate(aggCreator *es_models.AggregateCreator, existing *model.IAM, template *model.MailTemplate) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if template == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-s4PVD", "Errors.Internal")
|
||||
}
|
||||
agg, err := IAMAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := existing.DefaultMailTemplate.Changes(template)
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-hxxSm", "Errors.NoChangesFound")
|
||||
}
|
||||
return agg.AppendEvent(model.MailTemplateChanged, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func MailTextAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.IAM, text *model.MailText) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if text == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-ZCfDS", "Errors.Internal")
|
||||
}
|
||||
agg, err := IAMAggregate(ctx, aggCreator, existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validationQuery := es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.IAMAggregate).
|
||||
EventTypesFilter(model.MailTextAdded).
|
||||
AggregateIDFilter(existing.AggregateID)
|
||||
|
||||
validation := checkExistingMailTextValidation()
|
||||
agg.SetPrecondition(validationQuery, validation)
|
||||
return agg.AppendEvent(model.MailTextAdded, text)
|
||||
}
|
||||
}
|
||||
|
||||
func checkExistingMailTextValidation() func(...*es_models.Event) error {
|
||||
return func(events ...*es_models.Event) error {
|
||||
for _, event := range events {
|
||||
switch event.Type {
|
||||
case model.MailTextAdded:
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-ijzeq", "Errors.IAM.MailText.AlreadyExists")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func MailTextChangedAggregate(aggCreator *es_models.AggregateCreator, existingIAM *model.IAM, text *model.MailText) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if text == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-mgYpV", "Errors.Internal")
|
||||
}
|
||||
|
||||
agg, err := IAMAggregate(ctx, aggCreator, existingIAM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.MailTextChanged, text)
|
||||
}
|
||||
}
|
||||
|
||||
func checkExistingLoginPolicySecondFactorValidation(mfaType int32) func(...*es_models.Event) error {
|
||||
return func(events ...*es_models.Event) error {
|
||||
mfas := make([]int32, 0)
|
||||
|
@ -31,6 +31,8 @@ type IAM struct {
|
||||
IDPs []*IDPConfig `json:"-"`
|
||||
DefaultLoginPolicy *LoginPolicy `json:"-"`
|
||||
DefaultLabelPolicy *LabelPolicy `json:"-"`
|
||||
DefaultMailTemplate *MailTemplate `json:"-"`
|
||||
DefaultMailTexts []*MailText `json:"-"`
|
||||
DefaultOrgIAMPolicy *OrgIAMPolicy `json:"-"`
|
||||
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy `json:"-"`
|
||||
DefaultPasswordAgePolicy *PasswordAgePolicy `json:"-"`
|
||||
@ -40,14 +42,16 @@ type IAM struct {
|
||||
func IAMFromModel(iam *model.IAM) *IAM {
|
||||
members := IAMMembersFromModel(iam.Members)
|
||||
idps := IDPConfigsFromModel(iam.IDPs)
|
||||
mailTexts := MailTextsFromModel(iam.DefaultMailTexts)
|
||||
converted := &IAM{
|
||||
ObjectRoot: iam.ObjectRoot,
|
||||
SetUpStarted: Step(iam.SetUpStarted),
|
||||
SetUpDone: Step(iam.SetUpDone),
|
||||
GlobalOrgID: iam.GlobalOrgID,
|
||||
IAMProjectID: iam.IAMProjectID,
|
||||
Members: members,
|
||||
IDPs: idps,
|
||||
ObjectRoot: iam.ObjectRoot,
|
||||
SetUpStarted: Step(iam.SetUpStarted),
|
||||
SetUpDone: Step(iam.SetUpDone),
|
||||
GlobalOrgID: iam.GlobalOrgID,
|
||||
IAMProjectID: iam.IAMProjectID,
|
||||
Members: members,
|
||||
IDPs: idps,
|
||||
DefaultMailTexts: mailTexts,
|
||||
}
|
||||
if iam.DefaultLoginPolicy != nil {
|
||||
converted.DefaultLoginPolicy = LoginPolicyFromModel(iam.DefaultLoginPolicy)
|
||||
@ -55,6 +59,9 @@ func IAMFromModel(iam *model.IAM) *IAM {
|
||||
if iam.DefaultLabelPolicy != nil {
|
||||
converted.DefaultLabelPolicy = LabelPolicyFromModel(iam.DefaultLabelPolicy)
|
||||
}
|
||||
if iam.DefaultMailTemplate != nil {
|
||||
converted.DefaultMailTemplate = MailTemplateFromModel(iam.DefaultMailTemplate)
|
||||
}
|
||||
if iam.DefaultPasswordComplexityPolicy != nil {
|
||||
converted.DefaultPasswordComplexityPolicy = PasswordComplexityPolicyFromModel(iam.DefaultPasswordComplexityPolicy)
|
||||
}
|
||||
@ -73,14 +80,16 @@ func IAMFromModel(iam *model.IAM) *IAM {
|
||||
func IAMToModel(iam *IAM) *model.IAM {
|
||||
members := IAMMembersToModel(iam.Members)
|
||||
idps := IDPConfigsToModel(iam.IDPs)
|
||||
mailTexts := MailTextsToModel(iam.DefaultMailTexts)
|
||||
converted := &model.IAM{
|
||||
ObjectRoot: iam.ObjectRoot,
|
||||
SetUpStarted: model.Step(iam.SetUpStarted),
|
||||
SetUpDone: model.Step(iam.SetUpDone),
|
||||
GlobalOrgID: iam.GlobalOrgID,
|
||||
IAMProjectID: iam.IAMProjectID,
|
||||
Members: members,
|
||||
IDPs: idps,
|
||||
ObjectRoot: iam.ObjectRoot,
|
||||
SetUpStarted: model.Step(iam.SetUpStarted),
|
||||
SetUpDone: model.Step(iam.SetUpDone),
|
||||
GlobalOrgID: iam.GlobalOrgID,
|
||||
IAMProjectID: iam.IAMProjectID,
|
||||
Members: members,
|
||||
IDPs: idps,
|
||||
DefaultMailTexts: mailTexts,
|
||||
}
|
||||
if iam.DefaultLoginPolicy != nil {
|
||||
converted.DefaultLoginPolicy = LoginPolicyToModel(iam.DefaultLoginPolicy)
|
||||
@ -88,6 +97,9 @@ func IAMToModel(iam *IAM) *model.IAM {
|
||||
if iam.DefaultLabelPolicy != nil {
|
||||
converted.DefaultLabelPolicy = LabelPolicyToModel(iam.DefaultLabelPolicy)
|
||||
}
|
||||
if iam.DefaultMailTemplate != nil {
|
||||
converted.DefaultMailTemplate = MailTemplateToModel(iam.DefaultMailTemplate)
|
||||
}
|
||||
if iam.DefaultPasswordComplexityPolicy != nil {
|
||||
converted.DefaultPasswordComplexityPolicy = PasswordComplexityPolicyToModel(iam.DefaultPasswordComplexityPolicy)
|
||||
}
|
||||
@ -180,6 +192,14 @@ func (i *IAM) AppendEvent(event *es_models.Event) (err error) {
|
||||
return i.appendAddLabelPolicyEvent(event)
|
||||
case LabelPolicyChanged:
|
||||
return i.appendChangeLabelPolicyEvent(event)
|
||||
case MailTemplateAdded:
|
||||
return i.appendAddMailTemplateEvent(event)
|
||||
case MailTemplateChanged:
|
||||
return i.appendChangeMailTemplateEvent(event)
|
||||
case MailTextAdded:
|
||||
return i.appendAddMailTextEvent(event)
|
||||
case MailTextChanged:
|
||||
return i.appendChangeMailTextEvent(event)
|
||||
case PasswordComplexityPolicyAdded:
|
||||
return i.appendAddPasswordComplexityPolicyEvent(event)
|
||||
case PasswordComplexityPolicyChanged:
|
||||
|
64
internal/iam/repository/eventsourcing/model/mail_template.go
Normal file
64
internal/iam/repository/eventsourcing/model/mail_template.go
Normal file
@ -0,0 +1,64 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
b64 "encoding/base64"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
)
|
||||
|
||||
type MailTemplate struct {
|
||||
models.ObjectRoot
|
||||
State int32 `json:"-"`
|
||||
Template []byte
|
||||
}
|
||||
|
||||
func MailTemplateToModel(template *MailTemplate) *iam_model.MailTemplate {
|
||||
return &iam_model.MailTemplate{
|
||||
ObjectRoot: template.ObjectRoot,
|
||||
State: iam_model.PolicyState(template.State),
|
||||
Template: template.Template,
|
||||
}
|
||||
}
|
||||
|
||||
func MailTemplateFromModel(template *iam_model.MailTemplate) *MailTemplate {
|
||||
return &MailTemplate{
|
||||
ObjectRoot: template.ObjectRoot,
|
||||
State: int32(template.State),
|
||||
Template: template.Template,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *MailTemplate) Changes(changed *MailTemplate) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 1)
|
||||
if b64.StdEncoding.EncodeToString(changed.Template) != b64.StdEncoding.EncodeToString(p.Template) {
|
||||
changes["template"] = b64.StdEncoding.EncodeToString(changed.Template)
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
func (i *IAM) appendAddMailTemplateEvent(event *es_models.Event) error {
|
||||
i.DefaultMailTemplate = new(MailTemplate)
|
||||
err := i.DefaultMailTemplate.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.DefaultMailTemplate.ObjectRoot.CreationDate = event.CreationDate
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IAM) appendChangeMailTemplateEvent(event *es_models.Event) error {
|
||||
return i.DefaultMailTemplate.SetDataLabel(event)
|
||||
}
|
||||
|
||||
func (p *MailTemplate) SetDataLabel(event *es_models.Event) error {
|
||||
err := json.Unmarshal(event.Data, p)
|
||||
if err != nil {
|
||||
return errors.ThrowInternal(err, "MODEL-ikjhf", "unable to unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
func TestMailTemplateChanges(t *testing.T) {
|
||||
type args struct {
|
||||
existing *MailTemplate
|
||||
new *MailTemplate
|
||||
}
|
||||
type res struct {
|
||||
changesLen int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "mailtemplate all attributes change",
|
||||
args: args{
|
||||
existing: &MailTemplate{Template: []byte("<doctype html>")},
|
||||
new: &MailTemplate{Template: []byte("<!doctype html>")},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes",
|
||||
args: args{
|
||||
existing: &MailTemplate{Template: []byte("<!doctype html>")},
|
||||
new: &MailTemplate{Template: []byte("<!doctype html>")},
|
||||
},
|
||||
res: res{
|
||||
changesLen: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
changes := tt.args.existing.Changes(tt.args.new)
|
||||
if len(changes) != tt.res.changesLen {
|
||||
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendAddMailTemplateEvent(t *testing.T) {
|
||||
type args struct {
|
||||
iam *IAM
|
||||
policy *MailTemplate
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *IAM
|
||||
}{
|
||||
{
|
||||
name: "append add label policy event",
|
||||
args: args{
|
||||
iam: new(IAM),
|
||||
policy: &MailTemplate{Template: []byte("<!doctype html>")},
|
||||
event: new(es_models.Event),
|
||||
},
|
||||
result: &IAM{DefaultMailTemplate: &MailTemplate{Template: []byte("<!doctype html>")}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.policy != nil {
|
||||
data, _ := json.Marshal(tt.args.policy)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.iam.appendAddMailTemplateEvent(tt.args.event)
|
||||
if string(tt.result.DefaultMailTemplate.Template) != string(tt.args.iam.DefaultMailTemplate.Template) {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTemplate.Template, tt.args.iam.DefaultMailTemplate.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendChangeMailTemplateEvent(t *testing.T) {
|
||||
type args struct {
|
||||
iam *IAM
|
||||
policy *MailTemplate
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *IAM
|
||||
}{
|
||||
{
|
||||
name: "append change label policy event",
|
||||
args: args{
|
||||
iam: &IAM{DefaultMailTemplate: &MailTemplate{
|
||||
Template: []byte("<doctype html>"),
|
||||
}},
|
||||
policy: &MailTemplate{Template: []byte("<!doctype html>")},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &IAM{DefaultMailTemplate: &MailTemplate{
|
||||
Template: []byte("<!doctype html>"),
|
||||
}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.policy != nil {
|
||||
data, _ := json.Marshal(tt.args.policy)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.iam.appendChangeMailTemplateEvent(tt.args.event)
|
||||
if string(tt.result.DefaultMailTemplate.Template) != string(tt.args.iam.DefaultMailTemplate.Template) {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTemplate.Template, tt.args.iam.DefaultMailTemplate.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
157
internal/iam/repository/eventsourcing/model/mail_text.go
Normal file
157
internal/iam/repository/eventsourcing/model/mail_text.go
Normal file
@ -0,0 +1,157 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
)
|
||||
|
||||
type MailText struct {
|
||||
models.ObjectRoot
|
||||
State int32 `json:"-"`
|
||||
MailTextType string
|
||||
Language string
|
||||
Title string
|
||||
PreHeader string
|
||||
Subject string
|
||||
Greeting string
|
||||
Text string
|
||||
ButtonText string
|
||||
}
|
||||
|
||||
func GetMailText(mailTexts []*MailText, mailTextType string, language string) (int, *MailText) {
|
||||
for i, m := range mailTexts {
|
||||
if m.MailTextType == mailTextType && m.Language == language {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func MailTextsToModel(mailTexts []*MailText) []*iam_model.MailText {
|
||||
convertedMailTexts := make([]*iam_model.MailText, len(mailTexts))
|
||||
for i, m := range mailTexts {
|
||||
convertedMailTexts[i] = MailTextToModel(m)
|
||||
}
|
||||
return convertedMailTexts
|
||||
}
|
||||
|
||||
func MailTextToModel(mailText *MailText) *iam_model.MailText {
|
||||
return &iam_model.MailText{
|
||||
ObjectRoot: mailText.ObjectRoot,
|
||||
State: iam_model.PolicyState(mailText.State),
|
||||
MailTextType: mailText.MailTextType,
|
||||
Language: mailText.Language,
|
||||
Title: mailText.Title,
|
||||
PreHeader: mailText.PreHeader,
|
||||
Subject: mailText.Subject,
|
||||
Greeting: mailText.Greeting,
|
||||
Text: mailText.Text,
|
||||
ButtonText: mailText.ButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
func MailTextsFromModel(mailTexts []*iam_model.MailText) []*MailText {
|
||||
convertedMailTexts := make([]*MailText, len(mailTexts))
|
||||
for i, m := range mailTexts {
|
||||
convertedMailTexts[i] = MailTextFromModel(m)
|
||||
}
|
||||
return convertedMailTexts
|
||||
}
|
||||
|
||||
func MailTextFromModel(mailText *iam_model.MailText) *MailText {
|
||||
return &MailText{
|
||||
ObjectRoot: mailText.ObjectRoot,
|
||||
State: int32(mailText.State),
|
||||
MailTextType: mailText.MailTextType,
|
||||
Language: mailText.Language,
|
||||
Title: mailText.Title,
|
||||
PreHeader: mailText.PreHeader,
|
||||
Subject: mailText.Subject,
|
||||
Greeting: mailText.Greeting,
|
||||
Text: mailText.Text,
|
||||
ButtonText: mailText.ButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *MailText) Changes(changed *MailText) map[string]interface{} {
|
||||
changes := make(map[string]interface{}, 8)
|
||||
|
||||
changes["mailTextType"] = changed.MailTextType
|
||||
|
||||
changes["language"] = changed.Language
|
||||
|
||||
if changed.Title != p.Title {
|
||||
changes["title"] = changed.Title
|
||||
}
|
||||
|
||||
if changed.PreHeader != p.PreHeader {
|
||||
changes["preHeader"] = changed.PreHeader
|
||||
}
|
||||
|
||||
if changed.Subject != p.Subject {
|
||||
changes["subject"] = changed.Subject
|
||||
}
|
||||
|
||||
if changed.Greeting != p.Greeting {
|
||||
changes["greeting"] = changed.Greeting
|
||||
}
|
||||
|
||||
if changed.Text != p.Text {
|
||||
changes["text"] = changed.Text
|
||||
}
|
||||
|
||||
if changed.ButtonText != p.ButtonText {
|
||||
changes["buttonText"] = changed.ButtonText
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
func (i *IAM) appendAddMailTextEvent(event *es_models.Event) error {
|
||||
mailText := &MailText{}
|
||||
err := mailText.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mailText.ObjectRoot.CreationDate = event.CreationDate
|
||||
i.DefaultMailTexts = append(i.DefaultMailTexts, mailText)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IAM) appendChangeMailTextEvent(event *es_models.Event) error {
|
||||
mailText := &MailText{}
|
||||
err := mailText.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n, m := GetMailText(i.DefaultMailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
||||
i.DefaultMailTexts[n] = mailText
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IAM) appendRemoveMailTextEvent(event *es_models.Event) error {
|
||||
mailText := &MailText{}
|
||||
err := mailText.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n, m := GetMailText(i.DefaultMailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
||||
i.DefaultMailTexts[n] = i.DefaultMailTexts[len(i.DefaultMailTexts)-1]
|
||||
i.DefaultMailTexts[len(i.DefaultMailTexts)-1] = nil
|
||||
i.DefaultMailTexts = i.DefaultMailTexts[:len(i.DefaultMailTexts)-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MailText) SetDataLabel(event *es_models.Event) error {
|
||||
err := json.Unmarshal(event.Data, p)
|
||||
if err != nil {
|
||||
return errors.ThrowInternal(err, "MODEL-3FUV5", "unable to unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
134
internal/iam/repository/eventsourcing/model/mail_text_test.go
Normal file
134
internal/iam/repository/eventsourcing/model/mail_text_test.go
Normal file
@ -0,0 +1,134 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
)
|
||||
|
||||
func TestAppendAddMailTextEvent(t *testing.T) {
|
||||
type args struct {
|
||||
iam *IAM
|
||||
mailText *MailText
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *IAM
|
||||
}{
|
||||
{
|
||||
name: "append add mailText event",
|
||||
args: args{
|
||||
iam: &IAM{},
|
||||
mailText: &MailText{
|
||||
MailTextType: "PasswordReset",
|
||||
Language: "DE"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
||||
MailTextType: "PasswordReset",
|
||||
Language: "DE"}}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.mailText != nil {
|
||||
data, _ := json.Marshal(tt.args.mailText)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.iam.appendAddMailTextEvent(tt.args.event)
|
||||
if len(tt.args.iam.DefaultMailTexts) != 1 {
|
||||
t.Errorf("got wrong result should have one mailText actual: %v ", len(tt.args.iam.DefaultMailTexts))
|
||||
}
|
||||
if tt.args.iam.DefaultMailTexts[0] == tt.result.DefaultMailTexts[0] {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTexts[0], tt.args.iam.DefaultMailTexts[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendChangeMailTextEvent(t *testing.T) {
|
||||
type args struct {
|
||||
iam *IAM
|
||||
mailText *MailText
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *IAM
|
||||
}{
|
||||
{
|
||||
name: "append change mailText event",
|
||||
args: args{
|
||||
iam: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
||||
MailTextType: "PasswordReset",
|
||||
Language: "DE"}}},
|
||||
mailText: &MailText{
|
||||
MailTextType: "ChangedPasswordReset",
|
||||
Language: "DE"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
||||
MailTextType: "PasswordReset",
|
||||
Language: "ChangedDE"}}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.mailText != nil {
|
||||
data, _ := json.Marshal(tt.args.mailText)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.iam.appendChangeMailTextEvent(tt.args.event)
|
||||
if len(tt.args.iam.DefaultMailTexts) != 1 {
|
||||
t.Errorf("got wrong result should have one mailText actual: %v ", len(tt.args.iam.DefaultMailTexts))
|
||||
}
|
||||
if tt.args.iam.DefaultMailTexts[0] == tt.result.DefaultMailTexts[0] {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTexts[0], tt.args.iam.DefaultMailTexts[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendRemoveMailTextEvent(t *testing.T) {
|
||||
type args struct {
|
||||
iam *IAM
|
||||
mailText *MailText
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *IAM
|
||||
}{
|
||||
{
|
||||
name: "append remove mailText event",
|
||||
args: args{
|
||||
iam: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
||||
MailTextType: "PasswordReset",
|
||||
Language: "DE",
|
||||
Subject: "Subject"}}},
|
||||
mailText: &MailText{
|
||||
MailTextType: "PasswordReset",
|
||||
Language: "DE"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &IAM{DefaultMailTexts: []*MailText{}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.mailText != nil {
|
||||
data, _ := json.Marshal(tt.args.mailText)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.iam.appendRemoveMailTextEvent(tt.args.event)
|
||||
if len(tt.args.iam.DefaultMailTexts) != 0 {
|
||||
t.Errorf("got wrong result should have no mailText actual: %v ", len(tt.args.iam.DefaultMailTexts))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -38,6 +38,11 @@ const (
|
||||
LabelPolicyAdded models.EventType = "iam.policy.label.added"
|
||||
LabelPolicyChanged models.EventType = "iam.policy.label.changed"
|
||||
|
||||
MailTemplateAdded models.EventType = "iam.mail.template.added"
|
||||
MailTemplateChanged models.EventType = "iam.mail.template.changed"
|
||||
MailTextAdded models.EventType = "iam.mail.text.added"
|
||||
MailTextChanged models.EventType = "iam.mail.text.changed"
|
||||
|
||||
PasswordComplexityPolicyAdded models.EventType = "iam.policy.password.complexity.added"
|
||||
PasswordComplexityPolicyChanged models.EventType = "iam.policy.password.complexity.changed"
|
||||
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func IDPByID(db *gorm.DB, table, idpID string) (*model.IDPConfigView, error) {
|
||||
idp := new(model.IDPConfigView)
|
||||
userIDQuery := &model.IDPConfigSearchQuery{Key: iam_model.IDPConfigSearchKeyIdpConfigID, Value: idpID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
idpIDQuery := &model.IDPConfigSearchQuery{Key: iam_model.IDPConfigSearchKeyIdpConfigID, Value: idpID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, idpIDQuery)
|
||||
err := query(db, idp)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Ahq2s", "Errors.IAM.IdpNotExisting")
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func GetLabelPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.LabelPolicyView, error) {
|
||||
policy := new(model.LabelPolicyView)
|
||||
userIDQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
aggregateIDQuery := &model.LabelPolicySearchQuery{Key: iam_model.LabelPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, policy)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-68G11", "Errors.IAM.LabelPolicy.NotExisting")
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func GetLoginPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.LoginPolicyView, error) {
|
||||
policy := new(model.LoginPolicyView)
|
||||
userIDQuery := &model.LoginPolicySearchQuery{Key: iam_model.LoginPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
aggregateIDQuery := &model.LoginPolicySearchQuery{Key: iam_model.LoginPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, policy)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Lso0cs", "Errors.IAM.LoginPolicy.NotExisting")
|
||||
|
32
internal/iam/repository/view/mail_template_view.go
Normal file
32
internal/iam/repository/view/mail_template_view.go
Normal file
@ -0,0 +1,32 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
func GetMailTemplateByAggregateID(db *gorm.DB, table, aggregateID string) (*model.MailTemplateView, error) {
|
||||
template := new(model.MailTemplateView)
|
||||
aggregateIDQuery := &model.MailTemplateSearchQuery{Key: iam_model.MailTemplateSearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, template)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-iPnmU", "Errors.IAM.MailTemplate.NotExisting")
|
||||
}
|
||||
return template, err
|
||||
}
|
||||
|
||||
func PutMailTemplate(db *gorm.DB, table string, template *model.MailTemplateView) error {
|
||||
save := repository.PrepareSave(table)
|
||||
return save(db, template)
|
||||
}
|
||||
|
||||
func DeleteMailTemplate(db *gorm.DB, table, aggregateID string) error {
|
||||
delete := repository.PrepareDeleteByKey(table, model.MailTemplateSearchKey(iam_model.MailTemplateSearchKeyAggregateID), aggregateID)
|
||||
|
||||
return delete(db)
|
||||
}
|
53
internal/iam/repository/view/mail_text_view.go
Normal file
53
internal/iam/repository/view/mail_text_view.go
Normal file
@ -0,0 +1,53 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
func GetMailTexts(db *gorm.DB, table string, aggregateID string) ([]*model.MailTextView, error) {
|
||||
texts := make([]*model.MailTextView, 0)
|
||||
queries := []*iam_model.MailTextSearchQuery{
|
||||
{
|
||||
Key: iam_model.MailTextSearchKeyAggregateID,
|
||||
Value: aggregateID,
|
||||
Method: global_model.SearchMethodEquals,
|
||||
},
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.MailTextSearchRequest{Queries: queries})
|
||||
_, err := query(db, &texts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return texts, nil
|
||||
}
|
||||
|
||||
func GetMailTextByIDs(db *gorm.DB, table, aggregateID string, textType string, language string) (*model.MailTextView, error) {
|
||||
mailText := new(model.MailTextView)
|
||||
aggregateIDQuery := &model.MailTextSearchQuery{Key: iam_model.MailTextSearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
textTypeQuery := &model.MailTextSearchQuery{Key: iam_model.MailTextSearchKeyMailTextType, Value: textType, Method: global_model.SearchMethodEquals}
|
||||
languageQuery := &model.MailTextSearchQuery{Key: iam_model.MailTextSearchKeyLanguage, Value: language, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery, textTypeQuery, languageQuery)
|
||||
err := query(db, mailText)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-IiJjm", "Errors.IAM.MailText.NotExisting")
|
||||
}
|
||||
return mailText, err
|
||||
}
|
||||
|
||||
func PutMailText(db *gorm.DB, table string, mailText *model.MailTextView) error {
|
||||
save := repository.PrepareSave(table)
|
||||
return save(db, mailText)
|
||||
}
|
||||
|
||||
func DeleteMailText(db *gorm.DB, table, aggregateID string, textType string, language string) error {
|
||||
aggregateIDSearch := repository.Key{Key: model.MailTextSearchKey(iam_model.MailTextSearchKeyAggregateID), Value: aggregateID}
|
||||
textTypeSearch := repository.Key{Key: model.MailTextSearchKey(iam_model.MailTextSearchKeyMailTextType), Value: textType}
|
||||
languageSearch := repository.Key{Key: model.MailTextSearchKey(iam_model.MailTextSearchKeyLanguage), Value: language}
|
||||
delete := repository.PrepareDeleteByKeys(table, aggregateIDSearch, textTypeSearch, languageSearch)
|
||||
return delete(db)
|
||||
}
|
80
internal/iam/repository/view/model/mail_template.go
Normal file
80
internal/iam/repository/view/model/mail_template.go
Normal file
@ -0,0 +1,80 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
|
||||
es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/iam/model"
|
||||
)
|
||||
|
||||
const (
|
||||
MailTemplateKeyAggregateID = "aggregate_id"
|
||||
)
|
||||
|
||||
type MailTemplateView struct {
|
||||
AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
State int32 `json:"-" gorm:"column:mail_template_state"`
|
||||
|
||||
Template []byte `json:"template" gorm:"column:template"`
|
||||
Default bool `json:"-" gorm:"-"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func MailTemplateViewFromModel(template *model.MailTemplateView) *MailTemplateView {
|
||||
return &MailTemplateView{
|
||||
AggregateID: template.AggregateID,
|
||||
Sequence: template.Sequence,
|
||||
CreationDate: template.CreationDate,
|
||||
ChangeDate: template.ChangeDate,
|
||||
Template: template.Template,
|
||||
Default: template.Default,
|
||||
}
|
||||
}
|
||||
|
||||
func MailTemplateViewToModel(template *MailTemplateView) *model.MailTemplateView {
|
||||
return &model.MailTemplateView{
|
||||
AggregateID: template.AggregateID,
|
||||
Sequence: template.Sequence,
|
||||
CreationDate: template.CreationDate,
|
||||
ChangeDate: template.ChangeDate,
|
||||
Template: template.Template,
|
||||
Default: template.Default,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *MailTemplateView) AppendEvent(event *models.Event) (err error) {
|
||||
i.Sequence = event.Sequence
|
||||
i.ChangeDate = event.CreationDate
|
||||
switch event.Type {
|
||||
case es_model.MailTemplateAdded, org_es_model.MailTemplateAdded:
|
||||
i.setRootData(event)
|
||||
i.CreationDate = event.CreationDate
|
||||
err = i.SetData(event)
|
||||
case es_model.MailTemplateChanged, org_es_model.MailTemplateChanged:
|
||||
i.ChangeDate = event.CreationDate
|
||||
err = i.SetData(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MailTemplateView) setRootData(event *models.Event) {
|
||||
r.AggregateID = event.AggregateID
|
||||
}
|
||||
|
||||
func (r *MailTemplateView) SetData(event *models.Event) error {
|
||||
if err := json.Unmarshal(event.Data, r); err != nil {
|
||||
logging.Log("MODEL-YDZmZ").WithError(err).Error("could not unmarshal event data")
|
||||
return caos_errs.ThrowInternal(err, "MODEL-sKWwO", "Could not unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
59
internal/iam/repository/view/model/mail_template_query.go
Normal file
59
internal/iam/repository/view/model/mail_template_query.go
Normal file
@ -0,0 +1,59 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
type MailTemplateSearchRequest iam_model.MailTemplateSearchRequest
|
||||
type MailTemplateSearchQuery iam_model.MailTemplateSearchQuery
|
||||
type MailTemplateSearchKey iam_model.MailTemplateSearchKey
|
||||
|
||||
func (req MailTemplateSearchRequest) GetLimit() uint64 {
|
||||
return req.Limit
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchRequest) GetOffset() uint64 {
|
||||
return req.Offset
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchRequest) GetSortingColumn() repository.ColumnKey {
|
||||
if req.SortingColumn == iam_model.MailTemplateSearchKeyUnspecified {
|
||||
return nil
|
||||
}
|
||||
return MailTemplateSearchKey(req.SortingColumn)
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchRequest) GetAsc() bool {
|
||||
return req.Asc
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchRequest) GetQueries() []repository.SearchQuery {
|
||||
result := make([]repository.SearchQuery, len(req.Queries))
|
||||
for i, q := range req.Queries {
|
||||
result[i] = MailTemplateSearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchQuery) GetKey() repository.ColumnKey {
|
||||
return MailTemplateSearchKey(req.Key)
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchQuery) GetMethod() global_model.SearchMethod {
|
||||
return req.Method
|
||||
}
|
||||
|
||||
func (req MailTemplateSearchQuery) GetValue() interface{} {
|
||||
return req.Value
|
||||
}
|
||||
|
||||
func (key MailTemplateSearchKey) ToColumnName() string {
|
||||
switch iam_model.MailTemplateSearchKey(key) {
|
||||
case iam_model.MailTemplateSearchKeyAggregateID:
|
||||
return MailTemplateKeyAggregateID
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
117
internal/iam/repository/view/model/mail_text.go
Normal file
117
internal/iam/repository/view/model/mail_text.go
Normal file
@ -0,0 +1,117 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
|
||||
es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/iam/model"
|
||||
)
|
||||
|
||||
const (
|
||||
MailTextKeyAggregateID = "aggregate_id"
|
||||
MailTextKeyMailTextType = "mail_text_type"
|
||||
MailTextKeyLanguage = "language"
|
||||
)
|
||||
|
||||
type MailTextView struct {
|
||||
AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
State int32 `json:"-" gorm:"column:mail_text_state"`
|
||||
|
||||
MailTextType string `json:"mailTextType" gorm:"column:mail_text_type;primary_key"`
|
||||
Language string `json:"language" gorm:"column:language;primary_key"`
|
||||
Title string `json:"title" gorm:"column:title"`
|
||||
PreHeader string `json:"preHeader" gorm:"column:pre_header"`
|
||||
Subject string `json:"subject" gorm:"column:subject"`
|
||||
Greeting string `json:"greeting" gorm:"column:greeting"`
|
||||
Text string `json:"text" gorm:"column:text"`
|
||||
ButtonText string `json:"buttonText" gorm:"column:button_text"`
|
||||
Default bool `json:"-" gorm:"-"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func MailTextViewFromModel(template *model.MailTextView) *MailTextView {
|
||||
return &MailTextView{
|
||||
AggregateID: template.AggregateID,
|
||||
Sequence: template.Sequence,
|
||||
CreationDate: template.CreationDate,
|
||||
ChangeDate: template.ChangeDate,
|
||||
MailTextType: template.MailTextType,
|
||||
Language: template.Language,
|
||||
Title: template.Title,
|
||||
PreHeader: template.PreHeader,
|
||||
Subject: template.Subject,
|
||||
Greeting: template.Greeting,
|
||||
Text: template.Text,
|
||||
ButtonText: template.ButtonText,
|
||||
Default: template.Default,
|
||||
}
|
||||
}
|
||||
|
||||
func MailTextsViewToModel(textsIn []*MailTextView, defaultIn bool) *model.MailTextsView {
|
||||
return &model.MailTextsView{
|
||||
Texts: mailTextsViewToModelArr(textsIn, defaultIn),
|
||||
}
|
||||
}
|
||||
|
||||
func mailTextsViewToModelArr(texts []*MailTextView, defaultIn bool) []*model.MailTextView {
|
||||
result := make([]*model.MailTextView, len(texts))
|
||||
for i, r := range texts {
|
||||
r.Default = defaultIn
|
||||
result[i] = MailTextViewToModel(r)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func MailTextViewToModel(template *MailTextView) *model.MailTextView {
|
||||
return &model.MailTextView{
|
||||
AggregateID: template.AggregateID,
|
||||
Sequence: template.Sequence,
|
||||
CreationDate: template.CreationDate,
|
||||
ChangeDate: template.ChangeDate,
|
||||
MailTextType: template.MailTextType,
|
||||
Language: template.Language,
|
||||
Title: template.Title,
|
||||
PreHeader: template.PreHeader,
|
||||
Subject: template.Subject,
|
||||
Greeting: template.Greeting,
|
||||
Text: template.Text,
|
||||
ButtonText: template.ButtonText,
|
||||
Default: template.Default,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *MailTextView) AppendEvent(event *models.Event) (err error) {
|
||||
i.Sequence = event.Sequence
|
||||
switch event.Type {
|
||||
case es_model.MailTextAdded, org_es_model.MailTextAdded:
|
||||
i.setRootData(event)
|
||||
i.CreationDate = event.CreationDate
|
||||
err = i.SetData(event)
|
||||
case es_model.MailTextChanged, org_es_model.MailTextChanged:
|
||||
i.ChangeDate = event.CreationDate
|
||||
err = i.SetData(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MailTextView) setRootData(event *models.Event) {
|
||||
r.AggregateID = event.AggregateID
|
||||
}
|
||||
|
||||
func (r *MailTextView) SetData(event *models.Event) error {
|
||||
if err := json.Unmarshal(event.Data, r); err != nil {
|
||||
logging.Log("MODEL-UFqAG").WithError(err).Error("could not unmarshal event data")
|
||||
return caos_errs.ThrowInternal(err, "MODEL-5CVaR", "Could not unmarshal data")
|
||||
}
|
||||
return nil
|
||||
}
|
63
internal/iam/repository/view/model/mail_text_query.go
Normal file
63
internal/iam/repository/view/model/mail_text_query.go
Normal file
@ -0,0 +1,63 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
type MailTextSearchRequest iam_model.MailTextSearchRequest
|
||||
type MailTextSearchQuery iam_model.MailTextSearchQuery
|
||||
type MailTextSearchKey iam_model.MailTextSearchKey
|
||||
|
||||
func (req MailTextSearchRequest) GetLimit() uint64 {
|
||||
return req.Limit
|
||||
}
|
||||
|
||||
func (req MailTextSearchRequest) GetOffset() uint64 {
|
||||
return req.Offset
|
||||
}
|
||||
|
||||
func (req MailTextSearchRequest) GetSortingColumn() repository.ColumnKey {
|
||||
if req.SortingColumn == iam_model.MailTextSearchKeyUnspecified {
|
||||
return nil
|
||||
}
|
||||
return MailTextSearchKey(req.SortingColumn)
|
||||
}
|
||||
|
||||
func (req MailTextSearchRequest) GetAsc() bool {
|
||||
return req.Asc
|
||||
}
|
||||
|
||||
func (req MailTextSearchRequest) GetQueries() []repository.SearchQuery {
|
||||
result := make([]repository.SearchQuery, len(req.Queries))
|
||||
for i, q := range req.Queries {
|
||||
result[i] = MailTextSearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (req MailTextSearchQuery) GetKey() repository.ColumnKey {
|
||||
return MailTextSearchKey(req.Key)
|
||||
}
|
||||
|
||||
func (req MailTextSearchQuery) GetMethod() global_model.SearchMethod {
|
||||
return req.Method
|
||||
}
|
||||
|
||||
func (req MailTextSearchQuery) GetValue() interface{} {
|
||||
return req.Value
|
||||
}
|
||||
|
||||
func (key MailTextSearchKey) ToColumnName() string {
|
||||
switch iam_model.MailTextSearchKey(key) {
|
||||
case iam_model.MailTextSearchKeyAggregateID:
|
||||
return MailTextKeyAggregateID
|
||||
case iam_model.MailTextSearchKeyMailTextType:
|
||||
return MailTextKeyMailTextType
|
||||
case iam_model.MailTextSearchKeyLanguage:
|
||||
return MailTextKeyLanguage
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func GetOrgIAMPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.OrgIAMPolicyView, error) {
|
||||
policy := new(model.OrgIAMPolicyView)
|
||||
userIDQuery := &model.OrgIAMPolicySearchQuery{Key: iam_model.OrgIAMPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
aggregateIDQuery := &model.OrgIAMPolicySearchQuery{Key: iam_model.OrgIAMPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, policy)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-5fi9s", "Errors.IAM.OrgIAMPolicy.NotExisting")
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func GetPasswordAgePolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.PasswordAgePolicyView, error) {
|
||||
policy := new(model.PasswordAgePolicyView)
|
||||
userIDQuery := &model.PasswordAgePolicySearchQuery{Key: iam_model.PasswordAgePolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
aggregateIDQuery := &model.PasswordAgePolicySearchQuery{Key: iam_model.PasswordAgePolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, policy)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Lso0cs", "Errors.IAM.PasswordAgePolicy.NotExisting")
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func GetPasswordComplexityPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.PasswordComplexityPolicyView, error) {
|
||||
policy := new(model.PasswordComplexityPolicyView)
|
||||
userIDQuery := &model.PasswordComplexityPolicySearchQuery{Key: iam_model.PasswordComplexityPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
aggregateIDQuery := &model.PasswordComplexityPolicySearchQuery{Key: iam_model.PasswordComplexityPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, policy)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Lso0cs", "Errors.IAM.PasswordComplexityPolicy.NotExisting")
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
func GetPasswordLockoutPolicyByAggregateID(db *gorm.DB, table, aggregateID string) (*model.PasswordLockoutPolicyView, error) {
|
||||
policy := new(model.PasswordLockoutPolicyView)
|
||||
userIDQuery := &model.PasswordLockoutPolicySearchQuery{Key: iam_model.PasswordLockoutPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery)
|
||||
aggregateIDQuery := &model.PasswordLockoutPolicySearchQuery{Key: iam_model.PasswordLockoutPolicySearchKeyAggregateID, Value: aggregateID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery)
|
||||
err := query(db, policy)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Lso0cs", "Errors.IAM.PasswordLockoutPolicy.NotExisting")
|
||||
|
@ -703,3 +703,83 @@ func (repo *OrgRepository) RemovePasswordLockoutPolicy(ctx context.Context) erro
|
||||
}}
|
||||
return repo.OrgEventstore.RemovePasswordLockoutPolicy(ctx, policy)
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) {
|
||||
template, err := repo.View.MailTemplateByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
template.Default = true
|
||||
return iam_es_model.MailTemplateViewToModel(template), err
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) GetMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) {
|
||||
template, err := repo.View.MailTemplateByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if errors.IsNotFound(err) {
|
||||
template, err = repo.View.MailTemplateByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
template.Default = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTemplateViewToModel(template), err
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) AddMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
template.AggregateID = authz.GetCtxData(ctx).OrgID
|
||||
return repo.OrgEventstore.AddMailTemplate(ctx, template)
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) ChangeMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
template.AggregateID = authz.GetCtxData(ctx).OrgID
|
||||
return repo.OrgEventstore.ChangeMailTemplate(ctx, template)
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) RemoveMailTemplate(ctx context.Context) error {
|
||||
template := &iam_model.MailTemplate{ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: authz.GetCtxData(ctx).OrgID,
|
||||
}}
|
||||
return repo.OrgEventstore.RemoveMailTemplate(ctx, template)
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error) {
|
||||
texts, err := repo.View.MailTextsByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTextsViewToModel(texts, true), err
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) GetMailTexts(ctx context.Context) (*iam_model.MailTextsView, error) {
|
||||
defaultIn := false
|
||||
texts, err := repo.View.MailTextsByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if errors.IsNotFound(err) || len(texts) == 0 {
|
||||
texts, err = repo.View.MailTextsByAggregateID(repo.SystemDefaults.IamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defaultIn = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTextsViewToModel(texts, defaultIn), err
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) AddMailText(ctx context.Context, text *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
text.AggregateID = authz.GetCtxData(ctx).OrgID
|
||||
return repo.OrgEventstore.AddMailText(ctx, text)
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) ChangeMailText(ctx context.Context, text *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
text.AggregateID = authz.GetCtxData(ctx).OrgID
|
||||
return repo.OrgEventstore.ChangeMailText(ctx, text)
|
||||
}
|
||||
|
||||
func (repo *OrgRepository) RemoveMailText(ctx context.Context, text *iam_model.MailText) error {
|
||||
text.AggregateID = authz.GetCtxData(ctx).OrgID
|
||||
return repo.OrgEventstore.RemoveMailText(ctx, text)
|
||||
}
|
||||
|
@ -103,6 +103,10 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
||||
handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount, es}),
|
||||
newOrgIAMPolicy(
|
||||
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
|
||||
newMailTemplate(
|
||||
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
|
||||
newMailText(
|
||||
handler{view, bulkLimit, configs.cycleDuration("MailText"), errorCount, es}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,107 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/query"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
type MailTemplate struct {
|
||||
handler
|
||||
subscription *eventstore.Subscription
|
||||
}
|
||||
|
||||
func newMailTemplate(handler handler) *MailTemplate {
|
||||
h := &MailTemplate{
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *MailTemplate) subscribe() {
|
||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||
go func() {
|
||||
for event := range m.subscription.Events {
|
||||
query.ReduceEvent(m, event)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
const (
|
||||
mailTemplateTable = "management.mail_templates"
|
||||
)
|
||||
|
||||
func (m *MailTemplate) ViewModel() string {
|
||||
return mailTemplateTable
|
||||
}
|
||||
|
||||
func (_ *MailTemplate) AggregateTypes() []es_models.AggregateType {
|
||||
return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
|
||||
}
|
||||
|
||||
func (p *MailTemplate) CurrentSequence(event *models.Event) (uint64, error) {
|
||||
sequence, err := p.view.GetLatestMailTemplateSequence(string(event.AggregateType))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return sequence.CurrentSequence, nil
|
||||
}
|
||||
|
||||
func (m *MailTemplate) EventQuery() (*models.SearchQuery, error) {
|
||||
sequence, err := m.view.GetLatestMailTemplateSequence("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(m.AggregateTypes()...).
|
||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||
}
|
||||
|
||||
func (m *MailTemplate) Reduce(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case model.OrgAggregate, iam_es_model.IAMAggregate:
|
||||
err = m.processMailTemplate(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *MailTemplate) processMailTemplate(event *models.Event) (err error) {
|
||||
template := new(iam_model.MailTemplateView)
|
||||
switch event.Type {
|
||||
case iam_es_model.MailTemplateAdded, model.MailTemplateAdded:
|
||||
err = template.AppendEvent(event)
|
||||
case iam_es_model.MailTemplateChanged, model.MailTemplateChanged:
|
||||
template, err = m.view.MailTemplateByAggregateID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = template.AppendEvent(event)
|
||||
case model.MailTemplateRemoved:
|
||||
return m.view.DeleteMailTemplate(event.AggregateID, event)
|
||||
default:
|
||||
return m.view.ProcessedMailTemplateSequence(event)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutMailTemplate(template, event)
|
||||
}
|
||||
|
||||
func (m *MailTemplate) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in label template handler")
|
||||
return spooler.HandleError(event, err, m.view.GetLatestMailTemplateFailedEvent, m.view.ProcessedMailTemplateFailedEvent, m.view.ProcessedMailTemplateSequence, m.errorCountUntilSkip)
|
||||
}
|
||||
|
||||
func (o *MailTemplate) OnSuccess() error {
|
||||
return spooler.HandleSuccess(o.view.UpdateMailTemplateSpoolerRunTimestamp)
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/query"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
type MailText struct {
|
||||
handler
|
||||
subscription *eventstore.Subscription
|
||||
}
|
||||
|
||||
func newMailText(handler handler) *MailText {
|
||||
h := &MailText{
|
||||
handler: handler,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *MailText) subscribe() {
|
||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||
go func() {
|
||||
for event := range m.subscription.Events {
|
||||
query.ReduceEvent(m, event)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
const (
|
||||
mailTextTable = "management.mail_texts"
|
||||
)
|
||||
|
||||
func (m *MailText) ViewModel() string {
|
||||
return mailTextTable
|
||||
}
|
||||
|
||||
func (_ *MailText) AggregateTypes() []es_models.AggregateType {
|
||||
return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
|
||||
}
|
||||
|
||||
func (p *MailText) CurrentSequence(event *models.Event) (uint64, error) {
|
||||
sequence, err := p.view.GetLatestMailTextSequence(string(event.AggregateType))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return sequence.CurrentSequence, nil
|
||||
}
|
||||
|
||||
func (m *MailText) EventQuery() (*models.SearchQuery, error) {
|
||||
sequence, err := m.view.GetLatestMailTextSequence("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(m.AggregateTypes()...).
|
||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||
}
|
||||
|
||||
func (m *MailText) Reduce(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case model.OrgAggregate, iam_es_model.IAMAggregate:
|
||||
err = m.processMailText(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *MailText) processMailText(event *models.Event) (err error) {
|
||||
text := new(iam_model.MailTextView)
|
||||
switch event.Type {
|
||||
case iam_es_model.MailTextAdded, model.MailTextAdded:
|
||||
err = text.AppendEvent(event)
|
||||
case iam_es_model.MailTextChanged, model.MailTextChanged:
|
||||
err = text.SetData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
text, err = m.view.MailTextByIDs(event.AggregateID, text.MailTextType, text.Language)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
text.ChangeDate = event.CreationDate
|
||||
err = text.AppendEvent(event)
|
||||
case model.MailTextRemoved:
|
||||
err = text.SetData(event)
|
||||
return m.view.DeleteMailText(event.AggregateID, text.MailTextType, text.Language, event)
|
||||
default:
|
||||
return m.view.ProcessedMailTextSequence(event)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutMailText(text, event)
|
||||
}
|
||||
|
||||
func (m *MailText) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in label text handler")
|
||||
return spooler.HandleError(event, err, m.view.GetLatestMailTextFailedEvent, m.view.ProcessedMailTextFailedEvent, m.view.ProcessedMailTextSequence, m.errorCountUntilSkip)
|
||||
}
|
||||
|
||||
func (o *MailText) OnSuccess() error {
|
||||
return spooler.HandleSuccess(o.view.UpdateMailTextSpoolerRunTimestamp)
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
mailTemplateTable = "management.mail_templates"
|
||||
)
|
||||
|
||||
func (v *View) MailTemplateByAggregateID(aggregateID string) (*model.MailTemplateView, error) {
|
||||
return view.GetMailTemplateByAggregateID(v.Db, mailTemplateTable, aggregateID)
|
||||
}
|
||||
|
||||
func (v *View) PutMailTemplate(template *model.MailTemplateView, event *models.Event) error {
|
||||
err := view.PutMailTemplate(v.Db, mailTemplateTable, template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedMailTemplateSequence(event)
|
||||
}
|
||||
|
||||
func (v *View) DeleteMailTemplate(aggregateID string, event *models.Event) error {
|
||||
err := view.DeleteMailTemplate(v.Db, mailTemplateTable, aggregateID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedMailTemplateSequence(event)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTemplateSequence(aggregateType string) (*global_view.CurrentSequence, error) {
|
||||
return v.latestSequence(mailTemplateTable, aggregateType)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTemplateSequence(event *models.Event) error {
|
||||
return v.saveCurrentSequence(mailTemplateTable, event)
|
||||
}
|
||||
|
||||
func (v *View) UpdateMailTemplateSpoolerRunTimestamp() error {
|
||||
return v.updateSpoolerRunSequence(mailTemplateTable)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTemplateFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||
return v.latestFailedEvent(mailTemplateTable, sequence)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTemplateFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||
return v.saveFailedEvent(failedEvent)
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
mailTextTable = "management.mail_texts"
|
||||
)
|
||||
|
||||
func (v *View) MailTextsByAggregateID(aggregateID string) ([]*model.MailTextView, error) {
|
||||
return view.GetMailTexts(v.Db, mailTextTable, aggregateID)
|
||||
}
|
||||
|
||||
func (v *View) MailTextByIDs(aggregateID string, textType string, language string) (*model.MailTextView, error) {
|
||||
return view.GetMailTextByIDs(v.Db, mailTextTable, aggregateID, textType, language)
|
||||
}
|
||||
|
||||
func (v *View) PutMailText(template *model.MailTextView, event *models.Event) error {
|
||||
err := view.PutMailText(v.Db, mailTextTable, template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedMailTextSequence(event)
|
||||
}
|
||||
|
||||
func (v *View) DeleteMailText(aggregateID string, textType string, language string, event *models.Event) error {
|
||||
err := view.DeleteMailText(v.Db, mailTextTable, aggregateID, textType, language)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedMailTextSequence(event)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTextSequence(aggregateType string) (*global_view.CurrentSequence, error) {
|
||||
return v.latestSequence(mailTextTable, aggregateType)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTextSequence(event *models.Event) error {
|
||||
return v.saveCurrentSequence(mailTextTable, event)
|
||||
}
|
||||
|
||||
func (v *View) UpdateMailTextSpoolerRunTimestamp() error {
|
||||
return v.updateSpoolerRunSequence(mailTextTable)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestMailTextFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||
return v.latestFailedEvent(mailTextTable, sequence)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedMailTextFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||
return v.saveFailedEvent(failedEvent)
|
||||
}
|
@ -2,6 +2,7 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
@ -73,4 +74,16 @@ type OrgRepository interface {
|
||||
AddPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error)
|
||||
ChangePasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error)
|
||||
RemovePasswordLockoutPolicy(ctx context.Context) error
|
||||
|
||||
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||
GetMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||
AddMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error)
|
||||
ChangeMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error)
|
||||
RemoveMailTemplate(ctx context.Context) error
|
||||
|
||||
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
||||
GetMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
||||
AddMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
||||
ChangeMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_model.MailText, error)
|
||||
RemoveMailText(ctx context.Context, mailText *iam_model.MailText) error
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
@ -24,10 +25,19 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
notificationTable = "notification.notifications"
|
||||
NotifyUserID = "NOTIFICATION"
|
||||
labelPolicyTableOrg = "management.label_policies"
|
||||
labelPolicyTableDef = "adminapi.label_policies"
|
||||
notificationTable = "notification.notifications"
|
||||
NotifyUserID = "NOTIFICATION"
|
||||
labelPolicyTableOrg = "management.label_policies"
|
||||
labelPolicyTableDef = "adminapi.label_policies"
|
||||
mailTemplateTableOrg = "management.mail_templates"
|
||||
mailTemplateTableDef = "adminapi.mail_templates"
|
||||
mailTextTableOrg = "management.mail_texts"
|
||||
mailTextTableDef = "adminapi.mail_texts"
|
||||
mailTextTypeDomainClaimed = "DomainClaimed"
|
||||
mailTextTypeInitCode = "InitCode"
|
||||
mailTextTypePasswordReset = "PasswordReset"
|
||||
mailTextTypeVerifyEmail = "VerifyEmail"
|
||||
mailTextTypeVerifyPhone = "VerifyPhone"
|
||||
)
|
||||
|
||||
type Notification struct {
|
||||
@ -135,11 +145,22 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := n.getMailTemplate(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := n.view.NotifyUserByID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendUserInitCode(n.statikDir, n.i18n, user, initCode, n.systemDefaults, n.AesCrypto, colors)
|
||||
|
||||
text, err := n.getMailText(context.Background(), mailTextTypeInitCode, user.PreferredLanguage[len(user.PreferredLanguage)-2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendUserInitCode(string(template.Template), text, user, initCode, n.systemDefaults, n.AesCrypto, colors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -163,11 +184,21 @@ func (n *Notification) handlePasswordCode(event *models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := n.getMailTemplate(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := n.view.NotifyUserByID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendPasswordCode(n.statikDir, n.i18n, user, pwCode, n.systemDefaults, n.AesCrypto, colors)
|
||||
|
||||
text, err := n.getMailText(context.Background(), mailTextTypePasswordReset, user.PreferredLanguage[len(user.PreferredLanguage)-2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendPasswordCode(string(template.Template), text, user, pwCode, n.systemDefaults, n.AesCrypto, colors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -191,11 +222,22 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := n.getMailTemplate(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := n.view.NotifyUserByID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendEmailVerificationCode(n.statikDir, n.i18n, user, emailCode, n.systemDefaults, n.AesCrypto, colors)
|
||||
|
||||
text, err := n.getMailText(context.Background(), mailTextTypeVerifyEmail, user.PreferredLanguage[len(user.PreferredLanguage)-2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendEmailVerificationCode(string(template.Template), text, user, emailCode, n.systemDefaults, n.AesCrypto, colors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -238,7 +280,21 @@ func (n *Notification) handleDomainClaimed(event *models.Event) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendDomainClaimed(n.statikDir, n.i18n, user, data["userName"], n.systemDefaults)
|
||||
colors, err := n.getLabelPolicy(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := n.getMailTemplate(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
text, err := n.getMailText(context.Background(), mailTextTypeDomainClaimed, user.PreferredLanguage[len(user.PreferredLanguage)-2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendDomainClaimed(string(template.Template), text, user, data["userName"], n.systemDefaults, colors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -306,3 +362,39 @@ func (n *Notification) getLabelPolicy(ctx context.Context) (*iam_model.LabelPoli
|
||||
}
|
||||
return iam_es_model.LabelPolicyViewToModel(policy), err
|
||||
}
|
||||
|
||||
// Read organization specific template
|
||||
func (n *Notification) getMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error) {
|
||||
// read from Org
|
||||
template, err := n.view.MailTemplateByAggregateID(authz.GetCtxData(ctx).OrgID, mailTemplateTableOrg)
|
||||
if errors.IsNotFound(err) {
|
||||
// read from default
|
||||
template, err = n.view.MailTemplateByAggregateID(n.systemDefaults.IamID, mailTemplateTableDef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
template.Default = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTemplateViewToModel(template), err
|
||||
}
|
||||
|
||||
// Read organization specific texts
|
||||
func (n *Notification) getMailText(ctx context.Context, textType string, language string) (*iam_model.MailTextView, error) {
|
||||
// read from Org
|
||||
mailText, err := n.view.MailTextByIDs(authz.GetCtxData(ctx).OrgID, textType, language, mailTextTableOrg)
|
||||
if errors.IsNotFound(err) {
|
||||
// read from default
|
||||
mailText, err = n.view.MailTextByIDs(n.systemDefaults.IamID, textType, language, mailTextTableDef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mailText.Default = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTextViewToModel(mailText), err
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
)
|
||||
|
||||
func (v *View) MailTemplateByAggregateID(aggregateID string, mailTemplateTableVar string) (*model.MailTemplateView, error) {
|
||||
return view.GetMailTemplateByAggregateID(v.Db, mailTemplateTableVar, aggregateID)
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||
)
|
||||
|
||||
func (v *View) MailTextByIDs(aggregateID string, textType string, language string, mailTextTableVar string) (*model.MailTextView, error) {
|
||||
return view.GetMailTextByIDs(v.Db, mailTextTableVar, aggregateID, textType, language)
|
||||
}
|
@ -12,23 +12,21 @@ const (
|
||||
templateFileName = "template.html"
|
||||
)
|
||||
|
||||
func GetParsedTemplate(dir http.FileSystem, contentData interface{}) (string, error) {
|
||||
template, err := ParseTemplateFile(dir, "", contentData)
|
||||
func GetParsedTemplate(mailhtml string, contentData interface{}) (string, error) {
|
||||
template, err := ParseTemplateFile(mailhtml, contentData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ParseTemplateText(template, contentData)
|
||||
}
|
||||
|
||||
func ParseTemplateFile(dir http.FileSystem, fileName string, data interface{}) (string, error) {
|
||||
if fileName == "" {
|
||||
fileName = templateFileName
|
||||
}
|
||||
template, err := readFile(dir, fileName)
|
||||
func ParseTemplateFile(mailhtml string, data interface{}) (string, error) {
|
||||
tmpl, err := template.New("tmpl").Parse(mailhtml)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return parseTemplate(template, data)
|
||||
|
||||
return parseTemplate(tmpl, data)
|
||||
}
|
||||
|
||||
func ParseTemplateText(text string, data interface{}) (string, error) {
|
||||
@ -63,3 +61,20 @@ func readFile(dir http.FileSystem, fileName string) (*template.Template, error)
|
||||
}
|
||||
return tmpl, nil
|
||||
}
|
||||
|
||||
func readFileFromDatabase(dir http.FileSystem, fileName string) (*template.Template, error) {
|
||||
f, err := dir.Open(templatesPath + "/" + fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
content, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmpl, err := template.New(fileName).Parse(string(content))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tmpl, nil
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"html"
|
||||
"strings"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
@ -15,7 +15,7 @@ type DomainClaimedData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendDomainClaimed(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults) error {
|
||||
func SendDomainClaimed(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, colors *iam_model.LabelPolicyView) error {
|
||||
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
@ -27,11 +27,28 @@ func SendDomainClaimed(dir http.FileSystem, i18n *i18n.Translator, user *view_mo
|
||||
"TempUsername": username,
|
||||
"Domain": strings.Split(user.LastEmail, "@")[1],
|
||||
}
|
||||
systemDefaults.Notifications.TemplateData.DomainClaimed.Translate(i18n, args, user.PreferredLanguage)
|
||||
data := &DomainClaimedData{TemplateData: systemDefaults.Notifications.TemplateData.DomainClaimed, URL: url}
|
||||
template, err := templates.GetParsedTemplate(dir, data)
|
||||
|
||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||
text.Text = html.UnescapeString(text.Text)
|
||||
|
||||
emailCodeData := &DomainClaimedData{
|
||||
TemplateData: templates.TemplateData{
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: html.UnescapeString(text.Text),
|
||||
Href: url,
|
||||
ButtonText: text.ButtonText,
|
||||
PrimaryColor: colors.PrimaryColor,
|
||||
SecondaryColor: colors.SecondaryColor,
|
||||
},
|
||||
URL: url,
|
||||
}
|
||||
template, err := templates.GetParsedTemplate(mailhtml, emailCodeData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, systemDefaults.Notifications.TemplateData.DomainClaimed.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(user, text.Subject, template, systemDefaults.Notifications, true)
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"html"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@ -17,7 +16,7 @@ type EmailVerificationCodeData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendEmailVerificationCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
|
||||
func SendEmailVerificationCode(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -31,15 +30,29 @@ func SendEmailVerificationCode(dir http.FileSystem, i18n *i18n.Translator, user
|
||||
"LastName": user.LastName,
|
||||
"Code": codeString,
|
||||
}
|
||||
systemDefaults.Notifications.TemplateData.VerifyEmail.Translate(i18n, args, user.PreferredLanguage)
|
||||
emailCodeData := &EmailVerificationCodeData{TemplateData: systemDefaults.Notifications.TemplateData.VerifyEmail, URL: url}
|
||||
|
||||
// Set the color in initCodeData
|
||||
emailCodeData.PrimaryColor = colors.PrimaryColor
|
||||
emailCodeData.SecondaryColor = colors.SecondaryColor
|
||||
template, err := templates.GetParsedTemplate(dir, emailCodeData)
|
||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||
text.Text = html.UnescapeString(text.Text)
|
||||
|
||||
emailCodeData := &EmailVerificationCodeData{
|
||||
TemplateData: templates.TemplateData{
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: html.UnescapeString(text.Text),
|
||||
Href: url,
|
||||
ButtonText: text.ButtonText,
|
||||
PrimaryColor: colors.PrimaryColor,
|
||||
SecondaryColor: colors.SecondaryColor,
|
||||
},
|
||||
URL: url,
|
||||
}
|
||||
|
||||
template, err := templates.GetParsedTemplate(mailhtml, emailCodeData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, systemDefaults.Notifications.TemplateData.VerifyEmail.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(user, text.Subject, template, systemDefaults.Notifications, true)
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"html"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@ -23,7 +22,7 @@ type UrlData struct {
|
||||
PasswordSet bool
|
||||
}
|
||||
|
||||
func SendUserInitCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
|
||||
func SendUserInitCode(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -38,15 +37,28 @@ func SendUserInitCode(dir http.FileSystem, i18n *i18n.Translator, user *view_mod
|
||||
"Code": codeString,
|
||||
"PreferredLoginName": user.PreferredLoginName,
|
||||
}
|
||||
systemDefaults.Notifications.TemplateData.InitCode.Translate(i18n, args, user.PreferredLanguage)
|
||||
initCodeData := &InitCodeEmailData{TemplateData: systemDefaults.Notifications.TemplateData.InitCode, URL: url}
|
||||
|
||||
// Set the color in initCodeData
|
||||
initCodeData.PrimaryColor = colors.PrimaryColor
|
||||
initCodeData.SecondaryColor = colors.SecondaryColor
|
||||
template, err := templates.GetParsedTemplate(dir, initCodeData)
|
||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||
text.Text = html.UnescapeString(text.Text)
|
||||
|
||||
emailCodeData := &InitCodeEmailData{
|
||||
TemplateData: templates.TemplateData{
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: html.UnescapeString(text.Text),
|
||||
Href: url,
|
||||
ButtonText: text.ButtonText,
|
||||
PrimaryColor: colors.PrimaryColor,
|
||||
SecondaryColor: colors.SecondaryColor,
|
||||
},
|
||||
URL: url,
|
||||
}
|
||||
template, err := templates.GetParsedTemplate(mailhtml, emailCodeData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, systemDefaults.Notifications.TemplateData.InitCode.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(user, text.Subject, template, systemDefaults.Notifications, true)
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"html"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@ -19,7 +18,7 @@ type PasswordCodeData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendPasswordCode(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
|
||||
func SendPasswordCode(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -33,15 +32,30 @@ func SendPasswordCode(dir http.FileSystem, i18n *i18n.Translator, user *view_mod
|
||||
"LastName": user.LastName,
|
||||
"Code": codeString,
|
||||
}
|
||||
systemDefaults.Notifications.TemplateData.PasswordReset.Translate(i18n, args, user.PreferredLanguage)
|
||||
passwordCodeData := &PasswordCodeData{TemplateData: systemDefaults.Notifications.TemplateData.PasswordReset, FirstName: user.FirstName, LastName: user.LastName, URL: url}
|
||||
|
||||
// Set the color in initCodeData
|
||||
passwordCodeData.PrimaryColor = colors.PrimaryColor
|
||||
passwordCodeData.SecondaryColor = colors.SecondaryColor
|
||||
template, err := templates.GetParsedTemplate(dir, passwordCodeData)
|
||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||
text.Text = html.UnescapeString(text.Text)
|
||||
|
||||
emailCodeData := &PasswordCodeData{
|
||||
TemplateData: templates.TemplateData{
|
||||
Title: text.Title,
|
||||
PreHeader: text.PreHeader,
|
||||
Subject: text.Subject,
|
||||
Greeting: text.Greeting,
|
||||
Text: html.UnescapeString(text.Text),
|
||||
Href: url,
|
||||
ButtonText: text.ButtonText,
|
||||
PrimaryColor: colors.PrimaryColor,
|
||||
SecondaryColor: colors.SecondaryColor,
|
||||
},
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
URL: url,
|
||||
}
|
||||
template, err := templates.GetParsedTemplate(mailhtml, emailCodeData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, systemDefaults.Notifications.TemplateData.PasswordReset.Subject, template, systemDefaults.Notifications, false)
|
||||
return generateEmail(user, text.Subject, template, systemDefaults.Notifications, true)
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ type Org struct {
|
||||
OrgIamPolicy *iam_model.OrgIAMPolicy
|
||||
LoginPolicy *iam_model.LoginPolicy
|
||||
LabelPolicy *iam_model.LabelPolicy
|
||||
MailTemplate *iam_model.MailTemplate
|
||||
MailTexts []*iam_model.MailText
|
||||
PasswordComplexityPolicy *iam_model.PasswordComplexityPolicy
|
||||
PasswordAgePolicy *iam_model.PasswordAgePolicy
|
||||
PasswordLockoutPolicy *iam_model.PasswordLockoutPolicy
|
||||
|
@ -1153,3 +1153,121 @@ func (es *OrgEventstore) RemovePasswordLockoutPolicy(ctx context.Context, policy
|
||||
addAggregate := PasswordLockoutPolicyRemovedAggregate(es.Eventstore.AggregateCreator(), repoOrg)
|
||||
return es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
}
|
||||
|
||||
func (es *OrgEventstore) AddMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
if template == nil || !template.IsValid() {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-nb66d", "Errors.Org.MailTemplateInvalid")
|
||||
}
|
||||
org, err := es.OrgByID(ctx, org_model.NewOrg(template.AggregateID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoOrg := model.OrgFromModel(org)
|
||||
repoMailTemplate := iam_es_model.MailTemplateFromModel(template)
|
||||
|
||||
addAggregate := MailTemplateAddedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoMailTemplate)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iam_es_model.MailTemplateToModel(repoOrg.MailTemplate), nil
|
||||
}
|
||||
|
||||
func (es *OrgEventstore) ChangeMailTemplate(ctx context.Context, template *iam_model.MailTemplate) (*iam_model.MailTemplate, error) {
|
||||
if template == nil || !template.IsValid() {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-FV2qE", "Errors.Org.MailTemplateInvalid")
|
||||
}
|
||||
org, err := es.OrgByID(ctx, org_model.NewOrg(template.AggregateID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoOrg := model.OrgFromModel(org)
|
||||
repoMailTemplate := iam_es_model.MailTemplateFromModel(template)
|
||||
|
||||
addAggregate := MailTemplateChangedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoMailTemplate)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoOrg.MailTemplate.Template = repoMailTemplate.Template
|
||||
return iam_es_model.MailTemplateToModel(repoOrg.MailTemplate), nil
|
||||
}
|
||||
|
||||
func (es *OrgEventstore) RemoveMailTemplate(ctx context.Context, template *iam_model.MailTemplate) error {
|
||||
if template == nil || !template.IsValid() {
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-LulaW", "Errors.Org.MailTemplate.Invalid")
|
||||
}
|
||||
org, err := es.OrgByID(ctx, org_model.NewOrg(template.AggregateID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoOrg := model.OrgFromModel(org)
|
||||
|
||||
addAggregate := MailTemplateRemovedAggregate(es.Eventstore.AggregateCreator(), repoOrg)
|
||||
return es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
}
|
||||
|
||||
func (es *OrgEventstore) AddMailText(ctx context.Context, mailtext *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
if mailtext == nil || !mailtext.IsValid() {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-108Iz", "Errors.Org.MailTextInvalid")
|
||||
}
|
||||
org, err := es.OrgByID(ctx, org_model.NewOrg(mailtext.AggregateID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoOrg := model.OrgFromModel(org)
|
||||
repoMailText := iam_es_model.MailTextFromModel(mailtext)
|
||||
|
||||
addAggregate := MailTextAddedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoMailText)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, r := iam_es_model.GetMailText(repoOrg.MailTexts, repoMailText.MailTextType, repoMailText.Language); r != nil {
|
||||
return iam_es_model.MailTextToModel(r), nil
|
||||
}
|
||||
return nil, errors.ThrowInternal(nil, "EVENT-oc1GN", "Errors.Internal")
|
||||
}
|
||||
|
||||
func (es *OrgEventstore) ChangeMailText(ctx context.Context, mailtext *iam_model.MailText) (*iam_model.MailText, error) {
|
||||
if mailtext == nil || !mailtext.IsValid() {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-fdbqE", "Errors.Org.MailTextInvalid")
|
||||
}
|
||||
org, err := es.OrgByID(ctx, org_model.NewOrg(mailtext.AggregateID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoOrg := model.OrgFromModel(org)
|
||||
repoMailText := iam_es_model.MailTextFromModel(mailtext)
|
||||
|
||||
addAggregate := MailTextChangedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoMailText)
|
||||
err = es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, r := iam_es_model.GetMailText(repoOrg.MailTexts, mailtext.MailTextType, mailtext.Language); r != nil {
|
||||
return iam_es_model.MailTextToModel(r), nil
|
||||
}
|
||||
return nil, errors.ThrowInternal(nil, "EVENT-F2whI", "Errors.Internal")
|
||||
}
|
||||
|
||||
func (es *OrgEventstore) RemoveMailText(ctx context.Context, mailtext *iam_model.MailText) error {
|
||||
if mailtext == nil || !mailtext.IsValid() {
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-LulaW", "Errors.Org.MailText.Invalid")
|
||||
}
|
||||
org, err := es.OrgByID(ctx, org_model.NewOrg(mailtext.AggregateID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoOrg := model.OrgFromModel(org)
|
||||
repoMailText := iam_es_model.MailTextFromModel(mailtext)
|
||||
|
||||
addAggregate := MailTextRemovedAggregate(es.Eventstore.AggregateCreator(), repoOrg, repoMailText)
|
||||
return es_sdk.Push(ctx, es.PushAggregates, repoOrg.AppendEvents, addAggregate)
|
||||
}
|
||||
|
@ -192,3 +192,31 @@ func GetMockChangesOrgWithLabelPolicy(ctrl *gomock.Controller) *OrgEventstore {
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockChangesOrgWithMailTemplate(ctrl *gomock.Controller) *OrgEventstore {
|
||||
orgData, _ := json.Marshal(model.Org{Name: "MusterOrg"})
|
||||
mailTemplate, _ := json.Marshal(iam_es_model.MailTemplate{Template: []byte("<!doctype htm>")})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.OrgAdded, Data: orgData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.MailTemplateAdded, Data: mailTemplate},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
||||
func GetMockChangesOrgWithMailText(ctrl *gomock.Controller) *OrgEventstore {
|
||||
orgData, _ := json.Marshal(model.Org{Name: "MusterOrg"})
|
||||
mailText, _ := json.Marshal(iam_es_model.MailText{MailTextType: "Type", Language: "DE"})
|
||||
events := []*es_models.Event{
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.OrgAdded, Data: orgData},
|
||||
&es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: model.MailTextAdded, Data: mailText},
|
||||
}
|
||||
mockEs := mock.NewMockEventstore(ctrl)
|
||||
mockEs.EXPECT().FilterEvents(gomock.Any(), gomock.Any()).Return(events, nil)
|
||||
mockEs.EXPECT().AggregateCreator().Return(es_models.NewAggregateCreator("TEST"))
|
||||
mockEs.EXPECT().PushAggregates(gomock.Any(), gomock.Any()).Return(nil)
|
||||
return GetMockedEventstore(ctrl, mockEs)
|
||||
}
|
||||
|
@ -3996,3 +3996,327 @@ func TestRemovePasswordLockoutPolicy(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddMailTemplate(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *OrgEventstore
|
||||
ctx context.Context
|
||||
template *iam_model.MailTemplate
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailTemplate
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add label template, ok",
|
||||
args: args{
|
||||
es: GetMockChangesOrgOK(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid template",
|
||||
args: args{
|
||||
es: GetMockChangesOrgOK(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing org not found",
|
||||
args: args{
|
||||
es: GetMockChangesOrgNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.AddMailTemplate(tt.args.ctx, tt.args.template)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.Template) != string(tt.res.result.Template) {
|
||||
t.Errorf("got wrong result Template: expected: %v, actual: %v ", tt.res.result.Template, result.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeMailTemplate(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *OrgEventstore
|
||||
ctx context.Context
|
||||
template *iam_model.MailTemplate
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailTemplate
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add mail template, ok",
|
||||
args: args{
|
||||
es: GetMockChangesOrgWithMailTemplate(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid template",
|
||||
args: args{
|
||||
es: GetMockChangesOrgOK(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing iam not found",
|
||||
args: args{
|
||||
es: GetMockChangesOrgNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
template: &iam_model.MailTemplate{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ChangeMailTemplate(tt.args.ctx, tt.args.template)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.Template) != string(tt.res.result.Template) {
|
||||
t.Errorf("got wrong result Template: expected: %v, actual: %v ", tt.res.result.Template, result.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddMailText(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *OrgEventstore
|
||||
ctx context.Context
|
||||
mailtext *iam_model.MailText
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailText
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add label mailtext, ok",
|
||||
args: args{
|
||||
es: GetMockChangesOrgOK(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
mailtext: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type",
|
||||
Language: "DE",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type",
|
||||
Language: "DE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid mailtext",
|
||||
args: args{
|
||||
es: GetMockChangesOrgOK(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
mailtext: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing org not found",
|
||||
args: args{
|
||||
es: GetMockChangesOrgNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
mailtext: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.AddMailText(tt.args.ctx, tt.args.mailtext)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if result.MailTextType != tt.res.result.MailTextType {
|
||||
t.Errorf("got wrong result MailTextType: expected: %v, actual: %v ", tt.res.result.MailTextType, result.MailTextType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeMailText(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
type args struct {
|
||||
es *OrgEventstore
|
||||
ctx context.Context
|
||||
mailtext *iam_model.MailText
|
||||
}
|
||||
type res struct {
|
||||
result *iam_model.MailText
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add label mailtext, ok",
|
||||
args: args{
|
||||
es: GetMockChangesOrgWithMailText(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
mailtext: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type",
|
||||
Language: "DE",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
result: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
MailTextType: "Type",
|
||||
Language: "DE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid mailtext",
|
||||
args: args{
|
||||
es: GetMockChangesOrgOK(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
mailtext: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing iam not found",
|
||||
args: args{
|
||||
es: GetMockChangesOrgNoEvents(ctrl),
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
mailtext: &iam_model.MailText{
|
||||
ObjectRoot: es_models.ObjectRoot{AggregateID: "AggregateID", Sequence: 0},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := tt.args.es.ChangeMailText(tt.args.ctx, tt.args.mailtext)
|
||||
if (tt.res.wantErr && !tt.res.errFunc(err)) || (err != nil && !tt.res.wantErr) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
return
|
||||
}
|
||||
if tt.res.wantErr && tt.res.errFunc(err) {
|
||||
return
|
||||
}
|
||||
if string(result.MailTextType) != string(tt.res.result.MailTextType) {
|
||||
t.Errorf("got wrong result MailTextType: expected: %v, actual: %v ", tt.res.result.MailTextType, result.MailTextType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func TestLabelPolicyAddedAggregate(t *testing.T) {
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add label polciy",
|
||||
name: "add label policy",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{
|
||||
|
77
internal/org/repository/eventsourcing/mail_template.go
Normal file
77
internal/org/repository/eventsourcing/mail_template.go
Normal file
@ -0,0 +1,77 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func MailTemplateAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, policy *iam_es_model.MailTemplate) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if policy == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-4BeRi", "Errors.Internal")
|
||||
}
|
||||
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validationQuery := es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.OrgAggregate).
|
||||
AggregateIDFilter(existing.AggregateID)
|
||||
|
||||
validation := checkExistingMailTemplateValidation()
|
||||
agg.SetPrecondition(validationQuery, validation)
|
||||
return agg.AppendEvent(model.MailTemplateAdded, policy)
|
||||
}
|
||||
}
|
||||
|
||||
func MailTemplateChangedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, template *iam_es_model.MailTemplate) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if template == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-yzXO0", "Errors.Internal")
|
||||
}
|
||||
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := existing.MailTemplate.Changes(template)
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-erTCI", "Errors.NoChangesFound")
|
||||
}
|
||||
return agg.AppendEvent(model.MailTemplateChanged, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func MailTemplateRemovedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-2jVit", "Errors.Internal")
|
||||
}
|
||||
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return agg.AppendEvent(model.MailTemplateRemoved, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func checkExistingMailTemplateValidation() func(...*es_models.Event) error {
|
||||
return func(events ...*es_models.Event) error {
|
||||
existing := false
|
||||
for _, event := range events {
|
||||
switch event.Type {
|
||||
case model.MailTemplateAdded:
|
||||
existing = true
|
||||
case model.MailTemplateRemoved:
|
||||
existing = false
|
||||
}
|
||||
}
|
||||
if existing {
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-aUH4D", "Errors.Org.MailTemplate.AlreadyExists")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
185
internal/org/repository/eventsourcing/mail_template_test.go
Normal file
185
internal/org/repository/eventsourcing/mail_template_test.go
Normal file
@ -0,0 +1,185 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func TestMailTemplateAddedAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *model.Org
|
||||
new *iam_es_model.MailTemplate
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventTypes []models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add mailtemplate",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
},
|
||||
new: &iam_es_model.MailTemplate{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventTypes: []models.EventType{model.MailTemplateAdded},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing org nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mailtemplate config nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := MailTemplateAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if !tt.res.wantErr && agg.Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], agg.Events[i].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
}
|
||||
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMailTemplateChangedAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *model.Org
|
||||
new *iam_es_model.MailTemplate
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventTypes []models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "change mailtemplate",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
MailTemplate: &iam_es_model.MailTemplate{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
},
|
||||
},
|
||||
new: &iam_es_model.MailTemplate{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
Template: []byte("<!doctype html>"),
|
||||
},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventTypes: []models.EventType{model.MailTemplateChanged},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing org nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mailtemplate config nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := MailTemplateChangedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if !tt.res.wantErr && agg.Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], agg.Events[i].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
}
|
||||
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
94
internal/org/repository/eventsourcing/mail_text.go
Normal file
94
internal/org/repository/eventsourcing/mail_text.go
Normal file
@ -0,0 +1,94 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func MailTextAddedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, mailText *iam_es_model.MailText) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if mailText == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-Gk3Cn", "Errors.Internal")
|
||||
}
|
||||
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validationQuery := es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(model.OrgAggregate).
|
||||
AggregateIDFilter(existing.AggregateID)
|
||||
|
||||
validation := checkExistingMailTextValidation(mailText, existing.MailTexts)
|
||||
agg.SetPrecondition(validationQuery, validation)
|
||||
return agg.AppendEvent(model.MailTextAdded, mailText)
|
||||
}
|
||||
}
|
||||
|
||||
func MailTextChangedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, mailText *iam_es_model.MailText) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if mailText == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-Hog8a", "Errors.Internal")
|
||||
}
|
||||
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := make(map[string]interface{}, 2)
|
||||
for _, exMailText := range existing.MailTexts {
|
||||
if exMailText.MailTextType == mailText.MailTextType && exMailText.Language == mailText.Language {
|
||||
changes = exMailText.Changes(mailText)
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-DuRxA", "Errors.NoChangesFound")
|
||||
}
|
||||
}
|
||||
}
|
||||
return agg.AppendEvent(model.MailTextChanged, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func MailTextRemovedAggregate(aggCreator *es_models.AggregateCreator, existing *model.Org, mailText *iam_es_model.MailText) func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
||||
if existing == nil {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-cJ5Wp", "Errors.Internal")
|
||||
}
|
||||
agg, err := OrgAggregate(ctx, aggCreator, existing.AggregateID, existing.Sequence)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes := make(map[string]interface{}, 2)
|
||||
for _, exMailText := range existing.MailTexts {
|
||||
if exMailText.MailTextType == mailText.MailTextType && exMailText.Language == mailText.Language {
|
||||
mailText.ButtonText = exMailText.ButtonText
|
||||
mailText.Greeting = exMailText.Greeting
|
||||
mailText.Text = exMailText.Text
|
||||
mailText.Title = exMailText.Title
|
||||
mailText.Subject = exMailText.Subject
|
||||
mailText.PreHeader = exMailText.PreHeader
|
||||
changes = exMailText.Changes(mailText)
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-DuRxA", "Errors.NoChangesFound")
|
||||
}
|
||||
}
|
||||
}
|
||||
return agg.AppendEvent(model.MailTextRemoved, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func checkExistingMailTextValidation(mailText *iam_es_model.MailText, existingMailTexts []*iam_es_model.MailText) func(...*es_models.Event) error {
|
||||
return func(events ...*es_models.Event) error {
|
||||
existing := false
|
||||
for _, text := range existingMailTexts {
|
||||
if text.MailTextType == mailText.MailTextType && text.Language == mailText.Language {
|
||||
existing = true
|
||||
}
|
||||
}
|
||||
if existing {
|
||||
return errors.ThrowPreconditionFailed(nil, "EVENT-zEZh7", "Errors.Org.MailText.AlreadyExists")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
188
internal/org/repository/eventsourcing/mail_text_test.go
Normal file
188
internal/org/repository/eventsourcing/mail_text_test.go
Normal file
@ -0,0 +1,188 @@
|
||||
package eventsourcing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func TestMailTextAddedAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *model.Org
|
||||
new *iam_es_model.MailText
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventTypes []models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "add mailtext",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
},
|
||||
new: &iam_es_model.MailText{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
MailTextType: "Type",
|
||||
Language: "DE",
|
||||
},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventTypes: []models.EventType{model.MailTextAdded},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing org nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mailtext config nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := MailTextAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if !tt.res.wantErr && agg.Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], agg.Events[i].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
}
|
||||
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMailTextChangedAggregate(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
existing *model.Org
|
||||
new *iam_es_model.MailText
|
||||
aggCreator *models.AggregateCreator
|
||||
}
|
||||
type res struct {
|
||||
eventLen int
|
||||
eventTypes []models.EventType
|
||||
wantErr bool
|
||||
errFunc func(err error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "change mailtext",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
|
||||
},
|
||||
},
|
||||
new: &iam_es_model.MailText{
|
||||
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
|
||||
MailTextType: "Type",
|
||||
Language: "DE",
|
||||
Subject: "Subject",
|
||||
},
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
eventLen: 1,
|
||||
eventTypes: []models.EventType{model.MailTextChanged},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing org nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mailtext config nil",
|
||||
args: args{
|
||||
ctx: authz.NewMockContext("orgID", "userID"),
|
||||
existing: &model.Org{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}},
|
||||
new: nil,
|
||||
aggCreator: models.NewAggregateCreator("Test"),
|
||||
},
|
||||
res: res{
|
||||
wantErr: true,
|
||||
errFunc: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
agg, err := MailTextChangedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new)(tt.args.ctx)
|
||||
|
||||
if !tt.res.wantErr && len(agg.Events) != tt.res.eventLen {
|
||||
t.Errorf("got wrong event len: expected: %v, actual: %v ", tt.res.eventLen, len(agg.Events))
|
||||
}
|
||||
for i := 0; i < tt.res.eventLen; i++ {
|
||||
if !tt.res.wantErr && agg.Events[i].Type != tt.res.eventTypes[i] {
|
||||
t.Errorf("got wrong event type: expected: %v, actual: %v ", tt.res.eventTypes[i], agg.Events[i].Type.String())
|
||||
}
|
||||
if !tt.res.wantErr && agg.Events[i].Data == nil {
|
||||
t.Errorf("should have data in event")
|
||||
}
|
||||
}
|
||||
|
||||
if tt.res.wantErr && !tt.res.errFunc(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
31
internal/org/repository/eventsourcing/model/mail_template.go
Normal file
31
internal/org/repository/eventsourcing/model/mail_template.go
Normal file
@ -0,0 +1,31 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func (o *Org) appendAddMailTemplateEvent(event *es_models.Event) error {
|
||||
o.MailTemplate = new(iam_es_model.MailTemplate)
|
||||
err := o.MailTemplate.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.MailTemplate.ObjectRoot.CreationDate = event.CreationDate
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Org) appendChangeMailTemplateEvent(event *es_models.Event) error {
|
||||
mailTemplate := &iam_es_model.MailTemplate{}
|
||||
err := mailTemplate.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mailTemplate.ObjectRoot.ChangeDate = event.CreationDate
|
||||
o.MailTemplate = mailTemplate
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Org) appendRemoveMailTemplateEvent(event *es_models.Event) {
|
||||
o.MailTemplate = nil
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func TestAppendAddMailTemplateEvent(t *testing.T) {
|
||||
type args struct {
|
||||
org *Org
|
||||
policy *iam_es_model.MailTemplate
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Org
|
||||
}{
|
||||
{
|
||||
name: "append add label policy event",
|
||||
args: args{
|
||||
org: &Org{},
|
||||
policy: &iam_es_model.MailTemplate{Template: []byte("<!doctype html>")},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Org{MailTemplate: &iam_es_model.MailTemplate{Template: []byte("<!doctype html>")}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.policy != nil {
|
||||
data, _ := json.Marshal(tt.args.policy)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.org.appendAddMailTemplateEvent(tt.args.event)
|
||||
if string(tt.result.MailTemplate.Template) != string(tt.args.org.MailTemplate.Template) {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.MailTemplate.Template, tt.args.org.MailTemplate.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendChangeMailTemplateEvent(t *testing.T) {
|
||||
type args struct {
|
||||
org *Org
|
||||
policy *iam_es_model.MailTemplate
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Org
|
||||
}{
|
||||
{
|
||||
name: "append change label policy event",
|
||||
args: args{
|
||||
org: &Org{MailTemplate: &iam_es_model.MailTemplate{
|
||||
Template: []byte("<x!doctype html>"),
|
||||
}},
|
||||
policy: &iam_es_model.MailTemplate{Template: []byte("<!doctype html>")},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Org{MailTemplate: &iam_es_model.MailTemplate{
|
||||
Template: []byte("<!doctype html>"),
|
||||
}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.policy != nil {
|
||||
data, _ := json.Marshal(tt.args.policy)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.org.appendChangeMailTemplateEvent(tt.args.event)
|
||||
if string(tt.result.MailTemplate.Template) != string(tt.args.org.MailTemplate.Template) {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.MailTemplate.Template, tt.args.org.MailTemplate.Template)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
44
internal/org/repository/eventsourcing/model/mail_text.go
Normal file
44
internal/org/repository/eventsourcing/model/mail_text.go
Normal file
@ -0,0 +1,44 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func (o *Org) appendAddMailTextEvent(event *es_models.Event) error {
|
||||
mailText := &iam_es_model.MailText{}
|
||||
err := mailText.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mailText.ObjectRoot.CreationDate = event.CreationDate
|
||||
o.MailTexts = append(o.MailTexts, mailText)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Org) appendChangeMailTextEvent(event *es_models.Event) error {
|
||||
mailText := &iam_es_model.MailText{}
|
||||
err := mailText.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mailText.ObjectRoot.ChangeDate = event.CreationDate
|
||||
if n, m := iam_es_model.GetMailText(o.MailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
||||
o.MailTexts[n] = mailText
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Org) appendRemoveMailTextEvent(event *es_models.Event) error {
|
||||
mailText := &iam_es_model.MailText{}
|
||||
err := mailText.SetDataLabel(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n, m := iam_es_model.GetMailText(o.MailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
||||
o.MailTexts[n] = o.MailTexts[len(o.MailTexts)-1]
|
||||
o.MailTexts[len(o.MailTexts)-1] = nil
|
||||
o.MailTexts = o.MailTexts[:len(o.MailTexts)-1]
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
func TestAppendAddMailTextEvent(t *testing.T) {
|
||||
type args struct {
|
||||
org *Org
|
||||
mailText *iam_es_model.MailText
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Org
|
||||
}{
|
||||
{
|
||||
name: "append add mail text event",
|
||||
args: args{
|
||||
org: &Org{},
|
||||
mailText: &iam_es_model.MailText{MailTextType: "Type", Language: "DE"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Org{MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{MailTextType: "Type", Language: "DE"}}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.mailText != nil {
|
||||
data, _ := json.Marshal(tt.args.mailText)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.org.appendAddMailTextEvent(tt.args.event)
|
||||
if len(tt.args.org.MailTexts) != 1 {
|
||||
t.Errorf("got wrong result should have one mailtext actual: %v ", len(tt.args.org.MailTexts))
|
||||
}
|
||||
if tt.result.MailTexts[0].Language != tt.args.org.MailTexts[0].Language {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.MailTexts[0].Language, tt.args.org.MailTexts[0].Language)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendChangeMailTextEvent(t *testing.T) {
|
||||
type args struct {
|
||||
org *Org
|
||||
mailText *iam_es_model.MailText
|
||||
event *es_models.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
result *Org
|
||||
}{
|
||||
{
|
||||
name: "append change mail text event",
|
||||
args: args{
|
||||
org: &Org{MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{
|
||||
Language: "DE",
|
||||
MailTextType: "TypeX",
|
||||
}}},
|
||||
mailText: &iam_es_model.MailText{MailTextType: "Type", Language: "DE"},
|
||||
event: &es_models.Event{},
|
||||
},
|
||||
result: &Org{MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{
|
||||
Language: "DE",
|
||||
MailTextType: "Type",
|
||||
}}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.mailText != nil {
|
||||
data, _ := json.Marshal(tt.args.mailText)
|
||||
tt.args.event.Data = data
|
||||
}
|
||||
tt.args.org.appendChangeMailTextEvent(tt.args.event)
|
||||
if len(tt.args.org.MailTexts) != 1 {
|
||||
t.Errorf("got wrong result should have one mailtext actual: %v ", len(tt.args.org.MailTexts))
|
||||
}
|
||||
if tt.result.MailTexts[0].Language != tt.args.org.MailTexts[0].Language {
|
||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.MailTexts[0].Language, tt.args.org.MailTexts[0].Language)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -25,6 +25,8 @@ type Org struct {
|
||||
Members []*OrgMember `json:"-"`
|
||||
OrgIAMPolicy *iam_es_model.OrgIAMPolicy `json:"-"`
|
||||
LabelPolicy *iam_es_model.LabelPolicy `json:"-"`
|
||||
MailTemplate *iam_es_model.MailTemplate `json:"-"`
|
||||
MailTexts []*iam_es_model.MailText `json:"-"`
|
||||
IDPs []*iam_es_model.IDPConfig `json:"-"`
|
||||
LoginPolicy *iam_es_model.LoginPolicy `json:"-"`
|
||||
PasswordComplexityPolicy *iam_es_model.PasswordComplexityPolicy `json:"-"`
|
||||
@ -36,11 +38,13 @@ func OrgFromModel(org *org_model.Org) *Org {
|
||||
members := OrgMembersFromModel(org.Members)
|
||||
domains := OrgDomainsFromModel(org.Domains)
|
||||
idps := iam_es_model.IDPConfigsFromModel(org.IDPs)
|
||||
mailTexts := iam_es_model.MailTextsFromModel(org.MailTexts)
|
||||
converted := &Org{
|
||||
ObjectRoot: org.ObjectRoot,
|
||||
Name: org.Name,
|
||||
State: int32(org.State),
|
||||
Domains: domains,
|
||||
MailTexts: mailTexts,
|
||||
Members: members,
|
||||
IDPs: idps,
|
||||
}
|
||||
@ -53,6 +57,9 @@ func OrgFromModel(org *org_model.Org) *Org {
|
||||
if org.LabelPolicy != nil {
|
||||
converted.LabelPolicy = iam_es_model.LabelPolicyFromModel(org.LabelPolicy)
|
||||
}
|
||||
if org.MailTemplate != nil {
|
||||
converted.MailTemplate = iam_es_model.MailTemplateFromModel(org.MailTemplate)
|
||||
}
|
||||
if org.PasswordComplexityPolicy != nil {
|
||||
converted.PasswordComplexityPolicy = iam_es_model.PasswordComplexityPolicyFromModel(org.PasswordComplexityPolicy)
|
||||
}
|
||||
@ -72,6 +79,7 @@ func OrgToModel(org *Org) *org_model.Org {
|
||||
State: org_model.OrgState(org.State),
|
||||
Domains: OrgDomainsToModel(org.Domains),
|
||||
Members: OrgMembersToModel(org.Members),
|
||||
MailTexts: iam_es_model.MailTextsToModel(org.MailTexts),
|
||||
IDPs: iam_es_model.IDPConfigsToModel(org.IDPs),
|
||||
}
|
||||
if org.OrgIAMPolicy != nil {
|
||||
@ -83,6 +91,9 @@ func OrgToModel(org *Org) *org_model.Org {
|
||||
if org.LabelPolicy != nil {
|
||||
converted.LabelPolicy = iam_es_model.LabelPolicyToModel(org.LabelPolicy)
|
||||
}
|
||||
if org.MailTemplate != nil {
|
||||
converted.MailTemplate = iam_es_model.MailTemplateToModel(org.MailTemplate)
|
||||
}
|
||||
if org.PasswordComplexityPolicy != nil {
|
||||
converted.PasswordComplexityPolicy = iam_es_model.PasswordComplexityPolicyToModel(org.PasswordComplexityPolicy)
|
||||
}
|
||||
@ -199,6 +210,18 @@ func (o *Org) AppendEvent(event *es_models.Event) (err error) {
|
||||
err = o.appendAddIdpProviderToLoginPolicyEvent(event)
|
||||
case LoginPolicyIDPProviderRemoved:
|
||||
err = o.appendRemoveIdpProviderFromLoginPolicyEvent(event)
|
||||
case MailTemplateAdded:
|
||||
err = o.appendAddMailTemplateEvent(event)
|
||||
case MailTemplateChanged:
|
||||
err = o.appendChangeMailTemplateEvent(event)
|
||||
case MailTemplateRemoved:
|
||||
o.appendRemoveMailTemplateEvent(event)
|
||||
case MailTextAdded:
|
||||
err = o.appendAddMailTextEvent(event)
|
||||
case MailTextChanged:
|
||||
err = o.appendChangeMailTextEvent(event)
|
||||
case MailTextRemoved:
|
||||
o.appendRemoveMailTextEvent(event)
|
||||
case LoginPolicySecondFactorAdded:
|
||||
err = o.appendAddSecondFactorToLoginPolicyEvent(event)
|
||||
case LoginPolicySecondFactorRemoved:
|
||||
|
@ -60,6 +60,13 @@ const (
|
||||
LabelPolicyChanged models.EventType = "org.policy.label.changed"
|
||||
LabelPolicyRemoved models.EventType = "org.policy.label.removed"
|
||||
|
||||
MailTemplateAdded models.EventType = "org.mail.template.added"
|
||||
MailTemplateChanged models.EventType = "org.mail.template.changed"
|
||||
MailTemplateRemoved models.EventType = "org.mail.template.removed"
|
||||
MailTextAdded models.EventType = "org.mail.text.added"
|
||||
MailTextChanged models.EventType = "org.mail.text.changed"
|
||||
MailTextRemoved models.EventType = "org.mail.text.removed"
|
||||
|
||||
PasswordComplexityPolicyAdded models.EventType = "org.policy.password.complexity.added"
|
||||
PasswordComplexityPolicyChanged models.EventType = "org.policy.password.complexity.changed"
|
||||
PasswordComplexityPolicyRemoved models.EventType = "org.policy.password.complexity.removed"
|
||||
|
@ -1,8 +1,9 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/model"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/model"
|
||||
)
|
||||
|
||||
type ProjectRoleView struct {
|
||||
@ -13,6 +14,7 @@ type ProjectRoleView struct {
|
||||
DisplayName string
|
||||
Group string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,13 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/project/model"
|
||||
es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -27,6 +28,7 @@ type ProjectRoleView struct {
|
||||
|
||||
ResourceOwner string `json:"-" gorm:"resource_owner"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
}
|
||||
|
||||
func ProjectRoleViewFromModel(role *model.ProjectRoleView) *ProjectRoleView {
|
||||
@ -39,6 +41,7 @@ func ProjectRoleViewFromModel(role *model.ProjectRoleView) *ProjectRoleView {
|
||||
Group: role.Group,
|
||||
Sequence: role.Sequence,
|
||||
CreationDate: role.CreationDate,
|
||||
ChangeDate: role.ChangeDate,
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +55,7 @@ func ProjectRoleToModel(role *ProjectRoleView) *model.ProjectRoleView {
|
||||
Group: role.Group,
|
||||
Sequence: role.Sequence,
|
||||
CreationDate: role.CreationDate,
|
||||
ChangeDate: role.ChangeDate,
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,6 +75,7 @@ func (r *ProjectRoleView) AppendEvent(event *models.Event) (err error) {
|
||||
r.CreationDate = event.CreationDate
|
||||
err = r.SetData(event)
|
||||
case es_model.ProjectRoleChanged:
|
||||
r.ChangeDate = event.CreationDate
|
||||
err = r.SetData(event)
|
||||
}
|
||||
return err
|
||||
|
@ -6,15 +6,16 @@ import (
|
||||
)
|
||||
|
||||
type IAMSetUp struct {
|
||||
Step1 *Step1
|
||||
Step2 *Step2
|
||||
Step3 *Step3
|
||||
Step4 *Step4
|
||||
Step5 *Step5
|
||||
Step6 *Step6
|
||||
Step7 *Step7
|
||||
Step8 *Step8
|
||||
Step9 *Step9
|
||||
Step1 *Step1
|
||||
Step2 *Step2
|
||||
Step3 *Step3
|
||||
Step4 *Step4
|
||||
Step5 *Step5
|
||||
Step6 *Step6
|
||||
Step7 *Step7
|
||||
Step8 *Step8
|
||||
Step9 *Step9
|
||||
Step10 *Step10
|
||||
}
|
||||
|
||||
func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) {
|
||||
@ -31,6 +32,7 @@ func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) {
|
||||
setup.Step7,
|
||||
setup.Step8,
|
||||
setup.Step9,
|
||||
setup.Step10,
|
||||
} {
|
||||
if step.step() <= currentDone {
|
||||
continue
|
||||
|
107
internal/setup/step10.go
Normal file
107
internal/setup/step10.go
Normal file
@ -0,0 +1,107 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
)
|
||||
|
||||
type Step10 struct {
|
||||
DefaultMailTemplate iam_model.MailTemplate
|
||||
DefaultMailTexts []iam_model.MailText
|
||||
|
||||
setup *Setup
|
||||
}
|
||||
|
||||
func (s *Step10) isNil() bool {
|
||||
return s == nil
|
||||
}
|
||||
|
||||
func (step *Step10) step() iam_model.Step {
|
||||
return iam_model.Step10
|
||||
}
|
||||
|
||||
func (step *Step10) init(setup *Setup) {
|
||||
step.setup = setup
|
||||
}
|
||||
|
||||
func (step *Step10) execute(ctx context.Context) (*iam_model.IAM, error) {
|
||||
iam, agg, err := step.mailTemplate(ctx, &step.DefaultMailTemplate)
|
||||
if err != nil {
|
||||
logging.Log("SETUP-1UYCt").WithField("step", step.step()).WithError(err).Error("unable to finish setup (Mail template)")
|
||||
return nil, err
|
||||
}
|
||||
iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step())
|
||||
if err != nil {
|
||||
logging.Log("SETUP-fMLsb").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)")
|
||||
return nil, err
|
||||
}
|
||||
err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg)
|
||||
if err != nil {
|
||||
logging.Log("SETUP-GuS3f").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iam, agg, err = step.defaultMailTexts(ctx, &step.DefaultMailTexts)
|
||||
if err != nil {
|
||||
logging.Log("SETUP-p4oWq").WithError(err).Error("unable to set up defaultMailTexts")
|
||||
return nil, err
|
||||
}
|
||||
iam, agg, push, err = step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step())
|
||||
if err != nil {
|
||||
logging.Log("SETUP-fMLsb").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)")
|
||||
return nil, err
|
||||
}
|
||||
err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg)
|
||||
if err != nil {
|
||||
logging.Log("SETUP-GuS3f").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return iam_es_model.IAMToModel(iam), nil
|
||||
}
|
||||
|
||||
func (step *Step10) mailTemplate(ctx context.Context, mailTemplate *iam_model.MailTemplate) (*iam_es_model.IAM, *models.Aggregate, error) {
|
||||
logging.Log("SETUP-cNrF3").Info("setting up mail template")
|
||||
mailTemplate.AggregateID = step.setup.iamID
|
||||
iam, aggregate, err := step.setup.IamEvents.PrepareAddMailTemplate(ctx, mailTemplate)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return iam, aggregate, nil
|
||||
}
|
||||
|
||||
func (step *Step10) defaultMailTexts(ctx context.Context, defaultMailTexts *[]iam_model.MailText) (*iam_es_model.IAM, *models.Aggregate, error) {
|
||||
logging.Log("SETUP-dsTh3").Info("setting up defaultMailTexts")
|
||||
iam := &iam_es_model.IAM{}
|
||||
var aggregate *models.Aggregate
|
||||
for index, iamDefaultMailText := range *defaultMailTexts {
|
||||
iaml, aggregatel, err := step.defaultMailText(ctx, &iamDefaultMailText)
|
||||
if err != nil {
|
||||
logging.LogWithFields("SETUP-IlLif", "DefaultMailText", iamDefaultMailText.MailTextType).WithError(err).Error("unable to create defaultMailText")
|
||||
return nil, nil, err
|
||||
}
|
||||
if index == 0 {
|
||||
aggregate = aggregatel
|
||||
} else {
|
||||
aggregate.Events = append(aggregate.Events, aggregatel.Events...)
|
||||
}
|
||||
iam = iaml
|
||||
}
|
||||
logging.Log("SETUP-dgjT4").Info("defaultMailTexts set up")
|
||||
return iam, aggregate, nil
|
||||
}
|
||||
|
||||
func (step *Step10) defaultMailText(ctx context.Context, mailText *iam_model.MailText) (*iam_es_model.IAM, *models.Aggregate, error) {
|
||||
logging.Log("SETUP-cNrF3").Info("setting up mail text")
|
||||
mailText.AggregateID = step.setup.iamID
|
||||
iam, aggregate, err := step.setup.IamEvents.PrepareAddMailText(ctx, mailText)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return iam, aggregate, nil
|
||||
}
|
78
migrations/cockroach/V1.27__templates.sql
Normal file
78
migrations/cockroach/V1.27__templates.sql
Normal file
@ -0,0 +1,78 @@
|
||||
CREATE TABLE adminapi.mail_templates (
|
||||
aggregate_id TEXT,
|
||||
|
||||
creation_date TIMESTAMPTZ,
|
||||
change_date TIMESTAMPTZ,
|
||||
mail_template_state SMALLINT,
|
||||
sequence BIGINT,
|
||||
|
||||
template BYTES,
|
||||
|
||||
PRIMARY KEY (aggregate_id)
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE management.mail_templates (
|
||||
aggregate_id TEXT,
|
||||
|
||||
creation_date TIMESTAMPTZ,
|
||||
change_date TIMESTAMPTZ,
|
||||
mail_template_state SMALLINT,
|
||||
sequence BIGINT,
|
||||
|
||||
template BYTES,
|
||||
|
||||
PRIMARY KEY (aggregate_id)
|
||||
);
|
||||
|
||||
GRANT SELECT ON TABLE adminapi.mail_templates TO notification;
|
||||
GRANT SELECT ON TABLE management.mail_templates TO notification;
|
||||
|
||||
|
||||
CREATE TABLE adminapi.mail_texts (
|
||||
aggregate_id TEXT,
|
||||
|
||||
creation_date TIMESTAMPTZ,
|
||||
change_date TIMESTAMPTZ,
|
||||
mail_text_state SMALLINT,
|
||||
sequence BIGINT,
|
||||
|
||||
mail_text_type TEXT,
|
||||
language TEXT,
|
||||
title TEXT,
|
||||
pre_header TEXT,
|
||||
subject TEXT,
|
||||
greeting TEXT,
|
||||
text TEXT,
|
||||
button_text TEXT,
|
||||
|
||||
PRIMARY KEY (aggregate_id, mail_text_type, language)
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE management.mail_texts (
|
||||
aggregate_id TEXT,
|
||||
|
||||
creation_date TIMESTAMPTZ,
|
||||
change_date TIMESTAMPTZ,
|
||||
mail_text_state SMALLINT,
|
||||
sequence BIGINT,
|
||||
|
||||
mail_text_type TEXT,
|
||||
language TEXT,
|
||||
title TEXT,
|
||||
pre_header TEXT,
|
||||
subject TEXT,
|
||||
greeting TEXT,
|
||||
text TEXT,
|
||||
button_text TEXT,
|
||||
|
||||
PRIMARY KEY (aggregate_id, mail_text_type, language)
|
||||
);
|
||||
|
||||
GRANT SELECT ON TABLE adminapi.mail_texts TO notification;
|
||||
GRANT SELECT ON TABLE management.mail_texts TO notification;
|
||||
|
||||
|
||||
ALTER TABLE management.project_roles ADD COLUMN change_date TIMESTAMPTZ;
|
||||
ALTER TABLE auth.project_roles ADD COLUMN change_date TIMESTAMPTZ;
|
@ -316,6 +316,46 @@ func (mr *MockAdminServiceClientMockRecorder) GetDefaultLoginPolicySecondFactors
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultLoginPolicySecondFactors", reflect.TypeOf((*MockAdminServiceClient)(nil).GetDefaultLoginPolicySecondFactors), varargs...)
|
||||
}
|
||||
|
||||
// GetDefaultMailTemplate mocks base method
|
||||
func (m *MockAdminServiceClient) GetDefaultMailTemplate(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*admin.DefaultMailTemplateView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetDefaultMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*admin.DefaultMailTemplateView)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDefaultMailTemplate indicates an expected call of GetDefaultMailTemplate
|
||||
func (mr *MockAdminServiceClientMockRecorder) GetDefaultMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultMailTemplate", reflect.TypeOf((*MockAdminServiceClient)(nil).GetDefaultMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// GetDefaultMailTexts mocks base method
|
||||
func (m *MockAdminServiceClient) GetDefaultMailTexts(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*admin.DefaultMailTextsView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetDefaultMailTexts", varargs...)
|
||||
ret0, _ := ret[0].(*admin.DefaultMailTextsView)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDefaultMailTexts indicates an expected call of GetDefaultMailTexts
|
||||
func (mr *MockAdminServiceClientMockRecorder) GetDefaultMailTexts(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultMailTexts", reflect.TypeOf((*MockAdminServiceClient)(nil).GetDefaultMailTexts), varargs...)
|
||||
}
|
||||
|
||||
// GetDefaultOrgIamPolicy mocks base method
|
||||
func (m *MockAdminServiceClient) GetDefaultOrgIamPolicy(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*admin.OrgIamPolicyView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -836,6 +876,46 @@ func (mr *MockAdminServiceClientMockRecorder) UpdateDefaultLoginPolicy(arg0, arg
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDefaultLoginPolicy", reflect.TypeOf((*MockAdminServiceClient)(nil).UpdateDefaultLoginPolicy), varargs...)
|
||||
}
|
||||
|
||||
// UpdateDefaultMailTemplate mocks base method
|
||||
func (m *MockAdminServiceClient) UpdateDefaultMailTemplate(arg0 context.Context, arg1 *admin.DefaultMailTemplateUpdate, arg2 ...grpc.CallOption) (*admin.DefaultMailTemplate, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "UpdateDefaultMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*admin.DefaultMailTemplate)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateDefaultMailTemplate indicates an expected call of UpdateDefaultMailTemplate
|
||||
func (mr *MockAdminServiceClientMockRecorder) UpdateDefaultMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDefaultMailTemplate", reflect.TypeOf((*MockAdminServiceClient)(nil).UpdateDefaultMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// UpdateDefaultMailText mocks base method
|
||||
func (m *MockAdminServiceClient) UpdateDefaultMailText(arg0 context.Context, arg1 *admin.DefaultMailTextUpdate, arg2 ...grpc.CallOption) (*admin.DefaultMailText, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "UpdateDefaultMailText", varargs...)
|
||||
ret0, _ := ret[0].(*admin.DefaultMailText)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateDefaultMailText indicates an expected call of UpdateDefaultMailText
|
||||
func (mr *MockAdminServiceClientMockRecorder) UpdateDefaultMailText(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDefaultMailText", reflect.TypeOf((*MockAdminServiceClient)(nil).UpdateDefaultMailText), varargs...)
|
||||
}
|
||||
|
||||
// UpdateDefaultOrgIamPolicy mocks base method
|
||||
func (m *MockAdminServiceClient) UpdateDefaultOrgIamPolicy(arg0 context.Context, arg1 *admin.OrgIamPolicyRequest, arg2 ...grpc.CallOption) (*admin.OrgIamPolicy, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -349,6 +349,48 @@ service AdminService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetDefaultMailTemplate(google.protobuf.Empty) returns (DefaultMailTemplateView) {
|
||||
option (google.api.http) = {
|
||||
get: "/policies/mailtemplate"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "iam.policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc UpdateDefaultMailTemplate(DefaultMailTemplateUpdate) returns (DefaultMailTemplate) {
|
||||
option (google.api.http) = {
|
||||
put: "/policies/mailtemplate"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "iam.policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetDefaultMailTexts(google.protobuf.Empty) returns (DefaultMailTextsView) {
|
||||
option (google.api.http) = {
|
||||
get: "/policies/mailtexts"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "iam.policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc UpdateDefaultMailText(DefaultMailTextUpdate) returns (DefaultMailText) {
|
||||
option (google.api.http) = {
|
||||
put: "/policies/mailtext"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "iam.policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetDefaultLoginPolicy(google.protobuf.Empty) returns (DefaultLoginPolicyView) {
|
||||
option (google.api.http) = {
|
||||
get: "/policies/login"
|
||||
@ -992,6 +1034,63 @@ message DefaultLabelPolicyView {
|
||||
google.protobuf.Timestamp change_date = 4;
|
||||
}
|
||||
|
||||
message DefaultMailTemplate {
|
||||
bytes template = 1;
|
||||
google.protobuf.Timestamp creation_date = 2;
|
||||
google.protobuf.Timestamp change_date = 3;
|
||||
}
|
||||
|
||||
message DefaultMailTemplateUpdate {
|
||||
bytes template = 1;
|
||||
}
|
||||
|
||||
message DefaultMailTemplateView {
|
||||
bytes template = 1;
|
||||
google.protobuf.Timestamp creation_date = 2;
|
||||
google.protobuf.Timestamp change_date = 3;
|
||||
}
|
||||
|
||||
message DefaultMailText {
|
||||
string mail_text_type = 1;
|
||||
string language = 2;
|
||||
string title = 3;
|
||||
string pre_header = 4;
|
||||
string subject = 5;
|
||||
string greeting = 6;
|
||||
string text = 7;
|
||||
string button_text = 8;
|
||||
google.protobuf.Timestamp creation_date = 9;
|
||||
google.protobuf.Timestamp change_date = 10;
|
||||
}
|
||||
|
||||
message DefaultMailTextUpdate {
|
||||
string mail_text_type = 1;
|
||||
string language = 2;
|
||||
string title = 3;
|
||||
string pre_header = 4;
|
||||
string subject = 5;
|
||||
string greeting = 6;
|
||||
string text = 7;
|
||||
string button_text = 8;
|
||||
}
|
||||
|
||||
message DefaultMailTextsView{
|
||||
repeated DefaultMailTextView texts = 1;
|
||||
}
|
||||
|
||||
message DefaultMailTextView {
|
||||
string mail_text_type = 1;
|
||||
string language = 2;
|
||||
string title = 3;
|
||||
string pre_header = 4;
|
||||
string subject = 5;
|
||||
string greeting = 6;
|
||||
string text = 7;
|
||||
string button_text = 8;
|
||||
google.protobuf.Timestamp creation_date = 9;
|
||||
google.protobuf.Timestamp change_date = 10;
|
||||
}
|
||||
|
||||
message DefaultLoginPolicy {
|
||||
bool allow_username_password = 1;
|
||||
bool allow_register = 2;
|
||||
|
@ -216,6 +216,26 @@ func (mr *MockAuthServiceClientMockRecorder) GetMyPasswordComplexityPolicy(arg0,
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMyPasswordComplexityPolicy", reflect.TypeOf((*MockAuthServiceClient)(nil).GetMyPasswordComplexityPolicy), varargs...)
|
||||
}
|
||||
|
||||
// GetMyPasswordless mocks base method
|
||||
func (m *MockAuthServiceClient) GetMyPasswordless(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*auth.WebAuthNTokens, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetMyPasswordless", varargs...)
|
||||
ret0, _ := ret[0].(*auth.WebAuthNTokens)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMyPasswordless indicates an expected call of GetMyPasswordless
|
||||
func (mr *MockAuthServiceClientMockRecorder) GetMyPasswordless(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMyPasswordless", reflect.TypeOf((*MockAuthServiceClient)(nil).GetMyPasswordless), varargs...)
|
||||
}
|
||||
|
||||
// GetMyProjectPermissions mocks base method
|
||||
func (m *MockAuthServiceClient) GetMyProjectPermissions(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*auth.MyPermissions, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -456,6 +456,46 @@ func (mr *MockManagementServiceClientMockRecorder) CreateLoginPolicy(arg0, arg1
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateLoginPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).CreateLoginPolicy), varargs...)
|
||||
}
|
||||
|
||||
// CreateMailTemplate mocks base method
|
||||
func (m *MockManagementServiceClient) CreateMailTemplate(arg0 context.Context, arg1 *management.MailTemplateUpdate, arg2 ...grpc.CallOption) (*management.MailTemplate, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "CreateMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailTemplate)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateMailTemplate indicates an expected call of CreateMailTemplate
|
||||
func (mr *MockManagementServiceClientMockRecorder) CreateMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMailTemplate", reflect.TypeOf((*MockManagementServiceClient)(nil).CreateMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// CreateMailText mocks base method
|
||||
func (m *MockManagementServiceClient) CreateMailText(arg0 context.Context, arg1 *management.MailTextUpdate, arg2 ...grpc.CallOption) (*management.MailText, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "CreateMailText", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailText)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateMailText indicates an expected call of CreateMailText
|
||||
func (mr *MockManagementServiceClientMockRecorder) CreateMailText(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMailText", reflect.TypeOf((*MockManagementServiceClient)(nil).CreateMailText), varargs...)
|
||||
}
|
||||
|
||||
// CreateOIDCApplication mocks base method
|
||||
func (m *MockManagementServiceClient) CreateOIDCApplication(arg0 context.Context, arg1 *management.OIDCApplicationCreate, arg2 ...grpc.CallOption) (*management.Application, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -876,6 +916,46 @@ func (mr *MockManagementServiceClientMockRecorder) GetDefaultLoginPolicy(arg0, a
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultLoginPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).GetDefaultLoginPolicy), varargs...)
|
||||
}
|
||||
|
||||
// GetDefaultMailTemplate mocks base method
|
||||
func (m *MockManagementServiceClient) GetDefaultMailTemplate(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.MailTemplateView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetDefaultMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailTemplateView)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDefaultMailTemplate indicates an expected call of GetDefaultMailTemplate
|
||||
func (mr *MockManagementServiceClientMockRecorder) GetDefaultMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultMailTemplate", reflect.TypeOf((*MockManagementServiceClient)(nil).GetDefaultMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// GetDefaultMailTexts mocks base method
|
||||
func (m *MockManagementServiceClient) GetDefaultMailTexts(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.MailTextsView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetDefaultMailTexts", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailTextsView)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDefaultMailTexts indicates an expected call of GetDefaultMailTexts
|
||||
func (mr *MockManagementServiceClientMockRecorder) GetDefaultMailTexts(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultMailTexts", reflect.TypeOf((*MockManagementServiceClient)(nil).GetDefaultMailTexts), varargs...)
|
||||
}
|
||||
|
||||
// GetDefaultPasswordAgePolicy mocks base method
|
||||
func (m *MockManagementServiceClient) GetDefaultPasswordAgePolicy(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.PasswordAgePolicyView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -1076,6 +1156,46 @@ func (mr *MockManagementServiceClientMockRecorder) GetMachineKey(arg0, arg1 inte
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMachineKey", reflect.TypeOf((*MockManagementServiceClient)(nil).GetMachineKey), varargs...)
|
||||
}
|
||||
|
||||
// GetMailTemplate mocks base method
|
||||
func (m *MockManagementServiceClient) GetMailTemplate(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.MailTemplateView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailTemplateView)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMailTemplate indicates an expected call of GetMailTemplate
|
||||
func (mr *MockManagementServiceClientMockRecorder) GetMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMailTemplate", reflect.TypeOf((*MockManagementServiceClient)(nil).GetMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// GetMailTexts mocks base method
|
||||
func (m *MockManagementServiceClient) GetMailTexts(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.MailTextsView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetMailTexts", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailTextsView)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMailTexts indicates an expected call of GetMailTexts
|
||||
func (mr *MockManagementServiceClientMockRecorder) GetMailTexts(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMailTexts", reflect.TypeOf((*MockManagementServiceClient)(nil).GetMailTexts), varargs...)
|
||||
}
|
||||
|
||||
// GetMyOrg mocks base method
|
||||
func (m *MockManagementServiceClient) GetMyOrg(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.OrgView, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -1216,6 +1336,26 @@ func (mr *MockManagementServiceClientMockRecorder) GetPasswordLockoutPolicy(arg0
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPasswordLockoutPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).GetPasswordLockoutPolicy), varargs...)
|
||||
}
|
||||
|
||||
// GetPasswordless mocks base method
|
||||
func (m *MockManagementServiceClient) GetPasswordless(arg0 context.Context, arg1 *management.UserID, arg2 ...grpc.CallOption) (*management.WebAuthNTokens, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetPasswordless", varargs...)
|
||||
ret0, _ := ret[0].(*management.WebAuthNTokens)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetPasswordless indicates an expected call of GetPasswordless
|
||||
func (mr *MockManagementServiceClientMockRecorder) GetPasswordless(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPasswordless", reflect.TypeOf((*MockManagementServiceClient)(nil).GetPasswordless), varargs...)
|
||||
}
|
||||
|
||||
// GetProjectGrantMemberRoles mocks base method
|
||||
func (m *MockManagementServiceClient) GetProjectGrantMemberRoles(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*management.ProjectGrantMemberRoles, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -1836,6 +1976,46 @@ func (mr *MockManagementServiceClientMockRecorder) RemoveLoginPolicy(arg0, arg1
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveLoginPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).RemoveLoginPolicy), varargs...)
|
||||
}
|
||||
|
||||
// RemoveMailTemplate mocks base method
|
||||
func (m *MockManagementServiceClient) RemoveMailTemplate(arg0 context.Context, arg1 *emptypb.Empty, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "RemoveMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// RemoveMailTemplate indicates an expected call of RemoveMailTemplate
|
||||
func (mr *MockManagementServiceClientMockRecorder) RemoveMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveMailTemplate", reflect.TypeOf((*MockManagementServiceClient)(nil).RemoveMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// RemoveMailText mocks base method
|
||||
func (m *MockManagementServiceClient) RemoveMailText(arg0 context.Context, arg1 *management.MailTextRemove, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "RemoveMailText", varargs...)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// RemoveMailText indicates an expected call of RemoveMailText
|
||||
func (mr *MockManagementServiceClientMockRecorder) RemoveMailText(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveMailText", reflect.TypeOf((*MockManagementServiceClient)(nil).RemoveMailText), varargs...)
|
||||
}
|
||||
|
||||
// RemoveMfaOTP mocks base method
|
||||
func (m *MockManagementServiceClient) RemoveMfaOTP(arg0 context.Context, arg1 *management.UserID, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -1996,6 +2176,26 @@ func (mr *MockManagementServiceClientMockRecorder) RemovePasswordLockoutPolicy(a
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemovePasswordLockoutPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).RemovePasswordLockoutPolicy), varargs...)
|
||||
}
|
||||
|
||||
// RemovePasswordless mocks base method
|
||||
func (m *MockManagementServiceClient) RemovePasswordless(arg0 context.Context, arg1 *management.WebAuthNTokenID, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "RemovePasswordless", varargs...)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// RemovePasswordless indicates an expected call of RemovePasswordless
|
||||
func (mr *MockManagementServiceClientMockRecorder) RemovePasswordless(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemovePasswordless", reflect.TypeOf((*MockManagementServiceClient)(nil).RemovePasswordless), varargs...)
|
||||
}
|
||||
|
||||
// RemoveProject mocks base method
|
||||
func (m *MockManagementServiceClient) RemoveProject(arg0 context.Context, arg1 *management.ProjectID, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -2676,6 +2876,46 @@ func (mr *MockManagementServiceClientMockRecorder) UpdateLoginPolicy(arg0, arg1
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateLoginPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).UpdateLoginPolicy), varargs...)
|
||||
}
|
||||
|
||||
// UpdateMailTemplate mocks base method
|
||||
func (m *MockManagementServiceClient) UpdateMailTemplate(arg0 context.Context, arg1 *management.MailTemplateUpdate, arg2 ...grpc.CallOption) (*management.MailTemplate, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "UpdateMailTemplate", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailTemplate)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateMailTemplate indicates an expected call of UpdateMailTemplate
|
||||
func (mr *MockManagementServiceClientMockRecorder) UpdateMailTemplate(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMailTemplate", reflect.TypeOf((*MockManagementServiceClient)(nil).UpdateMailTemplate), varargs...)
|
||||
}
|
||||
|
||||
// UpdateMailText mocks base method
|
||||
func (m *MockManagementServiceClient) UpdateMailText(arg0 context.Context, arg1 *management.MailTextUpdate, arg2 ...grpc.CallOption) (*management.MailText, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "UpdateMailText", varargs...)
|
||||
ret0, _ := ret[0].(*management.MailText)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateMailText indicates an expected call of UpdateMailText
|
||||
func (mr *MockManagementServiceClientMockRecorder) UpdateMailText(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMailText", reflect.TypeOf((*MockManagementServiceClient)(nil).UpdateMailText), varargs...)
|
||||
}
|
||||
|
||||
// UpdateOidcIdpConfig mocks base method
|
||||
func (m *MockManagementServiceClient) UpdateOidcIdpConfig(arg0 context.Context, arg1 *management.OidcIdpConfigUpdate, arg2 ...grpc.CallOption) (*management.OidcIdpConfig, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -1620,6 +1620,112 @@ service ManagementService {
|
||||
permission: "policy.delete"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetMailTemplate(google.protobuf.Empty) returns (MailTemplateView) {
|
||||
option (google.api.http) = {
|
||||
get: "/orgs/me/policies/mailtemplate"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetDefaultMailTemplate(google.protobuf.Empty) returns (MailTemplateView) {
|
||||
option (google.api.http) = {
|
||||
get: "/orgs/default/policies/mailtemplate"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc CreateMailTemplate(MailTemplateUpdate) returns (MailTemplate) {
|
||||
option (google.api.http) = {
|
||||
post: "/orgs/me/policies/mailtemplate"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc UpdateMailTemplate(MailTemplateUpdate) returns (MailTemplate) {
|
||||
option (google.api.http) = {
|
||||
put: "/orgs/me/policies/mailtemplate"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc RemoveMailTemplate(google.protobuf.Empty) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
delete: "/orgs/me/policies/mailtemplate"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.delete"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
rpc GetMailTexts(google.protobuf.Empty) returns (MailTextsView) {
|
||||
option (google.api.http) = {
|
||||
get: "/orgs/me/policies/mailtexts"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetDefaultMailTexts(google.protobuf.Empty) returns (MailTextsView) {
|
||||
option (google.api.http) = {
|
||||
get: "/orgs/default/policies/mailtexts"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc CreateMailText(MailTextUpdate) returns (MailText) {
|
||||
option (google.api.http) = {
|
||||
post: "/orgs/me/policies/mailtext"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc UpdateMailText(MailTextUpdate) returns (MailText) {
|
||||
option (google.api.http) = {
|
||||
put: "/orgs/me/policies/mailtext"
|
||||
body: "*"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.write"
|
||||
};
|
||||
}
|
||||
|
||||
rpc RemoveMailText(MailTextRemove) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
delete: "/orgs/me/policies/mailtext/type/{mail_text_type}/language/{language}"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "policy.delete"
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message ZitadelDocs {
|
||||
@ -2437,6 +2543,7 @@ message ProjectRoleView {
|
||||
string key = 2;
|
||||
string display_name = 3;
|
||||
google.protobuf.Timestamp creation_date = 4;
|
||||
google.protobuf.Timestamp change_date = 5;
|
||||
string group = 6;
|
||||
uint64 sequence = 7;
|
||||
}
|
||||
@ -3324,3 +3431,66 @@ message PasswordLockoutPolicyView {
|
||||
google.protobuf.Timestamp creation_date = 5;
|
||||
google.protobuf.Timestamp change_date = 6;
|
||||
}
|
||||
message MailTemplate {
|
||||
bytes template = 1;
|
||||
google.protobuf.Timestamp creation_date = 2;
|
||||
google.protobuf.Timestamp change_date = 3;
|
||||
}
|
||||
|
||||
message MailTemplateUpdate {
|
||||
bytes template = 1;
|
||||
}
|
||||
|
||||
message MailTemplateView {
|
||||
bool default = 1;
|
||||
bytes template = 2;
|
||||
google.protobuf.Timestamp creation_date = 3;
|
||||
google.protobuf.Timestamp change_date = 4;
|
||||
}
|
||||
|
||||
message MailText {
|
||||
string mail_text_type = 1;
|
||||
string language = 2;
|
||||
string title = 3;
|
||||
string pre_header = 4;
|
||||
string subject = 5;
|
||||
string greeting = 6;
|
||||
string text = 7;
|
||||
string button_text = 8;
|
||||
google.protobuf.Timestamp creation_date = 9;
|
||||
google.protobuf.Timestamp change_date = 10;
|
||||
}
|
||||
|
||||
message MailTextUpdate {
|
||||
string mail_text_type = 1;
|
||||
string language = 2;
|
||||
string title = 3;
|
||||
string pre_header = 4;
|
||||
string subject = 5;
|
||||
string greeting = 6;
|
||||
string text = 7;
|
||||
string button_text = 8;
|
||||
}
|
||||
|
||||
message MailTextRemove {
|
||||
string mail_text_type = 1;
|
||||
string language = 2;
|
||||
}
|
||||
|
||||
message MailTextsView{
|
||||
repeated MailTextView texts = 1;
|
||||
}
|
||||
|
||||
message MailTextView {
|
||||
bool default = 1;
|
||||
string mail_text_type = 2;
|
||||
string language = 3;
|
||||
string title = 4;
|
||||
string pre_header = 5;
|
||||
string subject = 6;
|
||||
string greeting = 7;
|
||||
string text = 8;
|
||||
string button_text = 9;
|
||||
google.protobuf.Timestamp creation_date = 10;
|
||||
google.protobuf.Timestamp change_date = 11;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user