enhancement
major
minor
defect
critical
major
minor
major
#30223
Self-service mails: texts editable in the service configuration, language of an invitation selectable
Follow-up of #30041.
Context
#30041 made the mails of the self-service localized: the scripts of InvitationModule (invitation-mail, verification-mail, reset-password-mail, reset-mfa-mail, tl-security-selfservice-core.conf.config.xml) take subject and body from the static resource bundle tl-security-selfservice-core.app-messages (keys tl.security.selfservice.mail.<mail>.subject / .body). An application changes a text only by overriding the keys in its own bundle or by redefining the whole script, both in the deployed sources; an administrator cannot change them in the running application.
The mails are written in the language of the current user, or in the default language of the application when nobody is logged in. An invitation is therefore always sent in the language of the inviting administrator, and the verification mail of the invitation as well as the password and second-factor reset mails (sent before anyone is logged in) in the default language of the application - regardless of the language of the recipient.
Behavior
Mail texts in the application configuration
- Subject and body of each of the four mails are options of InvitationModule (invitation-text, verification-text, reset-password-text, reset-mfa-text; multilingual values, the body as HTML), so that they can be changed in the service editor of the running application and are stored in the application configuration.
- The shipped defaults are the previous German and English texts. The placeholders ({0} application title, {1} link or code) are described at the options.
- The mail scripts receive the configured texts unfilled as additional arguments and fill them themselves, so a script can add further information to a text. An application that redefines a script with the previous three arguments keeps working.
Language of the mails
- Inviting a person (React: Administration -> Access control -> Invitations, "Invite"; classic: "Nutzer einladen") offers a language selection: the supported languages of the application, preselected with the language of the inviting user.
- The invitation stores the selected language. The invitation mail, the verification mail and a mail sent again (invitationResend) are written in this language; so is a mail sent by the TL-Script function sendInvitation.
- The invitation lists (React and classic) show the language.
- The account created from an accepted invitation gets the language of the invitation.
- The password reset and second-factor reset mails are written in the language of the account they are sent for.
Multilingual texts in the React configuration form
- The React configuration form (service editor, <config-form>) did not display an option holding a multilingual text written in the configuration (<en>...</en><de>...</de>); a group of such texts, like the mail texts above, showed up empty. Such an option is now displayed and edited with the per-language editor, as an internationalized attribute is.
Technical notes
- MailText (tl-mail-smtp, com.top_logic.base.mail): reusable configuration of the internationalized texts of a mail, subject (ResKey) and body (ResKey, @Html). InvitationModule.Config has one per mail; the bundle tl-security-selfservice-core.app-messages is removed.
- The module calls each mail script with its previous arguments followed by subject and body (ResKey`s, unfilled). It runs the script in the language of the recipient (`SubSessionContext.withLocale), so the application title and localize() in the script - also in a redefined one - are in that language: the language of the invitation (invitationLanguage) or of the account (accountLanguage), else the default language of the application.
- InvitationModule.sendResetPasswordMail(Person, String) / sendResetMFAMail(Person, String) send the reset mails; the React and classic reset dialogs use them.
- tl.security.selfservice:Invitation#language (tl.util:Language, options: the supported languages, default: CurrentUserLanguageDefault). CurrentUserLanguageDefault (com.top_logic.model.provider) is a general default provider for a tl.util:Language attribute: the language of the current user, else the current locale if supported, else the default language of the application.
- The developer article authentication/self-service describes the options, the script arguments and the language rules.
- com.top_logic.layout.configedit: a ResKey property is COMPLEX, and ConfigEditorControl displayed a COMPLEX property only if its value has a text form; ResKey.ValueFormat writes no literal key as text. A COMPLEX property claimed by a configured control (format mapping, here I18NStringFormatProvider for ResKey$ValueFormat) is now edited in its typed form regardless of a text form: ConfigControlService.isEditedTyped / isEditedInField, used by ConfigEditorControl.isSupportedKind, ConfigControlService.checkSupportedKind and isEditedAsText. An @Encrypted property is never claimed.
Test
- TestInvitationMails (tl-security-selfservice-core): texts reach the scripts as fourth and fifth argument; invitation and verification mail in every supported language of the invitation, independent of the current locale; invitation without language in the default language; reset mails in the account language; reset for an account without address; a script with three parameters; the account gets the language of the invitation; a new invitation gets the current user's language.
- TestConfigEditorControlResKey (com.top_logic.layout.configedit): a literal ResKey is displayed top-level and in a nested item, edited typed, a change is written back as literal key; an unclaimed COMPLEX property without text form stays hidden.
- tl-demo-react and tl-demo: language field in the invite dialogs, preselected; language column in the invitation lists.
- tl-demo-react: Administration -> System -> Services -> "Servicemodul für Einladungen": the four mail texts show subject and body, can be edited per language, are stored and applied after a restart of the service.
Migration
- Existing invitations have no language and are sent in the default language of the application.
- An application that overrides the keys tl.security.selfservice.mail.* in its own bundle moves the texts to the options invitation-text, verification-text, reset-password-text, reset-mfa-text of InvitationModule (service editor or application configuration). The bundle tl-security-selfservice-core.app-messages no longer exists; a configuration referencing it drops the reference.
- An application that redefines a mail script may use the configured texts, passed as fourth and fifth argument (subject, body), unfilled.
- Code calling InvitationModule.getInvitationMail(), getVerificationMail(), getResetPasswordMail() or getResetMFAMail() (the compiled scripts) uses the operations sendInvitation, sendVerificationMail, sendResetPasswordMail or sendResetMFAMail instead.
- An application that changed the classic layouts admin/security/accounts/inviteUsers/dialog.layout.xml or existingInvitations/invitationsGrid.layout.xml in the layout editor adds the field / column language to its stored copy.