mirror of https://github.com/hrfee/jfa-go
All works now, but i'll add a field on the accounts tab for users with an expiry, as well as a 'disabled' badge.pull/75/head
parent
2934832a98
commit
1e9d184508
@ -0,0 +1,76 @@
|
|||||||
|
<mjml>
|
||||||
|
<mj-head>
|
||||||
|
<mj-raw>
|
||||||
|
<meta name="color-scheme" content="light dark">
|
||||||
|
<meta name="supported-color-schemes" content="light dark">
|
||||||
|
</mj-raw>
|
||||||
|
<mj-style>
|
||||||
|
:root {
|
||||||
|
Color-scheme: light dark;
|
||||||
|
supported-color-schemes: light dark;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
Color-scheme: dark;
|
||||||
|
.body {
|
||||||
|
background: #242424 !important;
|
||||||
|
background-color: #242424 !important;
|
||||||
|
}
|
||||||
|
[data-ogsc] .body {
|
||||||
|
background: #242424 !important;
|
||||||
|
background-color: #242424 !important;
|
||||||
|
}
|
||||||
|
[data-ogsb] .body {
|
||||||
|
background: #242424 !important;
|
||||||
|
background-color: #242424 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
Color-scheme: dark;
|
||||||
|
.body {
|
||||||
|
background: #242424 !important;
|
||||||
|
background-color: #242424 !important;
|
||||||
|
}
|
||||||
|
[data-ogsc] .body {
|
||||||
|
background: #242424 !important;
|
||||||
|
background-color: #242424 !important;
|
||||||
|
}
|
||||||
|
[data-ogsb] .body {
|
||||||
|
background: #242424 !important;
|
||||||
|
background-color: #242424 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</mj-style>
|
||||||
|
<mj-attributes>
|
||||||
|
<mj-class name="bg" background-color="#101010" />
|
||||||
|
<mj-class name="bg2" background-color="#242424" />
|
||||||
|
<mj-class name="text" color="#cacaca" />
|
||||||
|
<mj-class name="bold" color="rgba(255,255,255,0.87)" />
|
||||||
|
<mj-class name="secondary" color="rgb(153,153,153)" />
|
||||||
|
<mj-class name="blue" background-color="rgb(0,164,220)" />
|
||||||
|
</mj-attributes>
|
||||||
|
<mj-font name="Quicksand" href="https://fonts.googleapis.com/css2?family=Quicksand" />
|
||||||
|
<mj-font name="Noto Sans" href="https://fonts.googleapis.com/css2?family=Noto+Sans" />
|
||||||
|
</mj-head>
|
||||||
|
<mj-body>
|
||||||
|
<mj-section mj-class="bg2">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text mj-class="bold" font-size="25px" font-family="Quicksand, Noto Sans, Helvetica, Arial, sans-serif"> {{ .jellyfin }} </mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
<mj-section mj-class="bg">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text mj-class="text" font-size="16px" font-family="Noto Sans, Helvetica, Arial, sans-serif">
|
||||||
|
<h3>{{ .yourAccountHasExpired }}</h3>
|
||||||
|
<p>{{ .contactTheAdmin }}</p>
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
<mj-section mj-class="bg2">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text mj-class="secondary" font-style="italic" font-size="14px">
|
||||||
|
{{ .message }}
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</body>
|
||||||
|
</mjml>
|
@ -0,0 +1,5 @@
|
|||||||
|
{{ .yourAccountHasExpired }}
|
||||||
|
|
||||||
|
{{ .contactTheAdmin }}
|
||||||
|
|
||||||
|
{{ .message }}
|
@ -0,0 +1,113 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hrfee/jfa-go/mediabrowser"
|
||||||
|
)
|
||||||
|
|
||||||
|
type userDaemon struct {
|
||||||
|
Stopped bool
|
||||||
|
ShutdownChannel chan string
|
||||||
|
Interval time.Duration
|
||||||
|
period time.Duration
|
||||||
|
app *appContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUserDaemon(interval time.Duration, app *appContext) *userDaemon {
|
||||||
|
return &userDaemon{
|
||||||
|
Stopped: false,
|
||||||
|
ShutdownChannel: make(chan string),
|
||||||
|
Interval: interval,
|
||||||
|
period: interval,
|
||||||
|
app: app,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rt *userDaemon) run() {
|
||||||
|
rt.app.info.Println("User daemon started")
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-rt.ShutdownChannel:
|
||||||
|
rt.ShutdownChannel <- "Down"
|
||||||
|
return
|
||||||
|
case <-time.After(rt.period):
|
||||||
|
break
|
||||||
|
}
|
||||||
|
started := time.Now()
|
||||||
|
rt.app.storage.loadInvites()
|
||||||
|
rt.app.checkUsers()
|
||||||
|
finished := time.Now()
|
||||||
|
duration := finished.Sub(started)
|
||||||
|
rt.period = rt.Interval - duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *appContext) checkUsers() {
|
||||||
|
if len(app.storage.users) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app.info.Println("Daemon: Checking for user expiry")
|
||||||
|
users, status, err := app.jf.GetUsers(false)
|
||||||
|
if err != nil || status != 200 {
|
||||||
|
app.err.Printf("Failed to get users (%d): %s", status, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mode := "disable"
|
||||||
|
termPlural := "Disabling"
|
||||||
|
if app.config.Section("user_expiry").Key("behaviour").MustString("disable_user") == "delete_user" {
|
||||||
|
mode = "delete"
|
||||||
|
termPlural = "Deleting"
|
||||||
|
}
|
||||||
|
email := false
|
||||||
|
if emailEnabled && app.config.Section("user_expiry").Key("send_email").MustBool(true) {
|
||||||
|
email = true
|
||||||
|
}
|
||||||
|
for id, expiry := range app.storage.users {
|
||||||
|
if time.Now().After(expiry) {
|
||||||
|
found := false
|
||||||
|
var user mediabrowser.User
|
||||||
|
for _, u := range users {
|
||||||
|
if u.ID == id {
|
||||||
|
found = true
|
||||||
|
user = u
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
app.info.Printf("Expired user already deleted, ignoring.")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
app.info.Printf("%s expired user \"%s\"", termPlural, user.Name)
|
||||||
|
if mode == "delete" {
|
||||||
|
status, err = app.jf.DeleteUser(id)
|
||||||
|
} else if mode == "disable" {
|
||||||
|
user.Policy.IsDisabled = true
|
||||||
|
status, err = app.jf.SetPolicy(id, user.Policy)
|
||||||
|
}
|
||||||
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
|
app.err.Printf("Failed to %s \"%s\" (%d): %s", mode, user.Name, status, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(app.storage.users, id)
|
||||||
|
if email {
|
||||||
|
address, ok := app.storage.emails[id]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg, err := app.email.constructUserExpired(app, false)
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf("Failed to construct expiry email for \"%s\": %s", user.Name, err)
|
||||||
|
} else if err := app.email.send(msg, address.(string)); err != nil {
|
||||||
|
app.err.Printf("Failed to send expiry email to \"%s\": %s", user.Name, err)
|
||||||
|
} else {
|
||||||
|
app.info.Printf("Sent expiry notification to \"%s\"", address.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = app.storage.storeUsers()
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf("Failed to store user duration: %s", err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue