messages: custom content described in customcontent.go, message tests
customcontent.go constains a structure with all the custom content, methods for getting display names, subjects, etc., and a list of variables, conditionals, and placeholder values. Tests for constructX methods included in email_test.go, and all jfa-go tests can be run with make INTERNAL=off test.
This commit is contained in:
+84
-151
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -23,26 +22,16 @@ func (app *appContext) GetCustomContent(gc *gin.Context) {
|
||||
if _, ok := app.storage.lang.Email[lang]; !ok {
|
||||
lang = app.storage.lang.chosenEmailLang
|
||||
}
|
||||
adminLang := lang
|
||||
if _, ok := app.storage.lang.Admin[lang]; !ok {
|
||||
adminLang = app.storage.lang.chosenAdminLang
|
||||
}
|
||||
list := emailListDTO{
|
||||
"UserCreated": {Name: app.storage.lang.Email[lang].UserCreated["name"], Enabled: app.storage.MustGetCustomContentKey("UserCreated").Enabled},
|
||||
"InviteExpiry": {Name: app.storage.lang.Email[lang].InviteExpiry["name"], Enabled: app.storage.MustGetCustomContentKey("InviteExpiry").Enabled},
|
||||
"PasswordReset": {Name: app.storage.lang.Email[lang].PasswordReset["name"], Enabled: app.storage.MustGetCustomContentKey("PasswordReset").Enabled},
|
||||
"UserDeleted": {Name: app.storage.lang.Email[lang].UserDeleted["name"], Enabled: app.storage.MustGetCustomContentKey("UserDeleted").Enabled},
|
||||
"UserDisabled": {Name: app.storage.lang.Email[lang].UserDisabled["name"], Enabled: app.storage.MustGetCustomContentKey("UserDisabled").Enabled},
|
||||
"UserEnabled": {Name: app.storage.lang.Email[lang].UserEnabled["name"], Enabled: app.storage.MustGetCustomContentKey("UserEnabled").Enabled},
|
||||
"UserExpiryAdjusted": {Name: app.storage.lang.Email[lang].UserExpiryAdjusted["name"], Enabled: app.storage.MustGetCustomContentKey("UserExpiryAdjusted").Enabled},
|
||||
"InviteEmail": {Name: app.storage.lang.Email[lang].InviteEmail["name"], Enabled: app.storage.MustGetCustomContentKey("InviteEmail").Enabled},
|
||||
"WelcomeEmail": {Name: app.storage.lang.Email[lang].WelcomeEmail["name"], Enabled: app.storage.MustGetCustomContentKey("WelcomeEmail").Enabled},
|
||||
"EmailConfirmation": {Name: app.storage.lang.Email[lang].EmailConfirmation["name"], Enabled: app.storage.MustGetCustomContentKey("EmailConfirmation").Enabled},
|
||||
"UserExpired": {Name: app.storage.lang.Email[lang].UserExpired["name"], Enabled: app.storage.MustGetCustomContentKey("UserExpired").Enabled},
|
||||
"ExpiryReminder": {Name: app.storage.lang.Email[lang].ExpiryReminder["name"], Enabled: app.storage.MustGetCustomContentKey("ExpiryReminder").Enabled},
|
||||
"UserLogin": {Name: app.storage.lang.Admin[adminLang].Strings["userPageLogin"], Enabled: app.storage.MustGetCustomContentKey("UserLogin").Enabled},
|
||||
"UserPage": {Name: app.storage.lang.Admin[adminLang].Strings["userPagePage"], Enabled: app.storage.MustGetCustomContentKey("UserPage").Enabled},
|
||||
"PostSignupCard": {Name: app.storage.lang.Admin[adminLang].Strings["postSignupCard"], Enabled: app.storage.MustGetCustomContentKey("PostSignupCard").Enabled, Description: app.storage.lang.Admin[adminLang].Strings["postSignupCardDescription"]},
|
||||
list := emailListDTO{}
|
||||
for _, cc := range customContent {
|
||||
if cc.ContentType == CustomTemplate {
|
||||
continue
|
||||
}
|
||||
ccDescription := emailListEl{Name: cc.DisplayName(&app.storage.lang, lang), Enabled: app.storage.MustGetCustomContentKey(cc.Name).Enabled}
|
||||
if cc.Description != nil {
|
||||
ccDescription.Description = cc.Description(&app.storage.lang, lang)
|
||||
}
|
||||
list[cc.Name] = ccDescription
|
||||
}
|
||||
|
||||
filter := gc.Query("filter")
|
||||
@@ -74,11 +63,12 @@ func (app *appContext) SetCustomMessage(gc *gin.Context) {
|
||||
respondBool(400, false, gc)
|
||||
return
|
||||
}
|
||||
message, ok := app.storage.GetCustomContentKey(id)
|
||||
_, ok := customContent[id]
|
||||
if !ok {
|
||||
respondBool(400, false, gc)
|
||||
return
|
||||
}
|
||||
message, ok := app.storage.GetCustomContentKey(id)
|
||||
message.Content = req.Content
|
||||
message.Enabled = true
|
||||
app.storage.SetCustomContentKey(id, message)
|
||||
@@ -124,151 +114,92 @@ func (app *appContext) SetCustomMessageState(gc *gin.Context) {
|
||||
// @Security Bearer
|
||||
// @tags Configuration
|
||||
func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
|
||||
lang := app.storage.lang.chosenEmailLang
|
||||
id := gc.Param("id")
|
||||
var content string
|
||||
var err error
|
||||
var msg *Message
|
||||
var variables []string
|
||||
var conditionals []string
|
||||
var values map[string]interface{}
|
||||
username := app.storage.lang.Email[lang].Strings.get("username")
|
||||
emailAddress := app.storage.lang.Email[lang].Strings.get("emailAddress")
|
||||
customMessage, ok := app.storage.GetCustomContentKey(id)
|
||||
contentInfo, ok := customContent[id]
|
||||
// FIXME: Add announcement to customContent
|
||||
if !ok && id != "Announcement" {
|
||||
app.err.Printf(lm.FailedGetCustomMessage, id)
|
||||
respondBool(400, false, gc)
|
||||
return
|
||||
}
|
||||
if id == "WelcomeEmail" {
|
||||
conditionals = []string{"{yourAccountWillExpire}"}
|
||||
customMessage.Conditionals = conditionals
|
||||
} else if id == "UserPage" {
|
||||
variables = []string{"{username}"}
|
||||
customMessage.Variables = variables
|
||||
} else if id == "UserLogin" {
|
||||
variables = []string{}
|
||||
customMessage.Variables = variables
|
||||
} else if id == "PostSignupCard" {
|
||||
variables = []string{"{username}", "{myAccountURL}"}
|
||||
customMessage.Variables = variables
|
||||
|
||||
content, ok := app.storage.GetCustomContentKey(id)
|
||||
|
||||
if contentInfo.Variables == nil {
|
||||
contentInfo.Variables = []string{}
|
||||
}
|
||||
if contentInfo.Conditionals == nil {
|
||||
contentInfo.Conditionals = []string{}
|
||||
}
|
||||
if contentInfo.Placeholders == nil {
|
||||
contentInfo.Placeholders = map[string]any{}
|
||||
}
|
||||
|
||||
content = customMessage.Content
|
||||
noContent := content == ""
|
||||
if !noContent {
|
||||
variables = customMessage.Variables
|
||||
// Generate content from real email, if the user hasn't already customised this message.
|
||||
if content.Content == "" {
|
||||
var msg *Message
|
||||
switch id {
|
||||
// FIXME: Add announcement to customContent
|
||||
case "UserCreated":
|
||||
msg, err = app.email.constructCreated("", "", time.Time{}, Invite{}, true)
|
||||
case "InviteExpiry":
|
||||
msg, err = app.email.constructExpiry(Invite{}, true)
|
||||
case "PasswordReset":
|
||||
msg, err = app.email.constructReset(PasswordReset{}, true)
|
||||
case "UserDeleted":
|
||||
msg, err = app.email.constructDeleted("", true)
|
||||
case "UserDisabled":
|
||||
msg, err = app.email.constructDisabled("", true)
|
||||
case "UserEnabled":
|
||||
msg, err = app.email.constructEnabled("", true)
|
||||
case "UserExpiryAdjusted":
|
||||
msg, err = app.email.constructExpiryAdjusted("", time.Time{}, "", true)
|
||||
case "ExpiryReminder":
|
||||
msg, err = app.email.constructExpiryReminder("", time.Now().AddDate(0, 0, 3), true)
|
||||
case "InviteEmail":
|
||||
msg, err = app.email.constructInvite(Invite{Code: ""}, true)
|
||||
case "WelcomeEmail":
|
||||
msg, err = app.email.constructWelcome("", time.Time{}, true)
|
||||
case "EmailConfirmation":
|
||||
msg, err = app.email.constructConfirmation("", "", "", true)
|
||||
case "UserExpired":
|
||||
msg, err = app.email.constructUserExpired(true)
|
||||
case "Announcement":
|
||||
case "UserPage":
|
||||
case "UserLogin":
|
||||
case "PostSignupCard":
|
||||
// These don't have any example content
|
||||
msg = nil
|
||||
}
|
||||
if err != nil {
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
if msg != nil {
|
||||
content.Content = msg.Text
|
||||
}
|
||||
}
|
||||
switch id {
|
||||
case "Announcement":
|
||||
// Just send the email html
|
||||
content = ""
|
||||
case "UserCreated":
|
||||
if noContent {
|
||||
msg, err = app.email.constructCreated("", "", "", Invite{}, app, true)
|
||||
}
|
||||
values = app.email.createdValues("xxxxxx", username, emailAddress, Invite{}, app, false)
|
||||
case "InviteExpiry":
|
||||
if noContent {
|
||||
msg, err = app.email.constructExpiry("", Invite{}, app, true)
|
||||
}
|
||||
values = app.email.expiryValues("xxxxxx", Invite{}, app, false)
|
||||
case "PasswordReset":
|
||||
if noContent {
|
||||
msg, err = app.email.constructReset(PasswordReset{}, app, true)
|
||||
}
|
||||
values = app.email.resetValues(PasswordReset{Pin: "12-34-56", Username: username}, app, false)
|
||||
case "UserDeleted":
|
||||
if noContent {
|
||||
msg, err = app.email.constructDeleted("", app, true)
|
||||
}
|
||||
values = app.email.deletedValues(app.storage.lang.Email[lang].Strings.get("reason"), app, false)
|
||||
case "UserDisabled":
|
||||
if noContent {
|
||||
msg, err = app.email.constructDisabled("", app, true)
|
||||
}
|
||||
values = app.email.deletedValues(app.storage.lang.Email[lang].Strings.get("reason"), app, false)
|
||||
case "UserEnabled":
|
||||
if noContent {
|
||||
msg, err = app.email.constructEnabled("", app, true)
|
||||
}
|
||||
values = app.email.deletedValues(app.storage.lang.Email[lang].Strings.get("reason"), app, false)
|
||||
case "UserExpiryAdjusted":
|
||||
if noContent {
|
||||
msg, err = app.email.constructExpiryAdjusted("", time.Time{}, "", app, true)
|
||||
}
|
||||
values = app.email.expiryAdjustedValues(username, time.Time{}, app.storage.lang.Email[lang].Strings.get("reason"), app, false, true)
|
||||
case "ExpiryReminder":
|
||||
if noContent {
|
||||
msg, err = app.email.constructExpiryReminder("", time.Now().AddDate(0, 0, 3), app, true)
|
||||
}
|
||||
values = app.email.expiryReminderValues(username, time.Now().AddDate(0, 0, 3), app, false, true)
|
||||
case "InviteEmail":
|
||||
if noContent {
|
||||
msg, err = app.email.constructInvite("", Invite{}, app, true)
|
||||
}
|
||||
values = app.email.inviteValues("xxxxxx", Invite{}, app, false)
|
||||
case "WelcomeEmail":
|
||||
if noContent {
|
||||
msg, err = app.email.constructWelcome("", time.Time{}, app, true)
|
||||
}
|
||||
values = app.email.welcomeValues(username, time.Now(), app, false, true)
|
||||
case "EmailConfirmation":
|
||||
if noContent {
|
||||
msg, err = app.email.constructConfirmation("", "", "", app, true)
|
||||
}
|
||||
values = app.email.confirmationValues("xxxxxx", username, "xxxxxx", app, false)
|
||||
case "UserExpired":
|
||||
if noContent {
|
||||
msg, err = app.email.constructUserExpired(app, true)
|
||||
}
|
||||
values = app.email.userExpiredValues(app, false)
|
||||
case "UserLogin", "UserPage", "PostSignupCard":
|
||||
values = map[string]interface{}{}
|
||||
}
|
||||
if err != nil {
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
if noContent && id != "Announcement" && id != "UserPage" && id != "UserLogin" && id != "PostSignupCard" {
|
||||
content = msg.Text
|
||||
variables = make([]string, strings.Count(content, "{"))
|
||||
i := 0
|
||||
found := false
|
||||
buf := ""
|
||||
for _, c := range content {
|
||||
if !found && c != '{' && c != '}' {
|
||||
continue
|
||||
}
|
||||
found = true
|
||||
buf += string(c)
|
||||
if c == '}' {
|
||||
found = false
|
||||
variables[i] = buf
|
||||
buf = ""
|
||||
i++
|
||||
}
|
||||
}
|
||||
customMessage.Variables = variables
|
||||
}
|
||||
if variables == nil {
|
||||
variables = []string{}
|
||||
}
|
||||
app.storage.SetCustomContentKey(id, customMessage)
|
||||
|
||||
var mail *Message
|
||||
if id != "UserLogin" && id != "UserPage" && id != "PostSignupCard" {
|
||||
mail, err = app.email.constructTemplate("", "<div class=\"preview-content\"></div>", app)
|
||||
if contentInfo.ContentType == CustomMessage {
|
||||
mail = &Message{}
|
||||
err = app.email.construct(EmptyCustomContent, CustomContent{
|
||||
Name: EmptyCustomContent.Name,
|
||||
Enabled: true,
|
||||
Content: "<div class=\"preview-content\"></div>",
|
||||
}, map[string]any{}, mail)
|
||||
if err != nil {
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
} else if id == "PostSignupCard" {
|
||||
// Jankiness follows.
|
||||
// Specific workaround for the currently-unique "Post signup card".
|
||||
// Source content from "Success Message" setting.
|
||||
if noContent {
|
||||
content = "# " + app.storage.lang.User[app.storage.lang.chosenUserLang].Strings.get("successHeader") + "\n" + app.config.Section("ui").Key("success_message").String()
|
||||
if content.Content == "" {
|
||||
content.Content = "# " + app.storage.lang.User[app.storage.lang.chosenUserLang].Strings.get("successHeader") + "\n" + app.config.Section("ui").Key("success_message").String()
|
||||
if app.config.Section("user_page").Key("enabled").MustBool(false) {
|
||||
content += "\n\n<br>\n" + app.storage.lang.User[app.storage.lang.chosenUserLang].Strings.template("userPageSuccessMessage", tmpl{
|
||||
content.Content += "\n\n<br>\n" + app.storage.lang.User[app.storage.lang.chosenUserLang].Strings.template("userPageSuccessMessage", tmpl{
|
||||
"myAccount": "[" + app.storage.lang.User[app.storage.lang.chosenUserLang].Strings.get("myAccount") + "]({myAccountURL})",
|
||||
})
|
||||
}
|
||||
@@ -277,13 +208,15 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
|
||||
HTML: "<div class=\"card ~neutral dark:~d_neutral @low\"><div class=\"preview-content\"></div><br><button class=\"button ~urge dark:~d_urge @low full-width center supra submit\">" + app.storage.lang.User[app.storage.lang.chosenUserLang].Strings.get("continue") + "</a></div>",
|
||||
}
|
||||
mail.Markdown = mail.HTML
|
||||
} else {
|
||||
} else if contentInfo.ContentType == CustomCard {
|
||||
mail = &Message{
|
||||
HTML: "<div class=\"card ~neutral dark:~d_neutral @low preview-content\"></div>",
|
||||
}
|
||||
mail.Markdown = mail.HTML
|
||||
} else {
|
||||
app.err.Printf("unknown custom content type %d", contentInfo.ContentType)
|
||||
}
|
||||
gc.JSON(200, customEmailDTO{Content: content, Variables: variables, Conditionals: conditionals, Values: values, HTML: mail.HTML, Plaintext: mail.Text})
|
||||
gc.JSON(200, customEmailDTO{Content: content.Content, Variables: contentInfo.Variables, Conditionals: contentInfo.Conditionals, Values: contentInfo.Placeholders, HTML: mail.HTML, Plaintext: mail.Text})
|
||||
}
|
||||
|
||||
// @Summary Returns a new Telegram verification PIN, and the bot username.
|
||||
|
||||
Reference in New Issue
Block a user