mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
expiry: add option to delete after n days
Much like activities, you can have an expired account disabled, then deleted after n days (unless the admin intervenes and re-enables the account). For #341.
This commit is contained in:
parent
3c3297c8e7
commit
86c37fb423
@ -1797,6 +1797,15 @@
|
|||||||
"value": "disable_user",
|
"value": "disable_user",
|
||||||
"description": "Whether to delete or disable users on expiry."
|
"description": "Whether to delete or disable users on expiry."
|
||||||
},
|
},
|
||||||
|
"delete_expired_after_days": {
|
||||||
|
"name": "Delete expired accounts after (days)",
|
||||||
|
"required": false,
|
||||||
|
"requires_restart": false,
|
||||||
|
"type": "number",
|
||||||
|
"value": 0,
|
||||||
|
"depends_true": "behaviour",
|
||||||
|
"description": "When set, user accounts will be deleted this many days after expiring (if \"Behaviour\" is \"Disable user\"). Set to 0 to disable."
|
||||||
|
},
|
||||||
"send_email": {
|
"send_email": {
|
||||||
"name": "Send email",
|
"name": "Send email",
|
||||||
"required": false,
|
"required": false,
|
||||||
|
@ -63,8 +63,9 @@ type Activity struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserExpiry struct {
|
type UserExpiry struct {
|
||||||
JellyfinID string `badgerhold:"key"`
|
JellyfinID string `badgerhold:"key"`
|
||||||
Expiry time.Time
|
Expiry time.Time
|
||||||
|
DeleteAfterPeriod bool // Whether or not to further disable the user later on
|
||||||
}
|
}
|
||||||
|
|
||||||
type DebugLogAction int
|
type DebugLogAction int
|
||||||
|
135
user-d.go
135
user-d.go
@ -22,6 +22,7 @@ func (app *appContext) checkUsers() {
|
|||||||
if len(app.storage.GetUserExpiries()) == 0 {
|
if len(app.storage.GetUserExpiries()) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
app.info.Println(lm.CheckUserExpiries)
|
app.info.Println(lm.CheckUserExpiries)
|
||||||
users, status, err := app.jf.GetUsers(false)
|
users, status, err := app.jf.GetUsers(false)
|
||||||
if err != nil || status != 200 {
|
if err != nil || status != 200 {
|
||||||
@ -29,87 +30,93 @@ func (app *appContext) checkUsers() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
mode := "disable"
|
mode := "disable"
|
||||||
phrase := lm.DisableExpiredUser
|
|
||||||
if app.config.Section("user_expiry").Key("behaviour").MustString("disable_user") == "delete_user" {
|
if app.config.Section("user_expiry").Key("behaviour").MustString("disable_user") == "delete_user" {
|
||||||
mode = "delete"
|
mode = "delete"
|
||||||
phrase = lm.DeleteExpiredUser
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteAfterPeriod := app.config.Section("user_expiry").Key("delete_expired_after_days").MustInt(0)
|
||||||
|
if mode == "delete" {
|
||||||
|
deleteAfterPeriod = 0
|
||||||
|
}
|
||||||
|
|
||||||
contact := false
|
contact := false
|
||||||
if messagesEnabled && app.config.Section("user_expiry").Key("send_email").MustBool(true) {
|
if messagesEnabled && app.config.Section("user_expiry").Key("send_email").MustBool(true) {
|
||||||
contact = true
|
contact = true
|
||||||
}
|
}
|
||||||
// Use a map to speed up checking for deleted users later
|
// Use a map to speed up checking for deleted users later
|
||||||
userExists := map[string]bool{}
|
userExists := map[string]mediabrowser.User{}
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
userExists[user.ID] = true
|
userExists[user.ID] = user
|
||||||
}
|
}
|
||||||
for _, expiry := range app.storage.GetUserExpiries() {
|
for _, expiry := range app.storage.GetUserExpiries() {
|
||||||
id := expiry.JellyfinID
|
id := expiry.JellyfinID
|
||||||
if _, ok := userExists[id]; !ok {
|
user, ok := userExists[id]
|
||||||
|
if !ok {
|
||||||
app.info.Printf(lm.DeleteExpiryForOldUser, id)
|
app.info.Printf(lm.DeleteExpiryForOldUser, id)
|
||||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
||||||
} else if time.Now().After(expiry.Expiry) {
|
continue
|
||||||
found := false
|
}
|
||||||
var user mediabrowser.User
|
if !time.Now().After(expiry.Expiry) {
|
||||||
for _, u := range users {
|
continue
|
||||||
if u.ID == id {
|
}
|
||||||
found = true
|
deleteUserLater := deleteAfterPeriod != 0 && expiry.DeleteAfterPeriod
|
||||||
user = u
|
|
||||||
break
|
// Record activity
|
||||||
}
|
activity := Activity{
|
||||||
|
UserID: id,
|
||||||
|
SourceType: ActivityDaemon,
|
||||||
|
Time: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteUserNow := deleteUserLater && time.Now().After(expiry.Expiry.AddDate(0, 0, deleteAfterPeriod))
|
||||||
|
|
||||||
|
if mode == "delete" || deleteUserNow {
|
||||||
|
app.info.Printf(lm.DeleteExpiredUser, user.Name)
|
||||||
|
deleted := false
|
||||||
|
err, deleted = app.DeleteUser(user)
|
||||||
|
// Silence unimportant errors
|
||||||
|
if deleted {
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
if !found {
|
activity.Type = ActivityDeletion
|
||||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
// Store the user name, since there's no longer a user ID to reference back to
|
||||||
|
activity.Value = user.Name
|
||||||
|
} else if mode == "disable" && !deleteUserLater {
|
||||||
|
app.info.Printf(lm.DisableExpiredUser, user.Name)
|
||||||
|
// Admins can't be disabled
|
||||||
|
// so they're not an admin anymore, sorry
|
||||||
|
user.Policy.IsAdministrator = false
|
||||||
|
err, _, _ = app.SetUserDisabled(user, true)
|
||||||
|
activity.Type = ActivityDisabled
|
||||||
|
}
|
||||||
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
|
app.err.Printf(lm.FailedDeleteOrDisableExpiredUser, user.ID, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
app.storage.SetActivityKey(shortuuid.New(), activity, nil, false)
|
||||||
|
|
||||||
|
// If the we're not gonna be deleting the user later, we don't need this.
|
||||||
|
// also, if the admin re-enabled the user, we should get rid of the countdown.
|
||||||
|
if deleteAfterPeriod <= 0 || mode == "delete" || deleteUserNow || (deleteUserLater && !user.Policy.IsDisabled) {
|
||||||
|
app.storage.DeleteUserExpiryKey(user.ID)
|
||||||
|
} else if deleteAfterPeriod > 0 && !deleteUserLater {
|
||||||
|
expiry.DeleteAfterPeriod = true
|
||||||
|
app.storage.SetUserExpiryKey(user.ID, expiry)
|
||||||
|
}
|
||||||
|
app.jf.CacheExpiry = time.Now()
|
||||||
|
if contact {
|
||||||
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
app.info.Printf(phrase, user.Name)
|
name := app.getAddressOrName(user.ID)
|
||||||
|
msg, err := app.email.constructUserExpired(app, false)
|
||||||
// Record activity
|
if err != nil {
|
||||||
activity := Activity{
|
app.err.Printf(lm.FailedConstructExpiryMessage, user.ID, err)
|
||||||
UserID: id,
|
} else if err := app.sendByID(msg, user.ID); err != nil {
|
||||||
SourceType: ActivityDaemon,
|
app.err.Printf(lm.FailedSendExpiryMessage, user.ID, name, err)
|
||||||
Time: time.Now(),
|
} else {
|
||||||
}
|
app.err.Printf(lm.SentExpiryMessage, user.ID, name)
|
||||||
|
|
||||||
if mode == "delete" {
|
|
||||||
deleted := false
|
|
||||||
err, deleted = app.DeleteUser(user)
|
|
||||||
// Silence unimportant errors
|
|
||||||
if deleted {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
activity.Type = ActivityDeletion
|
|
||||||
// Store the user name, since there's no longer a user ID to reference back to
|
|
||||||
activity.Value = user.Name
|
|
||||||
} else if mode == "disable" {
|
|
||||||
// Admins can't be disabled
|
|
||||||
// so they're not an admin anymore, sorry
|
|
||||||
user.Policy.IsAdministrator = false
|
|
||||||
err, _, _ = app.SetUserDisabled(user, true)
|
|
||||||
activity.Type = ActivityDisabled
|
|
||||||
}
|
|
||||||
if !(status == 200 || status == 204) || err != nil {
|
|
||||||
app.err.Printf(lm.FailedDeleteOrDisableExpiredUser, user.ID, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
app.storage.SetActivityKey(shortuuid.New(), activity, nil, false)
|
|
||||||
|
|
||||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
|
||||||
app.jf.CacheExpiry = time.Now()
|
|
||||||
if contact {
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := app.getAddressOrName(user.ID)
|
|
||||||
msg, err := app.email.constructUserExpired(app, false)
|
|
||||||
if err != nil {
|
|
||||||
app.err.Printf(lm.FailedConstructExpiryMessage, user.ID, err)
|
|
||||||
} else if err := app.sendByID(msg, user.ID); err != nil {
|
|
||||||
app.err.Printf(lm.FailedConstructExpiryMessage, user.ID, name, err)
|
|
||||||
} else {
|
|
||||||
app.err.Printf(lm.SentExpiryMessage, user.ID, name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user