1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-28 20:10:11 +00:00

Compare commits

...

6 Commits

Author SHA1 Message Date
e1c215b72e
db: remove remaining storage.loadX calls 2023-06-25 20:18:40 +01:00
ea0598e507
db: move legacy data loading out of main/config
put it in loadLegacyData in migrations, which is only called by
migrateToBadger.
2023-06-25 20:17:10 +01:00
28c3d9d2e4
db: use db key to store migration status
the planned config key "migrated_to_db" is not used, instead it is
stored in the database since that's a bit cleaner.
2023-06-25 19:59:11 +01:00
e9f9d9dc98
db: mark migration as completed when it's done
migrated_to_db config key is used. Might also add an extra check to see
if anything is in the DB.
2023-06-25 19:47:31 +01:00
bb75bfd15d
db: deprecate customEmails/userPage 2023-06-25 19:40:54 +01:00
9c84fb5887
profiles: fully deprecate old system
ombi_template, configuration, displayprefs, and policy still stuck
around for the admin new user feature. They are now sourced from the
default profile, and eventually a feature to select the source (or no
source) will be added.

this was still used when creating a new user as admin for some reason.
template is now sourced from the default profile.
2023-06-25 18:59:55 +01:00
12 changed files with 275 additions and 223 deletions

View File

@ -15,7 +15,6 @@ import (
func (app *appContext) checkInvites() {
currentTime := time.Now()
app.storage.loadInvites()
for _, data := range app.storage.GetInvites() {
expiry := data.ValidTill
if !currentTime.After(expiry) {
@ -59,7 +58,6 @@ func (app *appContext) checkInvites() {
func (app *appContext) checkInvite(code string, used bool, username string) bool {
currentTime := time.Now()
app.storage.loadInvites()
inv, match := app.storage.GetInvitesKey(code)
if !match {
return false
@ -128,7 +126,6 @@ func (app *appContext) checkInvite(code string, used bool, username string) bool
func (app *appContext) GenerateInvite(gc *gin.Context) {
var req generateInviteDTO
app.debug.Println("Generating new invite")
app.storage.loadInvites()
gc.BindJSON(&req)
currentTime := time.Now()
validTill := currentTime.AddDate(0, req.Months, req.Days)
@ -222,7 +219,6 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
func (app *appContext) GetInvites(gc *gin.Context) {
app.debug.Println("Invites requested")
currentTime := time.Now()
app.storage.loadInvites()
app.checkInvites()
var invites []inviteDTO
for _, inv := range app.storage.GetInvites() {
@ -344,8 +340,6 @@ func (app *appContext) SetNotify(gc *gin.Context) {
changed := false
for code, settings := range req {
app.debug.Printf("%s: Notification settings change requested", code)
app.storage.loadInvites()
app.storage.loadEmails()
invite, ok := app.storage.GetInvitesKey(code)
if !ok {
app.err.Printf("%s Notification setting change failed: Invalid code", code)

View File

@ -25,18 +25,18 @@ func (app *appContext) GetCustomContent(gc *gin.Context) {
adminLang = app.storage.lang.chosenAdminLang
}
list := emailListDTO{
"UserCreated": {Name: app.storage.lang.Email[lang].UserCreated["name"], Enabled: app.storage.customEmails.UserCreated.Enabled},
"InviteExpiry": {Name: app.storage.lang.Email[lang].InviteExpiry["name"], Enabled: app.storage.customEmails.InviteExpiry.Enabled},
"PasswordReset": {Name: app.storage.lang.Email[lang].PasswordReset["name"], Enabled: app.storage.customEmails.PasswordReset.Enabled},
"UserDeleted": {Name: app.storage.lang.Email[lang].UserDeleted["name"], Enabled: app.storage.customEmails.UserDeleted.Enabled},
"UserDisabled": {Name: app.storage.lang.Email[lang].UserDisabled["name"], Enabled: app.storage.customEmails.UserDisabled.Enabled},
"UserEnabled": {Name: app.storage.lang.Email[lang].UserEnabled["name"], Enabled: app.storage.customEmails.UserEnabled.Enabled},
"InviteEmail": {Name: app.storage.lang.Email[lang].InviteEmail["name"], Enabled: app.storage.customEmails.InviteEmail.Enabled},
"WelcomeEmail": {Name: app.storage.lang.Email[lang].WelcomeEmail["name"], Enabled: app.storage.customEmails.WelcomeEmail.Enabled},
"EmailConfirmation": {Name: app.storage.lang.Email[lang].EmailConfirmation["name"], Enabled: app.storage.customEmails.EmailConfirmation.Enabled},
"UserExpired": {Name: app.storage.lang.Email[lang].UserExpired["name"], Enabled: app.storage.customEmails.UserExpired.Enabled},
"UserLogin": {Name: app.storage.lang.Admin[adminLang].Strings["userPageLogin"], Enabled: app.storage.userPage.Login.Enabled},
"UserPage": {Name: app.storage.lang.Admin[adminLang].Strings["userPagePage"], Enabled: app.storage.userPage.Page.Enabled},
"UserCreated": {Name: app.storage.lang.Email[lang].UserCreated["name"], Enabled: app.storage.MustGetCustomContentKey("UserCreated").Enabled},
"InviteExpiry": {Name: app.storage.lang.Email[lang].InviteExpiry["name"], Enabled: app.storage.MustGetCustomContentKey("InviteExpiry").Enabled},
"PasswordReset": {Name: app.storage.lang.Email[lang].PasswordReset["name"], Enabled: app.storage.MustGetCustomContentKey("PasswordReset").Enabled},
"UserDeleted": {Name: app.storage.lang.Email[lang].UserDeleted["name"], Enabled: app.storage.MustGetCustomContentKey("UserDeleted").Enabled},
"UserDisabled": {Name: app.storage.lang.Email[lang].UserDisabled["name"], Enabled: app.storage.MustGetCustomContentKey("UserDisabled").Enabled},
"UserEnabled": {Name: app.storage.lang.Email[lang].UserEnabled["name"], Enabled: app.storage.MustGetCustomContentKey("UserEnabled").Enabled},
"InviteEmail": {Name: app.storage.lang.Email[lang].InviteEmail["name"], Enabled: app.storage.MustGetCustomContentKey("InviteEmail").Enabled},
"WelcomeEmail": {Name: app.storage.lang.Email[lang].WelcomeEmail["name"], Enabled: app.storage.MustGetCustomContentKey("WelcomeEmail").Enabled},
"EmailConfirmation": {Name: app.storage.lang.Email[lang].EmailConfirmation["name"], Enabled: app.storage.MustGetCustomContentKey("EmailConfirmation").Enabled},
"UserExpired": {Name: app.storage.lang.Email[lang].UserExpired["name"], Enabled: app.storage.MustGetCustomContentKey("UserExpired").Enabled},
"UserLogin": {Name: app.storage.lang.Admin[adminLang].Strings["userPageLogin"], Enabled: app.storage.MustGetCustomContentKey("Login").Enabled},
"UserPage": {Name: app.storage.lang.Admin[adminLang].Strings["userPagePage"], Enabled: app.storage.MustGetCustomContentKey("Page").Enabled},
}
filter := gc.Query("filter")
@ -50,10 +50,11 @@ func (app *appContext) GetCustomContent(gc *gin.Context) {
gc.JSON(200, list)
}
func (app *appContext) getCustomMessage(id string) *customContent {
// No longer needed, these are stored by string keys in the database now.
/* func (app *appContext) getCustomMessage(id string) *CustomContent {
switch id {
case "Announcement":
return &customContent{}
return &CustomContent{}
case "UserCreated":
return &app.storage.customEmails.UserCreated
case "InviteExpiry":
@ -80,45 +81,38 @@ func (app *appContext) getCustomMessage(id string) *customContent {
return &app.storage.userPage.Page
}
return nil
}
} */
// @Summary Sets the corresponding custom email.
// @Summary Sets the corresponding custom content.
// @Produce json
// @Param customEmails body customEmails true "Content = email (in markdown)."
// @Param CustomContent body CustomContent true "Content = email (in markdown)."
// @Success 200 {object} boolResponse
// @Failure 400 {object} boolResponse
// @Failure 500 {object} boolResponse
// @Param id path string true "ID of email"
// @Param id path string true "ID of content"
// @Router /config/emails/{id} [post]
// @Security Bearer
// @tags Configuration
func (app *appContext) SetCustomMessage(gc *gin.Context) {
var req customContent
var req CustomContent
gc.BindJSON(&req)
id := gc.Param("id")
if req.Content == "" {
respondBool(400, false, gc)
return
}
message := app.getCustomMessage(id)
if message == nil {
message, ok := app.storage.GetCustomContentKey(id)
if !ok {
respondBool(400, false, gc)
return
}
message.Content = req.Content
message.Enabled = true
if app.storage.storeCustomEmails() != nil {
respondBool(500, false, gc)
return
}
if app.storage.storeUserPageContent() != nil {
respondBool(500, false, gc)
return
}
app.storage.SetCustomContentKey(id, message)
respondBool(200, true, gc)
}
// @Summary Enable/Disable custom email.
// @Summary Enable/Disable custom content.
// @Produce json
// @Success 200 {object} boolResponse
// @Failure 400 {object} boolResponse
@ -137,24 +131,17 @@ func (app *appContext) SetCustomMessageState(gc *gin.Context) {
} else if s != "disable" {
respondBool(400, false, gc)
}
message := app.getCustomMessage(id)
if message == nil {
message, ok := app.storage.GetCustomContentKey(id)
if !ok {
respondBool(400, false, gc)
return
}
message.Enabled = enabled
if app.storage.storeCustomEmails() != nil {
respondBool(500, false, gc)
return
}
if app.storage.storeUserPageContent() != nil {
respondBool(500, false, gc)
return
}
app.storage.SetCustomContentKey(id, message)
respondBool(200, true, gc)
}
// @Summary Returns the custom email/message (generating it if not set) and list of used variables in it.
// @Summary Returns the custom content/message (generating it if not set) and list of used variables in it.
// @Produce json
// @Success 200 {object} customEmailDTO
// @Failure 400 {object} boolResponse
@ -174,8 +161,8 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
var values map[string]interface{}
username := app.storage.lang.Email[lang].Strings.get("username")
emailAddress := app.storage.lang.Email[lang].Strings.get("emailAddress")
customMessage := app.getCustomMessage(id)
if customMessage == nil {
customMessage, ok := app.storage.GetCustomContentKey(id)
if !ok {
app.err.Printf("Failed to get custom message with ID \"%s\"", id)
respondBool(400, false, gc)
return
@ -280,13 +267,7 @@ func (app *appContext) GetCustomMessageTemplate(gc *gin.Context) {
if variables == nil {
variables = []string{}
}
if app.storage.storeCustomEmails() != nil {
respondBool(500, false, gc)
return
}
if app.storage.storeUserPageContent() != nil {
respondBool(500, false, gc)
}
app.storage.SetCustomContentKey(id, customMessage)
var mail *Message
if id != "UserLogin" && id != "UserPage" {
mail, err = app.email.constructTemplate("", "<div class=\"preview-content\"></div>", app)

View File

@ -42,11 +42,6 @@ func (app *appContext) MyDetails(gc *gin.Context) {
resp.Expiry = exp.Expiry.Unix()
}
app.storage.loadEmails()
app.storage.loadDiscordUsers()
app.storage.loadMatrixUsers()
app.storage.loadTelegramUsers()
if emailEnabled {
resp.Email = &MyDetailsContactMethodsDTO{}
if email, ok := app.storage.GetEmailsKey(user.ID); ok && email.Addr != "" {

View File

@ -44,16 +44,16 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
return
}
id := user.ID
if app.storage.policy.BlockedTags != nil {
status, err = app.jf.SetPolicy(id, app.storage.policy)
profile := app.storage.GetDefaultProfile()
// Check profile isn't empty
if profile.Policy.BlockedTags != nil {
status, err = app.jf.SetPolicy(id, profile.Policy)
if !(status == 200 || status == 204 || err == nil) {
app.err.Printf("%s: Failed to set user policy (%d): %v", req.Username, status, err)
}
}
if app.storage.configuration.GroupedFolders != nil && len(app.storage.displayprefs) != 0 {
status, err = app.jf.SetConfiguration(id, app.storage.configuration)
status, err = app.jf.SetConfiguration(id, profile.Configuration)
if (status == 200 || status == 204) && err == nil {
status, err = app.jf.SetDisplayPreferences(id, app.storage.displayprefs)
status, err = app.jf.SetDisplayPreferences(id, profile.Displayprefs)
}
if !((status == 200 || status == 204) && err == nil) {
app.err.Printf("%s: Failed to set configuration template (%d): %v", req.Username, status, err)
@ -64,15 +64,16 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
app.storage.SetEmailsKey(id, EmailAddress{Addr: req.Email, Contact: true})
}
if app.config.Section("ombi").Key("enabled").MustBool(false) {
app.storage.loadOmbiTemplate()
if len(app.storage.ombi_template) != 0 {
errors, code, err := app.ombi.NewUser(req.Username, req.Password, req.Email, app.storage.ombi_template)
if err != nil || code != 200 {
app.err.Printf("Failed to create Ombi user (%d): %v", code, err)
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
} else {
app.info.Println("Created Ombi user")
}
profile := app.storage.GetDefaultProfile()
if profile.Ombi == nil {
profile.Ombi = map[string]interface{}{}
}
errors, code, err := app.ombi.NewUser(req.Username, req.Password, req.Email, profile.Ombi)
if err != nil || code != 200 {
app.err.Printf("Failed to create Ombi user (%d): %v", code, err)
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
} else {
app.info.Println("Created Ombi user")
}
}
if emailEnabled && app.config.Section("welcome_email").Key("enabled").MustBool(false) && req.Email != "" {

View File

@ -37,8 +37,6 @@ func (app *appContext) loadConfig() error {
return err
}
app.MustSetValue("", "migrated_to_db", "false")
app.MustSetValue("jellyfin", "public_server", app.config.Section("jellyfin").Key("server").String())
app.MustSetValue("ui", "redirect_url", app.config.Section("jellyfin").Key("public_server").String())
@ -159,15 +157,6 @@ func (app *appContext) loadConfig() error {
app.MustSetValue("updates", "channel", releaseChannel)
}
app.storage.customEmails_path = app.config.Section("files").Key("custom_emails").String()
app.storage.loadCustomEmails()
app.MustSetValue("user_page", "enabled", "true")
if app.config.Section("user_page").Key("enabled").MustBool(false) {
app.storage.userPage_path = app.config.Section("files").Key("custom_user_page_content").String()
app.storage.loadUserPageContent()
}
substituteStrings = app.config.Section("jellyfin").Key("substitute_jellyfin_strings").MustString("")
if substituteStrings != "" {

View File

@ -116,7 +116,6 @@ func (rt *housekeepingDaemon) run() {
break
}
started := time.Now()
rt.app.storage.loadInvites()
for _, job := range rt.jobs {
job(rt.app)

View File

@ -331,10 +331,11 @@ func (emailer *Emailer) constructConfirmation(code, username, key string, app *a
}
var err error
template := emailer.confirmationValues(code, username, key, app, noSub)
if app.storage.customEmails.EmailConfirmation.Enabled {
message := app.storage.MustGetCustomContentKey("EmailConfirmation")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.EmailConfirmation.Content,
app.storage.customEmails.EmailConfirmation.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -414,10 +415,11 @@ func (emailer *Emailer) constructInvite(code string, invite Invite, app *appCont
}
template := emailer.inviteValues(code, invite, app, noSub)
var err error
if app.storage.customEmails.InviteEmail.Enabled {
message := app.storage.MustGetCustomContentKey("InviteEmail")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.InviteEmail.Content,
app.storage.customEmails.InviteEmail.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -453,10 +455,11 @@ func (emailer *Emailer) constructExpiry(code string, invite Invite, app *appCont
}
var err error
template := emailer.expiryValues(code, invite, app, noSub)
if app.storage.customEmails.InviteExpiry.Enabled {
message := app.storage.MustGetCustomContentKey("InviteExpiry")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.InviteExpiry.Content,
app.storage.customEmails.InviteExpiry.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -507,10 +510,11 @@ func (emailer *Emailer) constructCreated(code, username, address string, invite
}
template := emailer.createdValues(code, username, address, invite, app, noSub)
var err error
if app.storage.customEmails.UserCreated.Enabled {
message := app.storage.MustGetCustomContentKey("UserCreated")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.UserCreated.Content,
app.storage.customEmails.UserCreated.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -580,10 +584,11 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext, noSub
}
template := emailer.resetValues(pwr, app, noSub)
var err error
if app.storage.customEmails.PasswordReset.Enabled {
message := app.storage.MustGetCustomContentKey("PasswordReset")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.PasswordReset.Content,
app.storage.customEmails.PasswordReset.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -621,10 +626,11 @@ func (emailer *Emailer) constructDeleted(reason string, app *appContext, noSub b
}
var err error
template := emailer.deletedValues(reason, app, noSub)
if app.storage.customEmails.UserDeleted.Enabled {
message := app.storage.MustGetCustomContentKey("UserDeleted")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.UserDeleted.Content,
app.storage.customEmails.UserDeleted.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -662,10 +668,11 @@ func (emailer *Emailer) constructDisabled(reason string, app *appContext, noSub
}
var err error
template := emailer.disabledValues(reason, app, noSub)
if app.storage.customEmails.UserDisabled.Enabled {
message := app.storage.MustGetCustomContentKey("UserDisabled")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.UserDisabled.Content,
app.storage.customEmails.UserDisabled.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -703,10 +710,11 @@ func (emailer *Emailer) constructEnabled(reason string, app *appContext, noSub b
}
var err error
template := emailer.enabledValues(reason, app, noSub)
if app.storage.customEmails.UserEnabled.Enabled {
message := app.storage.MustGetCustomContentKey("UserEnabled")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.UserEnabled.Content,
app.storage.customEmails.UserEnabled.Variables,
message.Content,
message.Variables,
nil,
template,
)
@ -758,7 +766,8 @@ func (emailer *Emailer) constructWelcome(username string, expiry time.Time, app
}
var err error
var template map[string]interface{}
if app.storage.customEmails.WelcomeEmail.Enabled {
message := app.storage.MustGetCustomContentKey("WelcomeEmail")
if message.Enabled {
template = emailer.welcomeValues(username, expiry, app, noSub, true)
} else {
template = emailer.welcomeValues(username, expiry, app, noSub, false)
@ -768,11 +777,11 @@ func (emailer *Emailer) constructWelcome(username string, expiry time.Time, app
"date": "{yourAccountWillExpire}",
})
}
if app.storage.customEmails.WelcomeEmail.Enabled {
if message.Enabled {
content := templateEmail(
app.storage.customEmails.WelcomeEmail.Content,
app.storage.customEmails.WelcomeEmail.Variables,
app.storage.customEmails.WelcomeEmail.Conditionals,
message.Content,
message.Variables,
message.Conditionals,
template,
)
email, err = emailer.constructTemplate(email.Subject, content, app)
@ -803,10 +812,11 @@ func (emailer *Emailer) constructUserExpired(app *appContext, noSub bool) (*Mess
}
var err error
template := emailer.userExpiredValues(app, noSub)
if app.storage.customEmails.UserExpired.Enabled {
message := app.storage.MustGetCustomContentKey("UserExpired")
if message.Enabled {
content := templateEmail(
app.storage.customEmails.UserExpired.Content,
app.storage.customEmails.UserExpired.Variables,
message.Content,
message.Variables,
nil,
template,
)

53
main.go
View File

@ -335,59 +335,8 @@ func start(asDaemon, firstCall bool) {
app.debug.Printf("Loaded config file \"%s\"", app.configPath)
app.debug.Println("Loading storage")
app.storage.invite_path = app.config.Section("files").Key("invites").String()
if err := app.storage.loadInvites(); err != nil {
app.err.Printf("Failed to load Invites: %v", err)
}
app.storage.emails_path = app.config.Section("files").Key("emails").String()
if err := app.storage.loadEmails(); err != nil {
app.err.Printf("Failed to load Emails: %v", err)
err := migrateEmailStorage(app)
if err != nil {
app.err.Printf("Failed to migrate Email storage: %v", err)
}
}
app.storage.policy_path = app.config.Section("files").Key("user_template").String()
if err := app.storage.loadPolicy(); err != nil {
app.err.Printf("Failed to load Policy: %v", err)
}
app.storage.configuration_path = app.config.Section("files").Key("user_configuration").String()
if err := app.storage.loadConfiguration(); err != nil {
app.err.Printf("Failed to load Configuration: %v", err)
}
app.storage.displayprefs_path = app.config.Section("files").Key("user_displayprefs").String()
if err := app.storage.loadDisplayprefs(); err != nil {
app.err.Printf("Failed to load Displayprefs: %v", err)
}
app.storage.users_path = app.config.Section("files").Key("users").String()
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()
if err := app.storage.loadTelegramUsers(); err != nil {
app.err.Printf("Failed to load Telegram users: %v", err)
}
app.storage.discord_path = app.config.Section("files").Key("discord_users").String()
if err := app.storage.loadDiscordUsers(); err != nil {
app.err.Printf("Failed to load Discord users: %v", err)
}
app.storage.matrix_path = app.config.Section("files").Key("matrix_users").String()
if err := app.storage.loadMatrixUsers(); err != nil {
app.err.Printf("Failed to load Matrix users: %v", err)
}
app.storage.announcements_path = app.config.Section("files").Key("announcements").String()
if err := app.storage.loadAnnouncements(); err != nil {
app.err.Printf("Failed to load announcement templates: %v", err)
}
app.storage.profiles_path = app.config.Section("files").Key("user_profiles").String()
app.storage.loadProfiles()
if app.config.Section("ombi").Key("enabled").MustBool(false) {
app.storage.ombi_path = app.config.Section("files").Key("ombi_template").String()
app.storage.loadOmbiTemplate()
app.debug.Printf("Connecting to Ombi")
ombiServer := app.config.Section("ombi").Key("server").String()
app.ombi = ombi.NewOmbi(
ombiServer,

View File

@ -21,7 +21,7 @@ func runMigrations(app *appContext) {
// 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 {
if app.storage.deprecatedPolicy.BlockedTags == nil && app.storage.deprecatedConfiguration.GroupedFolders == nil && len(app.storage.deprecatedDisplayprefs) == 0 {
return
}
app.info.Println("Migrating user template files to new profile format")
@ -196,51 +196,141 @@ func linkExistingOmbiDiscordTelegram(app *appContext) error {
return nil
}
// MigrationStatus is just used to store whether data from JSON files has been migrated to the DB.
type MigrationStatus struct {
Done bool
}
func loadLegacyData(app *appContext) {
app.storage.invite_path = app.config.Section("files").Key("invites").String()
if err := app.storage.loadInvites(); err != nil {
app.err.Printf("LegacyData: Failed to load Invites: %v", err)
}
app.storage.emails_path = app.config.Section("files").Key("emails").String()
if err := app.storage.loadEmails(); err != nil {
app.err.Printf("LegacyData: Failed to load Emails: %v", err)
err := migrateEmailStorage(app)
if err != nil {
app.err.Printf("LegacyData: Failed to migrate Email storage: %v", err)
}
}
app.storage.users_path = app.config.Section("files").Key("users").String()
if err := app.storage.loadUserExpiries(); err != nil {
app.err.Printf("LegacyData: Failed to load Users: %v", err)
}
app.storage.telegram_path = app.config.Section("files").Key("telegram_users").String()
if err := app.storage.loadTelegramUsers(); err != nil {
app.err.Printf("LegacyData: Failed to load Telegram users: %v", err)
}
app.storage.discord_path = app.config.Section("files").Key("discord_users").String()
if err := app.storage.loadDiscordUsers(); err != nil {
app.err.Printf("LegacyData: Failed to load Discord users: %v", err)
}
app.storage.matrix_path = app.config.Section("files").Key("matrix_users").String()
if err := app.storage.loadMatrixUsers(); err != nil {
app.err.Printf("LegacyData: Failed to load Matrix users: %v", err)
}
app.storage.announcements_path = app.config.Section("files").Key("announcements").String()
if err := app.storage.loadAnnouncements(); err != nil {
app.err.Printf("LegacyData: Failed to load announcement templates: %v", err)
}
app.storage.profiles_path = app.config.Section("files").Key("user_profiles").String()
app.storage.loadProfiles()
app.storage.customEmails_path = app.config.Section("files").Key("custom_emails").String()
app.storage.loadCustomEmails()
app.MustSetValue("user_page", "enabled", "true")
if app.config.Section("user_page").Key("enabled").MustBool(false) {
app.storage.userPage_path = app.config.Section("files").Key("custom_user_page_content").String()
app.storage.loadUserPageContent()
}
}
func migrateToBadger(app *appContext) {
if app.config.Section("").Key("migrated_to_db").MustBool(false) {
// Check the DB to see if we've already migrated
migrated := MigrationStatus{}
app.storage.db.Get("migrated_to_db", &migrated)
if migrated.Done {
return
// FIXME: Mark as done at some point
}
app.info.Println("Migrating to Badger(hold)")
app.storage.loadAnnouncements()
loadLegacyData(app)
for k, v := range app.storage.deprecatedAnnouncements {
app.storage.SetAnnouncementsKey(k, v)
}
app.storage.loadDiscordUsers()
for jfID, v := range app.storage.deprecatedDiscord {
app.storage.SetDiscordKey(jfID, v)
}
app.storage.loadTelegramUsers()
for jfID, v := range app.storage.deprecatedTelegram {
app.storage.SetTelegramKey(jfID, v)
}
app.storage.loadMatrixUsers()
for jfID, v := range app.storage.deprecatedMatrix {
app.storage.SetMatrixKey(jfID, v)
}
app.storage.loadEmails()
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})
}
app.storage.loadProfiles()
for k, v := range app.storage.deprecatedProfiles {
app.storage.SetProfileKey(k, v)
}
if _, ok := app.storage.GetCustomContentKey("UserCreated"); !ok {
app.storage.SetCustomContentKey("UserCreated", app.storage.deprecatedCustomEmails.UserCreated)
}
if _, ok := app.storage.GetCustomContentKey("InviteExpiry"); !ok {
app.storage.SetCustomContentKey("InviteExpiry", app.storage.deprecatedCustomEmails.InviteExpiry)
}
if _, ok := app.storage.GetCustomContentKey("PasswordReset"); !ok {
app.storage.SetCustomContentKey("PasswordReset", app.storage.deprecatedCustomEmails.PasswordReset)
}
if _, ok := app.storage.GetCustomContentKey("UserDeleted"); !ok {
app.storage.SetCustomContentKey("UserDeleted", app.storage.deprecatedCustomEmails.UserDeleted)
}
if _, ok := app.storage.GetCustomContentKey("UserDisabled"); !ok {
app.storage.SetCustomContentKey("UserDisabled", app.storage.deprecatedCustomEmails.UserDisabled)
}
if _, ok := app.storage.GetCustomContentKey("UserEnabled"); !ok {
app.storage.SetCustomContentKey("UserEnabled", app.storage.deprecatedCustomEmails.UserEnabled)
}
if _, ok := app.storage.GetCustomContentKey("InviteEmail"); !ok {
app.storage.SetCustomContentKey("InviteEmail", app.storage.deprecatedCustomEmails.InviteEmail)
}
if _, ok := app.storage.GetCustomContentKey("WelcomeEmail"); !ok {
app.storage.SetCustomContentKey("WelcomeEmail", app.storage.deprecatedCustomEmails.WelcomeEmail)
}
if _, ok := app.storage.GetCustomContentKey("EmailConfirmation"); !ok {
app.storage.SetCustomContentKey("EmailConfirmation", app.storage.deprecatedCustomEmails.EmailConfirmation)
}
if _, ok := app.storage.GetCustomContentKey("UserExpired"); !ok {
app.storage.SetCustomContentKey("UserExpired", app.storage.deprecatedCustomEmails.UserExpired)
}
if _, ok := app.storage.GetCustomContentKey("UserLogin"); !ok {
app.storage.SetCustomContentKey("UserLogin", app.storage.deprecatedUserPageContent.Login)
}
if _, ok := app.storage.GetCustomContentKey("UserPage"); !ok {
app.storage.SetCustomContentKey("UserPage", app.storage.deprecatedUserPageContent.Page)
}
err := app.storage.db.Upsert("migrated_to_db", MigrationStatus{true})
if err != nil {
app.err.Fatalf("Failed to migrate to DB: %v\n", err)
}
app.info.Println("All data migrated to database. JSON files in the config folder can be deleted if you are sure all data is correct in the app. Create an issue if you have problems.")
}
// Migrate between hyphenated & non-hyphenated user IDs. Doesn't seem to happen anymore, so disabled.

View File

@ -100,7 +100,6 @@ func pwrMonitor(app *appContext, watcher *fsnotify.Watcher) {
app.debug.Printf("Error: %s", err)
return
}
app.storage.loadEmails()
uid := user.ID
if uid == "" {
app.err.Printf("Couldn't get user ID for user \"%s\"", pwr.Username)

View File

@ -35,17 +35,17 @@ type Storage struct {
deprecatedUserExpiries map[string]time.Time // Map of Jellyfin User IDs to their expiry times.
deprecatedInvites Invites
deprecatedProfiles map[string]Profile
displayprefs, ombi_template map[string]interface{}
deprecatedDisplayprefs, deprecatedOmbiTemplate map[string]interface{}
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
deprecatedPolicy mediabrowser.Policy
deprecatedConfiguration mediabrowser.Configuration
deprecatedAnnouncements map[string]announcementTemplate
deprecatedCustomEmails customEmails
deprecatedUserPageContent userPageContent
lang Lang
}
func (app *appContext) ConnectDB() {
@ -368,6 +368,49 @@ func (st *Storage) GetDefaultProfile() Profile {
return defaultProfile
}
// GetCustomContent returns a copy of the store.
func (st *Storage) GetCustomContent() []CustomContent {
result := []CustomContent{}
err := st.db.Find(&result, &badgerhold.Query{})
if err != nil {
// fmt.Printf("Failed to find custom content: %v\n", err)
}
return result
}
// GetCustomContentKey returns the value stored in the store's key.
func (st *Storage) GetCustomContentKey(k string) (CustomContent, bool) {
result := CustomContent{}
err := st.db.Get(k, &result)
ok := true
if err != nil {
// fmt.Printf("Failed to find custom content: %v\n", err)
ok = false
}
return result, ok
}
// MustGetCustomContentKey returns the value stored in the store's key, or an empty value.
func (st *Storage) MustGetCustomContentKey(k string) CustomContent {
result := CustomContent{}
st.db.Get(k, &result)
return result
}
// SetCustomContentKey stores value v in key k.
func (st *Storage) SetCustomContentKey(k string, v CustomContent) {
v.Name = k
err := st.db.Upsert(k, v)
if err != nil {
// fmt.Printf("Failed to set custom content: %v\n", err)
}
}
// DeleteCustomContentKey deletes value at key k.
func (st *Storage) DeleteCustomContentKey(k string) {
st.db.Delete(k, CustomContent{})
}
type TelegramUser struct {
JellyfinID string `badgerhold:"key"`
ChatID int64 `badgerhold:"index"`
@ -395,19 +438,21 @@ type EmailAddress struct {
}
type customEmails struct {
UserCreated customContent `json:"userCreated"`
InviteExpiry customContent `json:"inviteExpiry"`
PasswordReset customContent `json:"passwordReset"`
UserDeleted customContent `json:"userDeleted"`
UserDisabled customContent `json:"userDisabled"`
UserEnabled customContent `json:"userEnabled"`
InviteEmail customContent `json:"inviteEmail"`
WelcomeEmail customContent `json:"welcomeEmail"`
EmailConfirmation customContent `json:"emailConfirmation"`
UserExpired customContent `json:"userExpired"`
UserCreated CustomContent `json:"userCreated"`
InviteExpiry CustomContent `json:"inviteExpiry"`
PasswordReset CustomContent `json:"passwordReset"`
UserDeleted CustomContent `json:"userDeleted"`
UserDisabled CustomContent `json:"userDisabled"`
UserEnabled CustomContent `json:"userEnabled"`
InviteEmail CustomContent `json:"inviteEmail"`
WelcomeEmail CustomContent `json:"welcomeEmail"`
EmailConfirmation CustomContent `json:"emailConfirmation"`
UserExpired CustomContent `json:"userExpired"`
}
type customContent struct {
// CustomContent stores customized versions of jfa-go content, including emails and user messages.
type CustomContent struct {
Name string `json:"name" badgerhold:"key"`
Enabled bool `json:"enabled,omitempty"`
Content string `json:"content"`
Variables []string `json:"variables,omitempty"`
@ -415,8 +460,8 @@ type customContent struct {
}
type userPageContent struct {
Login customContent `json:"login"`
Page customContent `json:"page"`
Login CustomContent `json:"login"`
Page CustomContent `json:"page"`
}
// timePattern: %Y-%m-%dT%H:%M:%S.%f
@ -1197,51 +1242,51 @@ func (st *Storage) storeMatrixUsers() error {
}
func (st *Storage) loadCustomEmails() error {
return loadJSON(st.customEmails_path, &st.customEmails)
return loadJSON(st.customEmails_path, &st.deprecatedCustomEmails)
}
func (st *Storage) storeCustomEmails() error {
return storeJSON(st.customEmails_path, st.customEmails)
return storeJSON(st.customEmails_path, st.deprecatedCustomEmails)
}
func (st *Storage) loadUserPageContent() error {
return loadJSON(st.userPage_path, &st.userPage)
return loadJSON(st.userPage_path, &st.deprecatedUserPageContent)
}
func (st *Storage) storeUserPageContent() error {
return storeJSON(st.userPage_path, st.userPage)
return storeJSON(st.userPage_path, st.deprecatedUserPageContent)
}
func (st *Storage) loadPolicy() error {
return loadJSON(st.policy_path, &st.policy)
return loadJSON(st.policy_path, &st.deprecatedPolicy)
}
func (st *Storage) storePolicy() error {
return storeJSON(st.policy_path, st.policy)
return storeJSON(st.policy_path, st.deprecatedPolicy)
}
func (st *Storage) loadConfiguration() error {
return loadJSON(st.configuration_path, &st.configuration)
return loadJSON(st.configuration_path, &st.deprecatedConfiguration)
}
func (st *Storage) storeConfiguration() error {
return storeJSON(st.configuration_path, st.configuration)
return storeJSON(st.configuration_path, st.deprecatedConfiguration)
}
func (st *Storage) loadDisplayprefs() error {
return loadJSON(st.displayprefs_path, &st.displayprefs)
return loadJSON(st.displayprefs_path, &st.deprecatedDisplayprefs)
}
func (st *Storage) storeDisplayprefs() error {
return storeJSON(st.displayprefs_path, st.displayprefs)
return storeJSON(st.displayprefs_path, st.deprecatedDisplayprefs)
}
func (st *Storage) loadOmbiTemplate() error {
return loadJSON(st.ombi_path, &st.ombi_template)
return loadJSON(st.ombi_path, &st.deprecatedOmbiTemplate)
}
func (st *Storage) storeOmbiTemplate() error {
return storeJSON(st.ombi_path, st.ombi_template)
return storeJSON(st.ombi_path, st.deprecatedOmbiTemplate)
}
func (st *Storage) loadAnnouncements() error {
@ -1298,9 +1343,9 @@ func (st *Storage) migrateToProfile() error {
st.loadDisplayprefs()
st.loadProfiles()
st.deprecatedProfiles["Default"] = Profile{
Policy: st.policy,
Configuration: st.configuration,
Displayprefs: st.displayprefs,
Policy: st.deprecatedPolicy,
Configuration: st.deprecatedConfiguration,
Displayprefs: st.deprecatedDisplayprefs,
}
return st.storeProfiles()
}

View File

@ -224,13 +224,13 @@ func (app *appContext) MyUserPage(gc *gin.Context) {
data["discordInviteLink"] = app.discord.inviteChannelName != ""
}
pageMessages := map[string]*customContent{
"Login": app.getCustomMessage("UserLogin"),
"Page": app.getCustomMessage("UserPage"),
}
pageMessagesExist := map[string]bool{}
pageMessages := map[string]CustomContent{}
pageMessages["Login"], pageMessagesExist["Login"] = app.storage.GetCustomContentKey("UserLogin")
pageMessages["Page"], pageMessagesExist["Page"] = app.storage.GetCustomContentKey("UserPage")
for name, msg := range pageMessages {
if msg == nil {
if !pageMessagesExist[name] {
continue
}
data[name+"MessageEnabled"] = msg.Enabled