diff --git a/console/src/app/modules/policies/login-texts/login-texts.component.html b/console/src/app/modules/policies/login-texts/login-texts.component.html
index 042335c50..1f24a6386 100644
--- a/console/src/app/modules/policies/login-texts/login-texts.component.html
+++ b/console/src/app/modules/policies/login-texts/login-texts.component.html
@@ -36,23 +36,23 @@
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
- 'custom_text'})}}
+ 'custom_text.login'})}}
-
-
-
diff --git a/console/src/app/modules/policies/message-texts/message-texts.component.html b/console/src/app/modules/policies/message-texts/message-texts.component.html
index 7193de77e..be77861f6 100644
--- a/console/src/app/modules/policies/message-texts/message-texts.component.html
+++ b/console/src/app/modules/policies/message-texts/message-texts.component.html
@@ -20,21 +20,21 @@
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
- 'custom_text'})}}
+ 'custom_text.message'})}}
-
-
-
diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
index ed2a6f501..02054a8d4 100644
--- a/console/src/assets/i18n/de.json
+++ b/console/src/assets/i18n/de.json
@@ -660,7 +660,7 @@
"2": "Annuliert",
"3": "Durch IAM Owner gesetzt"
},
- "NOTAVAILABLE": "Feature {{value}} ist auf Ihrer organisation nicht freigeschaltet!",
+ "NOTAVAILABLE": "Feature {{value}} ist auf Ihrer Organisation nicht freigeschaltet!",
"RETENTIONDAYS": "Tage"
},
"POLICY": {
diff --git a/docs/docs/apis/proto/admin.md b/docs/docs/apis/proto/admin.md
index 1397afb0c..1b2c76665 100644
--- a/docs/docs/apis/proto/admin.md
+++ b/docs/docs/apis/proto/admin.md
@@ -2505,6 +2505,8 @@ This is an empty request
| custom_text | bool | - | |
| privacy_policy | bool | - | |
| metadata_user | bool | - | |
+| custom_text_message | bool | - | |
+| custom_text_login | bool | - | |
@@ -2691,6 +2693,8 @@ This is an empty request
| custom_text | bool | - | |
| privacy_policy | bool | - | |
| metadata_user | bool | - | |
+| custom_text_message | bool | - | |
+| custom_text_login | bool | - | |
diff --git a/internal/api/grpc/admin/features.go b/internal/api/grpc/admin/features.go
index 55ba275d2..ae74ec734 100644
--- a/internal/api/grpc/admin/features.go
+++ b/internal/api/grpc/admin/features.go
@@ -74,9 +74,10 @@ func setDefaultFeaturesRequestToDomain(req *admin_pb.SetDefaultFeaturesRequest)
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
LabelPolicyWatermark: req.LabelPolicyWatermark,
CustomDomain: req.CustomDomain,
- CustomText: req.CustomText,
PrivacyPolicy: req.PrivacyPolicy,
MetadataUser: req.MetadataUser,
+ CustomTextLogin: req.CustomTextLogin || req.CustomText,
+ CustomTextMessage: req.CustomTextMessage,
}
}
@@ -97,8 +98,9 @@ func setOrgFeaturesRequestToDomain(req *admin_pb.SetOrgFeaturesRequest) *domain.
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
LabelPolicyWatermark: req.LabelPolicyWatermark,
CustomDomain: req.CustomDomain,
- CustomText: req.CustomText,
PrivacyPolicy: req.PrivacyPolicy,
MetadataUser: req.MetadataUser,
+ CustomTextLogin: req.CustomTextLogin || req.CustomText,
+ CustomTextMessage: req.CustomTextMessage,
}
}
diff --git a/internal/api/grpc/features/features.go b/internal/api/grpc/features/features.go
index 3b9a78dcd..d2692a908 100644
--- a/internal/api/grpc/features/features.go
+++ b/internal/api/grpc/features/features.go
@@ -27,8 +27,10 @@ func FeaturesFromModel(features *features_model.FeaturesView) *features_pb.Featu
CustomDomain: features.CustomDomain,
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
LabelPolicyWatermark: features.LabelPolicyWatermark,
- CustomText: features.CustomText,
PrivacyPolicy: features.PrivacyPolicy,
+ CustomText: features.CustomTextMessage,
+ CustomTextMessage: features.CustomTextMessage,
+ CustomTextLogin: features.CustomTextLogin,
}
}
diff --git a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go
index 06d042297..123c95c16 100644
--- a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go
+++ b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go
@@ -151,8 +151,14 @@ func checkFeatures(features *features_view_model.FeaturesView, requiredFeatures
}
continue
}
- if requiredFeature == domain.FeatureCustomText {
- if !features.CustomText {
+ if requiredFeature == domain.FeatureCustomTextMessage {
+ if !features.CustomTextMessage {
+ return MissingFeatureErr(requiredFeature)
+ }
+ continue
+ }
+ if requiredFeature == domain.FeatureCustomTextLogin {
+ if !features.CustomTextLogin {
return MissingFeatureErr(requiredFeature)
}
continue
diff --git a/internal/command/custom_login_text_model.go b/internal/command/custom_login_text_model.go
index 2a5381402..9869e15de 100644
--- a/internal/command/custom_login_text_model.go
+++ b/internal/command/custom_login_text_model.go
@@ -10,6 +10,25 @@ import (
"github.com/caos/zitadel/internal/repository/policy"
)
+type CustomLoginTextsReadModel struct {
+ eventstore.WriteModel
+ CustomLoginTexts map[string]*CustomText
+}
+
+func (wm *CustomLoginTextsReadModel) Reduce() error {
+ for _, event := range wm.Events {
+ switch e := event.(type) {
+ case *policy.CustomTextSetEvent:
+ wm.CustomLoginTexts[e.Template+e.Language.String()] = &CustomText{Language: e.Language, Template: e.Template}
+ case *policy.CustomTextTemplateRemovedEvent:
+ if _, ok := wm.CustomLoginTexts[e.Template+e.Language.String()]; ok {
+ delete(wm.CustomLoginTexts, e.Template)
+ }
+ }
+ }
+ return wm.WriteModel.Reduce()
+}
+
type CustomLoginTextReadModel struct {
eventstore.WriteModel
@@ -558,6 +577,9 @@ func (wm *CustomLoginTextReadModel) Reduce() error {
continue
}
case *policy.CustomTextTemplateRemovedEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
wm.State = domain.PolicyStateRemoved
}
}
diff --git a/internal/command/features_model.go b/internal/command/features_model.go
index 82df49d78..d8471a59c 100644
--- a/internal/command/features_model.go
+++ b/internal/command/features_model.go
@@ -26,9 +26,10 @@ type FeaturesWriteModel struct {
LabelPolicyPrivateLabel bool
LabelPolicyWatermark bool
CustomDomain bool
- CustomText bool
PrivacyPolicy bool
MetadataUser bool
+ CustomTextMessage bool
+ CustomTextLogin bool
}
func (wm *FeaturesWriteModel) Reduce() error {
@@ -84,12 +85,15 @@ func (wm *FeaturesWriteModel) Reduce() error {
if e.CustomDomain != nil {
wm.CustomDomain = *e.CustomDomain
}
- if e.CustomText != nil {
- wm.CustomText = *e.CustomText
- }
if e.MetadataUser != nil {
wm.MetadataUser = *e.MetadataUser
}
+ if e.CustomTextMessage != nil {
+ wm.CustomTextMessage = *e.CustomTextMessage
+ }
+ if e.CustomTextLogin != nil {
+ wm.CustomTextLogin = *e.CustomTextLogin
+ }
case *features.FeaturesRemovedEvent:
wm.State = domain.FeaturesStateRemoved
}
diff --git a/internal/command/iam_features.go b/internal/command/iam_features.go
index fcfdc3bbf..526005533 100644
--- a/internal/command/iam_features.go
+++ b/internal/command/iam_features.go
@@ -49,9 +49,10 @@ func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *IAM
features.LabelPolicyPrivateLabel,
features.LabelPolicyWatermark,
features.CustomDomain,
- features.CustomText,
features.PrivacyPolicy,
features.MetadataUser,
+ features.CustomTextMessage,
+ features.CustomTextLogin,
)
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
diff --git a/internal/command/iam_features_model.go b/internal/command/iam_features_model.go
index 38718c86b..4e90206e7 100644
--- a/internal/command/iam_features_model.go
+++ b/internal/command/iam_features_model.go
@@ -67,9 +67,10 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
labelPolicyPrivateLabel,
labelPolicyWatermark,
customDomain,
- customText,
privacyPolicy,
- metadataUser bool,
+ metadataUser,
+ customTextMessage,
+ customTextLogin bool,
) (*iam.FeaturesSetEvent, bool) {
changes := make([]features.FeaturesChanges, 0)
@@ -116,15 +117,18 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
if wm.CustomDomain != customDomain {
changes = append(changes, features.ChangeCustomDomain(customDomain))
}
- if wm.CustomText != customText {
- changes = append(changes, features.ChangeCustomText(customText))
- }
if wm.PrivacyPolicy != privacyPolicy {
changes = append(changes, features.ChangePrivacyPolicy(privacyPolicy))
}
if wm.MetadataUser != metadataUser {
changes = append(changes, features.ChangeMetadataUser(metadataUser))
}
+ if wm.CustomTextMessage != customTextMessage {
+ changes = append(changes, features.ChangeCustomTextMessage(customTextMessage))
+ }
+ if wm.CustomTextLogin != customTextLogin {
+ changes = append(changes, features.ChangeCustomTextLogin(customTextLogin))
+ }
if len(changes) == 0 {
return nil, false
}
diff --git a/internal/command/org_custom_login_text.go b/internal/command/org_custom_login_text.go
index eafdf01c9..1b02668c7 100644
--- a/internal/command/org_custom_login_text.go
+++ b/internal/command/org_custom_login_text.go
@@ -67,6 +67,21 @@ func (c *Commands) RemoveOrgLoginTexts(ctx context.Context, resourceOwner string
return writeModelToObjectDetails(&customText.WriteModel), nil
}
+func (c *Commands) removeOrgLoginTextsIfExists(ctx context.Context, orgID string) ([]eventstore.EventPusher, error) {
+ msgTemplates := NewOrgCustomLoginTextsReadModel(orgID)
+ err := c.eventstore.FilterToQueryReducer(ctx, msgTemplates)
+ if err != nil {
+ return nil, err
+ }
+
+ orgAgg := OrgAggregateFromWriteModel(&msgTemplates.WriteModel)
+ events := make([]eventstore.EventPusher, 0, len(msgTemplates.CustomLoginTexts))
+ for _, tmpl := range msgTemplates.CustomLoginTexts {
+ events = append(events, org.NewCustomTextTemplateRemovedEvent(ctx, orgAgg, tmpl.Template, tmpl.Language))
+ }
+ return events, nil
+}
+
func (c *Commands) orgCustomLoginTextWriteModelByID(ctx context.Context, orgID string, lang language.Tag) (*OrgCustomLoginTextReadModel, error) {
writeModel := NewOrgCustomLoginTextReadModel(orgID, lang)
err := c.eventstore.FilterToQueryReducer(ctx, writeModel)
diff --git a/internal/command/org_custom_login_text_model.go b/internal/command/org_custom_login_text_model.go
index a7fdc6516..15ca17af5 100644
--- a/internal/command/org_custom_login_text_model.go
+++ b/internal/command/org_custom_login_text_model.go
@@ -3,6 +3,7 @@ package command
import (
"golang.org/x/text/language"
+ "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/repository/org"
)
@@ -27,10 +28,19 @@ func (wm *OrgCustomLoginTextReadModel) AppendEvents(events ...eventstore.EventRe
for _, event := range events {
switch e := event.(type) {
case *org.CustomTextSetEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
wm.CustomLoginTextReadModel.AppendEvents(&e.CustomTextSetEvent)
case *org.CustomTextRemovedEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
wm.CustomLoginTextReadModel.AppendEvents(&e.CustomTextRemovedEvent)
case *org.CustomTextTemplateRemovedEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
wm.CustomLoginTextReadModel.AppendEvents(&e.CustomTextTemplateRemovedEvent)
}
}
@@ -52,3 +62,58 @@ func (wm *OrgCustomLoginTextReadModel) Query() *eventstore.SearchQueryBuilder {
org.CustomTextTemplateRemovedEventType).
Builder()
}
+
+type OrgCustomLoginTextsReadModel struct {
+ CustomLoginTextsReadModel
+}
+
+func NewOrgCustomLoginTextsReadModel(orgID string) *OrgCustomLoginTextsReadModel {
+ return &OrgCustomLoginTextsReadModel{
+ CustomLoginTextsReadModel{
+ WriteModel: eventstore.WriteModel{
+ AggregateID: orgID,
+ ResourceOwner: orgID,
+ },
+ CustomLoginTexts: make(map[string]*CustomText),
+ },
+ }
+}
+
+func (wm *OrgCustomLoginTextsReadModel) AppendEvents(events ...eventstore.EventReader) {
+ for _, event := range events {
+ switch e := event.(type) {
+ case *org.CustomTextSetEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
+ wm.CustomLoginTextsReadModel.AppendEvents(&e.CustomTextSetEvent)
+ case *org.CustomTextRemovedEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
+ wm.CustomLoginTextsReadModel.AppendEvents(&e.CustomTextRemovedEvent)
+ case *org.CustomTextTemplateRemovedEvent:
+ if e.Template != domain.LoginCustomText {
+ continue
+ }
+ wm.CustomLoginTextsReadModel.AppendEvents(&e.CustomTextTemplateRemovedEvent)
+ }
+ }
+}
+
+func (wm *OrgCustomLoginTextsReadModel) Reduce() error {
+ return wm.CustomLoginTextsReadModel.Reduce()
+}
+
+func (wm *OrgCustomLoginTextsReadModel) Query() *eventstore.SearchQueryBuilder {
+ return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
+ ResourceOwner(wm.ResourceOwner).
+ AddQuery().
+ AggregateIDs(wm.CustomLoginTextsReadModel.AggregateID).
+ AggregateTypes(org.AggregateType).
+ EventTypes(
+ org.CustomTextSetEventType,
+ org.CustomTextRemovedEventType,
+ org.CustomTextTemplateRemovedEventType).
+ Builder()
+}
diff --git a/internal/command/org_custom_message_model.go b/internal/command/org_custom_message_model.go
index 6ee0faa41..86f2766ae 100644
--- a/internal/command/org_custom_message_model.go
+++ b/internal/command/org_custom_message_model.go
@@ -3,6 +3,7 @@ package command
import (
"golang.org/x/text/language"
+ "github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/repository/org"
)
@@ -74,10 +75,19 @@ func (wm *OrgCustomMessageTemplatesReadModel) AppendEvents(events ...eventstore.
for _, event := range events {
switch e := event.(type) {
case *org.CustomTextSetEvent:
+ if !domain.IsMessageTextType(e.Template) {
+ continue
+ }
wm.CustomMessageTemplatesReadModel.AppendEvents(&e.CustomTextSetEvent)
case *org.CustomTextRemovedEvent:
+ if !domain.IsMessageTextType(e.Template) {
+ continue
+ }
wm.CustomMessageTemplatesReadModel.AppendEvents(&e.CustomTextRemovedEvent)
case *org.CustomTextTemplateRemovedEvent:
+ if !domain.IsMessageTextType(e.Template) {
+ continue
+ }
wm.CustomMessageTemplatesReadModel.AppendEvents(&e.CustomTextTemplateRemovedEvent)
}
}
diff --git a/internal/command/org_features.go b/internal/command/org_features.go
index ba2602635..7ce095358 100644
--- a/internal/command/org_features.go
+++ b/internal/command/org_features.go
@@ -40,9 +40,10 @@ func (c *Commands) SetOrgFeatures(ctx context.Context, resourceOwner string, fea
features.LabelPolicyPrivateLabel,
features.LabelPolicyWatermark,
features.CustomDomain,
- features.CustomText,
features.PrivacyPolicy,
features.MetadataUser,
+ features.CustomTextMessage,
+ features.CustomTextLogin,
)
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
@@ -129,13 +130,22 @@ func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string
events = append(events, removeCustomDomainsEvents...)
}
}
- if !features.CustomText {
- removeCustomTextEvents, err := c.removeOrgMessageTextsIfExists(ctx, orgID)
+ if !features.CustomTextMessage {
+ removeCustomMessageTextEvents, err := c.removeOrgMessageTextsIfExists(ctx, orgID)
if err != nil {
return nil, err
}
- if removeCustomTextEvents != nil {
- events = append(events, removeCustomTextEvents...)
+ if removeCustomMessageTextEvents != nil {
+ events = append(events, removeCustomMessageTextEvents...)
+ }
+ }
+ if !features.CustomTextLogin {
+ removeCustomLoginTextEvents, err := c.removeOrgLoginTextsIfExists(ctx, orgID)
+ if err != nil {
+ return nil, err
+ }
+ if removeCustomLoginTextEvents != nil {
+ events = append(events, removeCustomLoginTextEvents...)
}
}
if !features.PrivacyPolicy {
diff --git a/internal/command/org_features_model.go b/internal/command/org_features_model.go
index 0bda8172c..2086f897a 100644
--- a/internal/command/org_features_model.go
+++ b/internal/command/org_features_model.go
@@ -74,9 +74,10 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
labelPolicyPrivateLabel,
labelPolicyWatermark,
customDomain,
- customText,
privacyPolicy,
- metadataUser bool,
+ metadataUser,
+ customTextMessage,
+ customTextLogin bool,
) (*org.FeaturesSetEvent, bool) {
changes := make([]features.FeaturesChanges, 0)
@@ -126,15 +127,18 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
if wm.CustomDomain != customDomain {
changes = append(changes, features.ChangeCustomDomain(customDomain))
}
- if wm.CustomText != customText {
- changes = append(changes, features.ChangeCustomText(customText))
- }
if wm.PrivacyPolicy != privacyPolicy {
changes = append(changes, features.ChangePrivacyPolicy(privacyPolicy))
}
if wm.MetadataUser != metadataUser {
changes = append(changes, features.ChangeMetadataUser(metadataUser))
}
+ if wm.CustomTextMessage != customTextMessage {
+ changes = append(changes, features.ChangeCustomTextMessage(customTextMessage))
+ }
+ if wm.CustomTextLogin != customTextLogin {
+ changes = append(changes, features.ChangeCustomTextLogin(customTextLogin))
+ }
if len(changes) == 0 {
return nil, false
diff --git a/internal/command/org_features_test.go b/internal/command/org_features_test.go
index 53f004b29..405d0caf6 100644
--- a/internal/command/org_features_test.go
+++ b/internal/command/org_features_test.go
@@ -242,6 +242,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ iam.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
iam.NewPrivacyPolicyAddedEvent(
@@ -280,7 +292,8 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
LabelPolicyPrivateLabel: false,
LabelPolicyWatermark: false,
CustomDomain: false,
- CustomText: false,
+ CustomTextMessage: false,
+ CustomTextLogin: false,
PrivacyPolicy: false,
MetadataUser: false,
},
@@ -415,6 +428,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ iam.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
iam.NewPrivacyPolicyAddedEvent(
@@ -600,6 +625,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ iam.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
iam.NewPrivacyPolicyAddedEvent(
@@ -795,6 +832,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ iam.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
iam.NewPrivacyPolicyAddedEvent(
@@ -1045,6 +1094,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ org.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
org.NewPrivacyPolicyAddedEvent(
@@ -1079,6 +1140,9 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
eventFromEventPusher(
org.NewCustomTextTemplateRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, domain.InitCodeMessageType, language.English),
),
+ eventFromEventPusher(
+ org.NewCustomTextTemplateRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, language.English),
+ ),
eventFromEventPusher(
org.NewPrivacyPolicyRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate),
),
@@ -1219,6 +1283,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ iam.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
iam.NewPrivacyPolicyAddedEvent(
@@ -1269,7 +1345,8 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
LabelPolicyPrivateLabel: false,
LabelPolicyWatermark: false,
CustomDomain: false,
- CustomText: false,
+ CustomTextMessage: false,
+ CustomTextLogin: false,
PrivacyPolicy: false,
MetadataUser: false,
},
@@ -1452,6 +1529,18 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
),
),
),
+ expectFilter(
+ eventFromEventPusher(
+ iam.NewCustomTextSetEvent(
+ context.Background(),
+ &iam.NewAggregate().Aggregate,
+ domain.LoginCustomText,
+ domain.LoginKeyExternalRegistrationUserOverviewTitle,
+ "text",
+ language.English,
+ ),
+ ),
+ ),
expectFilter(
eventFromEventPusher(
iam.NewPrivacyPolicyAddedEvent(
diff --git a/internal/domain/custom_message_text.go b/internal/domain/custom_message_text.go
index 0309d5f74..d2a14b28d 100644
--- a/internal/domain/custom_message_text.go
+++ b/internal/domain/custom_message_text.go
@@ -68,3 +68,12 @@ func (m *MessageTexts) GetMessageTextByType(msgType string) *CustomMessageText {
}
return nil
}
+
+func IsMessageTextType(textType string) bool {
+ return textType == InitCodeMessageType ||
+ textType == PasswordResetMessageType ||
+ textType == VerifyEmailMessageType ||
+ textType == VerifyPhoneMessageType ||
+ textType == DomainClaimedMessageType ||
+ textType == PasswordlessRegistrationMessageType
+}
diff --git a/internal/domain/features.go b/internal/domain/features.go
index 1ca4eb71e..8ffddd04f 100644
--- a/internal/domain/features.go
+++ b/internal/domain/features.go
@@ -18,10 +18,12 @@ const (
FeatureLabelPolicy = "label_policy"
FeatureLabelPolicyPrivateLabel = FeatureLabelPolicy + ".private_label"
FeatureLabelPolicyWatermark = FeatureLabelPolicy + ".watermark"
- FeatureCustomText = "custom_text"
FeatureCustomDomain = "custom_domain"
FeaturePrivacyPolicy = "privacy_policy"
FeatureMetadata = "metadata"
+ FeatureCustomText = "custom_text"
+ FeatureCustomTextMessage = FeatureCustomText + ".message"
+ FeatureCustomTextLogin = FeatureCustomText + ".login"
FeatureMetadataUser = FeatureMetadata + ".user"
)
@@ -45,7 +47,8 @@ type Features struct {
LabelPolicyPrivateLabel bool
LabelPolicyWatermark bool
CustomDomain bool
- CustomText bool
+ CustomTextMessage bool
+ CustomTextLogin bool
PrivacyPolicy bool
MetadataUser bool
}
diff --git a/internal/features/model/features_view.go b/internal/features/model/features_view.go
index cd0f2f191..4a435cdcf 100644
--- a/internal/features/model/features_view.go
+++ b/internal/features/model/features_view.go
@@ -28,9 +28,10 @@ type FeaturesView struct {
LabelPolicyPrivateLabel bool
LabelPolicyWatermark bool
CustomDomain bool
- CustomText bool
PrivacyPolicy bool
MetadataUser bool
+ CustomTextMessage bool
+ CustomTextLogin bool
}
func (f *FeaturesView) FeatureList() []string {
@@ -65,15 +66,18 @@ func (f *FeaturesView) FeatureList() []string {
if f.CustomDomain {
list = append(list, domain.FeatureCustomDomain)
}
- if f.CustomText {
- list = append(list, domain.FeatureCustomText)
- }
if f.PrivacyPolicy {
list = append(list, domain.FeaturePrivacyPolicy)
}
if f.MetadataUser {
list = append(list, domain.FeatureMetadataUser)
}
+ if f.CustomTextMessage {
+ list = append(list, domain.FeatureCustomTextMessage)
+ }
+ if f.CustomTextLogin {
+ list = append(list, domain.FeatureCustomTextLogin)
+ }
return list
}
diff --git a/internal/features/repository/view/model/features.go b/internal/features/repository/view/model/features.go
index e1779d004..b3efde1ff 100644
--- a/internal/features/repository/view/model/features.go
+++ b/internal/features/repository/view/model/features.go
@@ -42,9 +42,10 @@ type FeaturesView struct {
LabelPolicyPrivateLabel bool `json:"labelPolicyPrivateLabel" gorm:"column:label_policy_private_label"`
LabelPolicyWatermark bool `json:"labelPolicyWatermark" gorm:"column:label_policy_watermark"`
CustomDomain bool `json:"customDomain" gorm:"column:custom_domain"`
- CustomText bool `json:"customText" gorm:"column:custom_text"`
PrivacyPolicy bool `json:"privacyPolicy" gorm:"column:privacy_policy"`
MetadataUser bool `json:"metadataUser" gorm:"column:metadata_user"`
+ CustomTextMessage bool `json:"customTextMessage" gorm:"column:custom_text_message"`
+ CustomTextLogin bool `json:"customTextLogin" gorm:"column:custom_text_login"`
}
func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
@@ -69,9 +70,10 @@ func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
LabelPolicyWatermark: features.LabelPolicyWatermark,
CustomDomain: features.CustomDomain,
- CustomText: features.CustomText,
PrivacyPolicy: features.PrivacyPolicy,
MetadataUser: features.MetadataUser,
+ CustomTextMessage: features.CustomTextMessage,
+ CustomTextLogin: features.CustomTextLogin,
}
}
diff --git a/internal/repository/features/features.go b/internal/repository/features/features.go
index 32dd8f3d7..1355b8e31 100644
--- a/internal/repository/features/features.go
+++ b/internal/repository/features/features.go
@@ -35,9 +35,10 @@ type FeaturesSetEvent struct {
LabelPolicyPrivateLabel *bool `json:"labelPolicyPrivateLabel,omitempty"`
LabelPolicyWatermark *bool `json:"labelPolicyWatermark,omitempty"`
CustomDomain *bool `json:"customDomain,omitempty"`
- CustomText *bool `json:"customText,omitempty"`
PrivacyPolicy *bool `json:"privacyPolicy,omitempty"`
MetadataUser *bool `json:"metadataUser,omitempty"`
+ CustomTextMessage *bool `json:"customTextMessage,omitempty"`
+ CustomTextLogin *bool `json:"customTextLogin,omitempty"`
}
func (e *FeaturesSetEvent) Data() interface{} {
@@ -156,12 +157,6 @@ func ChangeCustomDomain(customDomain bool) func(event *FeaturesSetEvent) {
}
}
-func ChangeCustomText(customText bool) func(event *FeaturesSetEvent) {
- return func(e *FeaturesSetEvent) {
- e.CustomText = &customText
- }
-}
-
func ChangePrivacyPolicy(privacyPolicy bool) func(event *FeaturesSetEvent) {
return func(e *FeaturesSetEvent) {
e.PrivacyPolicy = &privacyPolicy
@@ -173,6 +168,19 @@ func ChangeMetadataUser(metadataUser bool) func(event *FeaturesSetEvent) {
e.MetadataUser = &metadataUser
}
}
+
+func ChangeCustomTextMessage(customTextMessage bool) func(event *FeaturesSetEvent) {
+ return func(e *FeaturesSetEvent) {
+ e.CustomTextMessage = &customTextMessage
+ }
+}
+
+func ChangeCustomTextLogin(customTextLogin bool) func(event *FeaturesSetEvent) {
+ return func(e *FeaturesSetEvent) {
+ e.CustomTextLogin = &customTextLogin
+ }
+}
+
func FeaturesSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &FeaturesSetEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
diff --git a/migrations/cockroach/V1.62__custom_text_feature.sql b/migrations/cockroach/V1.62__custom_text_feature.sql
new file mode 100644
index 000000000..51256c4fb
--- /dev/null
+++ b/migrations/cockroach/V1.62__custom_text_feature.sql
@@ -0,0 +1,9 @@
+ALTER TABLE adminapi.features RENAME COLUMN custom_text TO custom_text_message;
+ALTER TABLE auth.features RENAME COLUMN custom_text TO custom_text_message;
+ALTER TABLE authz.features RENAME COLUMN custom_text TO custom_text_message;
+ALTER TABLE management.features RENAME COLUMN custom_text TO custom_text_message;
+
+ALTER TABLE adminapi.features ADD COLUMN custom_text_login BOOLEAN;
+ALTER TABLE auth.features ADD COLUMN custom_text_login BOOLEAN;
+ALTER TABLE authz.features ADD COLUMN custom_text_login BOOLEAN;
+ALTER TABLE management.features ADD COLUMN custom_text_login BOOLEAN;
\ No newline at end of file
diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto
index 3143979de..5800b523b 100644
--- a/proto/zitadel/admin.proto
+++ b/proto/zitadel/admin.proto
@@ -2613,6 +2613,8 @@ message SetDefaultFeaturesRequest {
bool custom_text = 17;
bool privacy_policy = 18;
bool metadata_user = 19;
+ bool custom_text_message = 20;
+ bool custom_text_login = 21;
}
message SetDefaultFeaturesResponse {
@@ -2649,6 +2651,8 @@ message SetOrgFeaturesRequest {
bool custom_text = 18;
bool privacy_policy = 19;
bool metadata_user = 20;
+ bool custom_text_message = 21;
+ bool custom_text_login = 22;
}
message SetOrgFeaturesResponse {
diff --git a/proto/zitadel/features.proto b/proto/zitadel/features.proto
index 589193b06..92cdc4469 100644
--- a/proto/zitadel/features.proto
+++ b/proto/zitadel/features.proto
@@ -27,6 +27,8 @@ message Features {
bool custom_text = 16;
bool privacy_policy = 17;
bool metadata_user = 18;
+ bool custom_text_message = 19;
+ bool custom_text_login = 20;
}
message FeatureTier {
diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto
index 0ced5cc62..23fcf9203 100644
--- a/proto/zitadel/management.proto
+++ b/proto/zitadel/management.proto
@@ -2271,7 +2271,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.message"
};
}
@@ -2319,7 +2319,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.message"
};
}
@@ -2368,7 +2368,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.message"
};
}
@@ -2417,7 +2417,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.message"
};
}
@@ -2466,7 +2466,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.message"
};
}
@@ -2515,7 +2515,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.message"
};
}
@@ -2563,7 +2563,7 @@ service ManagementService {
option (zitadel.v1.auth_option) = {
permission: "policy.write";
- feature: "custom_text"
+ feature: "custom_text.login"
};
}