mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 10:57:35 +00:00
feat: custom message text (#1801)
* feat: default custom message text * feat: org custom message text * feat: org custom message text * feat: custom messages query side * feat: default messages * feat: message text user fields * feat: check for inactive user * feat: fix send password reset * feat: fix custom org text * feat: add variables to docs * feat: custom text tests * feat: fix notifications * feat: add custom text feature * feat: add custom text feature * feat: feature in custom message texts * feat: add custom text feature in frontend * feat: merge main * feat: feature tests * feat: change phone message in setup * fix: remove unused code, add event translation * fix: merge main and fix problems * fix: english translation file * fix: migration versions * fix: setup * feat: fix pr requests * feat: fix phone code message * feat: migration * feat: setup * fix: remove unused tests Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -1,117 +0,0 @@
|
||||
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/v1/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
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/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() domain.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 ""
|
||||
}
|
||||
}
|
184
internal/iam/repository/view/model/message_text.go
Normal file
184
internal/iam/repository/view/model/message_text.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
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/v1/models"
|
||||
"github.com/caos/zitadel/internal/iam/model"
|
||||
)
|
||||
|
||||
const (
|
||||
MessageTextKeyAggregateID = "aggregate_id"
|
||||
MessageTextKeyMessageTextType = "message_text_type"
|
||||
MessageTextKeyLanguage = "language"
|
||||
)
|
||||
|
||||
type MessageTextView 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:message_text_state"`
|
||||
|
||||
MessageTextType string `json:"-" gorm:"column:message_text_type;primary_key"`
|
||||
Language string `json:"-" gorm:"column:language;primary_key"`
|
||||
Title string `json:"-" gorm:"column:title"`
|
||||
PreHeader string `json:"-" gorm:"column:pre_header"`
|
||||
Subject string `json:"-" gorm:"column:subject"`
|
||||
Greeting string `json:"-" gorm:"column:greeting"`
|
||||
Text string `json:"-" gorm:"column:text"`
|
||||
ButtonText string `json:"-" gorm:"column:button_text"`
|
||||
FooterText string `json:"-" gorm:"column:footer_text"`
|
||||
Default bool `json:"-" gorm:"-"`
|
||||
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func MessageTextViewFromModel(template *model.MessageTextView) *MessageTextView {
|
||||
return &MessageTextView{
|
||||
AggregateID: template.AggregateID,
|
||||
Sequence: template.Sequence,
|
||||
CreationDate: template.CreationDate,
|
||||
ChangeDate: template.ChangeDate,
|
||||
MessageTextType: template.MessageTextType,
|
||||
Language: template.Language.String(),
|
||||
Title: template.Title,
|
||||
PreHeader: template.PreHeader,
|
||||
Subject: template.Subject,
|
||||
Greeting: template.Greeting,
|
||||
Text: template.Text,
|
||||
ButtonText: template.ButtonText,
|
||||
FooterText: template.FooterText,
|
||||
Default: template.Default,
|
||||
}
|
||||
}
|
||||
|
||||
func MessageTextsViewToModel(textsIn []*MessageTextView, defaultIn bool) *model.MessageTextsView {
|
||||
return &model.MessageTextsView{
|
||||
Texts: messageTextsViewToModelArr(textsIn, defaultIn),
|
||||
}
|
||||
}
|
||||
|
||||
func messageTextsViewToModelArr(texts []*MessageTextView, defaultIn bool) []*model.MessageTextView {
|
||||
result := make([]*model.MessageTextView, len(texts))
|
||||
for i, r := range texts {
|
||||
r.Default = defaultIn
|
||||
result[i] = MessageTextViewToModel(r)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func MessageTextViewToModel(template *MessageTextView) *model.MessageTextView {
|
||||
lang := language.Make(template.Language)
|
||||
return &model.MessageTextView{
|
||||
AggregateID: template.AggregateID,
|
||||
Sequence: template.Sequence,
|
||||
CreationDate: template.CreationDate,
|
||||
ChangeDate: template.ChangeDate,
|
||||
MessageTextType: template.MessageTextType,
|
||||
Language: lang,
|
||||
Title: template.Title,
|
||||
PreHeader: template.PreHeader,
|
||||
Subject: template.Subject,
|
||||
Greeting: template.Greeting,
|
||||
Text: template.Text,
|
||||
ButtonText: template.ButtonText,
|
||||
FooterText: template.FooterText,
|
||||
Default: template.Default,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *MessageTextView) AppendEvent(event *models.Event) (err error) {
|
||||
i.Sequence = event.Sequence
|
||||
switch event.Type {
|
||||
case es_model.CustomTextSet, org_es_model.CustomTextSet:
|
||||
i.setRootData(event)
|
||||
customText := new(CustomText)
|
||||
err = customText.SetData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if customText.Key == domain.MessageTitle {
|
||||
i.Title = customText.Text
|
||||
}
|
||||
if customText.Key == domain.MessagePreHeader {
|
||||
i.PreHeader = customText.Text
|
||||
}
|
||||
if customText.Key == domain.MessageSubject {
|
||||
i.Subject = customText.Text
|
||||
}
|
||||
if customText.Key == domain.MessageGreeting {
|
||||
i.Greeting = customText.Text
|
||||
}
|
||||
if customText.Key == domain.MessageText {
|
||||
i.Text = customText.Text
|
||||
}
|
||||
if customText.Key == domain.MessageButtonText {
|
||||
i.ButtonText = customText.Text
|
||||
}
|
||||
if customText.Key == domain.MessageFooterText {
|
||||
i.FooterText = customText.Text
|
||||
}
|
||||
i.ChangeDate = event.CreationDate
|
||||
case es_model.CustomTextRemoved, org_es_model.CustomTextRemoved:
|
||||
customText := new(CustomText)
|
||||
err = customText.SetData(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if customText.Key == domain.MessageTitle {
|
||||
i.Title = ""
|
||||
}
|
||||
if customText.Key == domain.MessagePreHeader {
|
||||
i.PreHeader = ""
|
||||
}
|
||||
if customText.Key == domain.MessageSubject {
|
||||
i.Subject = ""
|
||||
}
|
||||
if customText.Key == domain.MessageGreeting {
|
||||
i.Greeting = ""
|
||||
}
|
||||
if customText.Key == domain.MessageText {
|
||||
i.Text = ""
|
||||
}
|
||||
if customText.Key == domain.MessageButtonText {
|
||||
i.ButtonText = ""
|
||||
}
|
||||
if customText.Key == domain.MessageFooterText {
|
||||
i.FooterText = ""
|
||||
}
|
||||
i.ChangeDate = event.CreationDate
|
||||
case org_es_model.CustomTextMessageRemoved:
|
||||
i.State = int32(model.PolicyStateRemoved)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *MessageTextView) setRootData(event *models.Event) {
|
||||
r.AggregateID = event.AggregateID
|
||||
}
|
||||
|
||||
type CustomText struct {
|
||||
Template string `json:"template"`
|
||||
Key string `json:"key"`
|
||||
Language language.Tag `json:"language"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func (r *CustomText) SetData(event *models.Event) error {
|
||||
if err := json.Unmarshal(event.Data, r); err != nil {
|
||||
logging.Log("MODEL-3n9fs").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/message_text_query.go
Normal file
63
internal/iam/repository/view/model/message_text_query.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
type MessageTextSearchRequest iam_model.MessageTextSearchRequest
|
||||
type MessageTextSearchQuery iam_model.MessageTextSearchQuery
|
||||
type MessageTextSearchKey iam_model.MessageTextSearchKey
|
||||
|
||||
func (req MessageTextSearchRequest) GetLimit() uint64 {
|
||||
return req.Limit
|
||||
}
|
||||
|
||||
func (req MessageTextSearchRequest) GetOffset() uint64 {
|
||||
return req.Offset
|
||||
}
|
||||
|
||||
func (req MessageTextSearchRequest) GetSortingColumn() repository.ColumnKey {
|
||||
if req.SortingColumn == iam_model.MessageTextSearchKeyUnspecified {
|
||||
return nil
|
||||
}
|
||||
return MessageTextSearchKey(req.SortingColumn)
|
||||
}
|
||||
|
||||
func (req MessageTextSearchRequest) GetAsc() bool {
|
||||
return req.Asc
|
||||
}
|
||||
|
||||
func (req MessageTextSearchRequest) GetQueries() []repository.SearchQuery {
|
||||
result := make([]repository.SearchQuery, len(req.Queries))
|
||||
for i, q := range req.Queries {
|
||||
result[i] = MessageTextSearchQuery{Key: q.Key, Value: q.Value, Method: q.Method}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (req MessageTextSearchQuery) GetKey() repository.ColumnKey {
|
||||
return MessageTextSearchKey(req.Key)
|
||||
}
|
||||
|
||||
func (req MessageTextSearchQuery) GetMethod() domain.SearchMethod {
|
||||
return req.Method
|
||||
}
|
||||
|
||||
func (req MessageTextSearchQuery) GetValue() interface{} {
|
||||
return req.Value
|
||||
}
|
||||
|
||||
func (key MessageTextSearchKey) ToColumnName() string {
|
||||
switch iam_model.MessageTextSearchKey(key) {
|
||||
case iam_model.MessageTextSearchKeyAggregateID:
|
||||
return MessageTextKeyAggregateID
|
||||
case iam_model.MessageTextSearchKeyMessageTextType:
|
||||
return MessageTextKeyMessageTextType
|
||||
case iam_model.MessageTextSearchKeyLanguage:
|
||||
return MessageTextKeyLanguage
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user