fix: Custom text split features (#2225)

* fix: separate tier of custom text (message and login)

* fix: add migration

* fix: build problems

* fix: tests

* Update internal/api/grpc/admin/features.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/api/grpc/admin/features.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: rename sql file

* fix: change sql files

* fix: console

* fix: console

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Fabi
2021-08-18 12:58:57 +02:00
committed by GitHub
parent 0ab973b967
commit f4fa3ecef3
26 changed files with 339 additions and 60 deletions

View File

@@ -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
}
}

View File

@@ -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
}

View File

@@ -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")

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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()
}

View File

@@ -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)
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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(