mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
db: migrate invites, user expiry
some fixes to stuff in there too, probably
This commit is contained in:
parent
a470d77938
commit
63948a6de0
@ -15,16 +15,15 @@ import (
|
||||
func (app *appContext) checkInvites() {
|
||||
currentTime := time.Now()
|
||||
app.storage.loadInvites()
|
||||
changed := false
|
||||
for code, data := range app.storage.GetInvites() {
|
||||
for _, data := range app.storage.GetInvites() {
|
||||
expiry := data.ValidTill
|
||||
if !currentTime.After(expiry) {
|
||||
continue
|
||||
}
|
||||
app.debug.Printf("Housekeeping: Deleting old invite %s", code)
|
||||
app.debug.Printf("Housekeeping: Deleting old invite %s", data.Code)
|
||||
notify := data.Notify
|
||||
if emailEnabled && app.config.Section("notifications").Key("enabled").MustBool(false) && len(notify) != 0 {
|
||||
app.debug.Printf("%s: Expiry notification", code)
|
||||
app.debug.Printf("%s: Expiry notification", data.Code)
|
||||
var wait sync.WaitGroup
|
||||
for address, settings := range notify {
|
||||
if !settings["notify-expiry"] {
|
||||
@ -33,9 +32,9 @@ func (app *appContext) checkInvites() {
|
||||
wait.Add(1)
|
||||
go func(addr string) {
|
||||
defer wait.Done()
|
||||
msg, err := app.email.constructExpiry(code, data, app, false)
|
||||
msg, err := app.email.constructExpiry(data.Code, data, app, false)
|
||||
if err != nil {
|
||||
app.err.Printf("%s: Failed to construct expiry notification: %v", code, err)
|
||||
app.err.Printf("%s: Failed to construct expiry notification: %v", data.Code, err)
|
||||
} else {
|
||||
// Check whether notify "address" is an email address of Jellyfin ID
|
||||
if strings.Contains(addr, "@") {
|
||||
@ -44,7 +43,7 @@ func (app *appContext) checkInvites() {
|
||||
err = app.sendByID(msg, addr)
|
||||
}
|
||||
if err != nil {
|
||||
app.err.Printf("%s: Failed to send expiry notification: %v", code, err)
|
||||
app.err.Printf("%s: Failed to send expiry notification: %v", data.Code, err)
|
||||
} else {
|
||||
app.info.Printf("Sent expiry notification to %s", addr)
|
||||
}
|
||||
@ -53,18 +52,13 @@ func (app *appContext) checkInvites() {
|
||||
}
|
||||
wait.Wait()
|
||||
}
|
||||
changed = true
|
||||
app.storage.DeleteInvitesKey(code)
|
||||
}
|
||||
if changed {
|
||||
app.storage.storeInvites()
|
||||
app.storage.DeleteInvitesKey(data.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func (app *appContext) checkInvite(code string, used bool, username string) bool {
|
||||
currentTime := time.Now()
|
||||
app.storage.loadInvites()
|
||||
changed := false
|
||||
inv, match := app.storage.GetInvitesKey(code)
|
||||
if !match {
|
||||
return false
|
||||
@ -103,11 +97,9 @@ func (app *appContext) checkInvite(code string, used bool, username string) bool
|
||||
}
|
||||
wait.Wait()
|
||||
}
|
||||
changed = true
|
||||
match = false
|
||||
app.storage.DeleteInvitesKey(code)
|
||||
} else if used {
|
||||
changed = true
|
||||
del := false
|
||||
newInv := inv
|
||||
if newInv.RemainingUses == 1 {
|
||||
@ -122,9 +114,6 @@ func (app *appContext) checkInvite(code string, used bool, username string) bool
|
||||
app.storage.SetInvitesKey(code, newInv)
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
app.storage.storeInvites()
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
@ -220,7 +209,6 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
|
||||
}
|
||||
}
|
||||
app.storage.SetInvitesKey(inviteCode, invite)
|
||||
app.storage.storeInvites()
|
||||
respondBool(200, true, gc)
|
||||
}
|
||||
|
||||
@ -236,10 +224,10 @@ func (app *appContext) GetInvites(gc *gin.Context) {
|
||||
app.storage.loadInvites()
|
||||
app.checkInvites()
|
||||
var invites []inviteDTO
|
||||
for code, inv := range app.storage.GetInvites() {
|
||||
for _, inv := range app.storage.GetInvites() {
|
||||
_, months, days, hours, minutes, _ := timeDiff(inv.ValidTill, currentTime)
|
||||
invite := inviteDTO{
|
||||
Code: code,
|
||||
Code: inv.Code,
|
||||
Months: months,
|
||||
Days: days,
|
||||
Hours: hours,
|
||||
@ -277,21 +265,19 @@ func (app *appContext) GetInvites(gc *gin.Context) {
|
||||
invite.SendTo = inv.SendTo
|
||||
}
|
||||
if len(inv.Notify) != 0 {
|
||||
var address string
|
||||
// app.err.Printf("%s has notify section: %+v, you are %s\n", inv.Code, inv.Notify, gc.GetString("jfId"))
|
||||
var addressOrID string
|
||||
if app.config.Section("ui").Key("jellyfin_login").MustBool(false) {
|
||||
app.storage.loadEmails()
|
||||
if addr, ok := app.storage.GetEmailsKey(gc.GetString("jfId")); ok && addr.Addr != "" {
|
||||
address = addr.Addr
|
||||
}
|
||||
addressOrID = gc.GetString("jfId")
|
||||
} else {
|
||||
address = app.config.Section("ui").Key("email").String()
|
||||
addressOrID = app.config.Section("ui").Key("email").String()
|
||||
}
|
||||
if _, ok := inv.Notify[address]; ok {
|
||||
if _, ok = inv.Notify[address]["notify-expiry"]; ok {
|
||||
invite.NotifyExpiry = inv.Notify[address]["notify-expiry"]
|
||||
if _, ok := inv.Notify[addressOrID]; ok {
|
||||
if _, ok = inv.Notify[addressOrID]["notify-expiry"]; ok {
|
||||
invite.NotifyExpiry = inv.Notify[addressOrID]["notify-expiry"]
|
||||
}
|
||||
if _, ok = inv.Notify[address]["notify-creation"]; ok {
|
||||
invite.NotifyCreation = inv.Notify[address]["notify-creation"]
|
||||
if _, ok = inv.Notify[addressOrID]["notify-creation"]; ok {
|
||||
invite.NotifyCreation = inv.Notify[addressOrID]["notify-creation"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,7 +324,6 @@ func (app *appContext) SetProfile(gc *gin.Context) {
|
||||
inv, _ := app.storage.GetInvitesKey(req.Invite)
|
||||
inv.Profile = req.Profile
|
||||
app.storage.SetInvitesKey(req.Invite, inv)
|
||||
app.storage.storeInvites()
|
||||
respondBool(200, true, gc)
|
||||
}
|
||||
|
||||
@ -401,9 +386,6 @@ func (app *appContext) SetNotify(gc *gin.Context) {
|
||||
app.storage.SetInvitesKey(code, invite)
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
app.storage.storeInvites()
|
||||
}
|
||||
}
|
||||
|
||||
// @Summary Delete an invite.
|
||||
@ -422,7 +404,6 @@ func (app *appContext) DeleteInvite(gc *gin.Context) {
|
||||
_, ok = app.storage.GetInvitesKey(req.Code)
|
||||
if ok {
|
||||
app.storage.DeleteInvitesKey(req.Code)
|
||||
app.storage.storeInvites()
|
||||
app.info.Printf("%s: Invite deleted", req.Code)
|
||||
respondBool(200, true, gc)
|
||||
return
|
||||
|
@ -387,11 +387,6 @@ func (app *appContext) setContactMethods(req SetContactMethodsDTO, gc *gin.Conte
|
||||
change := dcUser.Contact != req.Discord
|
||||
dcUser.Contact = req.Discord
|
||||
app.storage.SetDiscordKey(req.ID, dcUser)
|
||||
if err := app.storage.storeDiscordUsers(); err != nil {
|
||||
respondBool(500, false, gc)
|
||||
app.err.Printf("Discord: Failed to store users: %v", err)
|
||||
return
|
||||
}
|
||||
if change {
|
||||
msg := ""
|
||||
if !req.Discord {
|
||||
@ -404,11 +399,6 @@ func (app *appContext) setContactMethods(req SetContactMethodsDTO, gc *gin.Conte
|
||||
change := mxUser.Contact != req.Matrix
|
||||
mxUser.Contact = req.Matrix
|
||||
app.storage.SetMatrixKey(req.ID, mxUser)
|
||||
if err := app.storage.storeMatrixUsers(); err != nil {
|
||||
respondBool(500, false, gc)
|
||||
app.err.Printf("Matrix: Failed to store users: %v", err)
|
||||
return
|
||||
}
|
||||
if change {
|
||||
msg := ""
|
||||
if !req.Matrix {
|
||||
@ -421,11 +411,6 @@ func (app *appContext) setContactMethods(req SetContactMethodsDTO, gc *gin.Conte
|
||||
change := email.Contact != req.Email
|
||||
email.Contact = req.Email
|
||||
app.storage.SetEmailsKey(req.ID, email)
|
||||
if err := app.storage.storeEmails(); err != nil {
|
||||
respondBool(500, false, gc)
|
||||
app.err.Printf("Failed to store emails: %v", err)
|
||||
return
|
||||
}
|
||||
if change {
|
||||
msg := ""
|
||||
if !req.Email {
|
||||
@ -646,7 +631,7 @@ func (app *appContext) MatrixConnect(gc *gin.Context) {
|
||||
var req MatrixConnectUserDTO
|
||||
gc.BindJSON(&req)
|
||||
if app.storage.GetMatrix() == nil {
|
||||
app.storage.matrix = matrixStore{}
|
||||
app.storage.deprecatedMatrix = matrixStore{}
|
||||
}
|
||||
roomID, encrypted, err := app.matrix.CreateRoom(req.UserID)
|
||||
if err != nil {
|
||||
@ -662,11 +647,6 @@ func (app *appContext) MatrixConnect(gc *gin.Context) {
|
||||
Encrypted: encrypted,
|
||||
})
|
||||
app.matrix.isEncrypted[roomID] = encrypted
|
||||
if err := app.storage.storeMatrixUsers(); err != nil {
|
||||
app.err.Printf("Failed to store Matrix users: %v", err)
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
respondBool(200, true, gc)
|
||||
}
|
||||
|
||||
@ -717,11 +697,6 @@ func (app *appContext) DiscordConnect(gc *gin.Context) {
|
||||
return
|
||||
}
|
||||
app.storage.SetDiscordKey(req.JellyfinID, user)
|
||||
if err := app.storage.storeDiscordUsers(); err != nil {
|
||||
app.err.Printf("Failed to store Discord users: %v", err)
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
}
|
||||
linkExistingOmbiDiscordTelegram(app)
|
||||
respondBool(200, true, gc)
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ func (app *appContext) MyDetails(gc *gin.Context) {
|
||||
}
|
||||
resp.Disabled = user.Policy.IsDisabled
|
||||
|
||||
if exp, ok := app.storage.users[user.ID]; ok {
|
||||
resp.Expiry = exp.Unix()
|
||||
if exp, ok := app.storage.GetUserExpiryKey(user.ID); ok {
|
||||
resp.Expiry = exp.Expiry.Unix()
|
||||
}
|
||||
|
||||
app.storage.loadEmails()
|
||||
@ -199,7 +199,6 @@ func (app *appContext) confirmMyAction(gc *gin.Context, key string) {
|
||||
}
|
||||
}
|
||||
|
||||
app.storage.storeEmails()
|
||||
app.info.Println("Email list modified")
|
||||
gc.Redirect(http.StatusSeeOther, "/my/account")
|
||||
return
|
||||
|
61
api-users.go
61
api-users.go
@ -62,7 +62,6 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
||||
app.jf.CacheExpiry = time.Now()
|
||||
if emailEnabled {
|
||||
app.storage.SetEmailsKey(id, EmailAddress{Addr: req.Email, Contact: true})
|
||||
app.storage.storeEmails()
|
||||
}
|
||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||
app.storage.loadOmbiTemplate()
|
||||
@ -327,29 +326,19 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
||||
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||
if req.Email != "" {
|
||||
app.storage.SetEmailsKey(id, EmailAddress{Addr: req.Email, Contact: true})
|
||||
app.storage.storeEmails()
|
||||
}
|
||||
expiry := time.Time{}
|
||||
if invite.UserExpiry {
|
||||
app.storage.usersLock.Lock()
|
||||
defer app.storage.usersLock.Unlock()
|
||||
expiry = time.Now().AddDate(0, invite.UserMonths, invite.UserDays).Add(time.Duration((60*invite.UserHours)+invite.UserMinutes) * time.Minute)
|
||||
app.storage.users[id] = expiry
|
||||
if err := app.storage.storeUsers(); err != nil {
|
||||
app.err.Printf("Failed to store user duration: %v", err)
|
||||
}
|
||||
app.storage.SetUserExpiryKey(id, UserExpiry{Expiry: expiry})
|
||||
}
|
||||
if discordVerified {
|
||||
discordUser.Contact = req.DiscordContact
|
||||
if app.storage.discord == nil {
|
||||
app.storage.discord = discordStore{}
|
||||
if app.storage.deprecatedDiscord == nil {
|
||||
app.storage.deprecatedDiscord = discordStore{}
|
||||
}
|
||||
app.storage.SetDiscordKey(user.ID, discordUser)
|
||||
if err := app.storage.storeDiscordUsers(); err != nil {
|
||||
app.err.Printf("Failed to store Discord users: %v", err)
|
||||
} else {
|
||||
delete(app.discord.verifiedTokens, req.DiscordPIN)
|
||||
}
|
||||
delete(app.discord.verifiedTokens, req.DiscordPIN)
|
||||
}
|
||||
if telegramVerified {
|
||||
tgUser := TelegramUser{
|
||||
@ -360,8 +349,8 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
||||
if lang, ok := app.telegram.languages[tgToken.ChatID]; ok {
|
||||
tgUser.Lang = lang
|
||||
}
|
||||
if app.storage.telegram == nil {
|
||||
app.storage.telegram = telegramStore{}
|
||||
if app.storage.deprecatedTelegram == nil {
|
||||
app.storage.deprecatedTelegram = telegramStore{}
|
||||
}
|
||||
app.telegram.DeleteVerifiedToken(req.TelegramPIN)
|
||||
app.storage.SetTelegramKey(user.ID, tgUser)
|
||||
@ -404,13 +393,10 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
||||
if matrixVerified {
|
||||
matrixUser.Contact = req.MatrixContact
|
||||
delete(app.matrix.tokens, req.MatrixPIN)
|
||||
if app.storage.matrix == nil {
|
||||
app.storage.matrix = matrixStore{}
|
||||
if app.storage.deprecatedMatrix == nil {
|
||||
app.storage.deprecatedMatrix = matrixStore{}
|
||||
}
|
||||
app.storage.SetMatrixKey(user.ID, matrixUser)
|
||||
if err := app.storage.storeMatrixUsers(); err != nil {
|
||||
app.err.Printf("Failed to store Matrix users: %v", err)
|
||||
}
|
||||
}
|
||||
if (emailEnabled && app.config.Section("welcome_email").Key("enabled").MustBool(false) && req.Email != "") || telegramVerified || discordVerified || matrixVerified {
|
||||
name := app.getAddressOrName(user.ID)
|
||||
@ -629,21 +615,16 @@ func (app *appContext) ExtendExpiry(gc *gin.Context) {
|
||||
respondBool(400, false, gc)
|
||||
return
|
||||
}
|
||||
app.storage.usersLock.Lock()
|
||||
defer app.storage.usersLock.Unlock()
|
||||
for _, id := range req.Users {
|
||||
if expiry, ok := app.storage.users[id]; ok {
|
||||
app.storage.users[id] = expiry.AddDate(0, req.Months, req.Days).Add(time.Duration(((60 * req.Hours) + req.Minutes)) * time.Minute)
|
||||
base := time.Now()
|
||||
if expiry, ok := app.storage.GetUserExpiryKey(id); ok {
|
||||
base = expiry.Expiry
|
||||
app.debug.Printf("Expiry extended for \"%s\"", id)
|
||||
} else {
|
||||
app.storage.users[id] = time.Now().AddDate(0, req.Months, req.Days).Add(time.Duration(((60 * req.Hours) + req.Minutes)) * time.Minute)
|
||||
app.debug.Printf("Created expiry for \"%s\"", id)
|
||||
}
|
||||
}
|
||||
if err := app.storage.storeUsers(); err != nil {
|
||||
app.err.Printf("Failed to store user duration: %v", err)
|
||||
respondBool(500, false, gc)
|
||||
return
|
||||
expiry := UserExpiry{Expiry: base.AddDate(0, req.Months, req.Days).Add(time.Duration(((60 * req.Hours) + req.Minutes)) * time.Minute)}
|
||||
app.storage.SetUserExpiryKey(id, expiry)
|
||||
}
|
||||
respondBool(204, true, gc)
|
||||
}
|
||||
@ -853,8 +834,6 @@ func (app *appContext) GetUsers(gc *gin.Context) {
|
||||
adminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
|
||||
allowAll := app.config.Section("ui").Key("allow_all").MustBool(false)
|
||||
i := 0
|
||||
app.storage.usersLock.Lock()
|
||||
defer app.storage.usersLock.Unlock()
|
||||
for _, jfUser := range users {
|
||||
user := respUser{
|
||||
ID: jfUser.ID,
|
||||
@ -871,9 +850,9 @@ func (app *appContext) GetUsers(gc *gin.Context) {
|
||||
user.Label = email.Label
|
||||
user.AccountsAdmin = (app.jellyfinLogin) && (email.Admin || (adminOnly && jfUser.Policy.IsAdministrator) || allowAll)
|
||||
}
|
||||
expiry, ok := app.storage.users[jfUser.ID]
|
||||
expiry, ok := app.storage.GetUserExpiryKey(jfUser.ID)
|
||||
if ok {
|
||||
user.Expiry = expiry.Unix()
|
||||
user.Expiry = expiry.Expiry.Unix()
|
||||
}
|
||||
if tgUser, ok := app.storage.GetTelegramKey(jfUser.ID); ok {
|
||||
user.Telegram = tgUser.Username
|
||||
@ -924,10 +903,6 @@ func (app *appContext) SetAccountsAdmin(gc *gin.Context) {
|
||||
app.storage.SetEmailsKey(id, emailStore)
|
||||
}
|
||||
}
|
||||
if err := app.storage.storeEmails(); err != nil {
|
||||
app.err.Printf("Failed to store email list: %v", err)
|
||||
respondBool(500, false, gc)
|
||||
}
|
||||
app.info.Println("Email list modified")
|
||||
respondBool(204, true, gc)
|
||||
}
|
||||
@ -961,10 +936,6 @@ func (app *appContext) ModifyLabels(gc *gin.Context) {
|
||||
app.storage.SetEmailsKey(id, emailStore)
|
||||
}
|
||||
}
|
||||
if err := app.storage.storeEmails(); err != nil {
|
||||
app.err.Printf("Failed to store email list: %v", err)
|
||||
respondBool(500, false, gc)
|
||||
}
|
||||
app.info.Println("Email list modified")
|
||||
respondBool(204, true, gc)
|
||||
}
|
||||
@ -999,7 +970,6 @@ func (app *appContext) ModifyEmails(gc *gin.Context) {
|
||||
// Auto enable contact by email for newly added addresses
|
||||
if !ok || oldEmail.Addr == "" {
|
||||
emailStore.Contact = true
|
||||
app.storage.storeEmails()
|
||||
}
|
||||
|
||||
emailStore.Addr = address
|
||||
@ -1016,7 +986,6 @@ func (app *appContext) ModifyEmails(gc *gin.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
app.storage.storeEmails()
|
||||
app.info.Println("Email list modified")
|
||||
respondBool(200, true, gc)
|
||||
}
|
||||
|
7
main.go
7
main.go
@ -362,7 +362,7 @@ func start(asDaemon, firstCall bool) {
|
||||
app.err.Printf("Failed to load Displayprefs: %v", err)
|
||||
}
|
||||
app.storage.users_path = app.config.Section("files").Key("users").String()
|
||||
if err := app.storage.loadUsers(); err != nil {
|
||||
if err := app.storage.loadUserExpiries(); err != nil {
|
||||
app.err.Printf("Failed to load Users: %v", err)
|
||||
}
|
||||
app.storage.telegram_path = app.config.Section("files").Key("telegram_users").String()
|
||||
@ -400,11 +400,6 @@ func start(asDaemon, firstCall bool) {
|
||||
app.storage.db_path = filepath.Join(app.dataPath, "db")
|
||||
app.ConnectDB()
|
||||
defer app.storage.db.Close()
|
||||
if !app.config.Section("").Key("migrated_to_db").MustBool(false) {
|
||||
// FIXME: Mark as done at some point
|
||||
migrateToBadger(app)
|
||||
}
|
||||
|
||||
// Read config-base for settings on web.
|
||||
app.configBasePath = "config-base.json"
|
||||
configBase, _ := fs.ReadFile(localFS, app.configBasePath)
|
||||
|
@ -16,26 +16,28 @@ func runMigrations(app *appContext) {
|
||||
migrateNotificationMethods(app)
|
||||
linkExistingOmbiDiscordTelegram(app)
|
||||
// migrateHyphens(app)
|
||||
migrateToBadger(app)
|
||||
}
|
||||
|
||||
// Migrate pre-0.2.0 user templates to profiles
|
||||
func migrateProfiles(app *appContext) {
|
||||
if !(app.storage.policy.BlockedTags == nil && app.storage.configuration.GroupedFolders == nil && len(app.storage.displayprefs) == 0) {
|
||||
app.info.Println("Migrating user template files to new profile format")
|
||||
app.storage.migrateToProfile()
|
||||
for _, path := range [3]string{app.storage.policy_path, app.storage.configuration_path, app.storage.displayprefs_path} {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
dir, fname := filepath.Split(path)
|
||||
newFname := strings.Replace(fname, ".json", ".old.json", 1)
|
||||
err := os.Rename(path, filepath.Join(dir, newFname))
|
||||
if err != nil {
|
||||
app.err.Fatalf("Failed to rename %s: %s", fname, err)
|
||||
}
|
||||
if app.storage.policy.BlockedTags == nil && app.storage.configuration.GroupedFolders == nil && len(app.storage.displayprefs) == 0 {
|
||||
return
|
||||
}
|
||||
app.info.Println("Migrating user template files to new profile format")
|
||||
app.storage.migrateToProfile()
|
||||
for _, path := range [3]string{app.storage.policy_path, app.storage.configuration_path, app.storage.displayprefs_path} {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
dir, fname := filepath.Split(path)
|
||||
newFname := strings.Replace(fname, ".json", ".old.json", 1)
|
||||
err := os.Rename(path, filepath.Join(dir, newFname))
|
||||
if err != nil {
|
||||
app.err.Fatalf("Failed to rename %s: %s", fname, err)
|
||||
}
|
||||
}
|
||||
app.info.Println("In case of a problem, your original files have been renamed to <file>.old.json")
|
||||
app.storage.storeProfiles()
|
||||
}
|
||||
app.info.Println("In case of a problem, your original files have been renamed to <file>.old.json")
|
||||
app.storage.storeProfiles()
|
||||
}
|
||||
|
||||
// Migrate pre-0.2.5 bootstrap theme choice to a17t version.
|
||||
@ -131,7 +133,7 @@ func migrateNotificationMethods(app *appContext) error {
|
||||
return nil
|
||||
}
|
||||
changes := false
|
||||
for code, invite := range app.storage.invites {
|
||||
for code, invite := range app.storage.deprecatedInvites {
|
||||
if invite.Notify == nil {
|
||||
continue
|
||||
}
|
||||
@ -149,7 +151,7 @@ func migrateNotificationMethods(app *appContext) error {
|
||||
}
|
||||
}
|
||||
if changes {
|
||||
app.storage.invites[code] = invite
|
||||
app.storage.deprecatedInvites[code] = invite
|
||||
}
|
||||
}
|
||||
if changes {
|
||||
@ -195,31 +197,45 @@ func linkExistingOmbiDiscordTelegram(app *appContext) error {
|
||||
}
|
||||
|
||||
func migrateToBadger(app *appContext) {
|
||||
if app.config.Section("").Key("migrated_to_db").MustBool(false) {
|
||||
return
|
||||
// FIXME: Mark as done at some point
|
||||
}
|
||||
app.info.Println("Migrating to Badger(hold)")
|
||||
app.storage.loadAnnouncements()
|
||||
for k, v := range app.storage.announcements {
|
||||
for k, v := range app.storage.deprecatedAnnouncements {
|
||||
app.storage.SetAnnouncementsKey(k, v)
|
||||
}
|
||||
|
||||
app.storage.loadDiscordUsers()
|
||||
for jfID, v := range app.storage.discord {
|
||||
for jfID, v := range app.storage.deprecatedDiscord {
|
||||
app.storage.SetDiscordKey(jfID, v)
|
||||
}
|
||||
|
||||
app.storage.loadTelegramUsers()
|
||||
for jfID, v := range app.storage.telegram {
|
||||
for jfID, v := range app.storage.deprecatedTelegram {
|
||||
app.storage.SetTelegramKey(jfID, v)
|
||||
}
|
||||
|
||||
app.storage.loadMatrixUsers()
|
||||
for jfID, v := range app.storage.matrix {
|
||||
for jfID, v := range app.storage.deprecatedMatrix {
|
||||
app.storage.SetMatrixKey(jfID, v)
|
||||
}
|
||||
|
||||
app.storage.loadEmails()
|
||||
for jfID, v := range app.storage.emails {
|
||||
for jfID, v := range app.storage.deprecatedEmails {
|
||||
app.storage.SetEmailsKey(jfID, v)
|
||||
}
|
||||
|
||||
app.storage.loadInvites()
|
||||
for k, v := range app.storage.deprecatedInvites {
|
||||
app.storage.SetInvitesKey(k, v)
|
||||
}
|
||||
|
||||
app.storage.loadUserExpiries()
|
||||
for k, v := range app.storage.deprecatedUserExpiries {
|
||||
app.storage.SetUserExpiryKey(k, UserExpiry{Expiry: v})
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate between hyphenated & non-hyphenated user IDs. Doesn't seem to happen anymore, so disabled.
|
||||
@ -283,7 +299,7 @@ func migrateToBadger(app *appContext) {
|
||||
// app.storage.emails = newEmails
|
||||
// app.storage.users = newUsers
|
||||
// err = app.storage.storeEmails()
|
||||
// err2 = app.storage.storeUsers()
|
||||
// err2 = app.storage.storeUserExpiries()
|
||||
// if err != nil {
|
||||
// app.err.Fatalf("couldn't store emails.json: %v", err)
|
||||
// }
|
||||
|
133
storage.go
133
storage.go
@ -8,7 +8,6 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hrfee/mediabrowser"
|
||||
@ -21,6 +20,11 @@ type telegramStore map[string]TelegramUser
|
||||
type matrixStore map[string]MatrixUser
|
||||
type emailStore map[string]EmailAddress
|
||||
|
||||
type UserExpiry struct {
|
||||
JellyfinID string `badgerhold:"key"`
|
||||
Expiry time.Time
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
timePattern string
|
||||
|
||||
@ -28,22 +32,21 @@ type Storage struct {
|
||||
db *badgerhold.Store
|
||||
|
||||
invite_path, emails_path, policy_path, configuration_path, displayprefs_path, ombi_path, profiles_path, customEmails_path, users_path, telegram_path, discord_path, matrix_path, announcements_path, matrix_sql_path, userPage_path string
|
||||
users map[string]time.Time // Map of Jellyfin User IDs to their expiry times.
|
||||
invites Invites
|
||||
deprecatedUserExpiries map[string]time.Time // Map of Jellyfin User IDs to their expiry times.
|
||||
deprecatedInvites Invites
|
||||
profiles map[string]Profile
|
||||
defaultProfile string
|
||||
displayprefs, ombi_template map[string]interface{}
|
||||
emails emailStore // Map of Jellyfin User IDs to Email addresses.
|
||||
telegram telegramStore // Map of Jellyfin User IDs to telegram users.
|
||||
discord discordStore // Map of Jellyfin user IDs to discord users.
|
||||
matrix matrixStore // Map of Jellyfin user IDs to Matrix users.
|
||||
deprecatedEmails emailStore // Map of Jellyfin User IDs to Email addresses.
|
||||
deprecatedTelegram telegramStore // Map of Jellyfin User IDs to telegram users.
|
||||
deprecatedDiscord discordStore // Map of Jellyfin user IDs to discord users.
|
||||
deprecatedMatrix matrixStore // Map of Jellyfin user IDs to Matrix users.
|
||||
customEmails customEmails
|
||||
userPage userPageContent
|
||||
policy mediabrowser.Policy
|
||||
configuration mediabrowser.Configuration
|
||||
lang Lang
|
||||
announcements map[string]announcementTemplate
|
||||
invitesLock, usersLock, discordLock, telegramLock, matrixLock, emailsLock sync.Mutex
|
||||
deprecatedAnnouncements map[string]announcementTemplate
|
||||
}
|
||||
|
||||
func (app *appContext) ConnectDB() {
|
||||
@ -203,36 +206,39 @@ func (st *Storage) DeleteMatrixKey(k string) {
|
||||
}
|
||||
|
||||
// GetInvites returns a copy of the store.
|
||||
func (st *Storage) GetInvites() Invites {
|
||||
if st.invites == nil {
|
||||
st.invites = Invites{}
|
||||
func (st *Storage) GetInvites() []Invite {
|
||||
result := []Invite{}
|
||||
err := st.db.Find(&result, &badgerhold.Query{})
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to find invites: %v\n", err)
|
||||
}
|
||||
return st.invites
|
||||
return result
|
||||
}
|
||||
|
||||
// GetInvitesKey returns the value stored in the store's key.
|
||||
func (st *Storage) GetInvitesKey(k string) (Invite, bool) {
|
||||
v, ok := st.invites[k]
|
||||
return v, ok
|
||||
result := Invite{}
|
||||
err := st.db.Get(k, &result)
|
||||
ok := true
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to find invite: %v\n", err)
|
||||
ok = false
|
||||
}
|
||||
return result, ok
|
||||
}
|
||||
|
||||
// SetInvitesKey stores value v in key k.
|
||||
func (st *Storage) SetInvitesKey(k string, v Invite) {
|
||||
st.invitesLock.Lock()
|
||||
if st.invites == nil {
|
||||
st.invites = Invites{}
|
||||
v.Code = k
|
||||
err := st.db.Upsert(k, v)
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to set invite: %v\n", err)
|
||||
}
|
||||
st.invites[k] = v
|
||||
st.storeInvites()
|
||||
st.invitesLock.Unlock()
|
||||
}
|
||||
|
||||
// DeleteInvitesKey deletes value at key k.
|
||||
func (st *Storage) DeleteInvitesKey(k string) {
|
||||
st.invitesLock.Lock()
|
||||
delete(st.invites, k)
|
||||
st.storeInvites()
|
||||
st.invitesLock.Unlock()
|
||||
st.db.Delete(k, Invite{})
|
||||
}
|
||||
|
||||
// GetAnnouncements returns a copy of the store.
|
||||
@ -270,6 +276,42 @@ func (st *Storage) DeleteAnnouncementsKey(k string) {
|
||||
st.db.Delete(k, announcementTemplate{})
|
||||
}
|
||||
|
||||
// GetUserExpiries returns a copy of the store.
|
||||
func (st *Storage) GetUserExpiries() []UserExpiry {
|
||||
result := []UserExpiry{}
|
||||
err := st.db.Find(&result, &badgerhold.Query{})
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to find expiries: %v\n", err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetUserExpiryKey returns the value stored in the store's key.
|
||||
func (st *Storage) GetUserExpiryKey(k string) (UserExpiry, bool) {
|
||||
result := UserExpiry{}
|
||||
err := st.db.Get(k, &result)
|
||||
ok := true
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to find expiry: %v\n", err)
|
||||
ok = false
|
||||
}
|
||||
return result, ok
|
||||
}
|
||||
|
||||
// SetUserExpiryKey stores value v in key k.
|
||||
func (st *Storage) SetUserExpiryKey(k string, v UserExpiry) {
|
||||
v.JellyfinID = k
|
||||
err := st.db.Upsert(k, v)
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to set expiry: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteUserExpiryKey deletes value at key k.
|
||||
func (st *Storage) DeleteUserExpiryKey(k string) {
|
||||
st.db.Delete(k, UserExpiry{})
|
||||
}
|
||||
|
||||
type TelegramUser struct {
|
||||
JellyfinID string `badgerhold:"key"`
|
||||
ChatID int64 `badgerhold:"index"`
|
||||
@ -335,6 +377,7 @@ type Profile struct {
|
||||
}
|
||||
|
||||
type Invite struct {
|
||||
Code string `badgerhold:"key"`
|
||||
Created time.Time `json:"created"`
|
||||
NoLimit bool `json:"no-limit"`
|
||||
RemainingUses int `json:"remaining-uses"`
|
||||
@ -1036,18 +1079,16 @@ func (st *Storage) loadLangTelegram(filesystems ...fs.FS) error {
|
||||
type Invites map[string]Invite
|
||||
|
||||
func (st *Storage) loadInvites() error {
|
||||
return loadJSON(st.invite_path, &st.invites)
|
||||
return loadJSON(st.invite_path, &st.deprecatedInvites)
|
||||
}
|
||||
|
||||
func (st *Storage) storeInvites() error {
|
||||
return storeJSON(st.invite_path, st.invites)
|
||||
return storeJSON(st.invite_path, st.deprecatedInvites)
|
||||
}
|
||||
|
||||
func (st *Storage) loadUsers() error {
|
||||
st.usersLock.Lock()
|
||||
defer st.usersLock.Unlock()
|
||||
if st.users == nil {
|
||||
st.users = map[string]time.Time{}
|
||||
func (st *Storage) loadUserExpiries() error {
|
||||
if st.deprecatedUserExpiries == nil {
|
||||
st.deprecatedUserExpiries = map[string]time.Time{}
|
||||
}
|
||||
temp := map[string]time.Time{}
|
||||
err := loadJSON(st.users_path, &temp)
|
||||
@ -1055,47 +1096,47 @@ func (st *Storage) loadUsers() error {
|
||||
return err
|
||||
}
|
||||
for id, t1 := range temp {
|
||||
if _, ok := st.users[id]; !ok {
|
||||
st.users[id] = t1
|
||||
if _, ok := st.deprecatedUserExpiries[id]; !ok {
|
||||
st.deprecatedUserExpiries[id] = t1
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *Storage) storeUsers() error {
|
||||
return storeJSON(st.users_path, st.users)
|
||||
func (st *Storage) storeUserExpiries() error {
|
||||
return storeJSON(st.users_path, st.deprecatedUserExpiries)
|
||||
}
|
||||
|
||||
func (st *Storage) loadEmails() error {
|
||||
return loadJSON(st.emails_path, &st.emails)
|
||||
return loadJSON(st.emails_path, &st.deprecatedEmails)
|
||||
}
|
||||
|
||||
func (st *Storage) storeEmails() error {
|
||||
return storeJSON(st.emails_path, st.emails)
|
||||
return storeJSON(st.emails_path, st.deprecatedEmails)
|
||||
}
|
||||
|
||||
func (st *Storage) loadTelegramUsers() error {
|
||||
return loadJSON(st.telegram_path, &st.telegram)
|
||||
return loadJSON(st.telegram_path, &st.deprecatedTelegram)
|
||||
}
|
||||
|
||||
func (st *Storage) storeTelegramUsers() error {
|
||||
return storeJSON(st.telegram_path, st.telegram)
|
||||
return storeJSON(st.telegram_path, st.deprecatedTelegram)
|
||||
}
|
||||
|
||||
func (st *Storage) loadDiscordUsers() error {
|
||||
return loadJSON(st.discord_path, &st.discord)
|
||||
return loadJSON(st.discord_path, &st.deprecatedDiscord)
|
||||
}
|
||||
|
||||
func (st *Storage) storeDiscordUsers() error {
|
||||
return storeJSON(st.discord_path, st.discord)
|
||||
return storeJSON(st.discord_path, st.deprecatedDiscord)
|
||||
}
|
||||
|
||||
func (st *Storage) loadMatrixUsers() error {
|
||||
return loadJSON(st.matrix_path, &st.matrix)
|
||||
return loadJSON(st.matrix_path, &st.deprecatedMatrix)
|
||||
}
|
||||
|
||||
func (st *Storage) storeMatrixUsers() error {
|
||||
return storeJSON(st.matrix_path, st.matrix)
|
||||
return storeJSON(st.matrix_path, st.deprecatedMatrix)
|
||||
}
|
||||
|
||||
func (st *Storage) loadCustomEmails() error {
|
||||
@ -1147,11 +1188,11 @@ func (st *Storage) storeOmbiTemplate() error {
|
||||
}
|
||||
|
||||
func (st *Storage) loadAnnouncements() error {
|
||||
return loadJSON(st.announcements_path, &st.announcements)
|
||||
return loadJSON(st.announcements_path, &st.deprecatedAnnouncements)
|
||||
}
|
||||
|
||||
func (st *Storage) storeAnnouncements() error {
|
||||
return storeJSON(st.announcements_path, st.announcements)
|
||||
return storeJSON(st.announcements_path, st.deprecatedAnnouncements)
|
||||
}
|
||||
|
||||
func (st *Storage) loadProfiles() error {
|
||||
|
@ -221,9 +221,6 @@ func (t *TelegramDaemon) commandLang(upd *tg.Update, sects []string, lang string
|
||||
if user.ChatID == upd.Message.Chat.ID {
|
||||
user.Lang = sects[1]
|
||||
t.app.storage.SetTelegramKey(user.JellyfinID, user)
|
||||
if err := t.app.storage.storeTelegramUsers(); err != nil {
|
||||
t.app.err.Printf("Failed to store Telegram users: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -50,13 +50,7 @@ func (rt *userDaemon) shutdown() {
|
||||
}
|
||||
|
||||
func (app *appContext) checkUsers() {
|
||||
if err := app.storage.loadUsers(); err != nil {
|
||||
app.err.Printf("Failed to load user expiries: %v", err)
|
||||
return
|
||||
}
|
||||
app.storage.usersLock.Lock()
|
||||
defer app.storage.usersLock.Unlock()
|
||||
if len(app.storage.users) == 0 {
|
||||
if len(app.storage.GetUserExpiries()) == 0 {
|
||||
return
|
||||
}
|
||||
app.info.Println("Daemon: Checking for user expiry")
|
||||
@ -80,11 +74,12 @@ func (app *appContext) checkUsers() {
|
||||
for _, user := range users {
|
||||
userExists[user.ID] = true
|
||||
}
|
||||
for id, expiry := range app.storage.users {
|
||||
for _, expiry := range app.storage.GetUserExpiries() {
|
||||
id := expiry.JellyfinID
|
||||
if _, ok := userExists[id]; !ok {
|
||||
app.info.Printf("Deleting expiry for non-existent user \"%s\"", id)
|
||||
delete(app.storage.users, id)
|
||||
} else if time.Now().After(expiry) {
|
||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
||||
} else if time.Now().After(expiry.Expiry) {
|
||||
found := false
|
||||
var user mediabrowser.User
|
||||
for _, u := range users {
|
||||
@ -96,7 +91,7 @@ func (app *appContext) checkUsers() {
|
||||
}
|
||||
if !found {
|
||||
app.info.Printf("Expired user already deleted, ignoring.")
|
||||
delete(app.storage.users, id)
|
||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
||||
continue
|
||||
}
|
||||
app.info.Printf("%s expired user \"%s\"", termPlural, user.Name)
|
||||
@ -112,7 +107,7 @@ func (app *appContext) checkUsers() {
|
||||
app.err.Printf("Failed to %s \"%s\" (%d): %s", mode, user.Name, status, err)
|
||||
continue
|
||||
}
|
||||
delete(app.storage.users, id)
|
||||
app.storage.DeleteUserExpiryKey(expiry.JellyfinID)
|
||||
app.jf.CacheExpiry = time.Now()
|
||||
if contact {
|
||||
if !ok {
|
||||
@ -130,8 +125,4 @@ func (app *appContext) checkUsers() {
|
||||
}
|
||||
}
|
||||
}
|
||||
err = app.storage.storeUsers()
|
||||
if err != nil {
|
||||
app.err.Printf("Failed to store user expiries: %s", err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user