mirror of
https://github.com/zitadel/zitadel.git
synced 2025-05-15 16:28:20 +00:00
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:
parent
0ab973b967
commit
f4fa3ecef3
@ -36,23 +36,23 @@
|
||||
</form>
|
||||
|
||||
<cnsl-info-section class="warn"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false"
|
||||
type="WARN">
|
||||
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||
'custom_text'})}}
|
||||
'custom_text.login'})}}
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="content" >
|
||||
<cnsl-edit-text label="one" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
|
||||
<cnsl-edit-text label="one" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
|
||||
$event)"></cnsl-edit-text>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
|
||||
<button class="save-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
<button class="save-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
|
@ -20,21 +20,21 @@
|
||||
</div>
|
||||
|
||||
<cnsl-info-section class="warn"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false"
|
||||
type="WARN">
|
||||
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||
'custom_text'})}}
|
||||
'custom_text.message'})}}
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="content" >
|
||||
<cnsl-edit-text [chips]="chips[currentType]" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" label="one" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
|
||||
<cnsl-edit-text [chips]="chips[currentType]" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" label="one" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
|
||||
$event)"></cnsl-edit-text>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
|
||||
<button class="save-button" [disabled]="!updateRequest || serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
<button class="save-button" [disabled]="!updateRequest || serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
|
@ -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": {
|
||||
|
@ -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 | - | |
|
||||
|
||||
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
9
migrations/cockroach/V1.62__custom_text_feature.sql
Normal file
9
migrations/cockroach/V1.62__custom_text_feature.sql
Normal file
@ -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;
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user