mirror of
https://github.com/hrfee/jfa-go.git
synced 2026-01-18 16:47:42 +01:00
emails: fix and confirm function of all emails
both custom and standard emails tested, quite a few fixes made, including to an old bug with admin notifs.
This commit is contained in:
@@ -124,7 +124,7 @@ func (app *appContext) deleteExpiredInvite(data Invite) {
|
|||||||
|
|
||||||
func (app *appContext) sendAdminExpiryNotification(data Invite) *sync.WaitGroup {
|
func (app *appContext) sendAdminExpiryNotification(data Invite) *sync.WaitGroup {
|
||||||
notify := data.Notify
|
notify := data.Notify
|
||||||
if !emailEnabled || !app.config.Section("notifications").Key("enabled").MustBool(false) || len(notify) != 0 {
|
if !emailEnabled || !app.config.Section("notifications").Key("enabled").MustBool(false) || len(notify) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var wait sync.WaitGroup
|
var wait sync.WaitGroup
|
||||||
@@ -283,7 +283,7 @@ func (app *appContext) GetInviteCount(gc *gin.Context) {
|
|||||||
// @Summary Get the number of invites stored in the database that have been used (but are still valid).
|
// @Summary Get the number of invites stored in the database that have been used (but are still valid).
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} PageCountDTO
|
// @Success 200 {object} PageCountDTO
|
||||||
// @Router /invites/count [get]
|
// @Router /invites/count/used [get]
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @tags Invites
|
// @tags Invites
|
||||||
func (app *appContext) GetInviteUsedCount(gc *gin.Context) {
|
func (app *appContext) GetInviteUsedCount(gc *gin.Context) {
|
||||||
|
|||||||
@@ -148,11 +148,11 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
|
|||||||
case "PasswordReset":
|
case "PasswordReset":
|
||||||
msg, err = app.email.constructReset(PasswordReset{}, true)
|
msg, err = app.email.constructReset(PasswordReset{}, true)
|
||||||
case "UserDeleted":
|
case "UserDeleted":
|
||||||
msg, err = app.email.constructDeleted("", true)
|
msg, err = app.email.constructDeleted("", "", true)
|
||||||
case "UserDisabled":
|
case "UserDisabled":
|
||||||
msg, err = app.email.constructDisabled("", true)
|
msg, err = app.email.constructDisabled("", "", true)
|
||||||
case "UserEnabled":
|
case "UserEnabled":
|
||||||
msg, err = app.email.constructEnabled("", true)
|
msg, err = app.email.constructEnabled("", "", true)
|
||||||
case "UserExpiryAdjusted":
|
case "UserExpiryAdjusted":
|
||||||
msg, err = app.email.constructExpiryAdjusted("", time.Time{}, "", true)
|
msg, err = app.email.constructExpiryAdjusted("", time.Time{}, "", true)
|
||||||
case "ExpiryReminder":
|
case "ExpiryReminder":
|
||||||
@@ -164,7 +164,7 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
|
|||||||
case "EmailConfirmation":
|
case "EmailConfirmation":
|
||||||
msg, err = app.email.constructConfirmation("", "", "", true)
|
msg, err = app.email.constructConfirmation("", "", "", true)
|
||||||
case "UserExpired":
|
case "UserExpired":
|
||||||
msg, err = app.email.constructUserExpired(true)
|
msg, err = app.email.constructUserExpired("", true)
|
||||||
case "Announcement":
|
case "Announcement":
|
||||||
case "UserPage":
|
case "UserPage":
|
||||||
case "UserLogin":
|
case "UserLogin":
|
||||||
@@ -181,14 +181,13 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mail *Message
|
var mail *Message = nil
|
||||||
if contentInfo.ContentType == CustomMessage {
|
if contentInfo.ContentType == CustomMessage {
|
||||||
mail = &Message{}
|
mail, err = app.email.construct(EmptyCustomContent, CustomContent{
|
||||||
err = app.email.construct(EmptyCustomContent, CustomContent{
|
|
||||||
Name: EmptyCustomContent.Name,
|
Name: EmptyCustomContent.Name,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Content: "<div class=\"preview-content\"></div>",
|
Content: "<div class=\"preview-content\"></div>",
|
||||||
}, map[string]any{}, mail)
|
}, map[string]any{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondBool(500, false, gc)
|
respondBool(500, false, gc)
|
||||||
return
|
return
|
||||||
|
|||||||
53
api-users.go
53
api-users.go
@@ -380,19 +380,6 @@ func (app *appContext) EnableDisableUsers(gc *gin.Context) {
|
|||||||
"SetPolicy": map[string]string{},
|
"SetPolicy": map[string]string{},
|
||||||
}
|
}
|
||||||
sendMail := messagesEnabled
|
sendMail := messagesEnabled
|
||||||
var msg *Message
|
|
||||||
var err error
|
|
||||||
if sendMail {
|
|
||||||
if req.Enabled {
|
|
||||||
msg, err = app.email.constructEnabled(req.Reason, false)
|
|
||||||
} else {
|
|
||||||
msg, err = app.email.constructDisabled(req.Reason, false)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
app.err.Printf(lm.FailedConstructEnableDisableMessage, "?", err)
|
|
||||||
sendMail = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
activityType := ActivityDisabled
|
activityType := ActivityDisabled
|
||||||
if req.Enabled {
|
if req.Enabled {
|
||||||
activityType = ActivityEnabled
|
activityType = ActivityEnabled
|
||||||
@@ -404,6 +391,18 @@ func (app *appContext) EnableDisableUsers(gc *gin.Context) {
|
|||||||
app.err.Printf(lm.FailedGetUser, user.ID, lm.Jellyfin, err)
|
app.err.Printf(lm.FailedGetUser, user.ID, lm.Jellyfin, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
var msg *Message
|
||||||
|
if sendMail {
|
||||||
|
if req.Enabled {
|
||||||
|
msg, err = app.email.constructEnabled(user.Name, req.Reason, false)
|
||||||
|
} else {
|
||||||
|
msg, err = app.email.constructDisabled(user.Name, req.Reason, false)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf(lm.FailedConstructEnableDisableMessage, "?", err)
|
||||||
|
sendMail = false
|
||||||
|
}
|
||||||
|
}
|
||||||
err, _, _ = app.SetUserDisabled(user, !req.Enabled)
|
err, _, _ = app.SetUserDisabled(user, !req.Enabled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors["SetPolicy"][user.ID] = err.Error()
|
errors["SetPolicy"][user.ID] = err.Error()
|
||||||
@@ -449,15 +448,6 @@ func (app *appContext) DeleteUsers(gc *gin.Context) {
|
|||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
errors := map[string]string{}
|
errors := map[string]string{}
|
||||||
sendMail := messagesEnabled
|
sendMail := messagesEnabled
|
||||||
var msg *Message
|
|
||||||
var err error
|
|
||||||
if sendMail {
|
|
||||||
msg, err = app.email.constructDeleted(req.Reason, false)
|
|
||||||
if err != nil {
|
|
||||||
app.err.Printf(lm.FailedConstructDeletionMessage, "?", err)
|
|
||||||
sendMail = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, userID := range req.Users {
|
for _, userID := range req.Users {
|
||||||
user, err := app.jf.UserByID(userID, false)
|
user, err := app.jf.UserByID(userID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -465,6 +455,15 @@ func (app *appContext) DeleteUsers(gc *gin.Context) {
|
|||||||
errors[userID] = err.Error()
|
errors[userID] = err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var msg *Message = nil
|
||||||
|
if sendMail {
|
||||||
|
msg, err = app.email.constructDeleted(user.Name, req.Reason, false)
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf(lm.FailedConstructDeletionMessage, "?", err)
|
||||||
|
sendMail = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deleted := false
|
deleted := false
|
||||||
err, deleted = app.DeleteUser(user)
|
err, deleted = app.DeleteUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -677,11 +676,10 @@ func (app *appContext) Announce(gc *gin.Context) {
|
|||||||
app.err.Printf(lm.FailedGetUser, userID, lm.Jellyfin, err)
|
app.err.Printf(lm.FailedGetUser, userID, lm.Jellyfin, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
msg := &Message{}
|
msg, err := app.email.construct(AnnouncementCustomContent(req.Subject), CustomContent{
|
||||||
err = app.email.construct(AnnouncementCustomContent(req.Subject), CustomContent{
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Content: req.Message,
|
Content: req.Message,
|
||||||
}, map[string]any{"username": user.Name}, msg)
|
}, map[string]any{"username": user.Name})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.err.Printf(lm.FailedConstructAnnouncementMessage, userID, err)
|
app.err.Printf(lm.FailedConstructAnnouncementMessage, userID, err)
|
||||||
respondBool(500, false, gc)
|
respondBool(500, false, gc)
|
||||||
@@ -694,11 +692,10 @@ func (app *appContext) Announce(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
// app.info.Printf(lm.SentAnnouncementMessage, "*", "?")
|
// app.info.Printf(lm.SentAnnouncementMessage, "*", "?")
|
||||||
} else {
|
} else {
|
||||||
msg := &Message{}
|
msg, err := app.email.construct(AnnouncementCustomContent(req.Subject), CustomContent{
|
||||||
err := app.email.construct(AnnouncementCustomContent(req.Subject), CustomContent{
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Content: req.Message,
|
Content: req.Message,
|
||||||
}, map[string]any{"username": ""}, msg)
|
}, map[string]any{"username": ""})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.err.Printf(lm.FailedConstructAnnouncementMessage, "*", err)
|
app.err.Printf(lm.FailedConstructAnnouncementMessage, "*", err)
|
||||||
respondBool(500, false, gc)
|
respondBool(500, false, gc)
|
||||||
|
|||||||
4
args.go
4
args.go
@@ -31,6 +31,7 @@ func (app *appContext) loadArgs(firstCall bool) {
|
|||||||
SWAGGER = flag.Bool("swagger", false, "Enable swagger at /swagger/index.html")
|
SWAGGER = flag.Bool("swagger", false, "Enable swagger at /swagger/index.html")
|
||||||
|
|
||||||
flag.BoolVar(&NO_API_AUTH_DO_NOT_USE, "disable-api-auth-do-not-use", false, "Disables API authentication. DO NOT USE!")
|
flag.BoolVar(&NO_API_AUTH_DO_NOT_USE, "disable-api-auth-do-not-use", false, "Disables API authentication. DO NOT USE!")
|
||||||
|
flag.StringVar(&NO_API_AUTH_FORCE_JFID, "disable-api-auth-force-jf-id", "", "Assume given JFID when API auth is disabled.")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *help {
|
if *help {
|
||||||
@@ -52,11 +53,14 @@ func (app *appContext) loadArgs(firstCall bool) {
|
|||||||
|
|
||||||
if NO_API_AUTH_DO_NOT_USE && *DEBUG {
|
if NO_API_AUTH_DO_NOT_USE && *DEBUG {
|
||||||
NO_API_AUTH_DO_NOT_USE = false
|
NO_API_AUTH_DO_NOT_USE = false
|
||||||
|
forceJfID := NO_API_AUTH_FORCE_JFID
|
||||||
|
NO_API_AUTH_FORCE_JFID = ""
|
||||||
buf := bufio.NewReader(os.Stdin)
|
buf := bufio.NewReader(os.Stdin)
|
||||||
app.err.Print(lm.NoAPIAuthPrompt)
|
app.err.Print(lm.NoAPIAuthPrompt)
|
||||||
sentence, err := buf.ReadBytes('\n')
|
sentence, err := buf.ReadBytes('\n')
|
||||||
if err == nil && strings.ContainsRune(string(sentence), 'y') {
|
if err == nil && strings.ContainsRune(string(sentence), 'y') {
|
||||||
NO_API_AUTH_DO_NOT_USE = true
|
NO_API_AUTH_DO_NOT_USE = true
|
||||||
|
NO_API_AUTH_FORCE_JFID = forceJfID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
auth.go
13
auth.go
@@ -40,7 +40,11 @@ func (app *appContext) logIpErr(gc *gin.Context, user bool, out string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) webAuth() gin.HandlerFunc {
|
func (app *appContext) webAuth() gin.HandlerFunc {
|
||||||
return app.authenticate
|
if NO_API_AUTH_DO_NOT_USE {
|
||||||
|
return app.bogusAuthenticate
|
||||||
|
} else {
|
||||||
|
return app.authenticate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) authLog(v any) { app.debug.PrintfCustomLevel(4, lm.FailedAuthRequest, v) }
|
func (app *appContext) authLog(v any) { app.debug.PrintfCustomLevel(4, lm.FailedAuthRequest, v) }
|
||||||
@@ -138,6 +142,13 @@ func (app *appContext) authenticate(gc *gin.Context) {
|
|||||||
gc.Next()
|
gc.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bogusAuthenticate is for use with NO_API_AUTH_DO_NOT_USE, it sets the jfId/userId value from NO_API_AUTH_FORCE_JF_ID.
|
||||||
|
func (app *appContext) bogusAuthenticate(gc *gin.Context) {
|
||||||
|
gc.Set("jfId", NO_API_AUTH_FORCE_JFID)
|
||||||
|
gc.Set("userId", NO_API_AUTH_FORCE_JFID)
|
||||||
|
gc.Next()
|
||||||
|
}
|
||||||
|
|
||||||
func checkToken(token *jwt.Token) (interface{}, error) {
|
func checkToken(token *jwt.Token) (interface{}, error) {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
return nil, fmt.Errorf("Unexpected signing method %v", token.Header["alg"])
|
return nil, fmt.Errorf("Unexpected signing method %v", token.Header["alg"])
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ var customContent = map[string]CustomContentInfo{
|
|||||||
"reason",
|
"reason",
|
||||||
),
|
),
|
||||||
Placeholders: defaultVals(map[string]any{
|
Placeholders: defaultVals(map[string]any{
|
||||||
"newExpiry": "",
|
"newExpiry": "01/01/01 00:00",
|
||||||
"reason": "Reason",
|
"reason": "Reason",
|
||||||
}),
|
}),
|
||||||
SourceFile: ContentSourceFileInfo{
|
SourceFile: ContentSourceFileInfo{
|
||||||
|
|||||||
99
email.go
99
email.go
@@ -246,14 +246,21 @@ type templ interface {
|
|||||||
Execute(wr io.Writer, data interface{}) error
|
Execute(wr io.Writer, data interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) construct(contentInfo CustomContentInfo, cc CustomContent, data map[string]any, msg *Message) error {
|
func (emailer *Emailer) construct(contentInfo CustomContentInfo, cc CustomContent, data map[string]any) (*Message, error) {
|
||||||
|
msg := &Message{
|
||||||
|
Subject: contentInfo.Subject(emailer.config, &emailer.lang),
|
||||||
|
}
|
||||||
|
// Template the subject for bonus points
|
||||||
|
if subject, err := templateEmail(msg.Subject, contentInfo.Variables, contentInfo.Conditionals, data); err == nil {
|
||||||
|
msg.Subject = subject
|
||||||
|
}
|
||||||
if cc.Enabled {
|
if cc.Enabled {
|
||||||
// Use template email, rather than the built-in's email file.
|
// Use template email, rather than the built-in's email file.
|
||||||
contentInfo.SourceFile = customContent["TemplateEmail"].SourceFile
|
contentInfo.SourceFile = customContent["TemplateEmail"].SourceFile
|
||||||
content, err := templateEmail(cc.Content, contentInfo.Variables, contentInfo.Conditionals, data)
|
content, err := templateEmail(cc.Content, contentInfo.Variables, contentInfo.Conditionals, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
emailer.err.Printf(lm.FailedConstructCustomContent, msg.Subject, err)
|
emailer.err.Printf(lm.FailedConstructCustomContent, msg.Subject, err)
|
||||||
return err
|
return msg, err
|
||||||
}
|
}
|
||||||
html := markdown.ToHTML([]byte(content), nil, markdownRenderer)
|
html := markdown.ToHTML([]byte(content), nil, markdownRenderer)
|
||||||
text := stripMarkdown(content)
|
text := stripMarkdown(content)
|
||||||
@@ -268,10 +275,6 @@ func (emailer *Emailer) construct(contentInfo CustomContentInfo, cc CustomConten
|
|||||||
data = templateData
|
data = templateData
|
||||||
}
|
}
|
||||||
var err error = nil
|
var err error = nil
|
||||||
// Template the subject for bonus points
|
|
||||||
if subject, err := templateEmail(msg.Subject, contentInfo.Variables, contentInfo.Conditionals, data); err == nil {
|
|
||||||
msg.Subject = subject
|
|
||||||
}
|
|
||||||
|
|
||||||
var tpl templ
|
var tpl templ
|
||||||
msg.Text = ""
|
msg.Text = ""
|
||||||
@@ -313,7 +316,7 @@ func (emailer *Emailer) construct(contentInfo CustomContentInfo, cc CustomConten
|
|||||||
tpl, err = textTemplate.ParseFS(filesystem, fpath)
|
tpl, err = textTemplate.ParseFS(filesystem, fpath)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading from fs path \"%s\": %v", fpath, err)
|
return msg, fmt.Errorf("error reading from fs path \"%s\": %v", fpath, err)
|
||||||
}
|
}
|
||||||
// For constructTemplate, if "md" is found in data it's used in stead of "text".
|
// For constructTemplate, if "md" is found in data it's used in stead of "text".
|
||||||
foundMarkdown := false
|
foundMarkdown := false
|
||||||
@@ -326,7 +329,7 @@ func (emailer *Emailer) construct(contentInfo CustomContentInfo, cc CustomConten
|
|||||||
var tplData bytes.Buffer
|
var tplData bytes.Buffer
|
||||||
err = tpl.Execute(&tplData, data)
|
err = tpl.Execute(&tplData, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return msg, err
|
||||||
}
|
}
|
||||||
if foundMarkdown {
|
if foundMarkdown {
|
||||||
data["plaintext"], data["md"] = data["md"], data["plaintext"]
|
data["plaintext"], data["md"] = data["md"], data["plaintext"]
|
||||||
@@ -339,10 +342,10 @@ func (emailer *Emailer) construct(contentInfo CustomContentInfo, cc CustomConten
|
|||||||
msg.Markdown = tplData.String()
|
msg.Markdown = tplData.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) baseValues(name string, username string, placeholders bool, values map[string]any) (CustomContentInfo, map[string]any, *Message) {
|
func (emailer *Emailer) baseValues(name string, username string, placeholders bool, values map[string]any) (CustomContentInfo, map[string]any) {
|
||||||
contentInfo := customContent[name]
|
contentInfo := customContent[name]
|
||||||
template := map[string]any{
|
template := map[string]any{
|
||||||
"username": username,
|
"username": username,
|
||||||
@@ -355,17 +358,14 @@ func (emailer *Emailer) baseValues(name string, username string, placeholders bo
|
|||||||
template[v] = "{" + v + "}"
|
template[v] = "{" + v + "}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
email := &Message{
|
return contentInfo, template
|
||||||
Subject: contentInfo.Subject(emailer.config, &emailer.lang),
|
|
||||||
}
|
|
||||||
return contentInfo, template, email
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructConfirmation(code, username, key string, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructConfirmation(code, username, key string, placeholders bool) (*Message, error) {
|
||||||
if placeholders {
|
if placeholders {
|
||||||
username = "{username}"
|
username = "{username}"
|
||||||
}
|
}
|
||||||
contentInfo, template, msg := emailer.baseValues("EmailConfirmation", username, placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("EmailConfirmation", username, placeholders, map[string]any{
|
||||||
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": username}),
|
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": username}),
|
||||||
"clickBelow": emailer.lang.EmailConfirmation.get("clickBelow"),
|
"clickBelow": emailer.lang.EmailConfirmation.get("clickBelow"),
|
||||||
"ifItWasNotYou": emailer.lang.Strings.get("ifItWasNotYou"),
|
"ifItWasNotYou": emailer.lang.Strings.get("ifItWasNotYou"),
|
||||||
@@ -381,15 +381,14 @@ func (emailer *Emailer) constructConfirmation(code, username, key string, placeh
|
|||||||
template["confirmationURL"] = inviteLink
|
template["confirmationURL"] = inviteLink
|
||||||
}
|
}
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructInvite(invite Invite, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructInvite(invite Invite, placeholders bool) (*Message, error) {
|
||||||
expiry := invite.ValidTill
|
expiry := invite.ValidTill
|
||||||
d, t, expiresIn := emailer.formatExpiry(expiry, false)
|
d, t, expiresIn := emailer.formatExpiry(expiry, false)
|
||||||
inviteLink := fmt.Sprintf("%s%s/%s", ExternalURI(nil), PAGES.Form, invite.Code)
|
inviteLink := fmt.Sprintf("%s%s/%s", ExternalURI(nil), PAGES.Form, invite.Code)
|
||||||
contentInfo, template, msg := emailer.baseValues("InviteEmail", "", placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("InviteEmail", "", placeholders, map[string]any{
|
||||||
"hello": emailer.lang.InviteEmail.get("hello"),
|
"hello": emailer.lang.InviteEmail.get("hello"),
|
||||||
"youHaveBeenInvited": emailer.lang.InviteEmail.get("youHaveBeenInvited"),
|
"youHaveBeenInvited": emailer.lang.InviteEmail.get("youHaveBeenInvited"),
|
||||||
"toJoin": emailer.lang.InviteEmail.get("toJoin"),
|
"toJoin": emailer.lang.InviteEmail.get("toJoin"),
|
||||||
@@ -404,13 +403,12 @@ func (emailer *Emailer) constructInvite(invite Invite, placeholders bool) (*Mess
|
|||||||
template["inviteExpiry"] = emailer.lang.InviteEmail.template("inviteExpiry", template)
|
template["inviteExpiry"] = emailer.lang.InviteEmail.template("inviteExpiry", template)
|
||||||
}
|
}
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructExpiry(invite Invite, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructExpiry(invite Invite, placeholders bool) (*Message, error) {
|
||||||
expiry := formatDatetime(invite.ValidTill)
|
expiry := formatDatetime(invite.ValidTill)
|
||||||
contentInfo, template, msg := emailer.baseValues("InviteExpiry", "", placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("InviteExpiry", "", placeholders, map[string]any{
|
||||||
"inviteExpired": emailer.lang.InviteExpiry.get("inviteExpired"),
|
"inviteExpired": emailer.lang.InviteExpiry.get("inviteExpired"),
|
||||||
"notificationNotice": emailer.lang.InviteExpiry.get("notificationNotice"),
|
"notificationNotice": emailer.lang.InviteExpiry.get("notificationNotice"),
|
||||||
"expiredAt": emailer.lang.InviteExpiry.get("expiredAt"),
|
"expiredAt": emailer.lang.InviteExpiry.get("expiredAt"),
|
||||||
@@ -421,14 +419,13 @@ func (emailer *Emailer) constructExpiry(invite Invite, placeholders bool) (*Mess
|
|||||||
template["expiredAt"] = emailer.lang.InviteExpiry.template("expiredAt", template)
|
template["expiredAt"] = emailer.lang.InviteExpiry.template("expiredAt", template)
|
||||||
}
|
}
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructCreated(username, address string, when time.Time, invite Invite, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructCreated(username, address string, when time.Time, invite Invite, placeholders bool) (*Message, error) {
|
||||||
// NOTE: This was previously invite.Created, not sure why.
|
// NOTE: This was previously invite.Created, not sure why.
|
||||||
created := formatDatetime(when)
|
created := formatDatetime(when)
|
||||||
contentInfo, template, msg := emailer.baseValues("UserCreated", username, placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("UserCreated", username, placeholders, map[string]any{
|
||||||
"aUserWasCreated": emailer.lang.UserCreated.get("aUserWasCreated"),
|
"aUserWasCreated": emailer.lang.UserCreated.get("aUserWasCreated"),
|
||||||
"nameString": emailer.lang.Strings.get("name"),
|
"nameString": emailer.lang.Strings.get("name"),
|
||||||
"addressString": emailer.lang.Strings.get("emailAddress"),
|
"addressString": emailer.lang.Strings.get("emailAddress"),
|
||||||
@@ -446,8 +443,7 @@ func (emailer *Emailer) constructCreated(username, address string, when time.Tim
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructReset(pwr PasswordReset, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructReset(pwr PasswordReset, placeholders bool) (*Message, error) {
|
||||||
@@ -456,7 +452,7 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, placeholders bool) (*M
|
|||||||
}
|
}
|
||||||
d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true)
|
d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true)
|
||||||
linkResetEnabled := emailer.config.Section("password_resets").Key("link_reset").MustBool(false)
|
linkResetEnabled := emailer.config.Section("password_resets").Key("link_reset").MustBool(false)
|
||||||
contentInfo, template, msg := emailer.baseValues("PasswordReset", pwr.Username, placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("PasswordReset", pwr.Username, placeholders, map[string]any{
|
||||||
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": pwr.Username}),
|
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": pwr.Username}),
|
||||||
"someoneHasRequestedReset": emailer.lang.PasswordReset.get("someoneHasRequestedReset"),
|
"someoneHasRequestedReset": emailer.lang.PasswordReset.get("someoneHasRequestedReset"),
|
||||||
"ifItWasYou": emailer.lang.PasswordReset.get("ifItWasYou"),
|
"ifItWasYou": emailer.lang.PasswordReset.get("ifItWasYou"),
|
||||||
@@ -487,50 +483,49 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, placeholders bool) (*M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructDeleted(reason string, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructDeleted(username, reason string, placeholders bool) (*Message, error) {
|
||||||
if placeholders {
|
if placeholders {
|
||||||
|
username = "{username}"
|
||||||
reason = "{reason}"
|
reason = "{reason}"
|
||||||
}
|
}
|
||||||
contentInfo, template, msg := emailer.baseValues("UserDeleted", "", placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("UserDeleted", username, placeholders, map[string]any{
|
||||||
"yourAccountWas": emailer.lang.UserDeleted.get("yourAccountWasDeleted"),
|
"yourAccountWas": emailer.lang.UserDeleted.get("yourAccountWasDeleted"),
|
||||||
"reasonString": emailer.lang.Strings.get("reason"),
|
"reasonString": emailer.lang.Strings.get("reason"),
|
||||||
"reason": reason,
|
"reason": reason,
|
||||||
})
|
})
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructDisabled(reason string, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructDisabled(username, reason string, placeholders bool) (*Message, error) {
|
||||||
if placeholders {
|
if placeholders {
|
||||||
|
username = "{username}"
|
||||||
reason = "{reason}"
|
reason = "{reason}"
|
||||||
}
|
}
|
||||||
contentInfo, template, msg := emailer.baseValues("UserDeleted", "", placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("UserDisabled", username, placeholders, map[string]any{
|
||||||
"yourAccountWas": emailer.lang.UserDisabled.get("yourAccountWasDisabled"),
|
"yourAccountWas": emailer.lang.UserDisabled.get("yourAccountWasDisabled"),
|
||||||
"reasonString": emailer.lang.Strings.get("reason"),
|
"reasonString": emailer.lang.Strings.get("reason"),
|
||||||
"reason": reason,
|
"reason": reason,
|
||||||
})
|
})
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructEnabled(reason string, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructEnabled(username, reason string, placeholders bool) (*Message, error) {
|
||||||
if placeholders {
|
if placeholders {
|
||||||
|
username = "{username}"
|
||||||
reason = "{reason}"
|
reason = "{reason}"
|
||||||
}
|
}
|
||||||
contentInfo, template, msg := emailer.baseValues("UserDeleted", "", placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("UserEnabled", username, placeholders, map[string]any{
|
||||||
"yourAccountWas": emailer.lang.UserEnabled.get("yourAccountWasEnabled"),
|
"yourAccountWas": emailer.lang.UserEnabled.get("yourAccountWasEnabled"),
|
||||||
"reasonString": emailer.lang.Strings.get("reason"),
|
"reasonString": emailer.lang.Strings.get("reason"),
|
||||||
"reason": reason,
|
"reason": reason,
|
||||||
})
|
})
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructExpiryAdjusted(username string, expiry time.Time, reason string, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructExpiryAdjusted(username string, expiry time.Time, reason string, placeholders bool) (*Message, error) {
|
||||||
@@ -538,7 +533,7 @@ func (emailer *Emailer) constructExpiryAdjusted(username string, expiry time.Tim
|
|||||||
username = "{username}"
|
username = "{username}"
|
||||||
}
|
}
|
||||||
exp := formatDatetime(expiry)
|
exp := formatDatetime(expiry)
|
||||||
contentInfo, template, msg := emailer.baseValues("UserExpiryAdjusted", username, placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("UserExpiryAdjusted", username, placeholders, map[string]any{
|
||||||
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": username}),
|
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": username}),
|
||||||
"yourExpiryWasAdjusted": emailer.lang.UserExpiryAdjusted.get("yourExpiryWasAdjusted"),
|
"yourExpiryWasAdjusted": emailer.lang.UserExpiryAdjusted.get("yourExpiryWasAdjusted"),
|
||||||
"ifPreviouslyDisabled": emailer.lang.UserExpiryAdjusted.get("ifPreviouslyDisabled"),
|
"ifPreviouslyDisabled": emailer.lang.UserExpiryAdjusted.get("ifPreviouslyDisabled"),
|
||||||
@@ -554,8 +549,7 @@ func (emailer *Emailer) constructExpiryAdjusted(username string, expiry time.Tim
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructExpiryReminder(username string, expiry time.Time, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructExpiryReminder(username string, expiry time.Time, placeholders bool) (*Message, error) {
|
||||||
@@ -563,7 +557,7 @@ func (emailer *Emailer) constructExpiryReminder(username string, expiry time.Tim
|
|||||||
username = "{username}"
|
username = "{username}"
|
||||||
}
|
}
|
||||||
d, t, expiresIn := emailer.formatExpiry(expiry, false)
|
d, t, expiresIn := emailer.formatExpiry(expiry, false)
|
||||||
contentInfo, template, msg := emailer.baseValues("ExpiryReminder", username, placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("ExpiryReminder", username, placeholders, map[string]any{
|
||||||
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": username}),
|
"helloUser": emailer.lang.Strings.template("helloUser", tmpl{"username": username}),
|
||||||
"yourAccountIsDueToExpire": emailer.lang.ExpiryReminder.get("yourAccountIsDueToExpire"),
|
"yourAccountIsDueToExpire": emailer.lang.ExpiryReminder.get("yourAccountIsDueToExpire"),
|
||||||
"expiresIn": expiresIn,
|
"expiresIn": expiresIn,
|
||||||
@@ -576,8 +570,7 @@ func (emailer *Emailer) constructExpiryReminder(username string, expiry time.Tim
|
|||||||
template["yourAccountIsDueToExpire"] = emailer.lang.ExpiryReminder.template("yourAccountIsDueToExpire", template)
|
template["yourAccountIsDueToExpire"] = emailer.lang.ExpiryReminder.template("yourAccountIsDueToExpire", template)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructWelcome(username string, expiry time.Time, placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructWelcome(username string, expiry time.Time, placeholders bool) (*Message, error) {
|
||||||
@@ -586,7 +579,7 @@ func (emailer *Emailer) constructWelcome(username string, expiry time.Time, plac
|
|||||||
username = "{username}"
|
username = "{username}"
|
||||||
exp = "{yourAccountWillExpire}"
|
exp = "{yourAccountWillExpire}"
|
||||||
}
|
}
|
||||||
contentInfo, template, msg := emailer.baseValues("WelcomeEmail", username, placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("WelcomeEmail", username, placeholders, map[string]any{
|
||||||
"welcome": emailer.lang.WelcomeEmail.get("welcome"),
|
"welcome": emailer.lang.WelcomeEmail.get("welcome"),
|
||||||
"youCanLoginWith": emailer.lang.WelcomeEmail.get("youCanLoginWith"),
|
"youCanLoginWith": emailer.lang.WelcomeEmail.get("youCanLoginWith"),
|
||||||
"jellyfinURLString": emailer.lang.WelcomeEmail.get("jellyfinURL"),
|
"jellyfinURLString": emailer.lang.WelcomeEmail.get("jellyfinURL"),
|
||||||
@@ -604,18 +597,16 @@ func (emailer *Emailer) constructWelcome(username string, expiry time.Time, plac
|
|||||||
template["yourAccountWillExpire"] = exp
|
template["yourAccountWillExpire"] = exp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emailer *Emailer) constructUserExpired(placeholders bool) (*Message, error) {
|
func (emailer *Emailer) constructUserExpired(username string, placeholders bool) (*Message, error) {
|
||||||
contentInfo, template, msg := emailer.baseValues("UserExpired", "", placeholders, map[string]any{
|
contentInfo, template := emailer.baseValues("UserExpired", username, placeholders, map[string]any{
|
||||||
"yourAccountHasExpired": emailer.lang.UserExpired.get("yourAccountHasExpired"),
|
"yourAccountHasExpired": emailer.lang.UserExpired.get("yourAccountHasExpired"),
|
||||||
"contactTheAdmin": emailer.lang.UserExpired.get("contactTheAdmin"),
|
"contactTheAdmin": emailer.lang.UserExpired.get("contactTheAdmin"),
|
||||||
})
|
})
|
||||||
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
cc := emailer.storage.MustGetCustomContentKey(contentInfo.Name)
|
||||||
err := emailer.construct(contentInfo, cc, template, msg)
|
return emailer.construct(contentInfo, cc, template)
|
||||||
return msg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// calls the send method in the underlying emailClient.
|
// calls the send method in the underlying emailClient.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
type GenericDaemon struct {
|
type GenericDaemon struct {
|
||||||
Stopped bool
|
Stopped bool
|
||||||
ShutdownChannel chan string
|
ShutdownChannel chan string
|
||||||
|
TriggerChannel chan bool
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
period time.Duration
|
period time.Duration
|
||||||
jobs []func(app *appContext)
|
jobs []func(app *appContext)
|
||||||
@@ -27,6 +28,7 @@ func NewGenericDaemon(interval time.Duration, app *appContext, jobs ...func(app
|
|||||||
d := GenericDaemon{
|
d := GenericDaemon{
|
||||||
Stopped: false,
|
Stopped: false,
|
||||||
ShutdownChannel: make(chan string),
|
ShutdownChannel: make(chan string),
|
||||||
|
TriggerChannel: make(chan bool),
|
||||||
Interval: interval,
|
Interval: interval,
|
||||||
period: interval,
|
period: interval,
|
||||||
app: app,
|
app: app,
|
||||||
@@ -46,6 +48,8 @@ func (d *GenericDaemon) run() {
|
|||||||
case <-d.ShutdownChannel:
|
case <-d.ShutdownChannel:
|
||||||
d.ShutdownChannel <- "Down"
|
d.ShutdownChannel <- "Down"
|
||||||
return
|
return
|
||||||
|
case <-d.TriggerChannel:
|
||||||
|
break
|
||||||
case <-time.After(d.period):
|
case <-time.After(d.period):
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -61,6 +65,10 @@ func (d *GenericDaemon) run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *GenericDaemon) Trigger() {
|
||||||
|
d.TriggerChannel <- true
|
||||||
|
}
|
||||||
|
|
||||||
func (d *GenericDaemon) Shutdown() {
|
func (d *GenericDaemon) Shutdown() {
|
||||||
d.Stopped = true
|
d.Stopped = true
|
||||||
d.ShutdownChannel <- "Down"
|
d.ShutdownChannel <- "Down"
|
||||||
|
|||||||
37
main.go
37
main.go
@@ -112,18 +112,19 @@ type appContext struct {
|
|||||||
adminUsers []User
|
adminUsers []User
|
||||||
invalidTokens []string
|
invalidTokens []string
|
||||||
// Keeping jf name because I can't think of a better one
|
// Keeping jf name because I can't think of a better one
|
||||||
jf *mediabrowser.MediaBrowser
|
jf *mediabrowser.MediaBrowser
|
||||||
authJf *mediabrowser.MediaBrowser
|
authJf *mediabrowser.MediaBrowser
|
||||||
ombi *OmbiWrapper
|
ombi *OmbiWrapper
|
||||||
js *JellyseerrWrapper
|
js *JellyseerrWrapper
|
||||||
thirdPartyServices []ThirdPartyService
|
thirdPartyServices []ThirdPartyService
|
||||||
storage *Storage
|
storage *Storage
|
||||||
validator Validator
|
validator Validator
|
||||||
email *Emailer
|
email *Emailer
|
||||||
telegram *TelegramDaemon
|
telegram *TelegramDaemon
|
||||||
discord *DiscordDaemon
|
discord *DiscordDaemon
|
||||||
matrix *MatrixDaemon
|
matrix *MatrixDaemon
|
||||||
contactMethods []ContactMethodLinker
|
housekeepingDaemon, userDaemon *GenericDaemon
|
||||||
|
contactMethods []ContactMethodLinker
|
||||||
LoggerSet
|
LoggerSet
|
||||||
host string
|
host string
|
||||||
port int
|
port int
|
||||||
@@ -505,13 +506,13 @@ func start(asDaemon, firstCall bool) {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
invDaemon := newHousekeepingDaemon(time.Duration(60*time.Second), app)
|
app.housekeepingDaemon = newHousekeepingDaemon(time.Duration(60*time.Second), app)
|
||||||
go invDaemon.run()
|
go app.housekeepingDaemon.run()
|
||||||
defer invDaemon.Shutdown()
|
defer app.housekeepingDaemon.Shutdown()
|
||||||
|
|
||||||
userDaemon := newUserDaemon(time.Duration(60*time.Second), app)
|
app.userDaemon = newUserDaemon(time.Duration(60*time.Second), app)
|
||||||
go userDaemon.run()
|
go app.userDaemon.run()
|
||||||
defer userDaemon.Shutdown()
|
defer app.userDaemon.Shutdown()
|
||||||
|
|
||||||
var jellyseerrDaemon *GenericDaemon
|
var jellyseerrDaemon *GenericDaemon
|
||||||
if app.config.Section("jellyseerr").Key("enabled").MustBool(false) && app.config.Section("jellyseerr").Key("import_existing").MustBool(false) {
|
if app.config.Section("jellyseerr").Key("enabled").MustBool(false) && app.config.Section("jellyseerr").Key("import_existing").MustBool(false) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
// Disables authentication for the API. Do not use!
|
// Disables authentication for the API. Do not use!
|
||||||
NO_API_AUTH_DO_NOT_USE = false
|
NO_API_AUTH_DO_NOT_USE = false
|
||||||
|
NO_API_AUTH_FORCE_JFID = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
// loads HTML templates. If [files]/html_templates is set, alternative files inside the directory are loaded in place of the internal templates.
|
// loads HTML templates. If [files]/html_templates is set, alternative files inside the directory are loaded in place of the internal templates.
|
||||||
@@ -188,11 +189,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var api *gin.RouterGroup
|
var api *gin.RouterGroup
|
||||||
if NO_API_AUTH_DO_NOT_USE && *DEBUG {
|
api = router.Group("/", app.webAuth())
|
||||||
api = router.Group("/")
|
|
||||||
} else {
|
|
||||||
api = router.Group("/", app.webAuth())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range routePrefixes {
|
for _, p := range routePrefixes {
|
||||||
var user *gin.RouterGroup
|
var user *gin.RouterGroup
|
||||||
@@ -244,6 +241,8 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
api.POST(p+"/config", app.ModifyConfig)
|
api.POST(p+"/config", app.ModifyConfig)
|
||||||
api.POST(p+"/restart", app.restart)
|
api.POST(p+"/restart", app.restart)
|
||||||
api.GET(p+"/logs", app.GetLog)
|
api.GET(p+"/logs", app.GetLog)
|
||||||
|
api.POST(p+"/tasks/housekeeping", func(gc *gin.Context) { app.housekeepingDaemon.Trigger(); gc.Status(http.StatusNoContent) })
|
||||||
|
api.POST(p+"/tasks/users", func(gc *gin.Context) { app.userDaemon.Trigger(); gc.Status(http.StatusNoContent) })
|
||||||
api.POST(p+"/backups", app.CreateBackup)
|
api.POST(p+"/backups", app.CreateBackup)
|
||||||
api.GET(p+"/backups/:fname", app.GetBackup)
|
api.GET(p+"/backups/:fname", app.GetBackup)
|
||||||
api.GET(p+"/backups", app.GetBackups)
|
api.GET(p+"/backups", app.GetBackups)
|
||||||
|
|||||||
@@ -1126,9 +1126,9 @@ class MessageEditor {
|
|||||||
this._variables.innerHTML = innerHTML
|
this._variables.innerHTML = innerHTML
|
||||||
let buttons = this._variables.querySelectorAll("span.button") as NodeListOf<HTMLSpanElement>;
|
let buttons = this._variables.querySelectorAll("span.button") as NodeListOf<HTMLSpanElement>;
|
||||||
for (let i = 0; i < this._templ.variables.length; i++) {
|
for (let i = 0; i < this._templ.variables.length; i++) {
|
||||||
buttons[i].innerHTML = `<span class="font-mono bg-inherit">` + this._templ.variables[i] + `</span>`;
|
buttons[i].innerHTML = `<span class="font-mono bg-inherit">` + "{" + this._templ.variables[i] + "}" + `</span>`;
|
||||||
buttons[i].onclick = () => {
|
buttons[i].onclick = () => {
|
||||||
insertText(this._textArea, this._templ.variables[i]);
|
insertText(this._textArea, "{" + this._templ.variables[i] + "}");
|
||||||
this.loadPreview();
|
this.loadPreview();
|
||||||
// this._timeout = setTimeout(this.loadPreview, this._finishInterval);
|
// this._timeout = setTimeout(this.loadPreview, this._finishInterval);
|
||||||
}
|
}
|
||||||
@@ -1146,9 +1146,9 @@ class MessageEditor {
|
|||||||
this._conditionals.innerHTML = innerHTML
|
this._conditionals.innerHTML = innerHTML
|
||||||
buttons = this._conditionals.querySelectorAll("span.button") as NodeListOf<HTMLSpanElement>;
|
buttons = this._conditionals.querySelectorAll("span.button") as NodeListOf<HTMLSpanElement>;
|
||||||
for (let i = 0; i < this._templ.conditionals.length; i++) {
|
for (let i = 0; i < this._templ.conditionals.length; i++) {
|
||||||
buttons[i].innerHTML = `<span class="font-mono bg-inherit">{if ` + this._templ.conditionals[i].slice(1) + `</span>`;
|
buttons[i].innerHTML = `<span class="font-mono bg-inherit">{if ` + this._templ.conditionals[i] + "}" + `</span>`;
|
||||||
buttons[i].onclick = () => {
|
buttons[i].onclick = () => {
|
||||||
insertText(this._textArea, "{if " + this._templ.conditionals[i].slice(1) + "{endif}");
|
insertText(this._textArea, "{if " + this._templ.conditionals[i] + "}" + "{endif}");
|
||||||
this.loadPreview();
|
this.loadPreview();
|
||||||
// this._timeout = setTimeout(this.loadPreview, this._finishInterval);
|
// this._timeout = setTimeout(this.loadPreview, this._finishInterval);
|
||||||
}
|
}
|
||||||
@@ -1162,9 +1162,9 @@ class MessageEditor {
|
|||||||
let content = this._textArea.value;
|
let content = this._textArea.value;
|
||||||
if (this._templ.variables) {
|
if (this._templ.variables) {
|
||||||
for (let variable of this._templ.variables) {
|
for (let variable of this._templ.variables) {
|
||||||
let value = this._templ.values[variable.slice(1, -1)];
|
let value = this._templ.values[variable];
|
||||||
if (value === undefined) { value = variable; }
|
if (value === undefined) { value = "{" + variable + "}"; }
|
||||||
content = content.replace(new RegExp(variable, "g"), value);
|
content = content.replace(new RegExp("{" + variable + "}", "g"), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this._templ.html == "") {
|
if (this._templ.html == "") {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ func (app *appContext) checkUsers(remindBeforeExpiry *DayTimerSet) {
|
|||||||
if name == "" {
|
if name == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
msg, err := app.email.constructUserExpired(false)
|
msg, err := app.email.constructUserExpired(user.Name, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.err.Printf(lm.FailedConstructExpiryMessage, user.ID, err)
|
app.err.Printf(lm.FailedConstructExpiryMessage, user.ID, err)
|
||||||
} else if err := app.sendByID(msg, user.ID); err != nil {
|
} else if err := app.sendByID(msg, user.ID); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user