mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 03:47:22 +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:
parent
67462eefe0
commit
bdf3887f9e
File diff suppressed because one or more lines are too long
@ -141,7 +141,15 @@
|
|||||||
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.customDomain"
|
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.customDomain"
|
||||||
[disabled]="(['iam.features.write'] | hasRole | async) == false">
|
[disabled]="(['iam.features.write'] | hasRole | async) == false">
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<span class="left-desc">{{'FEATURES.DATA.CUSTOMTEXT' | translate}}</span>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.customText"
|
||||||
|
[disabled]="(['iam.features.write'] | hasRole | async) == false">
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-container">
|
<div class="btn-container">
|
||||||
|
@ -161,6 +161,7 @@ export class FeaturesComponent implements OnDestroy {
|
|||||||
req.setLabelPolicyPrivateLabel(this.features.labelPolicyPrivateLabel);
|
req.setLabelPolicyPrivateLabel(this.features.labelPolicyPrivateLabel);
|
||||||
req.setLabelPolicyWatermark(this.features.labelPolicyWatermark);
|
req.setLabelPolicyWatermark(this.features.labelPolicyWatermark);
|
||||||
req.setCustomDomain(this.features.customDomain);
|
req.setCustomDomain(this.features.customDomain);
|
||||||
|
req.setCustomText(this.features.customText);
|
||||||
|
|
||||||
this.adminService.setOrgFeatures(req).then(() => {
|
this.adminService.setOrgFeatures(req).then(() => {
|
||||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
@ -181,6 +182,7 @@ export class FeaturesComponent implements OnDestroy {
|
|||||||
dreq.setLabelPolicyPrivateLabel(this.features.labelPolicyPrivateLabel);
|
dreq.setLabelPolicyPrivateLabel(this.features.labelPolicyPrivateLabel);
|
||||||
dreq.setLabelPolicyWatermark(this.features.labelPolicyWatermark);
|
dreq.setLabelPolicyWatermark(this.features.labelPolicyWatermark);
|
||||||
dreq.setCustomDomain(this.features.customDomain);
|
dreq.setCustomDomain(this.features.customDomain);
|
||||||
|
dreq.setCustomText(this.features.customText);
|
||||||
|
|
||||||
this.adminService.setDefaultFeatures(dreq).then(() => {
|
this.adminService.setDefaultFeatures(dreq).then(() => {
|
||||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||||
|
@ -611,12 +611,13 @@
|
|||||||
"LOGINPOLICYPASSWORDRESET": "Login Richtlinie: Passwort vergessen Link nicht anzeigen - benutzerdefiniert",
|
"LOGINPOLICYPASSWORDRESET": "Login Richtlinie: Passwort vergessen Link nicht anzeigen - benutzerdefiniert",
|
||||||
"LOGINPOLICYREGISTRATION": "Login Richtlinie: Registration erlauben - benutzerdefiniert",
|
"LOGINPOLICYREGISTRATION": "Login Richtlinie: Registration erlauben - benutzerdefiniert",
|
||||||
"LOGINPOLICYIDP": "Login Richtlinie: Identity Providers - benutzerdefiniert",
|
"LOGINPOLICYIDP": "Login Richtlinie: Identity Providers - benutzerdefiniert",
|
||||||
"LOGINPOLICYFACTORS": "Login Richtlinie: Mltifaktoren - benutzerdefiniert",
|
"LOGINPOLICYFACTORS": "Login Richtlinie: Multifaktoren - benutzerdefiniert",
|
||||||
"LOGINPOLICYPASSWORDLESS": "Login Richtlinie: Passwortlose Authentifizierung - benutzerdefiniert",
|
"LOGINPOLICYPASSWORDLESS": "Login Richtlinie: Passwortlose Authentifizierung - benutzerdefiniert",
|
||||||
"LOGINPOLICYCOMPLEXITYPOLICY": "Passwortkomplexitäts Richtlinie - benutzerdefiniert",
|
"LOGINPOLICYCOMPLEXITYPOLICY": "Passwortkomplexitäts Richtlinie - benutzerdefiniert",
|
||||||
"LABELPOLICYPRIVATELABEL": "Label Richtlinie - benutzerdefiniert",
|
"LABELPOLICYPRIVATELABEL": "Label Richtlinie - benutzerdefiniert",
|
||||||
"LABELPOLICYWATERMARK": "Label Richtlinie - Wasserzeichen",
|
"LABELPOLICYWATERMARK": "Label Richtlinie - Wasserzeichen",
|
||||||
"CUSTOMDOMAIN": "Domänen Verifikation - verfügbar"
|
"CUSTOMDOMAIN": "Domänen Verifikation - verfügbar",
|
||||||
|
"CUSTOMTEXT": "Benutzerdefinierte Texte"
|
||||||
},
|
},
|
||||||
"TIERSTATES": {
|
"TIERSTATES": {
|
||||||
"0": "Aktiv",
|
"0": "Aktiv",
|
||||||
|
@ -616,7 +616,8 @@
|
|||||||
"LOGINPOLICYCOMPLEXITYPOLICY": "Password Complexity Policy - custom",
|
"LOGINPOLICYCOMPLEXITYPOLICY": "Password Complexity Policy - custom",
|
||||||
"LABELPOLICYPRIVATELABEL": "Label Richtlinie - benutzerdefiniert",
|
"LABELPOLICYPRIVATELABEL": "Label Richtlinie - benutzerdefiniert",
|
||||||
"LABELPOLICYWATERMARK": "Label Richtlinie - Wasserzeichen",
|
"LABELPOLICYWATERMARK": "Label Richtlinie - Wasserzeichen",
|
||||||
"CUSTOMDOMAIN": "Domain Verification - available"
|
"CUSTOMDOMAIN": "Domain Verification - available",
|
||||||
|
"CUSTOMTEXT": "Custom texts"
|
||||||
},
|
},
|
||||||
"TIERSTATES": {
|
"TIERSTATES": {
|
||||||
"0": "Active",
|
"0": "Active",
|
||||||
|
@ -528,6 +528,121 @@ it impacts all organisations without a customised policy
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultInitMessageText
|
||||||
|
|
||||||
|
> **rpc** GetDefaultInitMessageText([GetDefaultInitMessageTextRequest](#getdefaultinitmessagetextrequest))
|
||||||
|
[GetDefaultInitMessageTextResponse](#getdefaultinitmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for initial message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultInitMessageText
|
||||||
|
|
||||||
|
> **rpc** SetDefaultInitMessageText([SetDefaultInitMessageTextRequest](#setdefaultinitmessagetextrequest))
|
||||||
|
[SetDefaultInitMessageTextResponse](#setdefaultinitmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for initial message
|
||||||
|
it impacts all organisations without customized initial message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultPasswordResetMessageText
|
||||||
|
|
||||||
|
> **rpc** GetDefaultPasswordResetMessageText([GetDefaultPasswordResetMessageTextRequest](#getdefaultpasswordresetmessagetextrequest))
|
||||||
|
[GetDefaultPasswordResetMessageTextResponse](#getdefaultpasswordresetmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for password reset message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultPasswordResetMessageText
|
||||||
|
|
||||||
|
> **rpc** SetDefaultPasswordResetMessageText([SetDefaultPasswordResetMessageTextRequest](#setdefaultpasswordresetmessagetextrequest))
|
||||||
|
[SetDefaultPasswordResetMessageTextResponse](#setdefaultpasswordresetmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for password reset message
|
||||||
|
it impacts all organisations without customized password reset message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultVerifyEmailMessageText
|
||||||
|
|
||||||
|
> **rpc** GetDefaultVerifyEmailMessageText([GetDefaultVerifyEmailMessageTextRequest](#getdefaultverifyemailmessagetextrequest))
|
||||||
|
[GetDefaultVerifyEmailMessageTextResponse](#getdefaultverifyemailmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for verify email message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultVerifyEmailMessageText
|
||||||
|
|
||||||
|
> **rpc** SetDefaultVerifyEmailMessageText([SetDefaultVerifyEmailMessageTextRequest](#setdefaultverifyemailmessagetextrequest))
|
||||||
|
[SetDefaultVerifyEmailMessageTextResponse](#setdefaultverifyemailmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for verify email message
|
||||||
|
it impacts all organisations without customized verify email message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultVerifyPhoneMessageText
|
||||||
|
|
||||||
|
> **rpc** GetDefaultVerifyPhoneMessageText([GetDefaultVerifyPhoneMessageTextRequest](#getdefaultverifyphonemessagetextrequest))
|
||||||
|
[GetDefaultVerifyPhoneMessageTextResponse](#getdefaultverifyphonemessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for verify phone message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultVerifyPhoneMessageText
|
||||||
|
|
||||||
|
> **rpc** SetDefaultVerifyPhoneMessageText([SetDefaultVerifyPhoneMessageTextRequest](#setdefaultverifyphonemessagetextrequest))
|
||||||
|
[SetDefaultVerifyPhoneMessageTextResponse](#setdefaultverifyphonemessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for verify phone message
|
||||||
|
it impacts all organisations without customized verify phone message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultDomainClaimedMessageText
|
||||||
|
|
||||||
|
> **rpc** GetDefaultDomainClaimedMessageText([GetDefaultDomainClaimedMessageTextRequest](#getdefaultdomainclaimedmessagetextrequest))
|
||||||
|
[GetDefaultDomainClaimedMessageTextResponse](#getdefaultdomainclaimedmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for domain claimed message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultDomainClaimedMessageText
|
||||||
|
|
||||||
|
> **rpc** SetDefaultDomainClaimedMessageText([SetDefaultDomainClaimedMessageTextRequest](#setdefaultdomainclaimedmessagetextrequest))
|
||||||
|
[SetDefaultDomainClaimedMessageTextResponse](#setdefaultdomainclaimedmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for domain claimed phone message
|
||||||
|
it impacts all organisations without customized verify phone message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Domain}} {{.TempUsername}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ListIAMMemberRoles
|
### ListIAMMemberRoles
|
||||||
|
|
||||||
> **rpc** ListIAMMemberRoles([ListIAMMemberRolesRequest](#listiammemberrolesrequest))
|
> **rpc** ListIAMMemberRoles([ListIAMMemberRolesRequest](#listiammemberrolesrequest))
|
||||||
@ -877,6 +992,28 @@ This is an empty response
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultDomainClaimedMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultDomainClaimedMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetDefaultFeaturesRequest
|
### GetDefaultFeaturesRequest
|
||||||
|
|
||||||
|
|
||||||
@ -894,6 +1031,94 @@ This is an empty response
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultInitMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultInitMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultPasswordResetMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultPasswordResetMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultVerifyEmailMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultVerifyEmailMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultVerifyPhoneMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetDefaultVerifyPhoneMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetIDPByIDRequest
|
### GetIDPByIDRequest
|
||||||
|
|
||||||
|
|
||||||
@ -1593,6 +1818,35 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultDomainClaimedMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultDomainClaimedMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### SetDefaultFeaturesRequest
|
### SetDefaultFeaturesRequest
|
||||||
|
|
||||||
|
|
||||||
@ -1613,6 +1867,7 @@ This is an empty request
|
|||||||
| login_policy_password_reset | bool | - | |
|
| login_policy_password_reset | bool | - | |
|
||||||
| label_policy_private_label | bool | - | |
|
| label_policy_private_label | bool | - | |
|
||||||
| label_policy_watermark | bool | - | |
|
| label_policy_watermark | bool | - | |
|
||||||
|
| custom_text | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1628,6 +1883,122 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultInitMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 1000<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultInitMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultPasswordResetMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultPasswordResetMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultVerifyEmailMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultVerifyEmailMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultVerifyPhoneMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetDefaultVerifyPhoneMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### SetOrgFeaturesRequest
|
### SetOrgFeaturesRequest
|
||||||
|
|
||||||
|
|
||||||
@ -1651,6 +2022,7 @@ This is an empty request
|
|||||||
| login_policy_password_reset | bool | - | |
|
| login_policy_password_reset | bool | - | |
|
||||||
| label_policy_private_label | bool | - | |
|
| label_policy_private_label | bool | - | |
|
||||||
| label_policy_watermark | bool | - | |
|
| label_policy_watermark | bool | - | |
|
||||||
|
| custom_text | bool | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1712,6 +1712,176 @@ The default policy of the IAM will trigger after
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomInitMessageText
|
||||||
|
|
||||||
|
> **rpc** GetCustomInitMessageText([GetCustomInitMessageTextRequest](#getcustominitmessagetextrequest))
|
||||||
|
[GetCustomInitMessageTextResponse](#getcustominitmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for initial message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomInitMessageText
|
||||||
|
|
||||||
|
> **rpc** SetCustomInitMessageText([SetCustomInitMessageTextRequest](#setcustominitmessagetextrequest))
|
||||||
|
[SetCustomInitMessageTextResponse](#setcustominitmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for initial message
|
||||||
|
it impacts all organisations without customized initial message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomInitMessageTextToDefault
|
||||||
|
|
||||||
|
> **rpc** ResetCustomInitMessageTextToDefault([ResetCustomInitMessageTextToDefaultRequest](#resetcustominitmessagetexttodefaultrequest))
|
||||||
|
[ResetCustomInitMessageTextToDefaultResponse](#resetcustominitmessagetexttodefaultresponse)
|
||||||
|
|
||||||
|
Removes the custom init message text of the organisation
|
||||||
|
The default text of the IAM will trigger after
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomPasswordResetMessageText
|
||||||
|
|
||||||
|
> **rpc** GetCustomPasswordResetMessageText([GetCustomPasswordResetMessageTextRequest](#getcustompasswordresetmessagetextrequest))
|
||||||
|
[GetCustomPasswordResetMessageTextResponse](#getcustompasswordresetmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for password reset message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomPasswordResetMessageText
|
||||||
|
|
||||||
|
> **rpc** SetCustomPasswordResetMessageText([SetCustomPasswordResetMessageTextRequest](#setcustompasswordresetmessagetextrequest))
|
||||||
|
[SetCustomPasswordResetMessageTextResponse](#setcustompasswordresetmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for password reset message
|
||||||
|
it impacts all organisations without customized password reset message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomPasswordResetMessageTextToDefault
|
||||||
|
|
||||||
|
> **rpc** ResetCustomPasswordResetMessageTextToDefault([ResetCustomPasswordResetMessageTextToDefaultRequest](#resetcustompasswordresetmessagetexttodefaultrequest))
|
||||||
|
[ResetCustomPasswordResetMessageTextToDefaultResponse](#resetcustompasswordresetmessagetexttodefaultresponse)
|
||||||
|
|
||||||
|
Removes the custom init message text of the organisation
|
||||||
|
The default text of the IAM will trigger after
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomVerifyEmailMessageText
|
||||||
|
|
||||||
|
> **rpc** GetCustomVerifyEmailMessageText([GetCustomVerifyEmailMessageTextRequest](#getcustomverifyemailmessagetextrequest))
|
||||||
|
[GetCustomVerifyEmailMessageTextResponse](#getcustomverifyemailmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for verify email message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomVerifyEmailMessageText
|
||||||
|
|
||||||
|
> **rpc** SetCustomVerifyEmailMessageText([SetCustomVerifyEmailMessageTextRequest](#setcustomverifyemailmessagetextrequest))
|
||||||
|
[SetCustomVerifyEmailMessageTextResponse](#setcustomverifyemailmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for verify email message
|
||||||
|
it impacts all organisations without customized verify email message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomVerifyEmailMessageTextToDefault
|
||||||
|
|
||||||
|
> **rpc** ResetCustomVerifyEmailMessageTextToDefault([ResetCustomVerifyEmailMessageTextToDefaultRequest](#resetcustomverifyemailmessagetexttodefaultrequest))
|
||||||
|
[ResetCustomVerifyEmailMessageTextToDefaultResponse](#resetcustomverifyemailmessagetexttodefaultresponse)
|
||||||
|
|
||||||
|
Removes the custom init message text of the organisation
|
||||||
|
The default text of the IAM will trigger after
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomVerifyPhoneMessageText
|
||||||
|
|
||||||
|
> **rpc** GetCustomVerifyPhoneMessageText([GetCustomVerifyPhoneMessageTextRequest](#getcustomverifyphonemessagetextrequest))
|
||||||
|
[GetCustomVerifyPhoneMessageTextResponse](#getcustomverifyphonemessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for verify email message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomVerifyPhoneMessageText
|
||||||
|
|
||||||
|
> **rpc** SetCustomVerifyPhoneMessageText([SetCustomVerifyPhoneMessageTextRequest](#setcustomverifyphonemessagetextrequest))
|
||||||
|
[SetCustomVerifyPhoneMessageTextResponse](#setcustomverifyphonemessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for verify email message
|
||||||
|
it impacts all organisations without customized verify email message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Code}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomVerifyPhoneMessageTextToDefault
|
||||||
|
|
||||||
|
> **rpc** ResetCustomVerifyPhoneMessageTextToDefault([ResetCustomVerifyPhoneMessageTextToDefaultRequest](#resetcustomverifyphonemessagetexttodefaultrequest))
|
||||||
|
[ResetCustomVerifyPhoneMessageTextToDefaultResponse](#resetcustomverifyphonemessagetexttodefaultresponse)
|
||||||
|
|
||||||
|
Removes the custom init message text of the organisation
|
||||||
|
The default text of the IAM will trigger after
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomDomainClaimedMessageText
|
||||||
|
|
||||||
|
> **rpc** GetCustomDomainClaimedMessageText([GetCustomDomainClaimedMessageTextRequest](#getcustomdomainclaimedmessagetextrequest))
|
||||||
|
[GetCustomDomainClaimedMessageTextResponse](#getcustomdomainclaimedmessagetextresponse)
|
||||||
|
|
||||||
|
Returns the custom text for domain claimed message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomDomainClaimedMessageCustomText
|
||||||
|
|
||||||
|
> **rpc** SetCustomDomainClaimedMessageCustomText([SetCustomDomainClaimedMessageTextRequest](#setcustomdomainclaimedmessagetextrequest))
|
||||||
|
[SetCustomDomainClaimedMessageTextResponse](#setcustomdomainclaimedmessagetextresponse)
|
||||||
|
|
||||||
|
Sets the default custom text for domain claimed message
|
||||||
|
it impacts all organisations without customized domain claimed message text
|
||||||
|
The Following Variables can be used:
|
||||||
|
{{.Domain}} {{.TempUsername}} {{.UserName}} {{.FirstName}} {{.LastName}} {{.NickName}} {{.DisplayName}} {{.LastEmail}} {{.VerifiedEmail}} {{.LastPhone}} {{.VerifiedPhone}} {{.PreferredLoginName}} {{.LoginNames}} {{.ChangeDate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomDomainClaimedMessageTextToDefault
|
||||||
|
|
||||||
|
> **rpc** ResetCustomDomainClaimedMessageTextToDefault([ResetCustomDomainClaimedMessageTextToDefaultRequest](#resetcustomdomainclaimedmessagetexttodefaultrequest))
|
||||||
|
[ResetCustomDomainClaimedMessageTextToDefaultResponse](#resetcustomdomainclaimedmessagetexttodefaultresponse)
|
||||||
|
|
||||||
|
Removes the custom init message text of the organisation
|
||||||
|
The default text of the IAM will trigger after
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetOrgIDPByID
|
### GetOrgIDPByID
|
||||||
|
|
||||||
> **rpc** GetOrgIDPByID([GetOrgIDPByIDRequest](#getorgidpbyidrequest))
|
> **rpc** GetOrgIDPByID([GetOrgIDPByIDRequest](#getorgidpbyidrequest))
|
||||||
@ -2758,6 +2928,116 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomDomainClaimedMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomDomainClaimedMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomInitMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomInitMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomPasswordResetMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomPasswordResetMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomVerifyEmailMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomVerifyEmailMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomVerifyPhoneMessageTextRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### GetCustomVerifyPhoneMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| custom_text | zitadel.text.v1.MessageCustomText | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### GetDefaultLabelPolicyRequest
|
### GetDefaultLabelPolicyRequest
|
||||||
This is an empty request
|
This is an empty request
|
||||||
|
|
||||||
@ -4972,6 +5252,116 @@ This is an empty response
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomDomainClaimedMessageTextToDefaultRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomDomainClaimedMessageTextToDefaultResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomInitMessageTextToDefaultRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomInitMessageTextToDefaultResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomPasswordResetMessageTextToDefaultRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomPasswordResetMessageTextToDefaultResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomVerifyEmailMessageTextToDefaultRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomVerifyEmailMessageTextToDefaultResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomVerifyPhoneMessageTextToDefaultRequest
|
||||||
|
This is an empty request
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### ResetCustomVerifyPhoneMessageTextToDefaultResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ResetLabelPolicyToDefaultRequest
|
### ResetLabelPolicyToDefaultRequest
|
||||||
This is an empty request
|
This is an empty request
|
||||||
|
|
||||||
@ -5080,6 +5470,151 @@ This is an empty request
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomDomainClaimedMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomDomainClaimedMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomInitMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomInitMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomPasswordResetMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomPasswordResetMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomVerifyEmailMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomVerifyEmailMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomVerifyPhoneMessageTextRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| language | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||||
|
| title | string | - | string.max_len: 200<br /> |
|
||||||
|
| pre_header | string | - | string.max_len: 200<br /> |
|
||||||
|
| subject | string | - | string.max_len: 200<br /> |
|
||||||
|
| greeting | string | - | string.max_len: 200<br /> |
|
||||||
|
| text | string | - | string.max_len: 800<br /> |
|
||||||
|
| button_text | string | - | string.max_len: 200<br /> |
|
||||||
|
| footer_text | string | - | string.max_len: 200<br /> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### SetCustomVerifyPhoneMessageTextResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Type | Description | Validation |
|
||||||
|
| ----- | ---- | ----------- | ----------- |
|
||||||
|
| details | zitadel.v1.ObjectDetails | - | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### SetHumanInitialPasswordRequest
|
### SetHumanInitialPasswordRequest
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,16 +2,18 @@ package eventstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
|
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
|
||||||
"github.com/caos/zitadel/internal/user/repository/view/model"
|
"github.com/caos/zitadel/internal/user/repository/view/model"
|
||||||
"strings"
|
|
||||||
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view"
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
@ -347,21 +349,21 @@ func (repo *IAMRepository) SearchIAMMembersx(ctx context.Context, request *iam_m
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *IAMRepository) GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error) {
|
func (repo *IAMRepository) GetDefaultMessageTexts(ctx context.Context) (*iam_model.MessageTextsView, error) {
|
||||||
text, err := repo.View.MailTexts(repo.SystemDefaults.IamID)
|
text, err := repo.View.MessageTexts(repo.SystemDefaults.IamID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return iam_es_model.MailTextsViewToModel(text, true), err
|
return iam_es_model.MessageTextsViewToModel(text, true), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *IAMRepository) GetDefaultMailText(ctx context.Context, textType string, language string) (*iam_model.MailTextView, error) {
|
func (repo *IAMRepository) GetDefaultMessageText(ctx context.Context, textType, lang string) (*iam_model.MessageTextView, error) {
|
||||||
text, err := repo.View.MailTextByIDs(repo.SystemDefaults.IamID, textType, language)
|
text, err := repo.View.MessageTextByIDs(repo.SystemDefaults.IamID, textType, lang)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
text.Default = true
|
text.Default = true
|
||||||
return iam_es_model.MailTextViewToModel(text), err
|
return iam_es_model.MessageTextViewToModel(text), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *IAMRepository) getIAMEvents(ctx context.Context, sequence uint64) ([]*models.Event, error) {
|
func (repo *IAMRepository) getIAMEvents(ctx context.Context, sequence uint64) ([]*models.Event, error) {
|
||||||
|
@ -62,8 +62,8 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
|||||||
defaults),
|
defaults),
|
||||||
newMailTemplate(
|
newMailTemplate(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
|
||||||
newMailText(
|
newMessageText(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("MailText"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("MessageText"), errorCount, es}),
|
||||||
newFeatures(
|
newFeatures(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("Features"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("Features"), errorCount, es}),
|
||||||
}
|
}
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/logging"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
|
||||||
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MailText struct {
|
|
||||||
handler
|
|
||||||
subscription *v1.Subscription
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMailText(handler handler) *MailText {
|
|
||||||
h := &MailText{
|
|
||||||
handler: handler,
|
|
||||||
}
|
|
||||||
|
|
||||||
h.subscribe()
|
|
||||||
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) subscribe() {
|
|
||||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
|
||||||
go func() {
|
|
||||||
for event := range m.subscription.Events {
|
|
||||||
query.ReduceEvent(m, event)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
mailTextTable = "adminapi.mail_texts"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (m *MailText) ViewModel() string {
|
|
||||||
return mailTextTable
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_ *MailText) AggregateTypes() []es_models.AggregateType {
|
|
||||||
return []es_models.AggregateType{iam_es_model.IAMAggregate}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *MailText) CurrentSequence() (uint64, error) {
|
|
||||||
sequence, err := p.view.GetLatestMailTextSequence()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return sequence.CurrentSequence, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) EventQuery() (*es_models.SearchQuery, error) {
|
|
||||||
sequence, err := m.view.GetLatestMailTextSequence()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return es_models.NewSearchQuery().
|
|
||||||
AggregateTypeFilter(m.AggregateTypes()...).
|
|
||||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) Reduce(event *es_models.Event) (err error) {
|
|
||||||
switch event.AggregateType {
|
|
||||||
case model.IAMAggregate:
|
|
||||||
err = m.processMailText(event)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) processMailText(event *es_models.Event) (err error) {
|
|
||||||
mailText := new(iam_model.MailTextView)
|
|
||||||
switch event.Type {
|
|
||||||
case model.MailTextAdded:
|
|
||||||
err = mailText.AppendEvent(event)
|
|
||||||
case model.MailTextChanged:
|
|
||||||
err = mailText.SetData(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mailText, err = m.view.MailTextByIDs(event.AggregateID, mailText.MailTextType, mailText.Language)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = mailText.AppendEvent(event)
|
|
||||||
default:
|
|
||||||
return m.view.ProcessedMailTextSequence(event)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return m.view.PutMailText(mailText, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) OnError(event *es_models.Event, err error) error {
|
|
||||||
logging.LogWithFields("HANDL-5jk84", "id", event.AggregateID).WithError(err).Warn("something went wrong in label mailText handler")
|
|
||||||
return spooler.HandleError(event, err, m.view.GetLatestMailTextFailedEvent, m.view.ProcessedMailTextFailedEvent, m.view.ProcessedMailTextSequence, m.errorCountUntilSkip)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *MailText) OnSuccess() error {
|
|
||||||
return spooler.HandleSuccess(o.view.UpdateMailTextSpoolerRunTimestamp)
|
|
||||||
}
|
|
116
internal/admin/repository/eventsourcing/handler/message_text.go
Normal file
116
internal/admin/repository/eventsourcing/handler/message_text.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/logging"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
|
|
||||||
|
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||||
|
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||||
|
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageText struct {
|
||||||
|
handler
|
||||||
|
subscription *v1.Subscription
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMessageText(handler handler) *MessageText {
|
||||||
|
h := &MessageText{
|
||||||
|
handler: handler,
|
||||||
|
}
|
||||||
|
|
||||||
|
h.subscribe()
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) subscribe() {
|
||||||
|
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||||
|
go func() {
|
||||||
|
for event := range m.subscription.Events {
|
||||||
|
query.ReduceEvent(m, event)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
mailTextTable = "adminapi.message_texts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *MessageText) ViewModel() string {
|
||||||
|
return mailTextTable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *MessageText) AggregateTypes() []es_models.AggregateType {
|
||||||
|
return []es_models.AggregateType{iam_es_model.IAMAggregate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MessageText) CurrentSequence() (uint64, error) {
|
||||||
|
sequence, err := p.view.GetLatestMessageTextSequence()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return sequence.CurrentSequence, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) EventQuery() (*es_models.SearchQuery, error) {
|
||||||
|
sequence, err := m.view.GetLatestMessageTextSequence()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return es_models.NewSearchQuery().
|
||||||
|
AggregateTypeFilter(m.AggregateTypes()...).
|
||||||
|
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) Reduce(event *es_models.Event) (err error) {
|
||||||
|
switch event.AggregateType {
|
||||||
|
case model.IAMAggregate:
|
||||||
|
err = m.processMessageText(event)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) processMessageText(event *es_models.Event) (err error) {
|
||||||
|
message := new(iam_model.MessageTextView)
|
||||||
|
switch event.Type {
|
||||||
|
case model.CustomTextSet,
|
||||||
|
model.CustomTextRemoved:
|
||||||
|
text := new(iam_model.CustomText)
|
||||||
|
err = text.SetData(event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
message, err = m.view.MessageTextByIDs(event.AggregateID, text.Template, text.Language.String())
|
||||||
|
if err != nil && !caos_errs.IsNotFound(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if caos_errs.IsNotFound(err) {
|
||||||
|
err = nil
|
||||||
|
message = new(iam_model.MessageTextView)
|
||||||
|
message.Language = text.Language.String()
|
||||||
|
message.MessageTextType = text.Template
|
||||||
|
message.CreationDate = event.CreationDate
|
||||||
|
}
|
||||||
|
err = message.AppendEvent(event)
|
||||||
|
default:
|
||||||
|
return m.view.ProcessedMessageTextSequence(event)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.view.PutMessageText(message, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) OnError(event *es_models.Event, err error) error {
|
||||||
|
logging.LogWithFields("HANDL-5jk84", "id", event.AggregateID).WithError(err).Warn("something went wrong in label mailText handler")
|
||||||
|
return spooler.HandleError(event, err, m.view.GetLatestMessageTextFailedEvent, m.view.ProcessedMessageTextFailedEvent, m.view.ProcessedMessageTextSequence, m.errorCountUntilSkip)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *MessageText) OnSuccess() error {
|
||||||
|
return spooler.HandleSuccess(o.view.UpdateMessageTextSpoolerRunTimestamp)
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
mailTextTable = "adminapi.mail_texts"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (v *View) MailTexts(aggregateID string) ([]*model.MailTextView, error) {
|
|
||||||
return view.GetMailTexts(v.Db, mailTextTable, aggregateID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) MailTextByIDs(aggregateID string, textType string, language string) (*model.MailTextView, error) {
|
|
||||||
return view.GetMailTextByIDs(v.Db, mailTextTable, aggregateID, textType, language)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) PutMailText(template *model.MailTextView, event *models.Event) error {
|
|
||||||
err := view.PutMailText(v.Db, mailTextTable, template)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return v.ProcessedMailTextSequence(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetLatestMailTextSequence() (*global_view.CurrentSequence, error) {
|
|
||||||
return v.latestSequence(mailTextTable)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) ProcessedMailTextSequence(event *models.Event) error {
|
|
||||||
return v.saveCurrentSequence(mailTextTable, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) UpdateMailTextSpoolerRunTimestamp() error {
|
|
||||||
return v.updateSpoolerRunSequence(mailTextTable)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetLatestMailTextFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
|
||||||
return v.latestFailedEvent(mailTextTable, sequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) ProcessedMailTextFailedEvent(failedEvent *global_view.FailedEvent) error {
|
|
||||||
return v.saveFailedEvent(failedEvent)
|
|
||||||
}
|
|
@ -0,0 +1,48 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
messageTextTable = "adminapi.message_texts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *View) MessageTexts(aggregateID string) ([]*model.MessageTextView, error) {
|
||||||
|
return view.GetMessageTexts(v.Db, messageTextTable, aggregateID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) MessageTextByIDs(aggregateID, textType, lang string) (*model.MessageTextView, error) {
|
||||||
|
return view.GetMessageTextByIDs(v.Db, messageTextTable, aggregateID, textType, lang)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) PutMessageText(template *model.MessageTextView, event *models.Event) error {
|
||||||
|
err := view.PutMessageText(v.Db, messageTextTable, template)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.ProcessedMessageTextSequence(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) GetLatestMessageTextSequence() (*global_view.CurrentSequence, error) {
|
||||||
|
return v.latestSequence(messageTextTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) ProcessedMessageTextSequence(event *models.Event) error {
|
||||||
|
return v.saveCurrentSequence(messageTextTable, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) UpdateMessageTextSpoolerRunTimestamp() error {
|
||||||
|
return v.updateSpoolerRunSequence(messageTextTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) GetLatestMessageTextFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||||
|
return v.latestFailedEvent(messageTextTable, sequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) ProcessedMessageTextFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||||
|
return v.saveFailedEvent(failedEvent)
|
||||||
|
}
|
@ -28,8 +28,8 @@ type IAMRepository interface {
|
|||||||
|
|
||||||
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||||
|
|
||||||
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
GetDefaultMessageTexts(ctx context.Context) (*iam_model.MessageTextsView, error)
|
||||||
GetDefaultMailText(ctx context.Context, textType string, language string) (*iam_model.MailTextView, error)
|
GetDefaultMessageText(ctx context.Context, textType string, language string) (*iam_model.MessageTextView, error)
|
||||||
|
|
||||||
GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
|
GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error)
|
||||||
|
|
||||||
|
130
internal/api/grpc/admin/custom_text.go
Normal file
130
internal/api/grpc/admin/custom_text.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||||
|
text_grpc "github.com/caos/zitadel/internal/api/grpc/text"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) GetDefaultInitMessageText(ctx context.Context, req *admin_pb.GetDefaultInitMessageTextRequest) (*admin_pb.GetDefaultInitMessageTextResponse, error) {
|
||||||
|
msg, err := s.iam.GetDefaultMessageText(ctx, domain.InitCodeMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.GetDefaultInitMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetDefaultInitMessageText(ctx context.Context, req *admin_pb.SetDefaultInitMessageTextRequest) (*admin_pb.SetDefaultInitMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetDefaultMessageText(ctx, SetInitCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.SetDefaultInitMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDefaultPasswordResetMessageText(ctx context.Context, req *admin_pb.GetDefaultPasswordResetMessageTextRequest) (*admin_pb.GetDefaultPasswordResetMessageTextResponse, error) {
|
||||||
|
msg, err := s.iam.GetDefaultMessageText(ctx, domain.PasswordResetMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.GetDefaultPasswordResetMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetDefaultPasswordResetMessageText(ctx context.Context, req *admin_pb.SetDefaultPasswordResetMessageTextRequest) (*admin_pb.SetDefaultPasswordResetMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetDefaultMessageText(ctx, SetPasswordResetCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.SetDefaultPasswordResetMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDefaultVerifyEmailMessageText(ctx context.Context, req *admin_pb.GetDefaultVerifyEmailMessageTextRequest) (*admin_pb.GetDefaultVerifyEmailMessageTextResponse, error) {
|
||||||
|
msg, err := s.iam.GetDefaultMessageText(ctx, domain.VerifyEmailMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.GetDefaultVerifyEmailMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetVerifyEmailMessageCustomText(ctx context.Context, req *admin_pb.SetDefaultVerifyEmailMessageTextRequest) (*admin_pb.SetDefaultVerifyEmailMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetDefaultMessageText(ctx, SetVerifyEmailCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.SetDefaultVerifyEmailMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDefaultVerifyPhoneMessageText(ctx context.Context, req *admin_pb.GetDefaultVerifyPhoneMessageTextRequest) (*admin_pb.GetDefaultVerifyPhoneMessageTextResponse, error) {
|
||||||
|
msg, err := s.iam.GetDefaultMessageText(ctx, domain.VerifyPhoneMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.GetDefaultVerifyPhoneMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetDefaultVerifyPhoneMessageText(ctx context.Context, req *admin_pb.SetDefaultVerifyPhoneMessageTextRequest) (*admin_pb.SetDefaultVerifyPhoneMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetDefaultMessageText(ctx, SetVerifyPhoneCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.SetDefaultVerifyPhoneMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDefaultDomainClaimedMessageText(ctx context.Context, req *admin_pb.GetDefaultDomainClaimedMessageTextRequest) (*admin_pb.GetDefaultDomainClaimedMessageTextResponse, error) {
|
||||||
|
msg, err := s.iam.GetDefaultMessageText(ctx, domain.DomainClaimedMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.GetDefaultDomainClaimedMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetDefaultDomainClaimedMessageText(ctx context.Context, req *admin_pb.SetDefaultDomainClaimedMessageTextRequest) (*admin_pb.SetDefaultDomainClaimedMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetDefaultMessageText(ctx, SetDomainClaimedCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.SetDefaultDomainClaimedMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
83
internal/api/grpc/admin/custom_text_converter.go
Normal file
83
internal/api/grpc/admin/custom_text_converter.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetInitCustomTextToDomain(msg *admin_pb.SetDefaultInitMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.InitCodeMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetPasswordResetCustomTextToDomain(msg *admin_pb.SetDefaultPasswordResetMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.PasswordResetMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetVerifyEmailCustomTextToDomain(msg *admin_pb.SetDefaultVerifyEmailMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.VerifyEmailMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetVerifyPhoneCustomTextToDomain(msg *admin_pb.SetDefaultVerifyPhoneMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.VerifyPhoneMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetDomainClaimedCustomTextToDomain(msg *admin_pb.SetDefaultDomainClaimedMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.DomainClaimedMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
@ -74,6 +74,7 @@ func setDefaultFeaturesRequestToDomain(req *admin_pb.SetDefaultFeaturesRequest)
|
|||||||
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
|
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
|
||||||
LabelPolicyWatermark: req.LabelPolicyWatermark,
|
LabelPolicyWatermark: req.LabelPolicyWatermark,
|
||||||
CustomDomain: req.CustomDomain,
|
CustomDomain: req.CustomDomain,
|
||||||
|
CustomText: req.CustomText,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,5 +95,6 @@ func setOrgFeaturesRequestToDomain(req *admin_pb.SetOrgFeaturesRequest) *domain.
|
|||||||
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
|
LabelPolicyPrivateLabel: req.LabelPolicy || req.LabelPolicyPrivateLabel,
|
||||||
LabelPolicyWatermark: req.LabelPolicyWatermark,
|
LabelPolicyWatermark: req.LabelPolicyWatermark,
|
||||||
CustomDomain: req.CustomDomain,
|
CustomDomain: req.CustomDomain,
|
||||||
|
CustomText: req.CustomText,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ func FeaturesFromModel(features *features_model.FeaturesView) *features_pb.Featu
|
|||||||
CustomDomain: features.CustomDomain,
|
CustomDomain: features.CustomDomain,
|
||||||
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
|
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
|
||||||
LabelPolicyWatermark: features.LabelPolicyWatermark,
|
LabelPolicyWatermark: features.LabelPolicyWatermark,
|
||||||
|
CustomText: features.CustomText,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
131
internal/api/grpc/management/custom_text.go
Normal file
131
internal/api/grpc/management/custom_text.go
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package management
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
|
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||||
|
text_grpc "github.com/caos/zitadel/internal/api/grpc/text"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) GetCustomInitMessageText(ctx context.Context, req *mgmt_pb.GetCustomInitMessageTextRequest) (*mgmt_pb.GetCustomInitMessageTextResponse, error) {
|
||||||
|
msg, err := s.org.GetMessageText(ctx, authz.GetCtxData(ctx).OrgID, domain.InitCodeMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.GetCustomInitMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetCustomInitMessageText(ctx context.Context, req *mgmt_pb.SetCustomInitMessageTextRequest) (*mgmt_pb.SetCustomInitMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, SetInitCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.SetCustomInitMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetCustomPasswordResetMessageText(ctx context.Context, req *mgmt_pb.GetCustomPasswordResetMessageTextRequest) (*mgmt_pb.GetCustomPasswordResetMessageTextResponse, error) {
|
||||||
|
msg, err := s.org.GetMessageText(ctx, authz.GetCtxData(ctx).OrgID, domain.PasswordResetMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.GetCustomPasswordResetMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetCustomPasswordResetMessageText(ctx context.Context, req *mgmt_pb.SetCustomPasswordResetMessageTextRequest) (*mgmt_pb.SetCustomPasswordResetMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, SetPasswordResetCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.SetCustomPasswordResetMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetCustomVerifyEmailMessageText(ctx context.Context, req *mgmt_pb.GetCustomVerifyEmailMessageTextRequest) (*mgmt_pb.GetCustomVerifyEmailMessageTextResponse, error) {
|
||||||
|
msg, err := s.org.GetMessageText(ctx, authz.GetCtxData(ctx).OrgID, domain.VerifyEmailMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.GetCustomVerifyEmailMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetCustomVerifyEmailMessageText(ctx context.Context, req *mgmt_pb.SetCustomVerifyEmailMessageTextRequest) (*mgmt_pb.SetCustomVerifyEmailMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, SetVerifyEmailCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.SetCustomVerifyEmailMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetCustomVerifyPhoneMessageText(ctx context.Context, req *mgmt_pb.GetCustomVerifyPhoneMessageTextRequest) (*mgmt_pb.GetCustomVerifyPhoneMessageTextResponse, error) {
|
||||||
|
msg, err := s.org.GetMessageText(ctx, authz.GetCtxData(ctx).OrgID, domain.VerifyPhoneMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.GetCustomVerifyPhoneMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetCustomVerifyPhoneMessageText(ctx context.Context, req *mgmt_pb.SetCustomVerifyPhoneMessageTextRequest) (*mgmt_pb.SetCustomVerifyPhoneMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, SetVerifyPhoneCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.SetCustomVerifyPhoneMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetCustomDomainClaimedMessageText(ctx context.Context, req *mgmt_pb.GetCustomDomainClaimedMessageTextRequest) (*mgmt_pb.GetCustomDomainClaimedMessageTextResponse, error) {
|
||||||
|
msg, err := s.org.GetMessageText(ctx, authz.GetCtxData(ctx).OrgID, domain.DomainClaimedMessageType, req.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.GetCustomDomainClaimedMessageTextResponse{
|
||||||
|
CustomText: text_grpc.ModelCustomMsgTextToPb(msg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetCustomDomainClaimedMessageText(ctx context.Context, req *mgmt_pb.SetCustomDomainClaimedMessageTextRequest) (*mgmt_pb.SetCustomDomainClaimedMessageTextResponse, error) {
|
||||||
|
result, err := s.command.SetOrgMessageText(ctx, authz.GetCtxData(ctx).OrgID, SetDomainClaimedCustomTextToDomain(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.SetCustomDomainClaimedMessageTextResponse{
|
||||||
|
Details: object.ChangeToDetailsPb(
|
||||||
|
result.Sequence,
|
||||||
|
result.EventDate,
|
||||||
|
result.ResourceOwner,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}
|
83
internal/api/grpc/management/custom_text_converter.go
Normal file
83
internal/api/grpc/management/custom_text_converter.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package management
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetInitCustomTextToDomain(msg *mgmt_pb.SetCustomInitMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.InitCodeMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetPasswordResetCustomTextToDomain(msg *mgmt_pb.SetCustomPasswordResetMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.PasswordResetMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetVerifyEmailCustomTextToDomain(msg *mgmt_pb.SetCustomVerifyEmailMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.VerifyEmailMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetVerifyPhoneCustomTextToDomain(msg *mgmt_pb.SetCustomVerifyPhoneMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.VerifyPhoneMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetDomainClaimedCustomTextToDomain(msg *mgmt_pb.SetCustomDomainClaimedMessageTextRequest) *domain.CustomMessageText {
|
||||||
|
langTag := language.Make(msg.Language)
|
||||||
|
return &domain.CustomMessageText{
|
||||||
|
MessageTextType: domain.DomainClaimedMessageType,
|
||||||
|
Language: langTag,
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
}
|
||||||
|
}
|
25
internal/api/grpc/text/custom_text.go
Normal file
25
internal/api/grpc/text/custom_text.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package text
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||||
|
"github.com/caos/zitadel/internal/iam/model"
|
||||||
|
text_pb "github.com/caos/zitadel/pkg/grpc/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ModelCustomMsgTextToPb(msg *model.MessageTextView) *text_pb.MessageCustomText {
|
||||||
|
return &text_pb.MessageCustomText{
|
||||||
|
Title: msg.Title,
|
||||||
|
PreHeader: msg.PreHeader,
|
||||||
|
Subject: msg.Subject,
|
||||||
|
Greeting: msg.Greeting,
|
||||||
|
Text: msg.Text,
|
||||||
|
ButtonText: msg.ButtonText,
|
||||||
|
FooterText: msg.FooterText,
|
||||||
|
Details: object.ToViewDetailsPb(
|
||||||
|
msg.Sequence,
|
||||||
|
msg.CreationDate,
|
||||||
|
msg.ChangeDate,
|
||||||
|
"", //TODO: resourceowner
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
@ -465,7 +465,9 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if user.State == int32(domain.UserStateInactive) {
|
||||||
|
return errors.ThrowPreconditionFailed(nil, "AUTH-2n8fs", "Errors.User.Inactive")
|
||||||
|
}
|
||||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,18 @@ func checkFeatures(features *features_view_model.FeaturesView, requiredFeatures
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if requiredFeature == domain.FeatureCustomDomain {
|
||||||
|
if !features.CustomDomain {
|
||||||
|
return MissingFeatureErr(requiredFeature)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if requiredFeature == domain.FeatureCustomText {
|
||||||
|
if !features.CustomText {
|
||||||
|
return MissingFeatureErr(requiredFeature)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
return MissingFeatureErr(requiredFeature)
|
return MissingFeatureErr(requiredFeature)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
167
internal/command/custom_message_text_model.go
Normal file
167
internal/command/custom_message_text_model.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
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/policy"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomMessageTextReadModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
MessageTextType string
|
||||||
|
Language language.Tag
|
||||||
|
Title string
|
||||||
|
PreHeader string
|
||||||
|
Subject string
|
||||||
|
Greeting string
|
||||||
|
Text string
|
||||||
|
ButtonText string
|
||||||
|
FooterText string
|
||||||
|
|
||||||
|
State domain.PolicyState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *CustomMessageTextReadModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *policy.CustomTextSetEvent:
|
||||||
|
if e.Template != wm.MessageTextType || wm.Language != e.Language {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageSubject {
|
||||||
|
wm.Subject = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageTitle {
|
||||||
|
wm.Title = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessagePreHeader {
|
||||||
|
wm.PreHeader = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageText {
|
||||||
|
wm.Text = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageGreeting {
|
||||||
|
wm.Greeting = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageButtonText {
|
||||||
|
wm.ButtonText = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageFooterText {
|
||||||
|
wm.FooterText = e.Text
|
||||||
|
}
|
||||||
|
wm.State = domain.PolicyStateActive
|
||||||
|
case *policy.CustomTextRemovedEvent:
|
||||||
|
if e.Key != wm.MessageTextType || wm.Language != e.Language {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageSubject {
|
||||||
|
wm.Subject = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageTitle {
|
||||||
|
wm.Title = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessagePreHeader {
|
||||||
|
wm.PreHeader = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageText {
|
||||||
|
wm.Text = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageGreeting {
|
||||||
|
wm.Greeting = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageButtonText {
|
||||||
|
wm.ButtonText = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageFooterText {
|
||||||
|
wm.FooterText = ""
|
||||||
|
}
|
||||||
|
case *policy.CustomTextTemplateRemovedEvent:
|
||||||
|
wm.State = domain.PolicyStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomMessageTemplatesReadModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
CustomMessageTemplate map[string]*CustomText
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomText struct {
|
||||||
|
Template string
|
||||||
|
Language language.Tag
|
||||||
|
Title string
|
||||||
|
PreHeader string
|
||||||
|
Subject string
|
||||||
|
Greeting string
|
||||||
|
Text string
|
||||||
|
ButtonText string
|
||||||
|
FooterText string
|
||||||
|
State domain.PolicyState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *CustomMessageTemplatesReadModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *policy.CustomTextSetEvent:
|
||||||
|
if _, ok := wm.CustomMessageTemplate[e.Template+e.Language.String()]; !ok {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()] = &CustomText{Language: e.Language, Template: e.Template}
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageSubject {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Subject = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageTitle {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Title = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessagePreHeader {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].PreHeader = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageText {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Text = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageGreeting {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Greeting = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageButtonText {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].ButtonText = e.Text
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageFooterText {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].FooterText = e.Text
|
||||||
|
}
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].State = domain.PolicyStateActive
|
||||||
|
case *policy.CustomTextRemovedEvent:
|
||||||
|
if _, ok := wm.CustomMessageTemplate[e.Template+e.Language.String()]; !ok {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()] = new(CustomText)
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageSubject {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Subject = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageTitle {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Title = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessagePreHeader {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].PreHeader = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageText {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Text = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageGreeting {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].Greeting = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageButtonText {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].ButtonText = ""
|
||||||
|
}
|
||||||
|
if e.Key == domain.MessageFooterText {
|
||||||
|
wm.CustomMessageTemplate[e.Template+e.Language.String()].FooterText = ""
|
||||||
|
}
|
||||||
|
case *policy.CustomTextTemplateRemovedEvent:
|
||||||
|
if _, ok := wm.CustomMessageTemplate[e.Template+e.Language.String()]; ok {
|
||||||
|
delete(wm.CustomMessageTemplate, e.Template)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
34
internal/command/custom_text_model.go
Normal file
34
internal/command/custom_text_model.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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/policy"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomTextWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Key string
|
||||||
|
Language language.Tag
|
||||||
|
Text string
|
||||||
|
State domain.CustomTextState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *CustomTextWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *policy.CustomTextSetEvent:
|
||||||
|
if wm.Key != e.Key || wm.Language != e.Language {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wm.Text = e.Text
|
||||||
|
wm.State = domain.CustomTextStateActive
|
||||||
|
case *policy.CustomTextRemovedEvent:
|
||||||
|
wm.State = domain.CustomTextStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
@ -26,6 +26,7 @@ type FeaturesWriteModel struct {
|
|||||||
LabelPolicyPrivateLabel bool
|
LabelPolicyPrivateLabel bool
|
||||||
LabelPolicyWatermark bool
|
LabelPolicyWatermark bool
|
||||||
CustomDomain bool
|
CustomDomain bool
|
||||||
|
CustomText bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *FeaturesWriteModel) Reduce() error {
|
func (wm *FeaturesWriteModel) Reduce() error {
|
||||||
@ -81,6 +82,9 @@ func (wm *FeaturesWriteModel) Reduce() error {
|
|||||||
if e.CustomDomain != nil {
|
if e.CustomDomain != nil {
|
||||||
wm.CustomDomain = *e.CustomDomain
|
wm.CustomDomain = *e.CustomDomain
|
||||||
}
|
}
|
||||||
|
if e.CustomText != nil {
|
||||||
|
wm.CustomText = *e.CustomText
|
||||||
|
}
|
||||||
case *features.FeaturesRemovedEvent:
|
case *features.FeaturesRemovedEvent:
|
||||||
wm.State = domain.FeaturesStateRemoved
|
wm.State = domain.FeaturesStateRemoved
|
||||||
}
|
}
|
||||||
|
@ -69,21 +69,6 @@ func writeModelToMailTemplate(wm *MailTemplateWriteModel) *domain.MailTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeModelToMailText(wm *MailTextWriteModel) *domain.MailText {
|
|
||||||
return &domain.MailText{
|
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
|
||||||
MailTextType: wm.MailTextType,
|
|
||||||
Language: wm.Language,
|
|
||||||
Title: wm.Title,
|
|
||||||
PreHeader: wm.PreHeader,
|
|
||||||
Subject: wm.Subject,
|
|
||||||
Greeting: wm.Greeting,
|
|
||||||
Text: wm.Text,
|
|
||||||
ButtonText: wm.ButtonText,
|
|
||||||
State: wm.State,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeModelToOrgIAMPolicy(wm *IAMOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
func writeModelToOrgIAMPolicy(wm *IAMOrgIAMPolicyWriteModel) *domain.OrgIAMPolicy {
|
||||||
return &domain.OrgIAMPolicy{
|
return &domain.OrgIAMPolicy{
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
|
||||||
@ -98,18 +83,13 @@ func writeModelToMailTemplatePolicy(wm *MailTemplateWriteModel) *domain.MailTemp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeModelToMailTextPolicy(wm *MailTextWriteModel) *domain.MailText {
|
func writeModelToCustomText(wm *CustomTextWriteModel) *domain.CustomText {
|
||||||
return &domain.MailText{
|
return &domain.CustomText{
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
State: wm.State,
|
State: wm.State,
|
||||||
MailTextType: wm.MailTextType,
|
Key: wm.Key,
|
||||||
Language: wm.Language,
|
Language: wm.Language,
|
||||||
Title: wm.Title,
|
Text: wm.Text,
|
||||||
PreHeader: wm.PreHeader,
|
|
||||||
Subject: wm.Subject,
|
|
||||||
Greeting: wm.Greeting,
|
|
||||||
Text: wm.Text,
|
|
||||||
ButtonText: wm.ButtonText,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
72
internal/command/iam_custom_message_text.go
Normal file
72
internal/command/iam_custom_message_text.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/repository/iam"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Commands) SetDefaultMessageText(ctx context.Context, messageText *domain.CustomMessageText) (*domain.ObjectDetails, error) {
|
||||||
|
iamAgg := iam.NewAggregate()
|
||||||
|
events, existingMessageText, err := c.setDefaultMessageText(ctx, &iamAgg.Aggregate, messageText)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, events...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingMessageText, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingMessageText.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) setDefaultMessageText(ctx context.Context, iamAgg *eventstore.Aggregate, msg *domain.CustomMessageText) ([]eventstore.EventPusher, *IAMCustomMessageTextReadModel, error) {
|
||||||
|
if !msg.IsValid() {
|
||||||
|
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "IAM-kd9fs", "Errors.CustomMessageText.Invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingMessageText, err := c.defaultCustomMessageTextWriteModelByID(ctx, msg.MessageTextType, msg.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
events := make([]eventstore.EventPusher, 0)
|
||||||
|
if existingMessageText.Greeting != msg.Greeting {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessageGreeting, msg.Greeting, msg.Language))
|
||||||
|
}
|
||||||
|
if existingMessageText.Subject != msg.Subject {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessageSubject, msg.Subject, msg.Language))
|
||||||
|
}
|
||||||
|
if existingMessageText.Title != msg.Title {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessageTitle, msg.Title, msg.Language))
|
||||||
|
}
|
||||||
|
if existingMessageText.PreHeader != msg.PreHeader {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessagePreHeader, msg.PreHeader, msg.Language))
|
||||||
|
}
|
||||||
|
if existingMessageText.Text != msg.Text {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessageText, msg.Text, msg.Language))
|
||||||
|
}
|
||||||
|
if existingMessageText.ButtonText != msg.ButtonText {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessageButtonText, msg.ButtonText, msg.Language))
|
||||||
|
}
|
||||||
|
if existingMessageText.FooterText != msg.FooterText {
|
||||||
|
events = append(events, iam.NewCustomTextSetEvent(ctx, iamAgg, msg.MessageTextType, domain.MessageFooterText, msg.FooterText, msg.Language))
|
||||||
|
}
|
||||||
|
return events, existingMessageText, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) defaultCustomMessageTextWriteModelByID(ctx context.Context, messageType string, lang language.Tag) (*IAMCustomMessageTextReadModel, error) {
|
||||||
|
writeModel := NewIAMCustomMessageTextWriteModel(messageType, lang)
|
||||||
|
err := c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
47
internal/command/iam_custom_message_text_model.go
Normal file
47
internal/command/iam_custom_message_text_model.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
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/iam"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IAMCustomMessageTextReadModel struct {
|
||||||
|
CustomMessageTextReadModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIAMCustomMessageTextWriteModel(messageTextType string, lang language.Tag) *IAMCustomMessageTextReadModel {
|
||||||
|
return &IAMCustomMessageTextReadModel{
|
||||||
|
CustomMessageTextReadModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: domain.IAMID,
|
||||||
|
ResourceOwner: domain.IAMID,
|
||||||
|
},
|
||||||
|
MessageTextType: messageTextType,
|
||||||
|
Language: lang,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *IAMCustomMessageTextReadModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *iam.CustomTextSetEvent:
|
||||||
|
wm.CustomMessageTextReadModel.AppendEvents(&e.CustomTextSetEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *IAMCustomMessageTextReadModel) Reduce() error {
|
||||||
|
return wm.CustomMessageTextReadModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *IAMCustomMessageTextReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
||||||
|
AggregateIDs(wm.CustomMessageTextReadModel.AggregateID).
|
||||||
|
ResourceOwner(wm.ResourceOwner).
|
||||||
|
EventTypes(
|
||||||
|
iam.CustomTextSetEventType)
|
||||||
|
}
|
163
internal/command/iam_custom_message_text_test.go
Normal file
163
internal/command/iam_custom_message_text_test.go
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
"github.com/caos/zitadel/internal/repository/iam"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommandSide_SetDefaultMessageText(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
config *domain.CustomMessageText
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "invalid custom text, error",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
config: &domain.CustomMessageText{},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsErrorInvalidArgument,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom text set all fields, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageGreeting,
|
||||||
|
"Greeting",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageSubject,
|
||||||
|
"Subject",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageTitle,
|
||||||
|
"Title",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessagePreHeader,
|
||||||
|
"PreHeader",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageText,
|
||||||
|
"Text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageButtonText,
|
||||||
|
"ButtonText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageFooterText,
|
||||||
|
"FooterText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
config: &domain.CustomMessageText{
|
||||||
|
MessageTextType: "Template",
|
||||||
|
Language: language.English,
|
||||||
|
Greeting: "Greeting",
|
||||||
|
Subject: "Subject",
|
||||||
|
Title: "Title",
|
||||||
|
PreHeader: "PreHeader",
|
||||||
|
Text: "Text",
|
||||||
|
ButtonText: "ButtonText",
|
||||||
|
FooterText: "FooterText",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "IAM",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
}
|
||||||
|
got, err := r.SetDefaultMessageText(tt.args.ctx, tt.args.config)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.Equal(t, tt.res.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,7 @@ func (c *Commands) setDefaultFeatures(ctx context.Context, existingFeatures *IAM
|
|||||||
features.LabelPolicyPrivateLabel,
|
features.LabelPolicyPrivateLabel,
|
||||||
features.LabelPolicyWatermark,
|
features.LabelPolicyWatermark,
|
||||||
features.CustomDomain,
|
features.CustomDomain,
|
||||||
|
features.CustomText,
|
||||||
)
|
)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||||
|
@ -64,7 +64,8 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
|||||||
passwordComplexityPolicy,
|
passwordComplexityPolicy,
|
||||||
labelPolicyPrivateLabel,
|
labelPolicyPrivateLabel,
|
||||||
labelPolicyWatermark,
|
labelPolicyWatermark,
|
||||||
customDomain bool,
|
customDomain,
|
||||||
|
customText bool,
|
||||||
) (*iam.FeaturesSetEvent, bool) {
|
) (*iam.FeaturesSetEvent, bool) {
|
||||||
|
|
||||||
changes := make([]features.FeaturesChanges, 0)
|
changes := make([]features.FeaturesChanges, 0)
|
||||||
@ -111,6 +112,9 @@ func (wm *IAMFeaturesWriteModel) NewSetEvent(
|
|||||||
if wm.CustomDomain != customDomain {
|
if wm.CustomDomain != customDomain {
|
||||||
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
||||||
}
|
}
|
||||||
|
if wm.CustomText != customText {
|
||||||
|
changes = append(changes, features.ChangeCustomText(customText))
|
||||||
|
}
|
||||||
|
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
iam_repo "github.com/caos/zitadel/internal/repository/iam"
|
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Commands) AddDefaultMailText(ctx context.Context, policy *domain.MailText) (*domain.MailText, error) {
|
|
||||||
addedPolicy := NewIAMMailTextWriteModel(policy.MailTextType, policy.Language)
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.MailTextWriteModel.WriteModel)
|
|
||||||
event, err := c.addDefaultMailText(ctx, iamAgg, addedPolicy, policy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pushedEvents, err := c.eventstore.PushEvents(ctx, event)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return writeModelToMailTextPolicy(&addedPolicy.MailTextWriteModel), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Commands) addDefaultMailText(ctx context.Context, iamAgg *eventstore.Aggregate, addedPolicy *IAMMailTextWriteModel, mailText *domain.MailText) (eventstore.EventPusher, error) {
|
|
||||||
if !mailText.IsValid() {
|
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-3n8fs", "Errors.IAM.MailText.Invalid")
|
|
||||||
}
|
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if addedPolicy.State == domain.PolicyStateActive {
|
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-9o0pM", "Errors.IAM.MailText.AlreadyExists")
|
|
||||||
}
|
|
||||||
|
|
||||||
return iam_repo.NewMailTextAddedEvent(
|
|
||||||
ctx,
|
|
||||||
iamAgg,
|
|
||||||
mailText.MailTextType,
|
|
||||||
mailText.Language,
|
|
||||||
mailText.Title,
|
|
||||||
mailText.PreHeader,
|
|
||||||
mailText.Subject,
|
|
||||||
mailText.Greeting,
|
|
||||||
mailText.Text,
|
|
||||||
mailText.ButtonText), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Commands) ChangeDefaultMailText(ctx context.Context, mailText *domain.MailText) (*domain.MailText, error) {
|
|
||||||
if !mailText.IsValid() {
|
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-kd9fs", "Errors.IAM.MailText.Invalid")
|
|
||||||
}
|
|
||||||
existingPolicy, err := c.defaultMailTextWriteModelByID(ctx, mailText.MailTextType, mailText.Language)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "IAM-2N8fs", "Errors.IAM.MailText.NotFound")
|
|
||||||
}
|
|
||||||
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.MailTextWriteModel.WriteModel)
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
|
||||||
ctx,
|
|
||||||
iamAgg,
|
|
||||||
mailText.MailTextType,
|
|
||||||
mailText.Language,
|
|
||||||
mailText.Title,
|
|
||||||
mailText.PreHeader,
|
|
||||||
mailText.Subject,
|
|
||||||
mailText.Greeting,
|
|
||||||
mailText.Text,
|
|
||||||
mailText.ButtonText)
|
|
||||||
if !hasChanged {
|
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-m9L0s", "Errors.IAM.MailText.NotChanged")
|
|
||||||
}
|
|
||||||
|
|
||||||
pushedEvents, err := c.eventstore.PushEvents(ctx, changedEvent)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return writeModelToMailTextPolicy(&existingPolicy.MailTextWriteModel), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Commands) defaultMailTextWriteModelByID(ctx context.Context, mailTextType, language string) (policy *IAMMailTextWriteModel, err error) {
|
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
|
||||||
defer func() { span.EndWithError(err) }()
|
|
||||||
|
|
||||||
writeModel := NewIAMMailTextWriteModel(mailTextType, language)
|
|
||||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return writeModel, nil
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
"github.com/caos/zitadel/internal/repository/iam"
|
|
||||||
"github.com/caos/zitadel/internal/repository/policy"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IAMMailTextWriteModel struct {
|
|
||||||
MailTextWriteModel
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIAMMailTextWriteModel(mailTextType, language string) *IAMMailTextWriteModel {
|
|
||||||
return &IAMMailTextWriteModel{
|
|
||||||
MailTextWriteModel{
|
|
||||||
WriteModel: eventstore.WriteModel{
|
|
||||||
AggregateID: domain.IAMID,
|
|
||||||
ResourceOwner: domain.IAMID,
|
|
||||||
},
|
|
||||||
MailTextType: mailTextType,
|
|
||||||
Language: language,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *IAMMailTextWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
|
||||||
for _, event := range events {
|
|
||||||
switch e := event.(type) {
|
|
||||||
case *iam.MailTextAddedEvent:
|
|
||||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextAddedEvent)
|
|
||||||
case *iam.MailTextChangedEvent:
|
|
||||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextChangedEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *IAMMailTextWriteModel) Reduce() error {
|
|
||||||
return wm.MailTextWriteModel.Reduce()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *IAMMailTextWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|
||||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
|
|
||||||
AggregateIDs(wm.MailTextWriteModel.AggregateID).
|
|
||||||
ResourceOwner(wm.ResourceOwner).
|
|
||||||
EventTypes(
|
|
||||||
iam.MailTextAddedEventType,
|
|
||||||
iam.MailTextChangedEventType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *IAMMailTextWriteModel) NewChangedEvent(
|
|
||||||
ctx context.Context,
|
|
||||||
aggregate *eventstore.Aggregate,
|
|
||||||
mailTextType,
|
|
||||||
language,
|
|
||||||
title,
|
|
||||||
preHeader,
|
|
||||||
subject,
|
|
||||||
greeting,
|
|
||||||
text,
|
|
||||||
buttonText string,
|
|
||||||
) (*iam.MailTextChangedEvent, bool) {
|
|
||||||
changes := make([]policy.MailTextChanges, 0)
|
|
||||||
if wm.Title != title {
|
|
||||||
changes = append(changes, policy.ChangeTitle(title))
|
|
||||||
}
|
|
||||||
if wm.PreHeader != preHeader {
|
|
||||||
changes = append(changes, policy.ChangePreHeader(preHeader))
|
|
||||||
}
|
|
||||||
if wm.Subject != subject {
|
|
||||||
changes = append(changes, policy.ChangeSubject(subject))
|
|
||||||
}
|
|
||||||
if wm.Greeting != greeting {
|
|
||||||
changes = append(changes, policy.ChangeGreeting(greeting))
|
|
||||||
}
|
|
||||||
if wm.Text != text {
|
|
||||||
changes = append(changes, policy.ChangeText(text))
|
|
||||||
}
|
|
||||||
if wm.ButtonText != buttonText {
|
|
||||||
changes = append(changes, policy.ChangeButtonText(buttonText))
|
|
||||||
}
|
|
||||||
if len(changes) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
changedEvent, err := iam.NewMailTextChangedEvent(ctx, aggregate, mailTextType, language, changes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return changedEvent, true
|
|
||||||
}
|
|
@ -1,366 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/repository/iam"
|
|
||||||
"github.com/caos/zitadel/internal/repository/policy"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCommandSide_AddDefaultMailTextPolicy(t *testing.T) {
|
|
||||||
type fields struct {
|
|
||||||
eventstore *eventstore.Eventstore
|
|
||||||
}
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
policy *domain.MailText
|
|
||||||
}
|
|
||||||
type res struct {
|
|
||||||
want *domain.MailText
|
|
||||||
err func(error) bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fields fields
|
|
||||||
args args
|
|
||||||
res res
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "mail text invalid, invalid argument error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorInvalidArgument,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mail text already existing, already exists error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
iam.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&iam.NewAggregate().Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorAlreadyExists,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "add mail template,ok",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(),
|
|
||||||
expectPush(
|
|
||||||
[]*repository.Event{
|
|
||||||
eventFromEventPusher(
|
|
||||||
iam.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&iam.NewAggregate().Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
uniqueConstraintsFromEventConstraint(policy.NewAddMailTextUniqueConstraint("IAM", "mail-text-type", "de")),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
want: &domain.MailText{
|
|
||||||
ObjectRoot: models.ObjectRoot{
|
|
||||||
AggregateID: "IAM",
|
|
||||||
ResourceOwner: "IAM",
|
|
||||||
},
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
State: domain.PolicyStateActive,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
r := &Commands{
|
|
||||||
eventstore: tt.fields.eventstore,
|
|
||||||
}
|
|
||||||
got, err := r.AddDefaultMailText(tt.args.ctx, tt.args.policy)
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
if tt.res.err != nil && !tt.res.err(err) {
|
|
||||||
t.Errorf("got wrong err: %v ", err)
|
|
||||||
}
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.Equal(t, tt.res.want, got)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCommandSide_ChangeDefaultMailTextPolicy(t *testing.T) {
|
|
||||||
type fields struct {
|
|
||||||
eventstore *eventstore.Eventstore
|
|
||||||
}
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
policy *domain.MailText
|
|
||||||
}
|
|
||||||
type res struct {
|
|
||||||
want *domain.MailText
|
|
||||||
err func(error) bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fields fields
|
|
||||||
args args
|
|
||||||
res res
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "mailtext invalid, invalid argument error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorInvalidArgument,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mail text not existing, not found error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsNotFound,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no changes, precondition error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
iam.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&iam.NewAggregate().Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsPreconditionFailed,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "change, ok",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
iam.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&iam.NewAggregate().Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
expectPush(
|
|
||||||
[]*repository.Event{
|
|
||||||
eventFromEventPusher(
|
|
||||||
newDefaultMailTextPolicyChangedEvent(
|
|
||||||
context.Background(),
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title-change",
|
|
||||||
"pre-header-change",
|
|
||||||
"subject-change",
|
|
||||||
"greeting-change",
|
|
||||||
"text-change",
|
|
||||||
"button-text-change"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title-change",
|
|
||||||
PreHeader: "pre-header-change",
|
|
||||||
Subject: "subject-change",
|
|
||||||
Greeting: "greeting-change",
|
|
||||||
Text: "text-change",
|
|
||||||
ButtonText: "button-text-change",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
want: &domain.MailText{
|
|
||||||
ObjectRoot: models.ObjectRoot{
|
|
||||||
AggregateID: "IAM",
|
|
||||||
ResourceOwner: "IAM",
|
|
||||||
},
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title-change",
|
|
||||||
PreHeader: "pre-header-change",
|
|
||||||
Subject: "subject-change",
|
|
||||||
Greeting: "greeting-change",
|
|
||||||
Text: "text-change",
|
|
||||||
ButtonText: "button-text-change",
|
|
||||||
State: domain.PolicyStateActive,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
r := &Commands{
|
|
||||||
eventstore: tt.fields.eventstore,
|
|
||||||
}
|
|
||||||
got, err := r.ChangeDefaultMailText(tt.args.ctx, tt.args.policy)
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
if tt.res.err != nil && !tt.res.err(err) {
|
|
||||||
t.Errorf("got wrong err: %v ", err)
|
|
||||||
}
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.Equal(t, tt.res.want, got)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDefaultMailTextPolicyChangedEvent(ctx context.Context, mailTextType, language, title, preHeader, subject, greeting, text, buttonText string) *iam.MailTextChangedEvent {
|
|
||||||
event, _ := iam.NewMailTextChangedEvent(ctx,
|
|
||||||
&iam.NewAggregate().Aggregate,
|
|
||||||
mailTextType,
|
|
||||||
language,
|
|
||||||
[]policy.MailTextChanges{
|
|
||||||
policy.ChangeTitle(title),
|
|
||||||
policy.ChangePreHeader(preHeader),
|
|
||||||
policy.ChangeSubject(subject),
|
|
||||||
policy.ChangeGreeting(greeting),
|
|
||||||
policy.ChangeText(text),
|
|
||||||
policy.ChangeButtonText(buttonText),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return event
|
|
||||||
}
|
|
95
internal/command/org_custom_message_model.go
Normal file
95
internal/command/org_custom_message_model.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrgCustomMessageTextReadModel struct {
|
||||||
|
CustomMessageTextReadModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgCustomMessageTextWriteModel(orgID, messageTextType string, lang language.Tag) *OrgCustomMessageTextReadModel {
|
||||||
|
return &OrgCustomMessageTextReadModel{
|
||||||
|
CustomMessageTextReadModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
ResourceOwner: orgID,
|
||||||
|
},
|
||||||
|
MessageTextType: messageTextType,
|
||||||
|
Language: lang,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgCustomMessageTextReadModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.CustomTextSetEvent:
|
||||||
|
wm.CustomMessageTextReadModel.AppendEvents(&e.CustomTextSetEvent)
|
||||||
|
case *org.CustomTextRemovedEvent:
|
||||||
|
wm.CustomMessageTextReadModel.AppendEvents(&e.CustomTextRemovedEvent)
|
||||||
|
case *org.CustomTextTemplateRemovedEvent:
|
||||||
|
wm.CustomMessageTextReadModel.AppendEvents(&e.CustomTextTemplateRemovedEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgCustomMessageTextReadModel) Reduce() error {
|
||||||
|
return wm.CustomMessageTextReadModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgCustomMessageTextReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||||
|
AggregateIDs(wm.CustomMessageTextReadModel.AggregateID).
|
||||||
|
ResourceOwner(wm.ResourceOwner).
|
||||||
|
EventTypes(
|
||||||
|
org.CustomTextSetEventType,
|
||||||
|
org.CustomTextRemovedEventType,
|
||||||
|
org.CustomTextTemplateRemovedEventType)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrgCustomMessageTemplatesReadModel struct {
|
||||||
|
CustomMessageTemplatesReadModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrgCustomMessageTextsWriteModel(orgID string) *OrgCustomMessageTemplatesReadModel {
|
||||||
|
return &OrgCustomMessageTemplatesReadModel{
|
||||||
|
CustomMessageTemplatesReadModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
ResourceOwner: orgID,
|
||||||
|
},
|
||||||
|
CustomMessageTemplate: make(map[string]*CustomText),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgCustomMessageTemplatesReadModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.CustomTextSetEvent:
|
||||||
|
wm.CustomMessageTemplatesReadModel.AppendEvents(&e.CustomTextSetEvent)
|
||||||
|
case *org.CustomTextRemovedEvent:
|
||||||
|
wm.CustomMessageTemplatesReadModel.AppendEvents(&e.CustomTextRemovedEvent)
|
||||||
|
case *org.CustomTextTemplateRemovedEvent:
|
||||||
|
wm.CustomMessageTemplatesReadModel.AppendEvents(&e.CustomTextTemplateRemovedEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgCustomMessageTemplatesReadModel) Reduce() error {
|
||||||
|
return wm.CustomMessageTemplatesReadModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgCustomMessageTemplatesReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
||||||
|
AggregateIDs(wm.CustomMessageTemplatesReadModel.AggregateID).
|
||||||
|
ResourceOwner(wm.ResourceOwner).
|
||||||
|
EventTypes(
|
||||||
|
org.CustomTextSetEventType,
|
||||||
|
org.CustomTextRemovedEventType,
|
||||||
|
org.CustomTextTemplateRemovedEventType)
|
||||||
|
}
|
137
internal/command/org_custom_message_text.go
Normal file
137
internal/command/org_custom_message_text.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Commands) SetOrgMessageText(ctx context.Context, resourceOwner string, messageText *domain.CustomMessageText) (*domain.ObjectDetails, error) {
|
||||||
|
if resourceOwner == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-2biiR", "Errors.ResourceOwnerMissing")
|
||||||
|
}
|
||||||
|
orgAgg := org.NewAggregate(resourceOwner, resourceOwner)
|
||||||
|
events, existingMessageText, err := c.setOrgMessageText(ctx, &orgAgg.Aggregate, messageText)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pushedEvents, err := c.eventstore.PushEvents(ctx, events...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = AppendAndReduce(existingMessageText, pushedEvents...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModelToObjectDetails(&existingMessageText.WriteModel), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) setOrgMessageText(ctx context.Context, orgAgg *eventstore.Aggregate, message *domain.CustomMessageText) ([]eventstore.EventPusher, *OrgCustomMessageTextReadModel, error) {
|
||||||
|
if !message.IsValid() {
|
||||||
|
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "ORG-2jfsf", "Errors.CustomText.Invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingMessageText, err := c.orgCustomMessageTextWriteModelByID(ctx, orgAgg.ID, message.MessageTextType, message.Language)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
events := make([]eventstore.EventPusher, 0)
|
||||||
|
if existingMessageText.Greeting != message.Greeting {
|
||||||
|
if message.Greeting != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessageGreeting, message.Greeting, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessageGreeting, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingMessageText.Subject != message.Subject {
|
||||||
|
if message.Subject != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessageSubject, message.Subject, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessageSubject, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingMessageText.Title != message.Title {
|
||||||
|
if message.Title != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessageTitle, message.Title, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessageTitle, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingMessageText.PreHeader != message.PreHeader {
|
||||||
|
if message.PreHeader != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessagePreHeader, message.PreHeader, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessagePreHeader, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingMessageText.Text != message.Text {
|
||||||
|
if message.Text != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessageText, message.Text, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessageText, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingMessageText.ButtonText != message.ButtonText {
|
||||||
|
if message.ButtonText != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessageButtonText, message.ButtonText, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessageButtonText, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingMessageText.FooterText != message.FooterText {
|
||||||
|
if message.FooterText != "" {
|
||||||
|
events = append(events, org.NewCustomTextSetEvent(ctx, orgAgg, message.MessageTextType, domain.MessageFooterText, message.FooterText, message.Language))
|
||||||
|
} else {
|
||||||
|
events = append(events, org.NewCustomTextRemovedEvent(ctx, orgAgg, message.MessageTextType, domain.MessageFooterText, message.Language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return events, existingMessageText, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) RemoveOrgMessageTexts(ctx context.Context, resourceOwner, messageTextType string, lang language.Tag) error {
|
||||||
|
if resourceOwner == "" {
|
||||||
|
return caos_errs.ThrowInvalidArgument(nil, "Org-3mfsf", "Errors.ResourceOwnerMissing")
|
||||||
|
}
|
||||||
|
if messageTextType == "" || lang == language.Und {
|
||||||
|
return caos_errs.ThrowInvalidArgument(nil, "Org-j59f", "Errors.CustomMessageText.Invalid")
|
||||||
|
}
|
||||||
|
customText, err := c.orgCustomMessageTextWriteModelByID(ctx, resourceOwner, messageTextType, lang)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if customText.State == domain.PolicyStateUnspecified || customText.State == domain.PolicyStateRemoved {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "Org-3b8Jf", "Errors.CustomMessageText.NotFound")
|
||||||
|
}
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&customText.WriteModel)
|
||||||
|
_, err = c.eventstore.PushEvents(ctx, org.NewCustomTextTemplateRemovedEvent(ctx, orgAgg, messageTextType, lang))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) removeOrgMessageTextsIfExists(ctx context.Context, orgID string) ([]eventstore.EventPusher, error) {
|
||||||
|
msgTemplates := NewOrgCustomMessageTextsWriteModel(orgID)
|
||||||
|
err := c.eventstore.FilterToQueryReducer(ctx, msgTemplates)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
orgAgg := OrgAggregateFromWriteModel(&msgTemplates.WriteModel)
|
||||||
|
events := make([]eventstore.EventPusher, 0, len(msgTemplates.CustomMessageTemplate))
|
||||||
|
for _, tmpl := range msgTemplates.CustomMessageTemplate {
|
||||||
|
events = append(events, org.NewCustomTextTemplateRemovedEvent(ctx, orgAgg, tmpl.Template, tmpl.Language))
|
||||||
|
}
|
||||||
|
return events, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) orgCustomMessageTextWriteModelByID(ctx context.Context, orgID, messageType string, lang language.Tag) (*OrgCustomMessageTextReadModel, error) {
|
||||||
|
writeModel := NewOrgCustomMessageTextWriteModel(orgID, messageType, lang)
|
||||||
|
err := c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
514
internal/command/org_custom_message_text_test.go
Normal file
514
internal/command/org_custom_message_text_test.go
Normal file
@ -0,0 +1,514 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
"github.com/caos/zitadel/internal/repository/org"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommandSide_SetCustomMessageText(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
resourceOwner string
|
||||||
|
config *domain.CustomMessageText
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no resource owner, error",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
config: &domain.CustomMessageText{},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsErrorInvalidArgument,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid custom text, error",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
config: &domain.CustomMessageText{},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsErrorInvalidArgument,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom text set all fields, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageGreeting,
|
||||||
|
"Greeting",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageSubject,
|
||||||
|
"Subject",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageTitle,
|
||||||
|
"Title",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessagePreHeader,
|
||||||
|
"PreHeader",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageText,
|
||||||
|
"Text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageButtonText,
|
||||||
|
"ButtonText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageFooterText,
|
||||||
|
"FooterText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
config: &domain.CustomMessageText{
|
||||||
|
MessageTextType: "Template",
|
||||||
|
Language: language.English,
|
||||||
|
Greeting: "Greeting",
|
||||||
|
Subject: "Subject",
|
||||||
|
Title: "Title",
|
||||||
|
PreHeader: "PreHeader",
|
||||||
|
Text: "Text",
|
||||||
|
ButtonText: "ButtonText",
|
||||||
|
FooterText: "FooterText",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom text remove all fields, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageGreeting,
|
||||||
|
"Greeting",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageSubject,
|
||||||
|
"Subject",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageTitle,
|
||||||
|
"Title",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessagePreHeader,
|
||||||
|
"PreHeader",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageText,
|
||||||
|
"Text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageButtonText,
|
||||||
|
"ButtonText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageFooterText,
|
||||||
|
"FooterText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageGreeting,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageSubject,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageTitle,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessagePreHeader,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageText,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageButtonText,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageFooterText,
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
config: &domain.CustomMessageText{
|
||||||
|
MessageTextType: "Template",
|
||||||
|
Language: language.English,
|
||||||
|
Greeting: "",
|
||||||
|
Subject: "",
|
||||||
|
Title: "",
|
||||||
|
PreHeader: "",
|
||||||
|
Text: "",
|
||||||
|
ButtonText: "",
|
||||||
|
FooterText: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
}
|
||||||
|
got, err := r.SetOrgMessageText(tt.args.ctx, tt.args.resourceOwner, tt.args.config)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.Equal(t, tt.res.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCommandSide_RemoveCustomMessageText(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
resourceOwner string
|
||||||
|
mailTextType string
|
||||||
|
lang language.Tag
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no resource owner, error",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
mailTextType: "Template",
|
||||||
|
lang: language.English,
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsErrorInvalidArgument,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no mail text type owner, error",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
lang: language.English,
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsErrorInvalidArgument,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no mail text type owner, error",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
mailTextType: "Template",
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errs.IsErrorInvalidArgument,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom text remove all fields, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(
|
||||||
|
t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageGreeting,
|
||||||
|
"Greeting",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageSubject,
|
||||||
|
"Subject",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageTitle,
|
||||||
|
"Title",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessagePreHeader,
|
||||||
|
"PreHeader",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageText,
|
||||||
|
"Text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageButtonText,
|
||||||
|
"ButtonText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
domain.MessageFooterText,
|
||||||
|
"FooterText",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextTemplateRemovedEvent(context.Background(),
|
||||||
|
&org.NewAggregate("org1", "org1").Aggregate,
|
||||||
|
"Template",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
mailTextType: "Template",
|
||||||
|
lang: language.English,
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
}
|
||||||
|
err := r.RemoveOrgMessageTexts(tt.args.ctx, tt.args.resourceOwner, tt.args.mailTextType, tt.args.lang)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -40,6 +40,7 @@ func (c *Commands) SetOrgFeatures(ctx context.Context, resourceOwner string, fea
|
|||||||
features.LabelPolicyPrivateLabel,
|
features.LabelPolicyPrivateLabel,
|
||||||
features.LabelPolicyWatermark,
|
features.LabelPolicyWatermark,
|
||||||
features.CustomDomain,
|
features.CustomDomain,
|
||||||
|
features.CustomText,
|
||||||
)
|
)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "Features-GE4h2", "Errors.Features.NotChanged")
|
||||||
@ -126,6 +127,15 @@ func (c *Commands) ensureOrgSettingsToFeatures(ctx context.Context, orgID string
|
|||||||
events = append(events, removeCustomDomainsEvents...)
|
events = append(events, removeCustomDomainsEvents...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !features.CustomText {
|
||||||
|
removeCustomTextEvents, err := c.removeOrgMessageTextsIfExists(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if removeCustomTextEvents != nil {
|
||||||
|
events = append(events, removeCustomTextEvents...)
|
||||||
|
}
|
||||||
|
}
|
||||||
return events, nil
|
return events, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,8 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
|||||||
passwordComplexityPolicy,
|
passwordComplexityPolicy,
|
||||||
labelPolicyPrivateLabel,
|
labelPolicyPrivateLabel,
|
||||||
labelPolicyWatermark,
|
labelPolicyWatermark,
|
||||||
customDomain bool,
|
customDomain,
|
||||||
|
customText bool,
|
||||||
) (*org.FeaturesSetEvent, bool) {
|
) (*org.FeaturesSetEvent, bool) {
|
||||||
|
|
||||||
changes := make([]features.FeaturesChanges, 0)
|
changes := make([]features.FeaturesChanges, 0)
|
||||||
@ -121,6 +122,9 @@ func (wm *OrgFeaturesWriteModel) NewSetEvent(
|
|||||||
if wm.CustomDomain != customDomain {
|
if wm.CustomDomain != customDomain {
|
||||||
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
changes = append(changes, features.ChangeCustomDomain(customDomain))
|
||||||
}
|
}
|
||||||
|
if wm.CustomText != customText {
|
||||||
|
changes = append(changes, features.ChangeCustomText(customText))
|
||||||
|
}
|
||||||
|
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
@ -226,6 +227,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
domain.InitCodeMessageType,
|
||||||
|
domain.MessageSubject,
|
||||||
|
"text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -253,6 +266,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
LabelPolicyPrivateLabel: false,
|
LabelPolicyPrivateLabel: false,
|
||||||
LabelPolicyWatermark: false,
|
LabelPolicyWatermark: false,
|
||||||
CustomDomain: false,
|
CustomDomain: false,
|
||||||
|
CustomText: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
@ -373,6 +387,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
domain.InitCodeMessageType,
|
||||||
|
domain.MessageSubject,
|
||||||
|
"text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -534,6 +560,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
domain.InitCodeMessageType,
|
||||||
|
domain.MessageSubject,
|
||||||
|
"text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -705,6 +743,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
domain.InitCodeMessageType,
|
||||||
|
domain.MessageSubject,
|
||||||
|
"text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -931,6 +981,18 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextSetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
domain.InitCodeMessageType,
|
||||||
|
domain.MessageSubject,
|
||||||
|
"text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
@ -951,6 +1013,9 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
|
|||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
org.NewLabelPolicyRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate),
|
org.NewLabelPolicyRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate),
|
||||||
),
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewCustomTextTemplateRemovedEvent(context.Background(), &org.NewAggregate("org1", "org1").Aggregate, domain.InitCodeMessageType, language.English),
|
||||||
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
newFeaturesSetEvent(context.Background(), "org1", "Test", domain.FeaturesStateActive, time.Hour),
|
newFeaturesSetEvent(context.Background(), "org1", "Test", domain.FeaturesStateActive, time.Hour),
|
||||||
),
|
),
|
||||||
@ -1144,6 +1209,18 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
iam.NewCustomTextSetEvent(
|
||||||
|
context.Background(),
|
||||||
|
&iam.NewAggregate().Aggregate,
|
||||||
|
domain.InitCodeMessageType,
|
||||||
|
domain.MessageSubject,
|
||||||
|
"text",
|
||||||
|
language.English,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
[]*repository.Event{
|
[]*repository.Event{
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/repository/org"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Commands) AddMailText(ctx context.Context, resourceOwner string, mailText *domain.MailText) (*domain.MailText, error) {
|
|
||||||
if resourceOwner == "" {
|
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-MFiig", "Errors.ResourceOwnerMissing")
|
|
||||||
}
|
|
||||||
if !mailText.IsValid() {
|
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-4778u", "Errors.Org.MailText.Invalid")
|
|
||||||
}
|
|
||||||
addedPolicy := NewOrgMailTextWriteModel(resourceOwner, mailText.MailTextType, mailText.Language)
|
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if addedPolicy.State == domain.PolicyStateActive {
|
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-9kufs", "Errors.Org.MailText.AlreadyExists")
|
|
||||||
}
|
|
||||||
|
|
||||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.MailTextWriteModel.WriteModel)
|
|
||||||
pushedEvents, err := c.eventstore.PushEvents(
|
|
||||||
ctx,
|
|
||||||
org.NewMailTextAddedEvent(
|
|
||||||
ctx,
|
|
||||||
orgAgg,
|
|
||||||
mailText.MailTextType,
|
|
||||||
mailText.Language,
|
|
||||||
mailText.Title,
|
|
||||||
mailText.PreHeader,
|
|
||||||
mailText.Subject,
|
|
||||||
mailText.Greeting,
|
|
||||||
mailText.Text,
|
|
||||||
mailText.ButtonText))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return writeModelToMailText(&addedPolicy.MailTextWriteModel), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Commands) ChangeMailText(ctx context.Context, resourceOwner string, mailText *domain.MailText) (*domain.MailText, error) {
|
|
||||||
if resourceOwner == "" {
|
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-NFus3", "Errors.ResourceOwnerMissing")
|
|
||||||
}
|
|
||||||
if !mailText.IsValid() {
|
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-3m9fs", "Errors.Org.MailText.Invalid")
|
|
||||||
}
|
|
||||||
existingPolicy := NewOrgMailTextWriteModel(resourceOwner, mailText.MailTextType, mailText.Language)
|
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "Org-3n8fM", "Errors.Org.MailText.NotFound")
|
|
||||||
}
|
|
||||||
|
|
||||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.MailTextWriteModel.WriteModel)
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
|
||||||
ctx,
|
|
||||||
orgAgg,
|
|
||||||
mailText.MailTextType,
|
|
||||||
mailText.Language,
|
|
||||||
mailText.Title,
|
|
||||||
mailText.PreHeader,
|
|
||||||
mailText.Subject,
|
|
||||||
mailText.Greeting,
|
|
||||||
mailText.Text,
|
|
||||||
mailText.ButtonText)
|
|
||||||
if !hasChanged {
|
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-2n9fs", "Errors.Org.MailText.NotChanged")
|
|
||||||
}
|
|
||||||
|
|
||||||
pushedEvents, err := c.eventstore.PushEvents(ctx, changedEvent)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return writeModelToMailText(&existingPolicy.MailTextWriteModel), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Commands) RemoveMailText(ctx context.Context, resourceOwner, mailTextType, language string) error {
|
|
||||||
if resourceOwner == "" {
|
|
||||||
return caos_errs.ThrowInvalidArgument(nil, "Org-2N7fd", "Errors.ResourceOwnerMissing")
|
|
||||||
}
|
|
||||||
if mailTextType == "" || language == "" {
|
|
||||||
return caos_errs.ThrowInvalidArgument(nil, "Org-N8fsf", "Errors.Org.MailText.Invalid")
|
|
||||||
}
|
|
||||||
existingPolicy := NewOrgMailTextWriteModel(resourceOwner, mailTextType, language)
|
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
|
||||||
return caos_errs.ThrowNotFound(nil, "Org-3b8Jf", "Errors.Org.MailText.NotFound")
|
|
||||||
}
|
|
||||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.WriteModel)
|
|
||||||
_, err = c.eventstore.PushEvents(ctx, org.NewMailTextRemovedEvent(ctx, orgAgg, mailTextType, language))
|
|
||||||
return err
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
"github.com/caos/zitadel/internal/repository/org"
|
|
||||||
"github.com/caos/zitadel/internal/repository/policy"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OrgMailTextWriteModel struct {
|
|
||||||
MailTextWriteModel
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewOrgMailTextWriteModel(orgID, mailTextType, language string) *OrgMailTextWriteModel {
|
|
||||||
return &OrgMailTextWriteModel{
|
|
||||||
MailTextWriteModel{
|
|
||||||
WriteModel: eventstore.WriteModel{
|
|
||||||
AggregateID: orgID,
|
|
||||||
ResourceOwner: orgID,
|
|
||||||
},
|
|
||||||
MailTextType: mailTextType,
|
|
||||||
Language: language,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *OrgMailTextWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
|
||||||
for _, event := range events {
|
|
||||||
switch e := event.(type) {
|
|
||||||
case *org.MailTextAddedEvent:
|
|
||||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextAddedEvent)
|
|
||||||
case *org.MailTextChangedEvent:
|
|
||||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextChangedEvent)
|
|
||||||
case *org.MailTextRemovedEvent:
|
|
||||||
wm.MailTextWriteModel.AppendEvents(&e.MailTextRemovedEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *OrgMailTextWriteModel) Reduce() error {
|
|
||||||
return wm.MailTextWriteModel.Reduce()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *OrgMailTextWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|
||||||
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
|
|
||||||
AggregateIDs(wm.MailTextWriteModel.AggregateID).
|
|
||||||
EventTypes(org.MailTextAddedEventType,
|
|
||||||
org.MailTextChangedEventType,
|
|
||||||
org.MailTextRemovedEventType)
|
|
||||||
if wm.ResourceOwner != "" {
|
|
||||||
query.ResourceOwner(wm.ResourceOwner)
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *OrgMailTextWriteModel) NewChangedEvent(
|
|
||||||
ctx context.Context,
|
|
||||||
aggregate *eventstore.Aggregate,
|
|
||||||
mailTextType,
|
|
||||||
language,
|
|
||||||
title,
|
|
||||||
preHeader,
|
|
||||||
subject,
|
|
||||||
greeting,
|
|
||||||
text,
|
|
||||||
buttonText string,
|
|
||||||
) (*org.MailTextChangedEvent, bool) {
|
|
||||||
changes := make([]policy.MailTextChanges, 0)
|
|
||||||
if wm.Title != title {
|
|
||||||
changes = append(changes, policy.ChangeTitle(title))
|
|
||||||
}
|
|
||||||
if wm.PreHeader != preHeader {
|
|
||||||
changes = append(changes, policy.ChangePreHeader(preHeader))
|
|
||||||
}
|
|
||||||
if wm.Subject != subject {
|
|
||||||
changes = append(changes, policy.ChangeSubject(subject))
|
|
||||||
}
|
|
||||||
if wm.Greeting != greeting {
|
|
||||||
changes = append(changes, policy.ChangeGreeting(greeting))
|
|
||||||
}
|
|
||||||
if wm.Text != text {
|
|
||||||
changes = append(changes, policy.ChangeText(text))
|
|
||||||
}
|
|
||||||
if wm.ButtonText != buttonText {
|
|
||||||
changes = append(changes, policy.ChangeButtonText(buttonText))
|
|
||||||
}
|
|
||||||
if len(changes) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
changedEvent, err := org.NewMailTextChangedEvent(ctx, aggregate, mailTextType, language, changes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return changedEvent, true
|
|
||||||
}
|
|
@ -1,563 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/repository/org"
|
|
||||||
"github.com/caos/zitadel/internal/repository/policy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCommandSide_AddMailText(t *testing.T) {
|
|
||||||
type fields struct {
|
|
||||||
eventstore *eventstore.Eventstore
|
|
||||||
}
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
orgID string
|
|
||||||
policy *domain.MailText
|
|
||||||
}
|
|
||||||
type res struct {
|
|
||||||
want *domain.MailText
|
|
||||||
err func(error) bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fields fields
|
|
||||||
args args
|
|
||||||
res res
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "org id missing, invalid argument error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorInvalidArgument,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mail text already existing, already exists error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorAlreadyExists,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mail text already existing, already exists error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorAlreadyExists,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "add policy,ok",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(),
|
|
||||||
expectPush(
|
|
||||||
[]*repository.Event{
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
uniqueConstraintsFromEventConstraint(policy.NewAddMailTextUniqueConstraint("org1", "mail-text-type", "de")),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
want: &domain.MailText{
|
|
||||||
ObjectRoot: models.ObjectRoot{
|
|
||||||
AggregateID: "org1",
|
|
||||||
ResourceOwner: "org1",
|
|
||||||
},
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
State: domain.PolicyStateActive,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
r := &Commands{
|
|
||||||
eventstore: tt.fields.eventstore,
|
|
||||||
}
|
|
||||||
got, err := r.AddMailText(tt.args.ctx, tt.args.orgID, tt.args.policy)
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
if tt.res.err != nil && !tt.res.err(err) {
|
|
||||||
t.Errorf("got wrong err: %v ", err)
|
|
||||||
}
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.Equal(t, tt.res.want, got)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCommandSide_ChangeMailText(t *testing.T) {
|
|
||||||
type fields struct {
|
|
||||||
eventstore *eventstore.Eventstore
|
|
||||||
}
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
orgID string
|
|
||||||
policy *domain.MailText
|
|
||||||
}
|
|
||||||
type res struct {
|
|
||||||
want *domain.MailText
|
|
||||||
err func(error) bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fields fields
|
|
||||||
args args
|
|
||||||
res res
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "org id missing, invalid argument error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorInvalidArgument,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mailtext invalid, invalid argument error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
policy: &domain.MailText{},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorInvalidArgument,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mail template not existing, not found error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsNotFound,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no changes, precondition error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title",
|
|
||||||
PreHeader: "pre-header",
|
|
||||||
Subject: "subject",
|
|
||||||
Greeting: "greeting",
|
|
||||||
Text: "text",
|
|
||||||
ButtonText: "button-text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsPreconditionFailed,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "change, ok",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
expectPush(
|
|
||||||
[]*repository.Event{
|
|
||||||
eventFromEventPusher(
|
|
||||||
newMailTextChangedEvent(
|
|
||||||
context.Background(),
|
|
||||||
"org1",
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title-change",
|
|
||||||
"pre-header-change",
|
|
||||||
"subject-change",
|
|
||||||
"greeting-change",
|
|
||||||
"text-change",
|
|
||||||
"button-text-change"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
policy: &domain.MailText{
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title-change",
|
|
||||||
PreHeader: "pre-header-change",
|
|
||||||
Subject: "subject-change",
|
|
||||||
Greeting: "greeting-change",
|
|
||||||
Text: "text-change",
|
|
||||||
ButtonText: "button-text-change",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
want: &domain.MailText{
|
|
||||||
ObjectRoot: models.ObjectRoot{
|
|
||||||
AggregateID: "org1",
|
|
||||||
ResourceOwner: "org1",
|
|
||||||
},
|
|
||||||
MailTextType: "mail-text-type",
|
|
||||||
Language: "de",
|
|
||||||
Title: "title-change",
|
|
||||||
PreHeader: "pre-header-change",
|
|
||||||
Subject: "subject-change",
|
|
||||||
Greeting: "greeting-change",
|
|
||||||
Text: "text-change",
|
|
||||||
ButtonText: "button-text-change",
|
|
||||||
State: domain.PolicyStateActive,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
r := &Commands{
|
|
||||||
eventstore: tt.fields.eventstore,
|
|
||||||
}
|
|
||||||
got, err := r.ChangeMailText(tt.args.ctx, tt.args.orgID, tt.args.policy)
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
if tt.res.err != nil && !tt.res.err(err) {
|
|
||||||
t.Errorf("got wrong err: %v ", err)
|
|
||||||
}
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.Equal(t, tt.res.want, got)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCommandSide_RemoveMailText(t *testing.T) {
|
|
||||||
type fields struct {
|
|
||||||
eventstore *eventstore.Eventstore
|
|
||||||
}
|
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
orgID string
|
|
||||||
mailTextType string
|
|
||||||
language string
|
|
||||||
}
|
|
||||||
type res struct {
|
|
||||||
want *domain.ObjectDetails
|
|
||||||
err func(error) bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
fields fields
|
|
||||||
args args
|
|
||||||
res res
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "org id missing, invalid argument error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsErrorInvalidArgument,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "policy not existing, not found error",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
mailTextType: "mail-text-type",
|
|
||||||
language: "de",
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
err: caos_errs.IsNotFound,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "remove, ok",
|
|
||||||
fields: fields{
|
|
||||||
eventstore: eventstoreExpect(
|
|
||||||
t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextAddedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de",
|
|
||||||
"title",
|
|
||||||
"pre-header",
|
|
||||||
"subject",
|
|
||||||
"greeting",
|
|
||||||
"text",
|
|
||||||
"button-text",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
expectPush(
|
|
||||||
[]*repository.Event{
|
|
||||||
eventFromEventPusher(
|
|
||||||
org.NewMailTextRemovedEvent(context.Background(),
|
|
||||||
&org.NewAggregate("org1", "org1").Aggregate,
|
|
||||||
"mail-text-type",
|
|
||||||
"de"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
uniqueConstraintsFromEventConstraint(policy.NewRemoveMailTextUniqueConstraint("org1", "mail-text-type", "de")),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
args: args{
|
|
||||||
ctx: context.Background(),
|
|
||||||
orgID: "org1",
|
|
||||||
mailTextType: "mail-text-type",
|
|
||||||
language: "de",
|
|
||||||
},
|
|
||||||
res: res{
|
|
||||||
want: &domain.ObjectDetails{
|
|
||||||
ResourceOwner: "org1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
r := &Commands{
|
|
||||||
eventstore: tt.fields.eventstore,
|
|
||||||
}
|
|
||||||
err := r.RemoveMailText(tt.args.ctx, tt.args.orgID, tt.args.mailTextType, tt.args.language)
|
|
||||||
if tt.res.err == nil {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
if tt.res.err != nil && !tt.res.err(err) {
|
|
||||||
t.Errorf("got wrong err: %v ", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMailTextChangedEvent(ctx context.Context, orgID, mailTextType, language, title, preHeader, subject, greeting, text, buttonText string) *org.MailTextChangedEvent {
|
|
||||||
event, _ := org.NewMailTextChangedEvent(ctx,
|
|
||||||
&org.NewAggregate(orgID, orgID).Aggregate,
|
|
||||||
mailTextType,
|
|
||||||
language,
|
|
||||||
[]policy.MailTextChanges{
|
|
||||||
policy.ChangeTitle(title),
|
|
||||||
policy.ChangePreHeader(preHeader),
|
|
||||||
policy.ChangeSubject(subject),
|
|
||||||
policy.ChangeGreeting(greeting),
|
|
||||||
policy.ChangeText(text),
|
|
||||||
policy.ChangeButtonText(buttonText),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return event
|
|
||||||
}
|
|
@ -65,7 +65,7 @@ func (c *Commands) ChangePasswordAgePolicy(ctx context.Context, resourceOwner st
|
|||||||
|
|
||||||
func (c *Commands) RemovePasswordAgePolicy(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
func (c *Commands) RemovePasswordAgePolicy(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
||||||
if orgID == "" {
|
if orgID == "" {
|
||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-2N8fs", "Errors.ResourceOwnerMissing")
|
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-M58wd", "Errors.ResourceOwnerMissing")
|
||||||
}
|
}
|
||||||
existingPolicy := NewOrgPasswordAgePolicyWriteModel(orgID)
|
existingPolicy := NewOrgPasswordAgePolicyWriteModel(orgID)
|
||||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
|
||||||
"github.com/caos/zitadel/internal/repository/policy"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MailTextWriteModel struct {
|
|
||||||
eventstore.WriteModel
|
|
||||||
|
|
||||||
MailTextType string
|
|
||||||
Language string
|
|
||||||
Title string
|
|
||||||
PreHeader string
|
|
||||||
Subject string
|
|
||||||
Greeting string
|
|
||||||
Text string
|
|
||||||
ButtonText string
|
|
||||||
|
|
||||||
State domain.PolicyState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *MailTextWriteModel) Reduce() error {
|
|
||||||
for _, event := range wm.Events {
|
|
||||||
switch e := event.(type) {
|
|
||||||
case *policy.MailTextAddedEvent:
|
|
||||||
if wm.MailTextType != e.MailTextType || wm.Language != e.Language {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wm.Title = e.Title
|
|
||||||
wm.PreHeader = e.PreHeader
|
|
||||||
wm.Subject = e.Subject
|
|
||||||
wm.Greeting = e.Greeting
|
|
||||||
wm.Text = e.Text
|
|
||||||
wm.ButtonText = e.ButtonText
|
|
||||||
wm.State = domain.PolicyStateActive
|
|
||||||
case *policy.MailTextChangedEvent:
|
|
||||||
if wm.MailTextType != e.MailTextType || wm.Language != e.Language {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e.Title != nil {
|
|
||||||
wm.Title = *e.Title
|
|
||||||
}
|
|
||||||
if e.PreHeader != nil {
|
|
||||||
wm.PreHeader = *e.PreHeader
|
|
||||||
}
|
|
||||||
if e.Subject != nil {
|
|
||||||
wm.Subject = *e.Subject
|
|
||||||
}
|
|
||||||
if e.Greeting != nil {
|
|
||||||
wm.Greeting = *e.Greeting
|
|
||||||
}
|
|
||||||
if e.Text != nil {
|
|
||||||
wm.Text = *e.Text
|
|
||||||
}
|
|
||||||
if e.ButtonText != nil {
|
|
||||||
wm.ButtonText = *e.ButtonText
|
|
||||||
}
|
|
||||||
case *policy.MailTextRemovedEvent:
|
|
||||||
wm.State = domain.PolicyStateRemoved
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wm.WriteModel.Reduce()
|
|
||||||
}
|
|
@ -2,14 +2,15 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
"github.com/caos/zitadel/internal/domain"
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Step10 struct {
|
type Step10 struct {
|
||||||
DefaultMailTemplate domain.MailTemplate
|
DefaultMailTemplate domain.MailTemplate
|
||||||
DefaultMailTexts []domain.MailText
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Step10) Step() domain.Step {
|
func (s *Step10) Step() domain.Step {
|
||||||
@ -30,13 +31,6 @@ func (c *Commands) SetupStep10(ctx context.Context, step *Step10) error {
|
|||||||
events := []eventstore.EventPusher{
|
events := []eventstore.EventPusher{
|
||||||
mailTemplateEvent,
|
mailTemplateEvent,
|
||||||
}
|
}
|
||||||
for _, text := range step.DefaultMailTexts {
|
|
||||||
defaultTextEvent, err := c.addDefaultMailText(ctx, iamAgg, NewIAMMailTextWriteModel(text.MailTextType, text.Language), &text)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
events = append(events, defaultTextEvent)
|
|
||||||
}
|
|
||||||
logging.Log("SETUP-3N9fs").Info("default mail template/text set up")
|
logging.Log("SETUP-3N9fs").Info("default mail template/text set up")
|
||||||
return events, nil
|
return events, nil
|
||||||
}
|
}
|
||||||
|
39
internal/command/setup_step16.go
Normal file
39
internal/command/setup_step16.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/caos/logging"
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Step16 struct {
|
||||||
|
DefaultMessageTexts []domain.CustomMessageText
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Step16) Step() domain.Step {
|
||||||
|
return domain.Step16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Step16) execute(ctx context.Context, commandSide *Commands) error {
|
||||||
|
return commandSide.SetupStep16(ctx, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) SetupStep16(ctx context.Context, step *Step16) error {
|
||||||
|
fn := func(iam *IAMWriteModel) ([]eventstore.EventPusher, error) {
|
||||||
|
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
|
||||||
|
events := make([]eventstore.EventPusher, 0)
|
||||||
|
|
||||||
|
for _, text := range step.DefaultMessageTexts {
|
||||||
|
mailEvents, _, err := c.setDefaultMessageText(ctx, iamAgg, &text)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
events = append(events, mailEvents...)
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.Log("SETUP-4k0LL").Info("default message text set up")
|
||||||
|
return events, nil
|
||||||
|
}
|
||||||
|
return c.setup(ctx, step, fn)
|
||||||
|
}
|
42
internal/domain/custom_messge_text.go
Normal file
42
internal/domain/custom_messge_text.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
InitCodeMessageType = "InitCode"
|
||||||
|
PasswordResetMessageType = "PasswordReset"
|
||||||
|
VerifyEmailMessageType = "VerifyEmail"
|
||||||
|
VerifyPhoneMessageType = "VerifyPhone"
|
||||||
|
DomainClaimedMessageType = "DomainClaimed"
|
||||||
|
MessageTitle = "Title"
|
||||||
|
MessagePreHeader = "PreHeader"
|
||||||
|
MessageSubject = "Subject"
|
||||||
|
MessageGreeting = "Greeting"
|
||||||
|
MessageText = "Text"
|
||||||
|
MessageButtonText = "ButtonText"
|
||||||
|
MessageFooterText = "FooterText"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomMessageText struct {
|
||||||
|
models.ObjectRoot
|
||||||
|
|
||||||
|
State PolicyState
|
||||||
|
Default bool
|
||||||
|
MessageTextType string
|
||||||
|
Language language.Tag
|
||||||
|
Title string
|
||||||
|
PreHeader string
|
||||||
|
Subject string
|
||||||
|
Greeting string
|
||||||
|
Text string
|
||||||
|
ButtonText string
|
||||||
|
FooterText string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CustomMessageText) IsValid() bool {
|
||||||
|
return m.MessageTextType != "" && m.Language != language.Und
|
||||||
|
}
|
32
internal/domain/custom_text.go
Normal file
32
internal/domain/custom_text.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomText struct {
|
||||||
|
models.ObjectRoot
|
||||||
|
|
||||||
|
State CustomTextState
|
||||||
|
Default bool
|
||||||
|
Template string
|
||||||
|
Key string
|
||||||
|
Language language.Tag
|
||||||
|
Text string
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomTextState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
CustomTextStateUnspecified CustomTextState = iota
|
||||||
|
CustomTextStateActive
|
||||||
|
CustomTextStateRemoved
|
||||||
|
|
||||||
|
customTextStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *CustomText) IsValid() bool {
|
||||||
|
return m.Key != "" && m.Language != language.Und && m.Text != ""
|
||||||
|
}
|
@ -18,6 +18,7 @@ const (
|
|||||||
FeatureLabelPolicy = "label_policy"
|
FeatureLabelPolicy = "label_policy"
|
||||||
FeatureLabelPolicyPrivateLabel = FeatureLabelPolicy + ".private_label"
|
FeatureLabelPolicyPrivateLabel = FeatureLabelPolicy + ".private_label"
|
||||||
FeatureLabelPolicyWatermark = FeatureLabelPolicy + ".watermark"
|
FeatureLabelPolicyWatermark = FeatureLabelPolicy + ".watermark"
|
||||||
|
FeatureCustomText = "custom_text"
|
||||||
FeatureCustomDomain = "custom_domain"
|
FeatureCustomDomain = "custom_domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ type Features struct {
|
|||||||
LabelPolicyPrivateLabel bool
|
LabelPolicyPrivateLabel bool
|
||||||
LabelPolicyWatermark bool
|
LabelPolicyWatermark bool
|
||||||
CustomDomain bool
|
CustomDomain bool
|
||||||
|
CustomText bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type FeaturesState int32
|
type FeaturesState int32
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
|
|
||||||
type MailText struct {
|
|
||||||
models.ObjectRoot
|
|
||||||
|
|
||||||
State PolicyState
|
|
||||||
Default bool
|
|
||||||
MailTextType string
|
|
||||||
Language string
|
|
||||||
Title string
|
|
||||||
PreHeader string
|
|
||||||
Subject string
|
|
||||||
Greeting string
|
|
||||||
Text string
|
|
||||||
ButtonText string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) IsValid() bool {
|
|
||||||
return m.MailTextType != "" && m.Language != "" && m.Title != "" && m.PreHeader != "" && m.Subject != "" && m.Greeting != "" && m.Text != "" && m.ButtonText != ""
|
|
||||||
}
|
|
@ -18,6 +18,7 @@ const (
|
|||||||
Step13
|
Step13
|
||||||
Step14
|
Step14
|
||||||
Step15
|
Step15
|
||||||
|
Step16
|
||||||
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
|
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
|
||||||
StepCount
|
StepCount
|
||||||
)
|
)
|
||||||
|
@ -28,6 +28,7 @@ type FeaturesView struct {
|
|||||||
LabelPolicyPrivateLabel bool
|
LabelPolicyPrivateLabel bool
|
||||||
LabelPolicyWatermark bool
|
LabelPolicyWatermark bool
|
||||||
CustomDomain bool
|
CustomDomain bool
|
||||||
|
CustomText bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FeaturesView) FeatureList() []string {
|
func (f *FeaturesView) FeatureList() []string {
|
||||||
@ -62,6 +63,9 @@ func (f *FeaturesView) FeatureList() []string {
|
|||||||
if f.CustomDomain {
|
if f.CustomDomain {
|
||||||
list = append(list, domain.FeatureCustomDomain)
|
list = append(list, domain.FeatureCustomDomain)
|
||||||
}
|
}
|
||||||
|
if f.CustomText {
|
||||||
|
list = append(list, domain.FeatureCustomText)
|
||||||
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ type FeaturesView struct {
|
|||||||
LabelPolicyPrivateLabel bool `json:"labelPolicyPrivateLabel" gorm:"column:label_policy_private_label"`
|
LabelPolicyPrivateLabel bool `json:"labelPolicyPrivateLabel" gorm:"column:label_policy_private_label"`
|
||||||
LabelPolicyWatermark bool `json:"labelPolicyWatermark" gorm:"column:label_policy_watermark"`
|
LabelPolicyWatermark bool `json:"labelPolicyWatermark" gorm:"column:label_policy_watermark"`
|
||||||
CustomDomain bool `json:"customDomain" gorm:"column:custom_domain"`
|
CustomDomain bool `json:"customDomain" gorm:"column:custom_domain"`
|
||||||
|
CustomText bool `json:"customText" gorm:"column:custom_text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
|
func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
|
||||||
@ -66,6 +67,7 @@ func FeaturesToModel(features *FeaturesView) *features_model.FeaturesView {
|
|||||||
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
|
LabelPolicyPrivateLabel: features.LabelPolicyPrivateLabel,
|
||||||
LabelPolicyWatermark: features.LabelPolicyWatermark,
|
LabelPolicyWatermark: features.LabelPolicyWatermark,
|
||||||
CustomDomain: features.CustomDomain,
|
CustomDomain: features.CustomDomain,
|
||||||
|
CustomText: features.CustomText,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ type MailText struct {
|
|||||||
Greeting string
|
Greeting string
|
||||||
Text string
|
Text string
|
||||||
ButtonText string
|
ButtonText string
|
||||||
|
FooterText string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MailText) IsValid() bool {
|
func (p *MailText) IsValid() bool {
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MailTextsView struct {
|
|
||||||
Texts []*MailTextView
|
|
||||||
Default bool
|
|
||||||
}
|
|
||||||
type MailTextView struct {
|
|
||||||
AggregateID string
|
|
||||||
MailTextType string
|
|
||||||
Language string
|
|
||||||
Title string
|
|
||||||
PreHeader string
|
|
||||||
Subject string
|
|
||||||
Greeting string
|
|
||||||
Text string
|
|
||||||
ButtonText string
|
|
||||||
Default bool
|
|
||||||
|
|
||||||
CreationDate time.Time
|
|
||||||
ChangeDate time.Time
|
|
||||||
Sequence uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type MailTextSearchRequest struct {
|
|
||||||
Offset uint64
|
|
||||||
Limit uint64
|
|
||||||
SortingColumn MailTextSearchKey
|
|
||||||
Asc bool
|
|
||||||
Queries []*MailTextSearchQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
type MailTextSearchKey int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
MailTextSearchKeyUnspecified MailTextSearchKey = iota
|
|
||||||
MailTextSearchKeyAggregateID
|
|
||||||
MailTextSearchKeyMailTextType
|
|
||||||
MailTextSearchKeyLanguage
|
|
||||||
)
|
|
||||||
|
|
||||||
type MailTextSearchQuery struct {
|
|
||||||
Key MailTextSearchKey
|
|
||||||
Method domain.SearchMethod
|
|
||||||
Value interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type MailTextSearchResponse struct {
|
|
||||||
Offset uint64
|
|
||||||
Limit uint64
|
|
||||||
TotalResult uint64
|
|
||||||
Result []*MailTextView
|
|
||||||
Sequence uint64
|
|
||||||
Timestamp time.Time
|
|
||||||
}
|
|
63
internal/iam/model/message_text_view.go
Normal file
63
internal/iam/model/message_text_view.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageTextsView struct {
|
||||||
|
Texts []*MessageTextView
|
||||||
|
Default bool
|
||||||
|
}
|
||||||
|
type MessageTextView struct {
|
||||||
|
AggregateID string
|
||||||
|
MessageTextType string
|
||||||
|
Language language.Tag
|
||||||
|
Title string
|
||||||
|
PreHeader string
|
||||||
|
Subject string
|
||||||
|
Greeting string
|
||||||
|
Text string
|
||||||
|
ButtonText string
|
||||||
|
FooterText string
|
||||||
|
Default bool
|
||||||
|
|
||||||
|
CreationDate time.Time
|
||||||
|
ChangeDate time.Time
|
||||||
|
Sequence uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageTextSearchRequest struct {
|
||||||
|
Offset uint64
|
||||||
|
Limit uint64
|
||||||
|
SortingColumn MessageTextSearchKey
|
||||||
|
Asc bool
|
||||||
|
Queries []*MessageTextSearchQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageTextSearchKey int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
MessageTextSearchKeyUnspecified MessageTextSearchKey = iota
|
||||||
|
MessageTextSearchKeyAggregateID
|
||||||
|
MessageTextSearchKeyMessageTextType
|
||||||
|
MessageTextSearchKeyLanguage
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageTextSearchQuery struct {
|
||||||
|
Key MessageTextSearchKey
|
||||||
|
Method domain.SearchMethod
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageTextSearchResponse struct {
|
||||||
|
Offset uint64
|
||||||
|
Limit uint64
|
||||||
|
TotalResult uint64
|
||||||
|
Result []*MessageTextView
|
||||||
|
Sequence uint64
|
||||||
|
Timestamp time.Time
|
||||||
|
}
|
@ -33,64 +33,23 @@ type IAM struct {
|
|||||||
DefaultLoginPolicy *LoginPolicy `json:"-"`
|
DefaultLoginPolicy *LoginPolicy `json:"-"`
|
||||||
DefaultLabelPolicy *LabelPolicy `json:"-"`
|
DefaultLabelPolicy *LabelPolicy `json:"-"`
|
||||||
DefaultMailTemplate *MailTemplate `json:"-"`
|
DefaultMailTemplate *MailTemplate `json:"-"`
|
||||||
DefaultMailTexts []*MailText `json:"-"`
|
|
||||||
DefaultOrgIAMPolicy *OrgIAMPolicy `json:"-"`
|
DefaultOrgIAMPolicy *OrgIAMPolicy `json:"-"`
|
||||||
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy `json:"-"`
|
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy `json:"-"`
|
||||||
DefaultPasswordAgePolicy *PasswordAgePolicy `json:"-"`
|
DefaultPasswordAgePolicy *PasswordAgePolicy `json:"-"`
|
||||||
DefaultPasswordLockoutPolicy *PasswordLockoutPolicy `json:"-"`
|
DefaultPasswordLockoutPolicy *PasswordLockoutPolicy `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func IAMFromModel(iam *model.IAM) *IAM {
|
|
||||||
members := IAMMembersFromModel(iam.Members)
|
|
||||||
idps := IDPConfigsFromModel(iam.IDPs)
|
|
||||||
mailTexts := MailTextsFromModel(iam.DefaultMailTexts)
|
|
||||||
converted := &IAM{
|
|
||||||
ObjectRoot: iam.ObjectRoot,
|
|
||||||
SetUpStarted: Step(iam.SetUpStarted),
|
|
||||||
SetUpDone: Step(iam.SetUpDone),
|
|
||||||
GlobalOrgID: iam.GlobalOrgID,
|
|
||||||
IAMProjectID: iam.IAMProjectID,
|
|
||||||
Members: members,
|
|
||||||
IDPs: idps,
|
|
||||||
DefaultMailTexts: mailTexts,
|
|
||||||
}
|
|
||||||
if iam.DefaultLoginPolicy != nil {
|
|
||||||
converted.DefaultLoginPolicy = LoginPolicyFromModel(iam.DefaultLoginPolicy)
|
|
||||||
}
|
|
||||||
if iam.DefaultLabelPolicy != nil {
|
|
||||||
converted.DefaultLabelPolicy = LabelPolicyFromModel(iam.DefaultLabelPolicy)
|
|
||||||
}
|
|
||||||
if iam.DefaultMailTemplate != nil {
|
|
||||||
converted.DefaultMailTemplate = MailTemplateFromModel(iam.DefaultMailTemplate)
|
|
||||||
}
|
|
||||||
if iam.DefaultPasswordComplexityPolicy != nil {
|
|
||||||
converted.DefaultPasswordComplexityPolicy = PasswordComplexityPolicyFromModel(iam.DefaultPasswordComplexityPolicy)
|
|
||||||
}
|
|
||||||
if iam.DefaultPasswordAgePolicy != nil {
|
|
||||||
converted.DefaultPasswordAgePolicy = PasswordAgePolicyFromModel(iam.DefaultPasswordAgePolicy)
|
|
||||||
}
|
|
||||||
if iam.DefaultPasswordLockoutPolicy != nil {
|
|
||||||
converted.DefaultPasswordLockoutPolicy = PasswordLockoutPolicyFromModel(iam.DefaultPasswordLockoutPolicy)
|
|
||||||
}
|
|
||||||
if iam.DefaultOrgIAMPolicy != nil {
|
|
||||||
converted.DefaultOrgIAMPolicy = OrgIAMPolicyFromModel(iam.DefaultOrgIAMPolicy)
|
|
||||||
}
|
|
||||||
return converted
|
|
||||||
}
|
|
||||||
|
|
||||||
func IAMToModel(iam *IAM) *model.IAM {
|
func IAMToModel(iam *IAM) *model.IAM {
|
||||||
members := IAMMembersToModel(iam.Members)
|
members := IAMMembersToModel(iam.Members)
|
||||||
idps := IDPConfigsToModel(iam.IDPs)
|
idps := IDPConfigsToModel(iam.IDPs)
|
||||||
mailTexts := MailTextsToModel(iam.DefaultMailTexts)
|
|
||||||
converted := &model.IAM{
|
converted := &model.IAM{
|
||||||
ObjectRoot: iam.ObjectRoot,
|
ObjectRoot: iam.ObjectRoot,
|
||||||
SetUpStarted: domain.Step(iam.SetUpStarted),
|
SetUpStarted: domain.Step(iam.SetUpStarted),
|
||||||
SetUpDone: domain.Step(iam.SetUpDone),
|
SetUpDone: domain.Step(iam.SetUpDone),
|
||||||
GlobalOrgID: iam.GlobalOrgID,
|
GlobalOrgID: iam.GlobalOrgID,
|
||||||
IAMProjectID: iam.IAMProjectID,
|
IAMProjectID: iam.IAMProjectID,
|
||||||
Members: members,
|
Members: members,
|
||||||
IDPs: idps,
|
IDPs: idps,
|
||||||
DefaultMailTexts: mailTexts,
|
|
||||||
}
|
}
|
||||||
if iam.DefaultLoginPolicy != nil {
|
if iam.DefaultLoginPolicy != nil {
|
||||||
converted.DefaultLoginPolicy = LoginPolicyToModel(iam.DefaultLoginPolicy)
|
converted.DefaultLoginPolicy = LoginPolicyToModel(iam.DefaultLoginPolicy)
|
||||||
@ -199,10 +158,6 @@ func (i *IAM) AppendEvent(event *es_models.Event) (err error) {
|
|||||||
return i.appendAddMailTemplateEvent(event)
|
return i.appendAddMailTemplateEvent(event)
|
||||||
case MailTemplateChanged:
|
case MailTemplateChanged:
|
||||||
return i.appendChangeMailTemplateEvent(event)
|
return i.appendChangeMailTemplateEvent(event)
|
||||||
case MailTextAdded:
|
|
||||||
return i.appendAddMailTextEvent(event)
|
|
||||||
case MailTextChanged:
|
|
||||||
return i.appendChangeMailTextEvent(event)
|
|
||||||
case PasswordComplexityPolicyAdded:
|
case PasswordComplexityPolicyAdded:
|
||||||
return i.appendAddPasswordComplexityPolicyEvent(event)
|
return i.appendAddPasswordComplexityPolicyEvent(event)
|
||||||
case PasswordComplexityPolicyChanged:
|
case PasswordComplexityPolicyChanged:
|
||||||
|
@ -110,43 +110,6 @@ func (p *MailText) Changes(changed *MailText) map[string]interface{} {
|
|||||||
return changes
|
return changes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IAM) appendAddMailTextEvent(event *es_models.Event) error {
|
|
||||||
mailText := &MailText{}
|
|
||||||
err := mailText.SetDataLabel(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mailText.ObjectRoot.CreationDate = event.CreationDate
|
|
||||||
i.DefaultMailTexts = append(i.DefaultMailTexts, mailText)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IAM) appendChangeMailTextEvent(event *es_models.Event) error {
|
|
||||||
mailText := &MailText{}
|
|
||||||
err := mailText.SetDataLabel(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if n, m := GetMailText(i.DefaultMailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
|
||||||
i.DefaultMailTexts[n] = mailText
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IAM) appendRemoveMailTextEvent(event *es_models.Event) error {
|
|
||||||
mailText := &MailText{}
|
|
||||||
err := mailText.SetDataLabel(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if n, m := GetMailText(i.DefaultMailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
|
||||||
i.DefaultMailTexts[n] = i.DefaultMailTexts[len(i.DefaultMailTexts)-1]
|
|
||||||
i.DefaultMailTexts[len(i.DefaultMailTexts)-1] = nil
|
|
||||||
i.DefaultMailTexts = i.DefaultMailTexts[:len(i.DefaultMailTexts)-1]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *MailText) SetDataLabel(event *es_models.Event) error {
|
func (p *MailText) SetDataLabel(event *es_models.Event) error {
|
||||||
err := json.Unmarshal(event.Data, p)
|
err := json.Unmarshal(event.Data, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAppendAddMailTextEvent(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
iam *IAM
|
|
||||||
mailText *MailText
|
|
||||||
event *es_models.Event
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
result *IAM
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "append add mailText event",
|
|
||||||
args: args{
|
|
||||||
iam: &IAM{},
|
|
||||||
mailText: &MailText{
|
|
||||||
MailTextType: "PasswordReset",
|
|
||||||
Language: "DE"},
|
|
||||||
event: &es_models.Event{},
|
|
||||||
},
|
|
||||||
result: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
|
||||||
MailTextType: "PasswordReset",
|
|
||||||
Language: "DE"}}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if tt.args.mailText != nil {
|
|
||||||
data, _ := json.Marshal(tt.args.mailText)
|
|
||||||
tt.args.event.Data = data
|
|
||||||
}
|
|
||||||
tt.args.iam.appendAddMailTextEvent(tt.args.event)
|
|
||||||
if len(tt.args.iam.DefaultMailTexts) != 1 {
|
|
||||||
t.Errorf("got wrong result should have one mailText actual: %v ", len(tt.args.iam.DefaultMailTexts))
|
|
||||||
}
|
|
||||||
if tt.args.iam.DefaultMailTexts[0] == tt.result.DefaultMailTexts[0] {
|
|
||||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTexts[0], tt.args.iam.DefaultMailTexts[0])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendChangeMailTextEvent(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
iam *IAM
|
|
||||||
mailText *MailText
|
|
||||||
event *es_models.Event
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
result *IAM
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "append change mailText event",
|
|
||||||
args: args{
|
|
||||||
iam: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
|
||||||
MailTextType: "PasswordReset",
|
|
||||||
Language: "DE"}}},
|
|
||||||
mailText: &MailText{
|
|
||||||
MailTextType: "ChangedPasswordReset",
|
|
||||||
Language: "DE"},
|
|
||||||
event: &es_models.Event{},
|
|
||||||
},
|
|
||||||
result: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
|
||||||
MailTextType: "PasswordReset",
|
|
||||||
Language: "ChangedDE"}}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if tt.args.mailText != nil {
|
|
||||||
data, _ := json.Marshal(tt.args.mailText)
|
|
||||||
tt.args.event.Data = data
|
|
||||||
}
|
|
||||||
tt.args.iam.appendChangeMailTextEvent(tt.args.event)
|
|
||||||
if len(tt.args.iam.DefaultMailTexts) != 1 {
|
|
||||||
t.Errorf("got wrong result should have one mailText actual: %v ", len(tt.args.iam.DefaultMailTexts))
|
|
||||||
}
|
|
||||||
if tt.args.iam.DefaultMailTexts[0] == tt.result.DefaultMailTexts[0] {
|
|
||||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTexts[0], tt.args.iam.DefaultMailTexts[0])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendRemoveMailTextEvent(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
iam *IAM
|
|
||||||
mailText *MailText
|
|
||||||
event *es_models.Event
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
result *IAM
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "append remove mailText event",
|
|
||||||
args: args{
|
|
||||||
iam: &IAM{DefaultMailTexts: []*MailText{&MailText{
|
|
||||||
MailTextType: "PasswordReset",
|
|
||||||
Language: "DE",
|
|
||||||
Subject: "Subject"}}},
|
|
||||||
mailText: &MailText{
|
|
||||||
MailTextType: "PasswordReset",
|
|
||||||
Language: "DE"},
|
|
||||||
event: &es_models.Event{},
|
|
||||||
},
|
|
||||||
result: &IAM{DefaultMailTexts: []*MailText{}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if tt.args.mailText != nil {
|
|
||||||
data, _ := json.Marshal(tt.args.mailText)
|
|
||||||
tt.args.event.Data = data
|
|
||||||
}
|
|
||||||
tt.args.iam.appendRemoveMailTextEvent(tt.args.event)
|
|
||||||
if len(tt.args.iam.DefaultMailTexts) != 0 {
|
|
||||||
t.Errorf("got wrong result should have no mailText actual: %v ", len(tt.args.iam.DefaultMailTexts))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -54,8 +54,9 @@ const (
|
|||||||
|
|
||||||
MailTemplateAdded models.EventType = "iam.mail.template.added"
|
MailTemplateAdded models.EventType = "iam.mail.template.added"
|
||||||
MailTemplateChanged models.EventType = "iam.mail.template.changed"
|
MailTemplateChanged models.EventType = "iam.mail.template.changed"
|
||||||
MailTextAdded models.EventType = "iam.mail.text.added"
|
|
||||||
MailTextChanged models.EventType = "iam.mail.text.changed"
|
CustomTextSet models.EventType = "iam.customtext.set"
|
||||||
|
CustomTextRemoved models.EventType = "iam.customtext.removed"
|
||||||
|
|
||||||
PasswordComplexityPolicyAdded models.EventType = "iam.policy.password.complexity.added"
|
PasswordComplexityPolicyAdded models.EventType = "iam.policy.password.complexity.added"
|
||||||
PasswordComplexityPolicyChanged models.EventType = "iam.policy.password.complexity.changed"
|
PasswordComplexityPolicyChanged models.EventType = "iam.policy.password.complexity.changed"
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/domain"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
"github.com/caos/zitadel/internal/view/repository"
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetMailTexts(db *gorm.DB, table string, aggregateID string) ([]*model.MailTextView, error) {
|
|
||||||
texts := make([]*model.MailTextView, 0)
|
|
||||||
queries := []*iam_model.MailTextSearchQuery{
|
|
||||||
{
|
|
||||||
Key: iam_model.MailTextSearchKeyAggregateID,
|
|
||||||
Value: aggregateID,
|
|
||||||
Method: domain.SearchMethodEquals,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
query := repository.PrepareSearchQuery(table, model.MailTextSearchRequest{Queries: queries})
|
|
||||||
_, err := query(db, &texts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return texts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMailTextByIDs(db *gorm.DB, table, aggregateID string, textType string, language string) (*model.MailTextView, error) {
|
|
||||||
mailText := new(model.MailTextView)
|
|
||||||
aggregateIDQuery := &model.MailTextSearchQuery{Key: iam_model.MailTextSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
|
||||||
textTypeQuery := &model.MailTextSearchQuery{Key: iam_model.MailTextSearchKeyMailTextType, Value: textType, Method: domain.SearchMethodEquals}
|
|
||||||
languageQuery := &model.MailTextSearchQuery{Key: iam_model.MailTextSearchKeyLanguage, Value: strings.ToUpper(language), Method: domain.SearchMethodEquals}
|
|
||||||
query := repository.PrepareGetByQuery(table, aggregateIDQuery, textTypeQuery, languageQuery)
|
|
||||||
err := query(db, mailText)
|
|
||||||
if caos_errs.IsNotFound(err) {
|
|
||||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-IiJjm", "Errors.IAM.MailText.NotExisting")
|
|
||||||
}
|
|
||||||
return mailText, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutMailText(db *gorm.DB, table string, mailText *model.MailTextView) error {
|
|
||||||
save := repository.PrepareSave(table)
|
|
||||||
return save(db, mailText)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteMailText(db *gorm.DB, table, aggregateID string, textType string, language string) error {
|
|
||||||
aggregateIDSearch := repository.Key{Key: model.MailTextSearchKey(iam_model.MailTextSearchKeyAggregateID), Value: aggregateID}
|
|
||||||
textTypeSearch := repository.Key{Key: model.MailTextSearchKey(iam_model.MailTextSearchKeyMailTextType), Value: textType}
|
|
||||||
languageSearch := repository.Key{Key: model.MailTextSearchKey(iam_model.MailTextSearchKeyLanguage), Value: language}
|
|
||||||
delete := repository.PrepareDeleteByKeys(table, aggregateIDSearch, textTypeSearch, languageSearch)
|
|
||||||
return delete(db)
|
|
||||||
}
|
|
54
internal/iam/repository/view/message_text_view.go
Normal file
54
internal/iam/repository/view/message_text_view.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/domain"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
"github.com/caos/zitadel/internal/view/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetMessageTexts(db *gorm.DB, table string, aggregateID string) ([]*model.MessageTextView, error) {
|
||||||
|
texts := make([]*model.MessageTextView, 0)
|
||||||
|
queries := []*iam_model.MessageTextSearchQuery{
|
||||||
|
{
|
||||||
|
Key: iam_model.MessageTextSearchKeyAggregateID,
|
||||||
|
Value: aggregateID,
|
||||||
|
Method: domain.SearchMethodEquals,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
query := repository.PrepareSearchQuery(table, model.MessageTextSearchRequest{Queries: queries})
|
||||||
|
_, err := query(db, &texts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return texts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMessageTextByIDs(db *gorm.DB, table, aggregateID, textType, lang string) (*model.MessageTextView, error) {
|
||||||
|
mailText := new(model.MessageTextView)
|
||||||
|
aggregateIDQuery := &model.MessageTextSearchQuery{Key: iam_model.MessageTextSearchKeyAggregateID, Value: aggregateID, Method: domain.SearchMethodEquals}
|
||||||
|
textTypeQuery := &model.MessageTextSearchQuery{Key: iam_model.MessageTextSearchKeyMessageTextType, Value: textType, Method: domain.SearchMethodEquals}
|
||||||
|
languageQuery := &model.MessageTextSearchQuery{Key: iam_model.MessageTextSearchKeyLanguage, Value: lang, Method: domain.SearchMethodEquals}
|
||||||
|
query := repository.PrepareGetByQuery(table, aggregateIDQuery, textTypeQuery, languageQuery)
|
||||||
|
err := query(db, mailText)
|
||||||
|
if caos_errs.IsNotFound(err) {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "VIEW-IiJjm", "Errors.IAM.CustomMessageText.NotExisting")
|
||||||
|
}
|
||||||
|
return mailText, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func PutMessageText(db *gorm.DB, table string, mailText *model.MessageTextView) error {
|
||||||
|
save := repository.PrepareSave(table)
|
||||||
|
return save(db, mailText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteMessageText(db *gorm.DB, table, aggregateID, textType, lang string) error {
|
||||||
|
aggregateIDSearch := repository.Key{Key: model.MessageTextSearchKey(iam_model.MessageTextSearchKeyAggregateID), Value: aggregateID}
|
||||||
|
textTypeSearch := repository.Key{Key: model.MessageTextSearchKey(iam_model.MessageTextSearchKeyMessageTextType), Value: textType}
|
||||||
|
languageSearch := repository.Key{Key: model.MessageTextSearchKey(iam_model.MessageTextSearchKeyLanguage), Value: lang}
|
||||||
|
delete := repository.PrepareDeleteByKeys(table, aggregateIDSearch, textTypeSearch, languageSearch)
|
||||||
|
return delete(db)
|
||||||
|
}
|
@ -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 ""
|
||||||
|
}
|
||||||
|
}
|
@ -548,19 +548,19 @@ func (repo *OrgRepository) GetMailTemplate(ctx context.Context) (*iam_model.Mail
|
|||||||
return iam_es_model.MailTemplateViewToModel(template), err
|
return iam_es_model.MailTemplateViewToModel(template), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *OrgRepository) GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error) {
|
func (repo *OrgRepository) GetDefaultMessageTexts(ctx context.Context) (*iam_model.MessageTextsView, error) {
|
||||||
texts, err := repo.View.MailTextsByAggregateID(repo.SystemDefaults.IamID)
|
texts, err := repo.View.MessageTextsByAggregateID(repo.SystemDefaults.IamID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return iam_es_model.MailTextsViewToModel(texts, true), err
|
return iam_es_model.MessageTextsViewToModel(texts, true), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *OrgRepository) GetMailTexts(ctx context.Context) (*iam_model.MailTextsView, error) {
|
func (repo *OrgRepository) GetMessageTexts(ctx context.Context) (*iam_model.MessageTextsView, error) {
|
||||||
defaultIn := false
|
defaultIn := false
|
||||||
texts, err := repo.View.MailTextsByAggregateID(authz.GetCtxData(ctx).OrgID)
|
texts, err := repo.View.MessageTextsByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||||
if errors.IsNotFound(err) || len(texts) == 0 {
|
if errors.IsNotFound(err) || len(texts) == 0 {
|
||||||
texts, err = repo.View.MailTextsByAggregateID(repo.SystemDefaults.IamID)
|
texts, err = repo.View.MessageTextsByAggregateID(repo.SystemDefaults.IamID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -569,7 +569,31 @@ func (repo *OrgRepository) GetMailTexts(ctx context.Context) (*iam_model.MailTex
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return iam_es_model.MailTextsViewToModel(texts, defaultIn), err
|
return iam_es_model.MessageTextsViewToModel(texts, defaultIn), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *OrgRepository) GetDefaultMessageText(ctx context.Context, textType, lang string) (*iam_model.MessageTextView, error) {
|
||||||
|
text, err := repo.View.MessageTextByIDs(repo.SystemDefaults.IamID, textType, lang)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
text.Default = true
|
||||||
|
return iam_es_model.MessageTextViewToModel(text), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *OrgRepository) GetMessageText(ctx context.Context, orgID, textType, lang string) (*iam_model.MessageTextView, error) {
|
||||||
|
text, err := repo.View.MessageTextByIDs(orgID, textType, lang)
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
result, err := repo.GetDefaultMessageText(ctx, textType, lang)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iam_es_model.MessageTextViewToModel(text), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *OrgRepository) getOrgChanges(ctx context.Context, orgID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error) {
|
func (repo *OrgRepository) getOrgChanges(ctx context.Context, orgID string, lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*org_model.OrgChanges, error) {
|
||||||
|
@ -77,8 +77,8 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
|||||||
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}),
|
||||||
newMailTemplate(
|
newMailTemplate(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("MailTemplate"), errorCount, es}),
|
||||||
newMailText(
|
newMessageText(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("MailText"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("MessageText"), errorCount, es}),
|
||||||
newFeatures(
|
newFeatures(
|
||||||
handler{view, bulkLimit, configs.cycleDuration("Features"), errorCount, es}),
|
handler{view, bulkLimit, configs.cycleDuration("Features"), errorCount, es}),
|
||||||
}
|
}
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/logging"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
|
||||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MailText struct {
|
|
||||||
handler
|
|
||||||
subscription *v1.Subscription
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMailText(handler handler) *MailText {
|
|
||||||
h := &MailText{
|
|
||||||
handler: handler,
|
|
||||||
}
|
|
||||||
|
|
||||||
h.subscribe()
|
|
||||||
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) subscribe() {
|
|
||||||
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
|
||||||
go func() {
|
|
||||||
for event := range m.subscription.Events {
|
|
||||||
query.ReduceEvent(m, event)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
mailTextTable = "management.mail_texts"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (m *MailText) ViewModel() string {
|
|
||||||
return mailTextTable
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_ *MailText) AggregateTypes() []es_models.AggregateType {
|
|
||||||
return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *MailText) CurrentSequence() (uint64, error) {
|
|
||||||
sequence, err := p.view.GetLatestMailTextSequence()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return sequence.CurrentSequence, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) EventQuery() (*es_models.SearchQuery, error) {
|
|
||||||
sequence, err := m.view.GetLatestMailTextSequence()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return es_models.NewSearchQuery().
|
|
||||||
AggregateTypeFilter(m.AggregateTypes()...).
|
|
||||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) Reduce(event *es_models.Event) (err error) {
|
|
||||||
switch event.AggregateType {
|
|
||||||
case model.OrgAggregate, iam_es_model.IAMAggregate:
|
|
||||||
err = m.processMailText(event)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) processMailText(event *es_models.Event) (err error) {
|
|
||||||
text := new(iam_model.MailTextView)
|
|
||||||
switch event.Type {
|
|
||||||
case iam_es_model.MailTextAdded, model.MailTextAdded:
|
|
||||||
err = text.AppendEvent(event)
|
|
||||||
case iam_es_model.MailTextChanged, model.MailTextChanged:
|
|
||||||
err = text.SetData(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
text, err = m.view.MailTextByIDs(event.AggregateID, text.MailTextType, text.Language)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
text.ChangeDate = event.CreationDate
|
|
||||||
err = text.AppendEvent(event)
|
|
||||||
case model.MailTextRemoved:
|
|
||||||
err = text.SetData(event)
|
|
||||||
return m.view.DeleteMailText(event.AggregateID, text.MailTextType, text.Language, event)
|
|
||||||
default:
|
|
||||||
return m.view.ProcessedMailTextSequence(event)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return m.view.PutMailText(text, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MailText) OnError(event *es_models.Event, err error) error {
|
|
||||||
logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in label text handler")
|
|
||||||
return spooler.HandleError(event, err, m.view.GetLatestMailTextFailedEvent, m.view.ProcessedMailTextFailedEvent, m.view.ProcessedMailTextSequence, m.errorCountUntilSkip)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *MailText) OnSuccess() error {
|
|
||||||
return spooler.HandleSuccess(o.view.UpdateMailTextSpoolerRunTimestamp)
|
|
||||||
}
|
|
@ -0,0 +1,122 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/logging"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
|
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/query"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||||
|
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||||
|
iam_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
"github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageText struct {
|
||||||
|
handler
|
||||||
|
subscription *v1.Subscription
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMessageText(handler handler) *MessageText {
|
||||||
|
h := &MessageText{
|
||||||
|
handler: handler,
|
||||||
|
}
|
||||||
|
|
||||||
|
h.subscribe()
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) subscribe() {
|
||||||
|
m.subscription = m.es.Subscribe(m.AggregateTypes()...)
|
||||||
|
go func() {
|
||||||
|
for event := range m.subscription.Events {
|
||||||
|
query.ReduceEvent(m, event)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
messageTextTable = "management.message_texts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *MessageText) ViewModel() string {
|
||||||
|
return messageTextTable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *MessageText) AggregateTypes() []es_models.AggregateType {
|
||||||
|
return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MessageText) CurrentSequence() (uint64, error) {
|
||||||
|
sequence, err := p.view.GetLatestMessageTextSequence()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return sequence.CurrentSequence, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) EventQuery() (*es_models.SearchQuery, error) {
|
||||||
|
sequence, err := m.view.GetLatestMessageTextSequence()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return es_models.NewSearchQuery().
|
||||||
|
AggregateTypeFilter(m.AggregateTypes()...).
|
||||||
|
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) Reduce(event *es_models.Event) (err error) {
|
||||||
|
switch event.AggregateType {
|
||||||
|
case model.OrgAggregate, iam_es_model.IAMAggregate:
|
||||||
|
err = m.processMessageText(event)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) processMessageText(event *es_models.Event) (err error) {
|
||||||
|
message := new(iam_model.MessageTextView)
|
||||||
|
switch event.Type {
|
||||||
|
case iam_es_model.CustomTextSet, model.CustomTextSet,
|
||||||
|
iam_es_model.CustomTextRemoved, model.CustomTextRemoved:
|
||||||
|
text := new(iam_model.CustomText)
|
||||||
|
err = text.SetData(event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
message, err = m.view.MessageTextByIDs(event.AggregateID, text.Template, text.Language.String())
|
||||||
|
if err != nil && !caos_errs.IsNotFound(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if caos_errs.IsNotFound(err) {
|
||||||
|
err = nil
|
||||||
|
message = new(iam_model.MessageTextView)
|
||||||
|
message.Language = text.Language.String()
|
||||||
|
message.MessageTextType = text.Template
|
||||||
|
message.CreationDate = event.CreationDate
|
||||||
|
}
|
||||||
|
err = message.AppendEvent(event)
|
||||||
|
case model.CustomTextMessageRemoved:
|
||||||
|
text := new(iam_model.CustomText)
|
||||||
|
err = text.SetData(event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.view.DeleteMessageText(event.AggregateID, text.Template, text.Language.String(), event)
|
||||||
|
default:
|
||||||
|
return m.view.ProcessedMessageTextSequence(event)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.view.PutMessageText(message, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageText) OnError(event *es_models.Event, err error) error {
|
||||||
|
logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in label text handler")
|
||||||
|
return spooler.HandleError(event, err, m.view.GetLatestMessageTextFailedEvent, m.view.ProcessedMessageTextFailedEvent, m.view.ProcessedMessageTextSequence, m.errorCountUntilSkip)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *MessageText) OnSuccess() error {
|
||||||
|
return spooler.HandleSuccess(o.view.UpdateMessageTextSpoolerRunTimestamp)
|
||||||
|
}
|
@ -1,57 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/errors"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
global_view "github.com/caos/zitadel/internal/view/repository"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
mailTextTable = "management.mail_texts"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (v *View) MailTextsByAggregateID(aggregateID string) ([]*model.MailTextView, error) {
|
|
||||||
return view.GetMailTexts(v.Db, mailTextTable, aggregateID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) MailTextByIDs(aggregateID string, textType string, language string) (*model.MailTextView, error) {
|
|
||||||
return view.GetMailTextByIDs(v.Db, mailTextTable, aggregateID, textType, language)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) PutMailText(template *model.MailTextView, event *models.Event) error {
|
|
||||||
err := view.PutMailText(v.Db, mailTextTable, template)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return v.ProcessedMailTextSequence(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) DeleteMailText(aggregateID string, textType string, language string, event *models.Event) error {
|
|
||||||
err := view.DeleteMailText(v.Db, mailTextTable, aggregateID, textType, language)
|
|
||||||
if err != nil && !errors.IsNotFound(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return v.ProcessedMailTextSequence(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetLatestMailTextSequence() (*global_view.CurrentSequence, error) {
|
|
||||||
return v.latestSequence(mailTextTable)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) ProcessedMailTextSequence(event *models.Event) error {
|
|
||||||
return v.saveCurrentSequence(mailTextTable, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) UpdateMailTextSpoolerRunTimestamp() error {
|
|
||||||
return v.updateSpoolerRunSequence(mailTextTable)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetLatestMailTextFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
|
||||||
return v.latestFailedEvent(mailTextTable, sequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) ProcessedMailTextFailedEvent(failedEvent *global_view.FailedEvent) error {
|
|
||||||
return v.saveFailedEvent(failedEvent)
|
|
||||||
}
|
|
@ -0,0 +1,57 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
global_view "github.com/caos/zitadel/internal/view/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
messageTextTable = "management.message_texts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *View) MessageTextsByAggregateID(aggregateID string) ([]*model.MessageTextView, error) {
|
||||||
|
return view.GetMessageTexts(v.Db, messageTextTable, aggregateID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) MessageTextByIDs(aggregateID, textType, lang string) (*model.MessageTextView, error) {
|
||||||
|
return view.GetMessageTextByIDs(v.Db, messageTextTable, aggregateID, textType, lang)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) PutMessageText(template *model.MessageTextView, event *models.Event) error {
|
||||||
|
err := view.PutMessageText(v.Db, messageTextTable, template)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.ProcessedMessageTextSequence(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) DeleteMessageText(aggregateID, textType, lang string, event *models.Event) error {
|
||||||
|
err := view.DeleteMessageText(v.Db, messageTextTable, aggregateID, textType, lang)
|
||||||
|
if err != nil && !errors.IsNotFound(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return v.ProcessedMessageTextSequence(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) GetLatestMessageTextSequence() (*global_view.CurrentSequence, error) {
|
||||||
|
return v.latestSequence(messageTextTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) ProcessedMessageTextSequence(event *models.Event) error {
|
||||||
|
return v.saveCurrentSequence(messageTextTable, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) UpdateMessageTextSpoolerRunTimestamp() error {
|
||||||
|
return v.updateSpoolerRunSequence(messageTextTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) GetLatestMessageTextFailedEvent(sequence uint64) (*global_view.FailedEvent, error) {
|
||||||
|
return v.latestFailedEvent(messageTextTable, sequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *View) ProcessedMessageTextFailedEvent(failedEvent *global_view.FailedEvent) error {
|
||||||
|
return v.saveFailedEvent(failedEvent)
|
||||||
|
}
|
@ -44,8 +44,10 @@ type OrgRepository interface {
|
|||||||
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
GetDefaultMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||||
GetMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
GetMailTemplate(ctx context.Context) (*iam_model.MailTemplateView, error)
|
||||||
|
|
||||||
GetDefaultMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
GetDefaultMessageTexts(ctx context.Context) (*iam_model.MessageTextsView, error)
|
||||||
GetMailTexts(ctx context.Context) (*iam_model.MailTextsView, error)
|
GetMessageTexts(ctx context.Context) (*iam_model.MessageTextsView, error)
|
||||||
|
GetDefaultMessageText(ctx context.Context, textType string, language string) (*iam_model.MessageTextView, error)
|
||||||
|
GetMessageText(ctx context.Context, orgID, textType, language string) (*iam_model.MessageTextView, error)
|
||||||
|
|
||||||
GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
GetLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||||
GetPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
GetPreviewLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error)
|
||||||
|
@ -29,19 +29,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
notificationTable = "notification.notifications"
|
notificationTable = "notification.notifications"
|
||||||
NotifyUserID = "NOTIFICATION"
|
NotifyUserID = "NOTIFICATION"
|
||||||
labelPolicyTableOrg = "management.label_policies"
|
labelPolicyTableOrg = "management.label_policies"
|
||||||
labelPolicyTableDef = "adminapi.label_policies"
|
labelPolicyTableDef = "adminapi.label_policies"
|
||||||
mailTemplateTableOrg = "management.mail_templates"
|
mailTemplateTableOrg = "management.mail_templates"
|
||||||
mailTemplateTableDef = "adminapi.mail_templates"
|
mailTemplateTableDef = "adminapi.mail_templates"
|
||||||
mailTextTableOrg = "management.mail_texts"
|
messageTextTableOrg = "management.message_texts"
|
||||||
mailTextTableDef = "adminapi.mail_texts"
|
messageTextTableDef = "adminapi.message_texts"
|
||||||
mailTextTypeDomainClaimed = "DomainClaimed"
|
messageTextTypeDomainClaimed = "DomainClaimed"
|
||||||
mailTextTypeInitCode = "InitCode"
|
messageTextTypeInitCode = "InitCode"
|
||||||
mailTextTypePasswordReset = "PasswordReset"
|
messageTextTypePasswordReset = "PasswordReset"
|
||||||
mailTextTypeVerifyEmail = "VerifyEmail"
|
messageTextTypeVerifyEmail = "VerifyEmail"
|
||||||
mailTextTypeVerifyPhone = "VerifyPhone"
|
messageTextTypeVerifyPhone = "VerifyPhone"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
@ -146,7 +146,6 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
|
|||||||
if err != nil || alreadyHandled {
|
if err != nil || alreadyHandled {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := getSetNotifyContextData(event.ResourceOwner)
|
ctx := getSetNotifyContextData(event.ResourceOwner)
|
||||||
colors, err := n.getLabelPolicy(ctx)
|
colors, err := n.getLabelPolicy(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -163,7 +162,7 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := n.getMailText(ctx, mailTextTypeInitCode, user.PreferredLanguage)
|
text, err := n.getMessageText(user, messageTextTypeInitCode, user.PreferredLanguage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -202,7 +201,7 @@ func (n *Notification) handlePasswordCode(event *models.Event) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := n.getMailText(ctx, mailTextTypePasswordReset, user.PreferredLanguage)
|
text, err := n.getMessageText(user, messageTextTypePasswordReset, user.PreferredLanguage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -224,7 +223,6 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
|
|||||||
if err != nil || alreadyHandled {
|
if err != nil || alreadyHandled {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := getSetNotifyContextData(event.ResourceOwner)
|
ctx := getSetNotifyContextData(event.ResourceOwner)
|
||||||
colors, err := n.getLabelPolicy(ctx)
|
colors, err := n.getLabelPolicy(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -241,7 +239,7 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := n.getMailText(ctx, mailTextTypeVerifyEmail, user.PreferredLanguage)
|
text, err := n.getMessageText(user, messageTextTypeVerifyEmail, user.PreferredLanguage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -268,7 +266,11 @@ func (n *Notification) handlePhoneVerificationCode(event *models.Event) (err err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = types.SendPhoneVerificationCode(n.i18n, user, phoneCode, n.systemDefaults, n.AesCrypto)
|
text, err := n.getMessageText(user, messageTextTypeVerifyPhone, user.PreferredLanguage)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = types.SendPhoneVerificationCode(text, user, phoneCode, n.systemDefaults, n.AesCrypto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -303,7 +305,7 @@ func (n *Notification) handleDomainClaimed(event *models.Event) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
text, err := n.getMailText(ctx, mailTextTypeDomainClaimed, user.PreferredLanguage)
|
text, err := n.getMessageText(user, messageTextTypeDomainClaimed, user.PreferredLanguage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -395,26 +397,29 @@ func (n *Notification) getMailTemplate(ctx context.Context) (*iam_model.MailTemp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read organization specific texts
|
// Read organization specific texts
|
||||||
func (n *Notification) getMailText(ctx context.Context, textType string, lang string) (*iam_model.MailTextView, error) {
|
func (n *Notification) getMessageText(user *model.NotifyUser, textType, lang string) (*iam_model.MessageTextView, error) {
|
||||||
langTag := language.Make(lang)
|
langTag := language.Make(lang)
|
||||||
if langTag == language.Und {
|
if langTag == language.Und {
|
||||||
langTag = n.systemDefaults.DefaultLanguage
|
langTag = language.English
|
||||||
}
|
}
|
||||||
base, _ := langTag.Base()
|
langBase, _ := langTag.Base()
|
||||||
|
|
||||||
|
defaultMessageText, err := n.view.MessageTextByIDs(n.systemDefaults.IamID, textType, langBase.String(), messageTextTableDef)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defaultMessageText.Default = true
|
||||||
|
|
||||||
// read from Org
|
// read from Org
|
||||||
mailText, err := n.view.MailTextByIDs(authz.GetCtxData(ctx).OrgID, textType, base.String(), mailTextTableOrg)
|
orgMessageText, err := n.view.MessageTextByIDs(user.ResourceOwner, textType, langBase.String(), messageTextTableOrg)
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
// read from default
|
return iam_es_model.MessageTextViewToModel(defaultMessageText), nil
|
||||||
mailText, err = n.view.MailTextByIDs(n.systemDefaults.IamID, textType, base.String(), mailTextTableDef)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
mailText.Default = true
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return iam_es_model.MailTextViewToModel(mailText), err
|
mergedText := mergeMessageTexts(defaultMessageText, orgMessageText)
|
||||||
|
return iam_es_model.MessageTextViewToModel(mergedText), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) getUserByID(userID string) (*model.NotifyUser, error) {
|
func (n *Notification) getUserByID(userID string) (*model.NotifyUser, error) {
|
||||||
@ -440,3 +445,28 @@ func (n *Notification) getUserByID(userID string) (*model.NotifyUser, error) {
|
|||||||
}
|
}
|
||||||
return &userCopy, nil
|
return &userCopy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeMessageTexts(defaultText *iam_es_model.MessageTextView, orgText *iam_es_model.MessageTextView) *iam_es_model.MessageTextView {
|
||||||
|
if orgText.Subject == "" {
|
||||||
|
orgText.Subject = defaultText.Subject
|
||||||
|
}
|
||||||
|
if orgText.Title == "" {
|
||||||
|
orgText.Title = defaultText.Title
|
||||||
|
}
|
||||||
|
if orgText.PreHeader == "" {
|
||||||
|
orgText.PreHeader = defaultText.PreHeader
|
||||||
|
}
|
||||||
|
if orgText.Text == "" {
|
||||||
|
orgText.Text = defaultText.Text
|
||||||
|
}
|
||||||
|
if orgText.Greeting == "" {
|
||||||
|
orgText.Greeting = defaultText.Greeting
|
||||||
|
}
|
||||||
|
if orgText.ButtonText == "" {
|
||||||
|
orgText.ButtonText = defaultText.ButtonText
|
||||||
|
}
|
||||||
|
if orgText.FooterText == "" {
|
||||||
|
orgText.FooterText = defaultText.FooterText
|
||||||
|
}
|
||||||
|
return orgText
|
||||||
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package view
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view"
|
|
||||||
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (v *View) MailTextByIDs(aggregateID string, textType string, language string, mailTextTableVar string) (*model.MailTextView, error) {
|
|
||||||
return view.GetMailTextByIDs(v.Db, mailTextTableVar, aggregateID, textType, language)
|
|
||||||
}
|
|
@ -0,0 +1,10 @@
|
|||||||
|
package view
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view"
|
||||||
|
"github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *View) MessageTextByIDs(aggregateID, textType, lang, messageTextTableVar string) (*model.MessageTextView, error) {
|
||||||
|
return view.GetMessageTextByIDs(v.Db, messageTextTableVar, aggregateID, textType, lang)
|
||||||
|
}
|
@ -53,7 +53,7 @@ func (data *TemplateData) Translate(i18n *i18n.Translator, args map[string]inter
|
|||||||
data.ButtonText = i18n.Localize(data.ButtonText, nil, langs...)
|
data.ButtonText = i18n.Localize(data.ButtonText, nil, langs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTemplateData(apiDomain, href string, text *iam_model.MailTextView, policy *iam_model.LabelPolicyView) TemplateData {
|
func GetTemplateData(apiDomain, href string, text *iam_model.MessageTextView, policy *iam_model.LabelPolicyView) TemplateData {
|
||||||
templateData := TemplateData{
|
templateData := TemplateData{
|
||||||
Title: text.Title,
|
Title: text.Title,
|
||||||
PreHeader: text.PreHeader,
|
PreHeader: text.PreHeader,
|
||||||
@ -62,6 +62,7 @@ func GetTemplateData(apiDomain, href string, text *iam_model.MailTextView, polic
|
|||||||
Text: html.UnescapeString(text.Text),
|
Text: html.UnescapeString(text.Text),
|
||||||
Href: href,
|
Href: href,
|
||||||
ButtonText: text.ButtonText,
|
ButtonText: text.ButtonText,
|
||||||
|
FooterText: text.FooterText,
|
||||||
PrimaryColor: defaultPrimaryColor,
|
PrimaryColor: defaultPrimaryColor,
|
||||||
BackgroundColor: defaultBackgroundColor,
|
BackgroundColor: defaultBackgroundColor,
|
||||||
FontColor: defaultFontColor,
|
FontColor: defaultFontColor,
|
||||||
|
@ -15,18 +15,14 @@ type DomainClaimedData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendDomainClaimed(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
func SendDomainClaimed(mailhtml string, text *iam_model.MessageTextView, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
||||||
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var args = map[string]interface{}{
|
var args = mapNotifyUserToArgs(user)
|
||||||
"FirstName": user.FirstName,
|
args["TempUsername"] = username
|
||||||
"LastName": user.LastName,
|
args["Domain"] = strings.Split(user.LastEmail, "@")[1]
|
||||||
"Username": user.LastEmail,
|
|
||||||
"TempUsername": username,
|
|
||||||
"Domain": strings.Split(user.LastEmail, "@")[1],
|
|
||||||
}
|
|
||||||
|
|
||||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||||
|
@ -16,7 +16,7 @@ type EmailVerificationCodeData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendEmailVerificationCode(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
func SendEmailVerificationCode(mailhtml string, text *iam_model.MessageTextView, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -25,11 +25,9 @@ func SendEmailVerificationCode(mailhtml string, text *iam_model.MailTextView, us
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var args = map[string]interface{}{
|
|
||||||
"FirstName": user.FirstName,
|
var args = mapNotifyUserToArgs(user)
|
||||||
"LastName": user.LastName,
|
args["Code"] = codeString
|
||||||
"Code": codeString,
|
|
||||||
}
|
|
||||||
|
|
||||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||||
|
@ -22,7 +22,7 @@ type UrlData struct {
|
|||||||
PasswordSet bool
|
PasswordSet bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendUserInitCode(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
func SendUserInitCode(mailhtml string, text *iam_model.MessageTextView, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -31,12 +31,8 @@ func SendUserInitCode(mailhtml string, text *iam_model.MailTextView, user *view_
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var args = map[string]interface{}{
|
var args = mapNotifyUserToArgs(user)
|
||||||
"FirstName": user.FirstName,
|
args["Code"] = codeString
|
||||||
"LastName": user.LastName,
|
|
||||||
"Code": codeString,
|
|
||||||
"PreferredLoginName": user.PreferredLoginName,
|
|
||||||
}
|
|
||||||
|
|
||||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||||
|
@ -18,7 +18,7 @@ type PasswordCodeData struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendPasswordCode(mailhtml string, text *iam_model.MailTextView, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
func SendPasswordCode(mailhtml string, text *iam_model.MessageTextView, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *iam_model.LabelPolicyView, apiDomain string) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -27,11 +27,8 @@ func SendPasswordCode(mailhtml string, text *iam_model.MailTextView, user *view_
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var args = map[string]interface{}{
|
var args = mapNotifyUserToArgs(user)
|
||||||
"FirstName": user.FirstName,
|
args["Code"] = codeString
|
||||||
"LastName": user.LastName,
|
|
||||||
"Code": codeString,
|
|
||||||
}
|
|
||||||
|
|
||||||
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
text.Greeting, err = templates.ParseTemplateText(text.Greeting, args)
|
||||||
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||||
|
@ -3,7 +3,7 @@ package types
|
|||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/i18n"
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
"github.com/caos/zitadel/internal/notification/templates"
|
"github.com/caos/zitadel/internal/notification/templates"
|
||||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||||
@ -13,19 +13,18 @@ type PhoneVerificationCodeData struct {
|
|||||||
UserID string
|
UserID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendPhoneVerificationCode(i18n *i18n.Translator, user *view_model.NotifyUser, code *es_model.PhoneCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
|
func SendPhoneVerificationCode(text *iam_model.MessageTextView, user *view_model.NotifyUser, code *es_model.PhoneCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm) error {
|
||||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var args = map[string]interface{}{
|
var args = mapNotifyUserToArgs(user)
|
||||||
"FirstName": user.FirstName,
|
args["Code"] = codeString
|
||||||
"LastName": user.LastName,
|
|
||||||
"Code": codeString,
|
text.Text, err = templates.ParseTemplateText(text.Text, args)
|
||||||
}
|
|
||||||
systemDefaults.Notifications.TemplateData.VerifyPhone.Translate(i18n, args, user.PreferredLanguage)
|
|
||||||
codeData := &PhoneVerificationCodeData{UserID: user.ID}
|
codeData := &PhoneVerificationCodeData{UserID: user.ID}
|
||||||
template, err := templates.ParseTemplateText(systemDefaults.Notifications.TemplateData.VerifyPhone.Text, codeData)
|
template, err := templates.ParseTemplateText(text.Text, codeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -42,3 +42,21 @@ func sendDebugEmail(message providers.Message, config systemdefaults.Notificatio
|
|||||||
}
|
}
|
||||||
return provider.HandleMessage(message)
|
return provider.HandleMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mapNotifyUserToArgs(user *view_model.NotifyUser) map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
"UserName": user.UserName,
|
||||||
|
"FirstName": user.FirstName,
|
||||||
|
"LastName": user.LastName,
|
||||||
|
"NickName": user.NickName,
|
||||||
|
"DisplayName": user.DisplayName,
|
||||||
|
"LastEmail": user.LastEmail,
|
||||||
|
"VerifiedEmail": user.VerifiedEmail,
|
||||||
|
"LastPhone": user.LastPhone,
|
||||||
|
"VerifiedPhone": user.VerifiedPhone,
|
||||||
|
"PreferredLoginName": user.PreferredLoginName,
|
||||||
|
"LoginNames": user.LoginNames,
|
||||||
|
"ChangeDate": user.ChangeDate,
|
||||||
|
"CreationDate": user.CreationDate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (o *Org) appendAddMailTextEvent(event *es_models.Event) error {
|
|
||||||
mailText := &iam_es_model.MailText{}
|
|
||||||
err := mailText.SetDataLabel(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mailText.ObjectRoot.CreationDate = event.CreationDate
|
|
||||||
o.MailTexts = append(o.MailTexts, mailText)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Org) appendChangeMailTextEvent(event *es_models.Event) error {
|
|
||||||
mailText := &iam_es_model.MailText{}
|
|
||||||
err := mailText.SetDataLabel(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mailText.ObjectRoot.ChangeDate = event.CreationDate
|
|
||||||
if n, m := iam_es_model.GetMailText(o.MailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
|
||||||
o.MailTexts[n] = mailText
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Org) appendRemoveMailTextEvent(event *es_models.Event) error {
|
|
||||||
mailText := &iam_es_model.MailText{}
|
|
||||||
err := mailText.SetDataLabel(event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if n, m := iam_es_model.GetMailText(o.MailTexts, mailText.MailTextType, mailText.Language); m != nil {
|
|
||||||
o.MailTexts[n] = o.MailTexts[len(o.MailTexts)-1]
|
|
||||||
o.MailTexts[len(o.MailTexts)-1] = nil
|
|
||||||
o.MailTexts = o.MailTexts[:len(o.MailTexts)-1]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
|
|
||||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAppendAddMailTextEvent(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
org *Org
|
|
||||||
mailText *iam_es_model.MailText
|
|
||||||
event *es_models.Event
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
result *Org
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "append add mail text event",
|
|
||||||
args: args{
|
|
||||||
org: &Org{},
|
|
||||||
mailText: &iam_es_model.MailText{MailTextType: "Type", Language: "DE"},
|
|
||||||
event: &es_models.Event{},
|
|
||||||
},
|
|
||||||
result: &Org{MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{MailTextType: "Type", Language: "DE"}}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if tt.args.mailText != nil {
|
|
||||||
data, _ := json.Marshal(tt.args.mailText)
|
|
||||||
tt.args.event.Data = data
|
|
||||||
}
|
|
||||||
tt.args.org.appendAddMailTextEvent(tt.args.event)
|
|
||||||
if len(tt.args.org.MailTexts) != 1 {
|
|
||||||
t.Errorf("got wrong result should have one mailtext actual: %v ", len(tt.args.org.MailTexts))
|
|
||||||
}
|
|
||||||
if tt.result.MailTexts[0].Language != tt.args.org.MailTexts[0].Language {
|
|
||||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.MailTexts[0].Language, tt.args.org.MailTexts[0].Language)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendChangeMailTextEvent(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
org *Org
|
|
||||||
mailText *iam_es_model.MailText
|
|
||||||
event *es_models.Event
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
result *Org
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "append change mail text event",
|
|
||||||
args: args{
|
|
||||||
org: &Org{MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{
|
|
||||||
Language: "DE",
|
|
||||||
MailTextType: "TypeX",
|
|
||||||
}}},
|
|
||||||
mailText: &iam_es_model.MailText{MailTextType: "Type", Language: "DE"},
|
|
||||||
event: &es_models.Event{},
|
|
||||||
},
|
|
||||||
result: &Org{MailTexts: []*iam_es_model.MailText{&iam_es_model.MailText{
|
|
||||||
Language: "DE",
|
|
||||||
MailTextType: "Type",
|
|
||||||
}}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if tt.args.mailText != nil {
|
|
||||||
data, _ := json.Marshal(tt.args.mailText)
|
|
||||||
tt.args.event.Data = data
|
|
||||||
}
|
|
||||||
tt.args.org.appendChangeMailTextEvent(tt.args.event)
|
|
||||||
if len(tt.args.org.MailTexts) != 1 {
|
|
||||||
t.Errorf("got wrong result should have one mailtext actual: %v ", len(tt.args.org.MailTexts))
|
|
||||||
}
|
|
||||||
if tt.result.MailTexts[0].Language != tt.args.org.MailTexts[0].Language {
|
|
||||||
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.MailTexts[0].Language, tt.args.org.MailTexts[0].Language)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,6 @@ type Org struct {
|
|||||||
OrgIAMPolicy *iam_es_model.OrgIAMPolicy `json:"-"`
|
OrgIAMPolicy *iam_es_model.OrgIAMPolicy `json:"-"`
|
||||||
LabelPolicy *iam_es_model.LabelPolicy `json:"-"`
|
LabelPolicy *iam_es_model.LabelPolicy `json:"-"`
|
||||||
MailTemplate *iam_es_model.MailTemplate `json:"-"`
|
MailTemplate *iam_es_model.MailTemplate `json:"-"`
|
||||||
MailTexts []*iam_es_model.MailText `json:"-"`
|
|
||||||
IDPs []*iam_es_model.IDPConfig `json:"-"`
|
IDPs []*iam_es_model.IDPConfig `json:"-"`
|
||||||
LoginPolicy *iam_es_model.LoginPolicy `json:"-"`
|
LoginPolicy *iam_es_model.LoginPolicy `json:"-"`
|
||||||
PasswordComplexityPolicy *iam_es_model.PasswordComplexityPolicy `json:"-"`
|
PasswordComplexityPolicy *iam_es_model.PasswordComplexityPolicy `json:"-"`
|
||||||
@ -34,44 +33,6 @@ type Org struct {
|
|||||||
PasswordLockoutPolicy *iam_es_model.PasswordLockoutPolicy `json:"-"`
|
PasswordLockoutPolicy *iam_es_model.PasswordLockoutPolicy `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func OrgFromModel(org *org_model.Org) *Org {
|
|
||||||
members := OrgMembersFromModel(org.Members)
|
|
||||||
domains := OrgDomainsFromModel(org.Domains)
|
|
||||||
idps := iam_es_model.IDPConfigsFromModel(org.IDPs)
|
|
||||||
mailTexts := iam_es_model.MailTextsFromModel(org.MailTexts)
|
|
||||||
converted := &Org{
|
|
||||||
ObjectRoot: org.ObjectRoot,
|
|
||||||
Name: org.Name,
|
|
||||||
State: int32(org.State),
|
|
||||||
Domains: domains,
|
|
||||||
MailTexts: mailTexts,
|
|
||||||
Members: members,
|
|
||||||
IDPs: idps,
|
|
||||||
}
|
|
||||||
if org.OrgIamPolicy != nil {
|
|
||||||
converted.OrgIAMPolicy = iam_es_model.OrgIAMPolicyFromModel(org.OrgIamPolicy)
|
|
||||||
}
|
|
||||||
if org.LoginPolicy != nil {
|
|
||||||
converted.LoginPolicy = iam_es_model.LoginPolicyFromModel(org.LoginPolicy)
|
|
||||||
}
|
|
||||||
if org.LabelPolicy != nil {
|
|
||||||
converted.LabelPolicy = iam_es_model.LabelPolicyFromModel(org.LabelPolicy)
|
|
||||||
}
|
|
||||||
if org.MailTemplate != nil {
|
|
||||||
converted.MailTemplate = iam_es_model.MailTemplateFromModel(org.MailTemplate)
|
|
||||||
}
|
|
||||||
if org.PasswordComplexityPolicy != nil {
|
|
||||||
converted.PasswordComplexityPolicy = iam_es_model.PasswordComplexityPolicyFromModel(org.PasswordComplexityPolicy)
|
|
||||||
}
|
|
||||||
if org.PasswordAgePolicy != nil {
|
|
||||||
converted.PasswordAgePolicy = iam_es_model.PasswordAgePolicyFromModel(org.PasswordAgePolicy)
|
|
||||||
}
|
|
||||||
if org.PasswordLockoutPolicy != nil {
|
|
||||||
converted.PasswordLockoutPolicy = iam_es_model.PasswordLockoutPolicyFromModel(org.PasswordLockoutPolicy)
|
|
||||||
}
|
|
||||||
return converted
|
|
||||||
}
|
|
||||||
|
|
||||||
func OrgToModel(org *Org) *org_model.Org {
|
func OrgToModel(org *Org) *org_model.Org {
|
||||||
converted := &org_model.Org{
|
converted := &org_model.Org{
|
||||||
ObjectRoot: org.ObjectRoot,
|
ObjectRoot: org.ObjectRoot,
|
||||||
@ -79,7 +40,6 @@ func OrgToModel(org *Org) *org_model.Org {
|
|||||||
State: org_model.OrgState(org.State),
|
State: org_model.OrgState(org.State),
|
||||||
Domains: OrgDomainsToModel(org.Domains),
|
Domains: OrgDomainsToModel(org.Domains),
|
||||||
Members: OrgMembersToModel(org.Members),
|
Members: OrgMembersToModel(org.Members),
|
||||||
MailTexts: iam_es_model.MailTextsToModel(org.MailTexts),
|
|
||||||
IDPs: iam_es_model.IDPConfigsToModel(org.IDPs),
|
IDPs: iam_es_model.IDPConfigsToModel(org.IDPs),
|
||||||
}
|
}
|
||||||
if org.OrgIAMPolicy != nil {
|
if org.OrgIAMPolicy != nil {
|
||||||
@ -216,12 +176,6 @@ func (o *Org) AppendEvent(event *es_models.Event) (err error) {
|
|||||||
err = o.appendChangeMailTemplateEvent(event)
|
err = o.appendChangeMailTemplateEvent(event)
|
||||||
case MailTemplateRemoved:
|
case MailTemplateRemoved:
|
||||||
o.appendRemoveMailTemplateEvent(event)
|
o.appendRemoveMailTemplateEvent(event)
|
||||||
case MailTextAdded:
|
|
||||||
err = o.appendAddMailTextEvent(event)
|
|
||||||
case MailTextChanged:
|
|
||||||
err = o.appendChangeMailTextEvent(event)
|
|
||||||
case MailTextRemoved:
|
|
||||||
o.appendRemoveMailTextEvent(event)
|
|
||||||
case LoginPolicySecondFactorAdded:
|
case LoginPolicySecondFactorAdded:
|
||||||
err = o.appendAddSecondFactorToLoginPolicyEvent(event)
|
err = o.appendAddSecondFactorToLoginPolicyEvent(event)
|
||||||
case LoginPolicySecondFactorRemoved:
|
case LoginPolicySecondFactorRemoved:
|
||||||
|
@ -76,9 +76,10 @@ const (
|
|||||||
MailTemplateAdded models.EventType = "org.mail.template.added"
|
MailTemplateAdded models.EventType = "org.mail.template.added"
|
||||||
MailTemplateChanged models.EventType = "org.mail.template.changed"
|
MailTemplateChanged models.EventType = "org.mail.template.changed"
|
||||||
MailTemplateRemoved models.EventType = "org.mail.template.removed"
|
MailTemplateRemoved models.EventType = "org.mail.template.removed"
|
||||||
MailTextAdded models.EventType = "org.mail.text.added"
|
|
||||||
MailTextChanged models.EventType = "org.mail.text.changed"
|
CustomTextSet models.EventType = "org.customtext.set"
|
||||||
MailTextRemoved models.EventType = "org.mail.text.removed"
|
CustomTextRemoved models.EventType = "org.customtext.removed"
|
||||||
|
CustomTextMessageRemoved models.EventType = "org.customtext.template.removed"
|
||||||
|
|
||||||
PasswordComplexityPolicyAdded models.EventType = "org.policy.password.complexity.added"
|
PasswordComplexityPolicyAdded models.EventType = "org.policy.password.complexity.added"
|
||||||
PasswordComplexityPolicyChanged models.EventType = "org.policy.password.complexity.changed"
|
PasswordComplexityPolicyChanged models.EventType = "org.policy.password.complexity.changed"
|
||||||
|
@ -81,7 +81,7 @@ func (r *ProjectGrantViewSearchRequest) AppendMyResourceOwnerQuery(orgID string)
|
|||||||
|
|
||||||
func (r *ProjectGrantViewSearchRequest) EnsureLimit(limit uint64) error {
|
func (r *ProjectGrantViewSearchRequest) EnsureLimit(limit uint64) error {
|
||||||
if r.Limit > limit {
|
if r.Limit > limit {
|
||||||
return caos_errors.ThrowInvalidArgument(nil, "SEARCH-2n8fS", "Errors.Limit.ExceedsDefault")
|
return caos_errors.ThrowInvalidArgument(nil, "SEARCH-0fj3s", "Errors.Limit.ExceedsDefault")
|
||||||
}
|
}
|
||||||
if r.Limit == 0 {
|
if r.Limit == 0 {
|
||||||
r.Limit = limit
|
r.Limit = limit
|
||||||
|
@ -35,6 +35,7 @@ type FeaturesSetEvent struct {
|
|||||||
LabelPolicyPrivateLabel *bool `json:"labelPolicyPrivateLabel,omitempty"`
|
LabelPolicyPrivateLabel *bool `json:"labelPolicyPrivateLabel,omitempty"`
|
||||||
LabelPolicyWatermark *bool `json:"labelPolicyWatermark,omitempty"`
|
LabelPolicyWatermark *bool `json:"labelPolicyWatermark,omitempty"`
|
||||||
CustomDomain *bool `json:"customDomain,omitempty"`
|
CustomDomain *bool `json:"customDomain,omitempty"`
|
||||||
|
CustomText *bool `json:"customText,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *FeaturesSetEvent) Data() interface{} {
|
func (e *FeaturesSetEvent) Data() interface{} {
|
||||||
@ -153,6 +154,11 @@ func ChangeCustomDomain(customDomain bool) func(event *FeaturesSetEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ChangeCustomText(customText bool) func(event *FeaturesSetEvent) {
|
||||||
|
return func(e *FeaturesSetEvent) {
|
||||||
|
e.CustomText = &customText
|
||||||
|
}
|
||||||
|
}
|
||||||
func FeaturesSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
func FeaturesSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
e := &FeaturesSetEvent{
|
e := &FeaturesSetEvent{
|
||||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
46
internal/repository/iam/custom_text.go
Normal file
46
internal/repository/iam/custom_text.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package iam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
"github.com/caos/zitadel/internal/repository/policy"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
CustomTextSetEventType = iamEventTypePrefix + policy.CustomTextSetEventType
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomTextSetEvent struct {
|
||||||
|
policy.CustomTextSetEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextSetEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
template,
|
||||||
|
key,
|
||||||
|
text string,
|
||||||
|
language language.Tag,
|
||||||
|
) *CustomTextSetEvent {
|
||||||
|
return &CustomTextSetEvent{
|
||||||
|
CustomTextSetEvent: *policy.NewCustomTextSetEvent(
|
||||||
|
eventstore.NewBaseEventForPush(ctx, aggregate, CustomTextSetEventType),
|
||||||
|
template,
|
||||||
|
key,
|
||||||
|
text,
|
||||||
|
language),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e, err := policy.CustomTextSetEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CustomTextSetEvent{CustomTextSetEvent: *e.(*policy.CustomTextSetEvent)}, nil
|
||||||
|
}
|
@ -56,5 +56,6 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
|||||||
RegisterFilterEventMapper(MailTemplateChangedEventType, MailTemplateChangedEventMapper).
|
RegisterFilterEventMapper(MailTemplateChangedEventType, MailTemplateChangedEventMapper).
|
||||||
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
|
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
|
||||||
RegisterFilterEventMapper(MailTextChangedEventType, MailTextChangedEventMapper).
|
RegisterFilterEventMapper(MailTextChangedEventType, MailTextChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(CustomTextSetEventType, CustomTextSetEventMapper).
|
||||||
RegisterFilterEventMapper(FeaturesSetEventType, FeaturesSetEventMapper)
|
RegisterFilterEventMapper(FeaturesSetEventType, FeaturesSetEventMapper)
|
||||||
}
|
}
|
||||||
|
107
internal/repository/org/custom_text.go
Normal file
107
internal/repository/org/custom_text.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package org
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
"github.com/caos/zitadel/internal/repository/policy"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
CustomTextSetEventType = orgEventTypePrefix + policy.CustomTextSetEventType
|
||||||
|
CustomTextRemovedEventType = orgEventTypePrefix + policy.CustomTextRemovedEventType
|
||||||
|
CustomTextTemplateRemovedEventType = orgEventTypePrefix + policy.CustomTextTemplateRemovedEventType
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomTextSetEvent struct {
|
||||||
|
policy.CustomTextSetEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextSetEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
template,
|
||||||
|
key,
|
||||||
|
text string,
|
||||||
|
language language.Tag,
|
||||||
|
) *CustomTextSetEvent {
|
||||||
|
return &CustomTextSetEvent{
|
||||||
|
CustomTextSetEvent: *policy.NewCustomTextSetEvent(
|
||||||
|
eventstore.NewBaseEventForPush(ctx, aggregate, CustomTextSetEventType),
|
||||||
|
template,
|
||||||
|
key,
|
||||||
|
text,
|
||||||
|
language),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e, err := policy.CustomTextSetEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CustomTextSetEvent{CustomTextSetEvent: *e.(*policy.CustomTextSetEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomTextRemovedEvent struct {
|
||||||
|
policy.CustomTextRemovedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextRemovedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
template,
|
||||||
|
key string,
|
||||||
|
language language.Tag,
|
||||||
|
) *CustomTextRemovedEvent {
|
||||||
|
return &CustomTextRemovedEvent{
|
||||||
|
CustomTextRemovedEvent: *policy.NewCustomTextRemovedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(ctx, aggregate, CustomTextRemovedEventType),
|
||||||
|
template,
|
||||||
|
key,
|
||||||
|
language,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e, err := policy.CustomTextRemovedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CustomTextRemovedEvent{CustomTextRemovedEvent: *e.(*policy.CustomTextRemovedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomTextTemplateRemovedEvent struct {
|
||||||
|
policy.CustomTextTemplateRemovedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextTemplateRemovedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
template string,
|
||||||
|
language language.Tag,
|
||||||
|
) *CustomTextTemplateRemovedEvent {
|
||||||
|
return &CustomTextTemplateRemovedEvent{
|
||||||
|
CustomTextTemplateRemovedEvent: *policy.NewCustomTextTemplateRemovedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(ctx, aggregate, CustomTextTemplateRemovedEventType),
|
||||||
|
template,
|
||||||
|
language,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextTemplateRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e, err := policy.CustomTextTemplateRemovedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CustomTextTemplateRemovedEvent{CustomTextTemplateRemovedEvent: *e.(*policy.CustomTextTemplateRemovedEvent)}, nil
|
||||||
|
}
|
@ -62,6 +62,9 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
|||||||
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
|
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
|
||||||
RegisterFilterEventMapper(MailTextChangedEventType, MailTextChangedEventMapper).
|
RegisterFilterEventMapper(MailTextChangedEventType, MailTextChangedEventMapper).
|
||||||
RegisterFilterEventMapper(MailTextRemovedEventType, MailTextRemovedEventMapper).
|
RegisterFilterEventMapper(MailTextRemovedEventType, MailTextRemovedEventMapper).
|
||||||
|
RegisterFilterEventMapper(CustomTextSetEventType, CustomTextSetEventMapper).
|
||||||
|
RegisterFilterEventMapper(CustomTextRemovedEventType, CustomTextRemovedEventMapper).
|
||||||
|
RegisterFilterEventMapper(CustomTextTemplateRemovedEventType, CustomTextTemplateRemovedEventMapper).
|
||||||
RegisterFilterEventMapper(IDPConfigAddedEventType, IDPConfigAddedEventMapper).
|
RegisterFilterEventMapper(IDPConfigAddedEventType, IDPConfigAddedEventMapper).
|
||||||
RegisterFilterEventMapper(IDPConfigChangedEventType, IDPConfigChangedEventMapper).
|
RegisterFilterEventMapper(IDPConfigChangedEventType, IDPConfigChangedEventMapper).
|
||||||
RegisterFilterEventMapper(IDPConfigRemovedEventType, IDPConfigRemovedEventMapper).
|
RegisterFilterEventMapper(IDPConfigRemovedEventType, IDPConfigRemovedEventMapper).
|
||||||
|
138
internal/repository/policy/custom_text.go
Normal file
138
internal/repository/policy/custom_text.go
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package policy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
customTextPrefix = "customtext."
|
||||||
|
CustomTextSetEventType = customTextPrefix + "set"
|
||||||
|
CustomTextRemovedEventType = customTextPrefix + "removed"
|
||||||
|
CustomTextTemplateRemovedEventType = customTextPrefix + "template.removed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomTextSetEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Template string `json:"template,omitempty"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Language language.Tag `json:"language,omitempty"`
|
||||||
|
Text string `json:"text,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CustomTextSetEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CustomTextSetEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextSetEvent(
|
||||||
|
base *eventstore.BaseEvent,
|
||||||
|
template,
|
||||||
|
key,
|
||||||
|
text string,
|
||||||
|
language language.Tag,
|
||||||
|
) *CustomTextSetEvent {
|
||||||
|
return &CustomTextSetEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
Template: template,
|
||||||
|
Key: key,
|
||||||
|
Language: language,
|
||||||
|
Text: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextSetEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e := &CustomTextSetEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "TEXT-28dwe", "unable to unmarshal custom text")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomTextRemovedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Template string `json:"template,omitempty"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Language language.Tag `json:"language,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CustomTextRemovedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CustomTextRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextRemovedEvent(base *eventstore.BaseEvent, template, key string, language language.Tag) *CustomTextRemovedEvent {
|
||||||
|
return &CustomTextRemovedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
Template: template,
|
||||||
|
Key: key,
|
||||||
|
Language: language,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e := &CustomTextRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "TEXT-28sMf", "unable to unmarshal custom text removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomTextTemplateRemovedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
Template string `json:"template,omitempty"`
|
||||||
|
Language language.Tag `json:"language,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CustomTextTemplateRemovedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CustomTextTemplateRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCustomTextTemplateRemovedEvent(base *eventstore.BaseEvent, template string, language language.Tag) *CustomTextTemplateRemovedEvent {
|
||||||
|
return &CustomTextTemplateRemovedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
Template: template,
|
||||||
|
Language: language,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomTextTemplateRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
|
e := &CustomTextTemplateRemovedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "TEXT-mKKRs", "unable to unmarshal custom text message removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
@ -21,6 +21,7 @@ type IAMSetUp struct {
|
|||||||
Step13 *command.Step13
|
Step13 *command.Step13
|
||||||
Step14 *command.Step14
|
Step14 *command.Step14
|
||||||
Step15 *command.Step15
|
Step15 *command.Step15
|
||||||
|
Step16 *command.Step16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (setup *IAMSetUp) Steps(currentDone domain.Step) ([]command.Step, error) {
|
func (setup *IAMSetUp) Steps(currentDone domain.Step) ([]command.Step, error) {
|
||||||
@ -42,6 +43,7 @@ func (setup *IAMSetUp) Steps(currentDone domain.Step) ([]command.Step, error) {
|
|||||||
setup.Step13,
|
setup.Step13,
|
||||||
setup.Step14,
|
setup.Step14,
|
||||||
setup.Step15,
|
setup.Step15,
|
||||||
|
setup.Step16,
|
||||||
} {
|
} {
|
||||||
if step.Step() <= currentDone {
|
if step.Step() <= currentDone {
|
||||||
continue
|
continue
|
||||||
|
@ -162,11 +162,11 @@ Errors:
|
|||||||
NotChanged: Default Mail Template wurde nicht verändert
|
NotChanged: Default Mail Template wurde nicht verändert
|
||||||
AlreadyExists: Default Mail Template existiert bereits
|
AlreadyExists: Default Mail Template existiert bereits
|
||||||
Invalid: Default Mail Template ist ungültig
|
Invalid: Default Mail Template ist ungültig
|
||||||
MailText:
|
CustomMessageText:
|
||||||
NotFound: Default Mail Text konnte nicht gefunden werden
|
NotFound: Default Message Text konnte nicht gefunden werden
|
||||||
NotChanged: Default Mail Text wurde nicht verändert
|
NotChanged: Default Message Text wurde nicht verändert
|
||||||
AlreadyExists: Default Mail Text existiert bereits
|
AlreadyExists: Default Message Text existiert bereits
|
||||||
Invalid: Default Mail Text ist ungültig
|
Invalid: Default Message Text ist ungültig
|
||||||
PasswordComplexity:
|
PasswordComplexity:
|
||||||
NotFound: Password Komplexitäts Policy konnte nicht gefunden werden
|
NotFound: Password Komplexitäts Policy konnte nicht gefunden werden
|
||||||
Empty: Passwort Komplexitäts Policy ist leer
|
Empty: Passwort Komplexitäts Policy ist leer
|
||||||
@ -276,11 +276,11 @@ Errors:
|
|||||||
NotChanged: Default Mail Template wurde nicht verändert
|
NotChanged: Default Mail Template wurde nicht verändert
|
||||||
AlreadyExists: Default Mail Template existiert bereits
|
AlreadyExists: Default Mail Template existiert bereits
|
||||||
Invalid: Default Mail Template ist ungültig
|
Invalid: Default Mail Template ist ungültig
|
||||||
MailText:
|
CustomMessageText:
|
||||||
NotFound: Default Mail Text konnte nicht gefunden werden
|
NotFound: Default Message Text konnte nicht gefunden werden
|
||||||
NotChanged: Default Mail Text wurde nicht verändert
|
NotChanged: Default Message Text wurde nicht verändert
|
||||||
AlreadyExists: Default Mail Text existiert bereits
|
AlreadyExists: Default Message Text existiert bereits
|
||||||
Invalid: Default Mail Text ist ungültig
|
Invalid: Default Message Text ist ungültig
|
||||||
PasswordComplexityPolicy:
|
PasswordComplexityPolicy:
|
||||||
NotFound: Default Password Complexity Policy konnte nicht gefunden werden
|
NotFound: Default Password Complexity Policy konnte nicht gefunden werden
|
||||||
NotExisting: Default Password Complexity Policy existiert nicht
|
NotExisting: Default Password Complexity Policy existiert nicht
|
||||||
@ -351,6 +351,10 @@ Errors:
|
|||||||
AlreadyExists: Schritt ausgeführt existiert bereits
|
AlreadyExists: Schritt ausgeführt existiert bereits
|
||||||
Features:
|
Features:
|
||||||
NotChanged: Feature hat nicht geändert
|
NotChanged: Feature hat nicht geändert
|
||||||
|
CustomText:
|
||||||
|
AlreadyExists: Kundenspezifischer Text existiert bereits
|
||||||
|
Invalid: Kundenspezifischer Text ist ungültig
|
||||||
|
NotFound: Kundenspezifischer Text nicht gefunden
|
||||||
EventTypes:
|
EventTypes:
|
||||||
user:
|
user:
|
||||||
added: Benutzer hinzugefügt
|
added: Benutzer hinzugefügt
|
||||||
@ -569,6 +573,11 @@ EventTypes:
|
|||||||
config:
|
config:
|
||||||
added: SAML IDP Konfiguration hinzugefügt
|
added: SAML IDP Konfiguration hinzugefügt
|
||||||
changed: SAML IDP Konfiguration geändert
|
changed: SAML IDP Konfiguration geändert
|
||||||
|
customtext:
|
||||||
|
set: Kundenspezifischer Text wurde gesetzt
|
||||||
|
removed: Kundenspezifischer Text wurde entfernt
|
||||||
|
template:
|
||||||
|
removed: Kundenspezifisches Text Template wurde entfernt
|
||||||
policy:
|
policy:
|
||||||
login:
|
login:
|
||||||
added: Login Richtlinie hinzugefügt
|
added: Login Richtlinie hinzugefügt
|
||||||
@ -715,6 +724,9 @@ EventTypes:
|
|||||||
config:
|
config:
|
||||||
added: SAML IDP Konfiguration hinzugefügt
|
added: SAML IDP Konfiguration hinzugefügt
|
||||||
changed: SAML IDP Konfiguration geändert
|
changed: SAML IDP Konfiguration geändert
|
||||||
|
customtext:
|
||||||
|
set: Text wurde gesetzt
|
||||||
|
removed: Text wurde entfernt
|
||||||
policy:
|
policy:
|
||||||
login:
|
login:
|
||||||
added: Default Login Policy hinzugefügt
|
added: Default Login Policy hinzugefügt
|
||||||
|
@ -162,11 +162,11 @@ Errors:
|
|||||||
NotChanged: Default Mail Template has not been changed
|
NotChanged: Default Mail Template has not been changed
|
||||||
AlreadyExists: Default Mail Template already exists
|
AlreadyExists: Default Mail Template already exists
|
||||||
Invalid: Default Mail Template is invalid
|
Invalid: Default Mail Template is invalid
|
||||||
MailText:
|
CustomMessageText:
|
||||||
NotFound: Default Mail Text not found
|
NotFound: Default Message Text not found
|
||||||
NotChanged: Default Mail Text has not been changed
|
NotChanged: Default Message Text has not been changed
|
||||||
AlreadyExists: Default Mail Text already exists
|
AlreadyExists: Default Message Text already exists
|
||||||
Invalid: Default Mail Text is invalid
|
Invalid: Default Message Text is invalid
|
||||||
PasswordComplexity:
|
PasswordComplexity:
|
||||||
NotFound: Password Complexity Policy not found
|
NotFound: Password Complexity Policy not found
|
||||||
Empty: Password Complexity Policy is empty
|
Empty: Password Complexity Policy is empty
|
||||||
@ -276,11 +276,11 @@ Errors:
|
|||||||
NotChanged: Default Mail Template has not been changed
|
NotChanged: Default Mail Template has not been changed
|
||||||
AlreadyExists: Default Mail Template already exists
|
AlreadyExists: Default Mail Template already exists
|
||||||
Invalid: Default Mail Template is invalid
|
Invalid: Default Mail Template is invalid
|
||||||
MailText:
|
CustomMessageText:
|
||||||
NotFound: Default Mail Text not found
|
NotFound: Default Message Text not found
|
||||||
NotChanged: Default Mail Text has not been changed
|
NotChanged: Default Message Text has not been changed
|
||||||
AlreadyExists: Default Mail Text already exists
|
AlreadyExists: Default Message Text already exists
|
||||||
Invalid: Default Mail Text is invalid
|
Invalid: Default Message Text is invalid
|
||||||
PasswordComplexityPolicy:
|
PasswordComplexityPolicy:
|
||||||
NotFound: Default Private Label Policy not found
|
NotFound: Default Private Label Policy not found
|
||||||
NotExisting: Default Password Complexity Policy not existing
|
NotExisting: Default Password Complexity Policy not existing
|
||||||
@ -351,6 +351,10 @@ Errors:
|
|||||||
AlreadyExists: Step done already exists
|
AlreadyExists: Step done already exists
|
||||||
Features:
|
Features:
|
||||||
NotChanged: Feature hat nicht geändert
|
NotChanged: Feature hat nicht geändert
|
||||||
|
CustomText:
|
||||||
|
AlreadyExists: Custom text already exists
|
||||||
|
Invalid: Custom text invalid
|
||||||
|
NotFound: Custom text not found
|
||||||
EventTypes:
|
EventTypes:
|
||||||
user:
|
user:
|
||||||
added: User added
|
added: User added
|
||||||
|
@ -42,7 +42,7 @@ func (l *Login) handleLoginNameCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
data := new(loginData)
|
data := new(loginData)
|
||||||
authReq, err := l.getAuthRequestAndParseData(r, data)
|
authReq, err := l.getAuthRequestAndParseData(r, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderLogin(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if data.Register {
|
if data.Register {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user