1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-09-19 19:00:11 +00:00

accounts: notify users of expiry adjustment

"Send notification message" in the extend expiry dialog will send a
message to the user with their new expiry. For #345.
This commit is contained in:
Harvey Tindall 2024-07-28 16:53:27 +01:00
parent cd98e51ea9
commit 48a2058e81
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
7 changed files with 53 additions and 27 deletions

View File

@ -187,9 +187,9 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
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)
msg, err = app.email.constructExpiryAdjusted("", time.Time{}, "", app, true)
}
values = app.email.expiryAdjustedValues(time.Now(), app.storage.lang.Email[lang].Strings.get("reason"), app, false, true)
values = app.email.expiryAdjustedValues(username, time.Now(), app.storage.lang.Email[lang].Strings.get("reason"), app, false, true)
case "InviteEmail":
if noContent {
msg, err = app.email.constructInvite("", Invite{}, app, true)

View File

@ -293,24 +293,24 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool, gc *gin.Context)
if emailEnabled && app.config.Section("notifications").Key("enabled").MustBool(false) {
for address, settings := range invite.Notify {
if settings["notify-creation"] {
go func() {
go func(addr string) {
msg, err := app.email.constructCreated(req.Code, req.Username, req.Email, invite, app, false)
if err != nil {
app.err.Printf("%s: Failed to construct user creation notification: %v", req.Code, err)
} else {
// Check whether notify "address" is an email address of Jellyfin ID
if strings.Contains(address, "@") {
err = app.email.send(msg, address)
// Check whether notify "addr" is an email address of Jellyfin ID
if strings.Contains(addr, "@") {
err = app.email.send(msg, addr)
} else {
err = app.sendByID(msg, address)
err = app.sendByID(msg, addr)
}
if err != nil {
app.err.Printf("%s: Failed to send user creation notification: %v", req.Code, err)
} else {
app.info.Printf("Sent user creation notification to %s", address)
app.info.Printf("Sent user creation notification to %s", addr)
}
}
}()
}(address)
}
}
}
@ -739,6 +739,22 @@ func (app *appContext) ExtendExpiry(gc *gin.Context) {
expiry.Expiry = base.AddDate(0, req.Months, req.Days).Add(time.Duration(((60 * req.Hours) + req.Minutes)) * time.Minute)
}
app.storage.SetUserExpiryKey(id, expiry)
if messagesEnabled && req.Notify {
go func(uid string, exp time.Time) {
user, status, err := app.jf.UserByID(uid, false)
if status != 200 || err != nil {
return
}
msg, err := app.email.constructExpiryAdjusted(user.Name, exp, req.Reason, app, false)
if err != nil {
app.err.Printf("%s: Failed to construct expiry adjustment notification: %v", uid, err)
return
}
if err := app.sendByID(msg, uid); err != nil {
app.err.Printf("%s: Failed to send expiry adjustment notification: %v", uid, err)
}
}(id, expiry.Expiry)
}
}
respondBool(204, true, gc)
}

View File

@ -741,7 +741,7 @@ func (emailer *Emailer) constructEnabled(reason string, app *appContext, noSub b
return email, nil
}
func (emailer *Emailer) expiryAdjustedValues(expiry time.Time, reason string, app *appContext, noSub bool, custom bool) map[string]interface{} {
func (emailer *Emailer) expiryAdjustedValues(username string, expiry time.Time, reason string, app *appContext, noSub bool, custom bool) map[string]interface{} {
template := map[string]interface{}{
"yourExpiryWasAdjusted": emailer.lang.UserExpiryAdjusted.get("yourExpiryWasAdjusted"),
"ifPreviouslyDisabled": emailer.lang.UserExpiryAdjusted.get("ifPreviouslyDisabled"),
@ -750,6 +750,7 @@ func (emailer *Emailer) expiryAdjustedValues(expiry time.Time, reason string, ap
"message": "",
}
if noSub {
template["helloUser"] = emailer.lang.Strings.get("helloUser")
empty := []string{"reason", "newExpiry"}
for _, v := range empty {
template[v] = "{" + v + "}"
@ -757,6 +758,7 @@ func (emailer *Emailer) expiryAdjustedValues(expiry time.Time, reason string, ap
} else {
template["reason"] = reason
template["message"] = app.config.Section("messages").Key("message").String()
template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": username})
exp := app.formatDatetime(expiry)
if !expiry.IsZero() {
if custom {
@ -771,7 +773,7 @@ func (emailer *Emailer) expiryAdjustedValues(expiry time.Time, reason string, ap
return template
}
func (emailer *Emailer) constructExpiryAdjusted(expiry time.Time, reason string, app *appContext, noSub bool) (*Message, error) {
func (emailer *Emailer) constructExpiryAdjusted(username string, expiry time.Time, reason string, app *appContext, noSub bool) (*Message, error) {
email := &Message{
Subject: app.config.Section("user_expiry").Key("adjustment_subject").MustString(emailer.lang.UserExpiryAdjusted.get("title")),
}
@ -779,9 +781,9 @@ func (emailer *Emailer) constructExpiryAdjusted(expiry time.Time, reason string,
var template map[string]interface{}
message := app.storage.MustGetCustomContentKey("UserExpiryAdjusted")
if message.Enabled {
template = emailer.expiryAdjustedValues(expiry, reason, app, noSub, true)
template = emailer.expiryAdjustedValues(username, expiry, reason, app, noSub, true)
} else {
template = emailer.expiryAdjustedValues(expiry, reason, app, noSub, false)
template = emailer.expiryAdjustedValues(username, expiry, reason, app, noSub, false)
}
if noSub {
template["newExpiry"] = emailer.lang.UserExpiryAdjusted.template("newExpiry", tmpl{

View File

@ -60,6 +60,8 @@
<mj-section mj-class="bg">
<mj-column>
<mj-text mj-class="text" font-size="16px" font-family="Noto Sans, Helvetica, Arial, sans-serif">
<p>{{ .helloUser }}</p>
<h3>{{ .yourExpiryWasAdjusted }}</h3>
<p>{{ .ifPreviouslyDisabled }}</p>

View File

@ -1,3 +1,5 @@
{{ .helloUser }}
{{ .yourExpiryWasAdjusted }}
{{ .ifPreviouslyDisabled }}
@ -7,4 +9,3 @@
{{ .reasonString }}: {{ .reason }}
{{ .message }}

View File

@ -267,6 +267,8 @@ type extendExpiryDTO struct {
Hours int `json:"hours" example:"2"` // Number of hours to add.
Minutes int `json:"minutes" example:"3"` // Number of minutes to add.
Timestamp int64 `json:"timestamp"` // Optional, exact time to expire at. Overrides other fields.
Notify bool `json:"notify"` // Whether to message the user(s) about the change.
Reason string `json:"reason" example:"i felt like it"` // Reason for adjustment.
}
type checkUpdateDTO struct {

View File

@ -1684,22 +1684,25 @@ export class accountsList {
applyList.push(id);
}
this._enableExpiryReason.classList.add("unfocused");
let header: string;
if (enableUser) {
header = window.lang.quantity("reEnableUsers", list.length);
this._enableExpiryNotify.parentElement.classList.remove("unfocused");
this._enableExpiryNotify.checked = false;
this._enableExpiryReason.value = "";
let header: string;
if (enableUser) {
header = window.lang.quantity("reEnableUsers", list.length);
} else if (this._settingExpiry) {
header = window.lang.quantity("setExpiry", list.length);
this._enableExpiryNotify.parentElement.classList.add("unfocused");
// this._enableExpiryNotify.parentElement.classList.add("unfocused");
} else {
header = window.lang.quantity("extendExpiry", applyList.length);
this._enableExpiryNotify.parentElement.classList.add("unfocused");
// this._enableExpiryNotify.parentElement.classList.add("unfocused");
}
document.getElementById("header-extend-expiry").textContent = header;
const extend = () => {
let send = { "users": applyList, "timestamp": 0 }
let send = { "users": applyList, "timestamp": 0, "notify": this._enableExpiryNotify.checked }
if (this._enableExpiryNotify.checked) {
send["reason"] = this._enableExpiryReason.value;
}
if (this._usingExtendExpiryTextInput) {
let date = (Date as any).fromString(this._extendExpiryTextInput.value) as Date;
send["timestamp"] = Math.floor(date.getTime() / 1000);
@ -1728,7 +1731,7 @@ export class accountsList {
this._extendExpiryForm.onsubmit = (event: Event) => {
event.preventDefault();
if (enableUser) {
this._enableDisableUsers(applyList, true, this._enableExpiryNotify.checked, this._enableExpiryNotify ? this._enableExpiryReason.value : null, (req: XMLHttpRequest) => {
this._enableDisableUsers(applyList, true, this._enableExpiryNotify.checked, this._enableExpiryNotify.checked ? this._enableExpiryReason.value : null, (req: XMLHttpRequest) => {
if (req.readyState == 4) {
if (req.status != 200 && req.status != 204) {
window.modals.extendExpiry.close();