From d629cae71e028378abe572204011914451bf8cd7 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Sat, 2 Jan 2021 21:24:26 +0000 Subject: [PATCH] change config-base format to allow easier parsing *note*: only GetConfig has been changed for now. the config now has "order" and "sections", and each section now has "meta", "order" and "settings". This allows for the use of a struct for loading in Go and less janky web code. Also now appears in swagger. --- api.go | 49 +- config/config-base.json | 1343 ++++++++++++++++++++------------------- config/fixconfig.py | 18 +- config/generate_ini.py | 23 +- main.go | 2 +- models.go | 29 + 6 files changed, 761 insertions(+), 703 deletions(-) diff --git a/api.go b/api.go index e01920f..6507c6a 100644 --- a/api.go +++ b/api.go @@ -1072,13 +1072,14 @@ func (app *appContext) ApplySettings(gc *gin.Context) { // @Summary Get jfa-go configuration. // @Produce json -// @Success 200 {object} configDTO "Uses the same format as config-base.json" +// @Success 200 {object} settings "Uses the same format as config-base.json" // @Router /config [get] // @Security Bearer // @tags Configuration func (app *appContext) GetConfig(gc *gin.Context) { app.info.Println("Config requested") - resp := map[string]interface{}{} + resp := app.configBase + // Load language options langPath := filepath.Join(app.localPath, "lang", "form") app.lang.langFiles, _ = ioutil.ReadDir(langPath) app.lang.langOptions = make([]string, len(app.lang.langFiles)) @@ -1095,37 +1096,25 @@ func (app *appContext) GetConfig(gc *gin.Context) { app.lang.langOptions[i] = meta.(map[string]interface{})["name"].(string) } } - for section, settings := range app.configBase { - if section == "order" { - resp[section] = settings.([]interface{}) - } else { - resp[section] = make(map[string]interface{}) - for key, values := range settings.(map[string]interface{}) { - if key == "order" { - resp[section].(map[string]interface{})[key] = values.([]interface{}) - } else { - resp[section].(map[string]interface{})[key] = values.(map[string]interface{}) - if key != "meta" { - dataType := resp[section].(map[string]interface{})[key].(map[string]interface{})["type"].(string) - configKey := app.config.Section(section).Key(key) - if dataType == "number" { - if val, err := configKey.Int(); err == nil { - resp[section].(map[string]interface{})[key].(map[string]interface{})["value"] = val - } - } else if dataType == "bool" { - resp[section].(map[string]interface{})[key].(map[string]interface{})["value"] = configKey.MustBool(false) - } else if dataType == "select" && key == "language" { - resp[section].(map[string]interface{})[key].(map[string]interface{})["options"] = app.lang.langOptions - resp[section].(map[string]interface{})[key].(map[string]interface{})["value"] = app.lang.langOptions[app.lang.chosenIndex] - } else { - resp[section].(map[string]interface{})[key].(map[string]interface{})["value"] = configKey.String() - } - } - } + s := resp.Sections["ui"].Settings["language"] + s.Options = app.lang.langOptions + s.Value = app.lang.langOptions[app.lang.chosenIndex] + resp.Sections["ui"].Settings["language"] = s + for sectName, section := range resp.Sections { + for settingName, setting := range section.Settings { + val := app.config.Section(sectName).Key(settingName) + s := resp.Sections[sectName].Settings[settingName] + switch setting.Type { + case "text", "email", "select": + s.Value = val.MustString("") + case "number": + s.Value = val.MustInt(0) + case "bool": + s.Value = val.MustBool(false) } + resp.Sections[sectName].Settings[settingName] = s } } - // resp["jellyfin"].(map[string]interface{})["language"].(map[string]interface{})["options"].([]string) gc.JSON(200, resp) } diff --git a/config/config-base.json b/config/config-base.json index 21e95a2..476b7dd 100644 --- a/config/config-base.json +++ b/config/config-base.json @@ -1,668 +1,707 @@ { - "jellyfin": { - "meta": { - "name": "Jellyfin", - "description": "Settings for connecting to Jellyfin" + "order": [], + "sections": { + "jellyfin": { + "order": [], + "meta": { + "name": "Jellyfin", + "description": "Settings for connecting to Jellyfin" + }, + "settings": { + "username": { + "name": "Jellyfin Username", + "required": true, + "requires_restart": true, + "type": "text", + "value": "username", + "description": "It is recommended to create a limited admin account for this program." + }, + "password": { + "name": "Jellyfin Password", + "required": true, + "requires_restart": true, + "type": "password", + "value": "password" + }, + "server": { + "name": "Server address", + "required": true, + "requires_restart": true, + "type": "text", + "value": "http://jellyfin.local:8096", + "description": "Jellyfin server address. Can be public, or local for security purposes." + }, + "public_server": { + "name": "Public address", + "required": false, + "requires_restart": false, + "type": "text", + "value": "https://jellyf.in:443", + "description": "Publicly accessible Jellyfin address for invite form. Leave blank to reuse the above address." + }, + "client": { + "name": "Client Name", + "required": true, + "requires_restart": true, + "type": "text", + "value": "jfa-go", + "description": "The name of the client that will show up in the Jellyfin dashboard." + }, + "cache_timeout": { + "name": "User cache timeout (minutes)", + "required": false, + "requires_restart": true, + "type": "number", + "value": 30, + "description": "Timeout of user cache in minutes. Set to 0 to disable." + } + } }, - "username": { - "name": "Jellyfin Username", - "required": true, - "requires_restart": true, - "type": "text", - "value": "username", - "description": "It is recommended to create a limited admin account for this program." + "ui": { + "order": [], + "meta": { + "name": "General", + "description": "Settings related to the UI and program functionality." + }, + "settings": { + "language": { + "name": "Language", + "required": false, + "requires_restart": true, + "type": "select", + "options": [ + "en-us" + ], + "value": "en-US", + "description": "UI Language. Currently only implemented for account creation form. Submit a PR on github if you'd like to translate." + }, + "theme": { + "name": "Default Look", + "required": false, + "requires_restart": true, + "type": "select", + "options": [ + "Bootstrap (Light)", + "Jellyfin (Dark)", + "Custom CSS" + ], + "value": "Jellyfin (Dark)", + "description": "Default appearance for all users." + }, + "host": { + "name": "Address", + "required": true, + "requires_restart": true, + "type": "text", + "value": "0.0.0.0", + "description": "Set 0.0.0.0 to run on localhost" + }, + "port": { + "name": "Port", + "required": true, + "requires_restart": true, + "type": "number", + "value": 8056 + }, + "jellyfin_login": { + "name": "Use Jellyfin for authentication", + "required": false, + "requires_restart": true, + "type": "bool", + "value": true, + "description": "Enable this to use Jellyfin users instead of the below username and pw." + }, + "admin_only": { + "name": "Allow admin users only", + "required": false, + "requires_restart": true, + "depends_true": "jellyfin_login", + "type": "bool", + "value": true, + "description": "Allows only admin users on Jellyfin to access the admin page." + }, + "username": { + "name": "Web Username", + "required": true, + "requires_restart": true, + "depends_false": "jellyfin_login", + "type": "text", + "value": "your username", + "description": "Username for admin page (Leave blank if using jellyfin_login)" + }, + "password": { + "name": "Web Password", + "required": true, + "requires_restart": true, + "depends_false": "jellyfin_login", + "type": "password", + "value": "your password", + "description": "Password for admin page (Leave blank if using jellyfin_login)" + }, + "email": { + "name": "Admin email address", + "required": false, + "requires_restart": false, + "depends_false": "jellyfin_login", + "type": "text", + "value": "example@example.com", + "description": "Address to send notifications to (Leave blank if using jellyfin_login)" + }, + "debug": { + "name": "Debug logging", + "required": false, + "requires_restart": true, + "type": "bool", + "value": false, + "description": "Enables debug logging and exposes pprof as a route (Don't use in production!)" + }, + "contact_message": { + "name": "Contact message", + "required": false, + "requires_restart": false, + "type": "text", + "value": "Need help? contact me.", + "description": "Displayed at bottom of all pages except admin" + }, + "help_message": { + "name": "Help message", + "required": false, + "requires_restart": false, + "type": "text", + "value": "Enter your details to create an account.", + "description": "Displayed at top of invite form." + }, + "success_message": { + "name": "Success message", + "required": false, + "requires_restart": false, + "type": "text", + "value": "Your account has been created. Click below to continue to Jellyfin.", + "description": "Displayed when a user creates an account" + }, + "bs5": { + "name": "Use Bootstrap 5", + "required": false, + "requires_restart": true, + "type": "bool", + "value": false, + "description": "Use the Bootstrap 5 Alpha. Looks better and removes the need for jQuery, so the page should load faster." + }, + "url_base": { + "name": "URL Base", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "URL base for when running jfa-go with a reverse proxy in a subfolder." + } + } }, - "password": { - "name": "Jellyfin Password", - "required": true, - "requires_restart": true, - "type": "password", - "value": "password" - }, - "server": { - "name": "Server address", - "required": true, - "requires_restart": true, - "type": "text", - "value": "http://jellyfin.local:8096", - "description": "Jellyfin server address. Can be public, or local for security purposes." - }, - "public_server": { - "name": "Public address", - "required": false, - "requires_restart": false, - "type": "text", - "value": "https://jellyf.in:443", - "description": "Publicly accessible Jellyfin address for invite form. Leave blank to reuse the above address." - }, - "client": { - "name": "Client Name", - "required": true, - "requires_restart": true, - "type": "text", - "value": "jfa-go", - "description": "The name of the client that will show up in the Jellyfin dashboard." - }, - "cache_timeout": { - "name": "User cache timeout (minutes)", - "required": false, - "requires_restart": true, - "type": "number", - "value": 30, - "description": "Timeout of user cache in minutes. Set to 0 to disable." - } - }, - "ui": { - "meta": { - "name": "General", - "description": "Settings related to the UI and program functionality." - }, - "language": { - "name": "Language", - "required": false, - "requires_restart": true, - "type": "select", - "options": [ - "en-us" - ], - "value": "en-US", - "description": "UI Language. Currently only implemented for account creation form. Submit a PR on github if you'd like to translate." - }, - "theme": { - "name": "Default Look", - "required": false, - "requires_restart": true, - "type": "select", - "options": [ - "Bootstrap (Light)", - "Jellyfin (Dark)", - "Custom CSS" - ], - "value": "Jellyfin (Dark)", - "description": "Default appearance for all users." - }, - "host": { - "name": "Address", - "required": true, - "requires_restart": true, - "type": "text", - "value": "0.0.0.0", - "description": "Set 0.0.0.0 to run on localhost" - }, - "port": { - "name": "Port", - "required": true, - "requires_restart": true, - "type": "number", - "value": 8056 - }, - "jellyfin_login": { - "name": "Use Jellyfin for authentication", - "required": false, - "requires_restart": true, - "type": "bool", - "value": true, - "description": "Enable this to use Jellyfin users instead of the below username and pw." - }, - "admin_only": { - "name": "Allow admin users only", - "required": false, - "requires_restart": true, - "depends_true": "jellyfin_login", - "type": "bool", - "value": true, - "description": "Allows only admin users on Jellyfin to access the admin page." - }, - "username": { - "name": "Web Username", - "required": true, - "requires_restart": true, - "depends_false": "jellyfin_login", - "type": "text", - "value": "your username", - "description": "Username for admin page (Leave blank if using jellyfin_login)" - }, - "password": { - "name": "Web Password", - "required": true, - "requires_restart": true, - "depends_false": "jellyfin_login", - "type": "password", - "value": "your password", - "description": "Password for admin page (Leave blank if using jellyfin_login)" + "password_validation": { + "order": [], + "meta": { + "name": "Password Validation", + "description": "Password validation (minimum length, etc.)" + }, + "settings": { + "enabled": { + "name": "Enabled", + "required": false, + "requires_restart": false, + "type": "bool", + "value": true + }, + "min_length": { + "name": "Minimum Length", + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "8" + }, + "upper": { + "name": "Minimum uppercase characters", + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "1" + }, + "lower": { + "name": "Minimum lowercase characters", + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "0" + }, + "number": { + "name": "Minimum number count", + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "1" + }, + "special": { + "name": "Minimum number of special characters", + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "0" + } + } }, "email": { - "name": "Admin email address", - "required": false, - "requires_restart": false, - "depends_false": "jellyfin_login", - "type": "text", - "value": "example@example.com", - "description": "Address to send notifications to (Leave blank if using jellyfin_login)" + "order": [], + "meta": { + "name": "Email", + "description": "General email settings. Ignore if not using email features." + }, + "settings": { + "no_username": { + "name": "Use email addresses as username", + "required": false, + "requires_restart": false, + "depends_true": "method", + "type": "bool", + "value": false, + "description": "Use email address from invite form as username on Jellyfin." + }, + "use_24h": { + "name": "Use 24h time", + "required": false, + "requires_restart": false, + "depends_true": "method", + "type": "bool", + "value": true + }, + "date_format": { + "name": "Date format", + "required": false, + "requires_restart": false, + "depends_true": "method", + "type": "text", + "value": "%d/%m/%y", + "description": "Date format used in emails. Follows datetime.strftime format." + }, + "message": { + "name": "Help message", + "required": false, + "requires_restart": false, + "depends_true": "method", + "type": "text", + "value": "Need help? contact me.", + "description": "Message displayed at bottom of emails." + }, + "method": { + "name": "Email method", + "required": false, + "requires_restart": false, + "type": "select", + "options": [ + "smtp", + "mailgun" + ], + "value": "smtp", + "description": "Method of sending email to use." + }, + "address": { + "name": "Sent from (address)", + "required": false, + "requires_restart": false, + "depends_true": "method", + "type": "email", + "value": "jellyfin@jellyf.in", + "description": "Address to send emails from" + }, + "from": { + "name": "Sent from (name)", + "required": false, + "requires_restart": false, + "depends_true": "method", + "type": "text", + "value": "Jellyfin", + "description": "The name of the sender" + } + } }, - "debug": { - "name": "Debug logging", - "required": false, - "requires_restart": true, - "type": "bool", - "value": false, - "description": "Enables debug logging and exposes pprof as a route (Don't use in production!)" + "password_resets": { + "order": [], + "meta": { + "name": "Password Resets", + "description": "Settings for the password reset handler." + }, + "settings": { + "enabled": { + "name": "Enabled", + "required": false, + "requires_restart": true, + "type": "bool", + "value": true, + "description": "Enable to store provided email addresses, monitor Jellyfin directory for pw-resets, and send reset pins" + }, + "watch_directory": { + "name": "Jellyfin directory", + "required": false, + "requires_restart": true, + "depends_true": "enabled", + "type": "text", + "value": "/path/to/jellyfin", + "description": "Path to the folder Jellyfin puts password-reset files." + }, + "email_html": { + "name": "Custom email (HTML)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to custom email html" + }, + "email_text": { + "name": "Custom email (plaintext)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to custom email in plain text" + }, + "subject": { + "name": "Email subject", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "Password Reset - Jellyfin", + "description": "Subject of password reset emails." + } + } }, - "contact_message": { - "name": "Contact message", - "required": false, - "requires_restart": false, - "type": "text", - "value": "Need help? contact me.", - "description": "Displayed at bottom of all pages except admin" + "invite_emails": { + "order": [], + "meta": { + "name": "Invite emails", + "description": "Settings for sending invites directly to users." + }, + "settings": { + "enabled": { + "name": "Enabled", + "required": false, + "requires_restart": false, + "type": "bool", + "value": true + }, + "email_html": { + "name": "Custom email (HTML)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to custom email HTML" + }, + "email_text": { + "name": "Custom email (plaintext)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to custom email in plain text" + }, + "subject": { + "name": "Email subject", + "required": true, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "Invite - Jellyfin", + "description": "Subject of invite emails." + }, + "url_base": { + "name": "URL Base", + "required": true, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "http://accounts.jellyf.in:8056/invite", + "description": "Base URL for jfa-go. This is necessary because using a reverse proxy means the program has no way of knowing the URL itself." + } + } }, - "help_message": { - "name": "Help message", - "required": false, - "requires_restart": false, - "type": "text", - "value": "Enter your details to create an account.", - "description": "Displayed at top of invite form." + "notifications": { + "order": [], + "meta": { + "name": "Notifications", + "description": "Notification related settings." + }, + "settings": { + "enabled": { + "name": "Enabled", + "required": "false", + "requires_restart": true, + "type": "bool", + "value": true, + "description": "Enabling adds optional toggles to invites to notify on expiry and user creation." + }, + "expiry_html": { + "name": "Expiry email (HTML)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to expiry notification email HTML." + }, + "expiry_text": { + "name": "Expiry email (Plaintext)", + "required": false, + "requires_restart": "false", + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to expiry notification email in plaintext." + }, + "created_html": { + "name": "User created email (HTML)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to user creation notification email HTML." + }, + "created_text": { + "name": "User created email (Plaintext)", + "required": false, + "requires_restart": false, + "depends_true": "enabled", + "type": "text", + "value": "", + "description": "Path to user creation notification email in plaintext." + } + } }, - "success_message": { - "name": "Success message", - "required": false, - "requires_restart": false, - "type": "text", - "value": "Your account has been created. Click below to continue to Jellyfin.", - "description": "Displayed when a user creates an account" + "mailgun": { + "order": [], + "meta": { + "name": "Mailgun (Email)", + "description": "Mailgun API connection settings" + }, + "settings": { + "api_url": { + "name": "API URL", + "required": false, + "requires_restart": false, + "type": "text", + "value": "https://api.mailgun.net..." + }, + "api_key": { + "name": "API Key", + "required": false, + "requires_restart": false, + "type": "text", + "value": "your api key" + } + } }, - "bs5": { - "name": "Use Bootstrap 5", - "required": false, - "requires_restart": true, - "type": "bool", - "value": false, - "description": "Use the Bootstrap 5 Alpha. Looks better and removes the need for jQuery, so the page should load faster." + "smtp": { + "order": [], + "meta": { + "name": "SMTP (Email)", + "description": "SMTP Server connection settings." + }, + "settings": { + "username": { + "name": "Username", + "required": false, + "requires_restart": false, + "type": "text", + "value": "", + "description": "Username for SMTP. Leave blank to user send from address as username." + }, + "encryption": { + "name": "Encryption Method", + "required": false, + "requires_restart": false, + "type": "select", + "options": [ + "ssl_tls", + "starttls" + ], + "value": "starttls", + "description": "Your email provider should provide different ports for each encryption method. Generally 465 for ssl_tls, 587 for starttls." + }, + "server": { + "name": "Server address", + "required": false, + "requires_restart": false, + "type": "text", + "value": "smtp.jellyf.in", + "description": "SMTP Server address." + }, + "port": { + "name": "Port", + "required": false, + "requires_restart": false, + "type": "number", + "value": 465 + }, + "password": { + "name": "Password", + "required": false, + "requires_restart": false, + "type": "password", + "value": "smtp password" + } + } }, - "url_base": { - "name": "URL Base", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "URL base for when running jfa-go with a reverse proxy in a subfolder." - } - }, - "password_validation": { - "meta": { - "name": "Password Validation", - "description": "Password validation (minimum length, etc.)" + "ombi": { + "order": [], + "meta": { + "name": "Ombi Integration", + "description": "Connect to Ombi to automatically create both Ombi and Jellyfin accounts for new users. You'll need to create a user template for this to work. Once enabled, refresh to see an option in settings for this." + }, + "settings": { + "enabled": { + "name": "Enabled", + "required": false, + "requires_restart": true, + "type": "bool", + "value": false, + "description": "Enable to create an Ombi account for new Jellyfin users" + }, + "server": { + "name": "URL", + "required": false, + "requires_restart": true, + "type": "text", + "value": "localhost:5000", + "depends_true": "enabled", + "description": "Ombi server URL, including http(s)://." + }, + "api_key": { + "name": "API Key", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "depends_true": "enabled", + "description": "API Key. Get this from the first tab in Ombi settings." + } + } }, - "enabled": { - "name": "Enabled", - "required": false, - "requires_restart": false, - "type": "bool", - "value": true + "deletion": { + "order": [], + "meta": { + "name": "Account Deletion", + "description": "Subject/email files for account deletion emails." + }, + "settings": { + "subject": { + "name": "Email subject", + "required": false, + "requires_restart": false, + "type": "text", + "value": "Your account was deleted - Jellyfin", + "description": "Subject of account deletion emails." + }, + "email_html": { + "name": "Custom email (HTML)", + "required": false, + "requires_restart": false, + "type": "text", + "value": "", + "description": "Path to custom email html" + }, + "email_text": { + "name": "Custom email (plaintext)", + "required": false, + "requires_restart": false, + "type": "text", + "value": "", + "description": "Path to custom email in plain text" + } + } }, - "min_length": { - "name": "Minimum Length", - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "8" - }, - "upper": { - "name": "Minimum uppercase characters", - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "1" - }, - "lower": { - "name": "Minimum lowercase characters", - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "0" - }, - "number": { - "name": "Minimum number count", - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "1" - }, - "special": { - "name": "Minimum number of special characters", - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "0" - } - }, - "email": { - "meta": { - "name": "Email", - "description": "General email settings. Ignore if not using email features." - }, - "no_username": { - "name": "Use email addresses as username", - "required": false, - "requires_restart": false, - "depends_true": "method", - "type": "bool", - "value": false, - "description": "Use email address from invite form as username on Jellyfin." - }, - "use_24h": { - "name": "Use 24h time", - "required": false, - "requires_restart": false, - "depends_true": "method", - "type": "bool", - "value": true - }, - "date_format": { - "name": "Date format", - "required": false, - "requires_restart": false, - "depends_true": "method", - "type": "text", - "value": "%d/%m/%y", - "description": "Date format used in emails. Follows datetime.strftime format." - }, - "message": { - "name": "Help message", - "required": false, - "requires_restart": false, - "depends_true": "method", - "type": "text", - "value": "Need help? contact me.", - "description": "Message displayed at bottom of emails." - }, - "method": { - "name": "Email method", - "required": false, - "requires_restart": false, - "type": "select", - "options": [ - "smtp", - "mailgun" - ], - "value": "smtp", - "description": "Method of sending email to use." - }, - "address": { - "name": "Sent from (address)", - "required": false, - "requires_restart": false, - "depends_true": "method", - "type": "email", - "value": "jellyfin@jellyf.in", - "description": "Address to send emails from" - }, - "from": { - "name": "Sent from (name)", - "required": false, - "requires_restart": false, - "depends_true": "method", - "type": "text", - "value": "Jellyfin", - "description": "The name of the sender" - } - }, - "password_resets": { - "meta": { - "name": "Password Resets", - "description": "Settings for the password reset handler." - }, - "enabled": { - "name": "Enabled", - "required": false, - "requires_restart": true, - "type": "bool", - "value": true, - "description": "Enable to store provided email addresses, monitor Jellyfin directory for pw-resets, and send reset pins" - }, - "watch_directory": { - "name": "Jellyfin directory", - "required": false, - "requires_restart": true, - "depends_true": "enabled", - "type": "text", - "value": "/path/to/jellyfin", - "description": "Path to the folder Jellyfin puts password-reset files." - }, - "email_html": { - "name": "Custom email (HTML)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to custom email html" - }, - "email_text": { - "name": "Custom email (plaintext)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to custom email in plain text" - }, - "subject": { - "name": "Email subject", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "Password Reset - Jellyfin", - "description": "Subject of password reset emails." - } - }, - "invite_emails": { - "meta": { - "name": "Invite emails", - "description": "Settings for sending invites directly to users." - }, - "enabled": { - "name": "Enabled", - "required": false, - "requires_restart": false, - "type": "bool", - "value": true - }, - "email_html": { - "name": "Custom email (HTML)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to custom email HTML" - }, - "email_text": { - "name": "Custom email (plaintext)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to custom email in plain text" - }, - "subject": { - "name": "Email subject", - "required": true, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "Invite - Jellyfin", - "description": "Subject of invite emails." - }, - "url_base": { - "name": "URL Base", - "required": true, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "http://accounts.jellyf.in:8056/invite", - "description": "Base URL for jfa-go. This is necessary because using a reverse proxy means the program has no way of knowing the URL itself." - } - }, - "notifications": { - "meta": { - "name": "Notifications", - "description": "Notification related settings." - }, - "enabled": { - "name": "Enabled", - "required": "false", - "requires_restart": true, - "type": "bool", - "value": true, - "description": "Enabling adds optional toggles to invites to notify on expiry and user creation." - }, - "expiry_html": { - "name": "Expiry email (HTML)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to expiry notification email HTML." - }, - "expiry_text": { - "name": "Expiry email (Plaintext)", - "required": false, - "requires_restart": "false", - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to expiry notification email in plaintext." - }, - "created_html": { - "name": "User created email (HTML)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to user creation notification email HTML." - }, - "created_text": { - "name": "User created email (Plaintext)", - "required": false, - "requires_restart": false, - "depends_true": "enabled", - "type": "text", - "value": "", - "description": "Path to user creation notification email in plaintext." - } - }, - "mailgun": { - "meta": { - "name": "Mailgun (Email)", - "description": "Mailgun API connection settings" - }, - "api_url": { - "name": "API URL", - "required": false, - "requires_restart": false, - "type": "text", - "value": "https://api.mailgun.net..." - }, - "api_key": { - "name": "API Key", - "required": false, - "requires_restart": false, - "type": "text", - "value": "your api key" - } - }, - "smtp": { - "meta": { - "name": "SMTP (Email)", - "description": "SMTP Server connection settings." - }, - "username": { - "name": "Username", - "required": false, - "requires_restart": false, - "type": "text", - "value": "", - "description": "Username for SMTP. Leave blank to user send from address as username." - }, - "encryption": { - "name": "Encryption Method", - "required": false, - "requires_restart": false, - "type": "select", - "options": [ - "ssl_tls", - "starttls" - ], - "value": "starttls", - "description": "Your email provider should provide different ports for each encryption method. Generally 465 for ssl_tls, 587 for starttls." - }, - "server": { - "name": "Server address", - "required": false, - "requires_restart": false, - "type": "text", - "value": "smtp.jellyf.in", - "description": "SMTP Server address." - }, - "port": { - "name": "Port", - "required": false, - "requires_restart": false, - "type": "number", - "value": 465 - }, - "password": { - "name": "Password", - "required": false, - "requires_restart": false, - "type": "password", - "value": "smtp password" - } - }, - "ombi": { - "meta": { - "name": "Ombi Integration", - "description": "Connect to Ombi to automatically create both Ombi and Jellyfin accounts for new users. You'll need to create a user template for this to work. Once enabled, refresh to see an option in settings for this." - }, - "enabled": { - "name": "Enabled", - "required": false, - "requires_restart": true, - "type": "bool", - "value": false, - "description": "Enable to create an Ombi account for new Jellyfin users" - }, - "server": { - "name": "URL", - "required": false, - "requires_restart": true, - "type": "text", - "value": "localhost:5000", - "depends_true": "enabled", - "description": "Ombi server URL, including http(s)://." - }, - "api_key": { - "name": "API Key", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "depends_true": "enabled", - "description": "API Key. Get this from the first tab in Ombi settings." - } - }, - "deletion": { - "meta": { - "name": "Account Deletion", - "description": "Subject/email files for account deletion emails." - }, - "subject": { - "name": "Email subject", - "required": false, - "requires_restart": false, - "type": "text", - "value": "Your account was deleted - Jellyfin", - "description": "Subject of account deletion emails." - }, - "email_html": { - "name": "Custom email (HTML)", - "required": false, - "requires_restart": false, - "type": "text", - "value": "", - "description": "Path to custom email html" - }, - "email_text": { - "name": "Custom email (plaintext)", - "required": false, - "requires_restart": false, - "type": "text", - "value": "", - "description": "Path to custom email in plain text" - } - }, - "files": { - "meta": { - "name": "File Storage", - "description": "Optional settings for changing storage locations." - }, - "invites": { - "name": "Invite Storage", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Location of stored invites (json)." - }, - "emails": { - "name": "Email Addresses", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Location of stored email addresses (json)." - }, - "ombi_template": { - "name": "Ombi user template", - "required": false, - "requires_restart": false, - "type": "text", - "value": "", - "description": "Location of stored Ombi user template." - }, - "user_template": { - "name": "User Template (Deprecated)", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Deprecated in favor of User Profiles. Location of stored user policy template (json)." - }, - "user_configuration": { - "name": "userConfiguration (Deprecated)", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Deprecated in favor of User Profiles. Location of stored user configuration template (used for setting homescreen layout) (json)" - }, - "user_displayprefs": { - "name": "displayPreferences (Deprecated)", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Deprecated in favor of User Profiles. Location of stored displayPreferences template (also used for homescreen layout) (json)" - }, - "user_profiles": { - "name": "User Profiles", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Location of stored user profiles (encompasses template and configuration and displayprefs) (json)" - }, - "custom_css": { - "name": "Custom CSS", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Location of custom bootstrap CSS." - }, - "html_templates": { - "name": "Custom HTML Template Directory", - "required": false, - "requires_restart": true, - "type": "text", - "value": "", - "description": "Path to directory containing custom versions of web ui pages. See wiki for more info." + "files": { + "order": [], + "meta": { + "name": "File Storage", + "description": "Optional settings for changing storage locations." + }, + "settings": { + "invites": { + "name": "Invite Storage", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of stored invites (json)." + }, + "emails": { + "name": "Email Addresses", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of stored email addresses (json)." + }, + "ombi_template": { + "name": "Ombi user template", + "required": false, + "requires_restart": false, + "type": "text", + "value": "", + "description": "Location of stored Ombi user template." + }, + "user_template": { + "name": "User Template (Deprecated)", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Deprecated in favor of User Profiles. Location of stored user policy template (json)." + }, + "user_configuration": { + "name": "userConfiguration (Deprecated)", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Deprecated in favor of User Profiles. Location of stored user configuration template (used for setting homescreen layout) (json)" + }, + "user_displayprefs": { + "name": "displayPreferences (Deprecated)", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Deprecated in favor of User Profiles. Location of stored displayPreferences template (also used for homescreen layout) (json)" + }, + "user_profiles": { + "name": "User Profiles", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of stored user profiles (encompasses template and configuration and displayprefs) (json)" + }, + "custom_css": { + "name": "Custom CSS", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of custom bootstrap CSS." + }, + "html_templates": { + "name": "Custom HTML Template Directory", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Path to directory containing custom versions of web ui pages. See wiki for more info." + } + } } } } diff --git a/config/fixconfig.py b/config/fixconfig.py index 180f2e4..2cf90b4 100644 --- a/config/fixconfig.py +++ b/config/fixconfig.py @@ -9,17 +9,17 @@ args = parser.parse_args() with open(args.input, 'r') as f: config = json.load(f) -newconfig = {"order": []} +newconfig = {"sections": {}, "order": []} -for sect in config: +for sect in config["sections"]: newconfig["order"].append(sect) - newconfig[sect] = {} - newconfig[sect]["order"] = [] - newconfig[sect]["meta"] = config[sect]["meta"] - for setting in config[sect]: - if setting != "meta": - newconfig[sect]["order"].append(setting) - newconfig[sect][setting] = config[sect][setting] + newconfig["sections"][sect] = {} + newconfig["sections"][sect]["order"] = [] + newconfig["sections"][sect]["meta"] = config["sections"][sect]["meta"] + newconfig["sections"][sect]["settings"] = {} + for setting in config["sections"][sect]["settings"]: + newconfig["sections"][sect]["order"].append(setting) + newconfig["sections"][sect]["settings"][setting] = config["sections"][sect]["settings"][setting] with open(args.output, 'w') as f: f.write(json.dumps(newconfig, indent=4)) diff --git a/config/generate_ini.py b/config/generate_ini.py index efc8c0a..a801b8b 100644 --- a/config/generate_ini.py +++ b/config/generate_ini.py @@ -14,18 +14,19 @@ def generate_ini(base_file, ini_file): ini = configparser.RawConfigParser(allow_no_value=True) - for section in config_base: + for section in config_base["sections"]: ini.add_section(section) - for entry in config_base[section]: - if "description" in config_base[section][entry]: - ini.set(section, "; " + config_base[section][entry]["description"]) - if entry != "meta": - value = config_base[section][entry]["value"] - if isinstance(value, bool): - value = str(value).lower() - else: - value = str(value) - ini.set(section, entry, value) + if "meta" in config_base["sections"][section]: + ini.set(section, "; " + config_base["sections"][section]["meta"]["description"]) + for entry in config_base["sections"][section]["settings"]: + if "description" in config_base["sections"][section]["settings"][entry]: + ini.set(section, "; " + config_base["sections"][section]["settings"][entry]["description"]) + value = config_base["sections"][section]["settings"][entry]["value"] + if isinstance(value, bool): + value = str(value).lower() + else: + value = str(value) + ini.set(section, entry, value) with open(Path(ini_file), "w") as config_file: ini.write(config_file) diff --git a/main.go b/main.go index c450c52..b041bca 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ type appContext struct { config *ini.File configPath string configBasePath string - configBase map[string]interface{} + configBase settings dataPath string localPath string cssFile string diff --git a/models.go b/models.go index 9235317..d8d8381 100644 --- a/models.go +++ b/models.go @@ -127,3 +127,32 @@ type errorListDTO map[string]map[string]string type configDTO map[string]interface{} +// Below are for sending config + +type meta struct { + Name string `json:"name"` + Description string `json:"description"` +} + +type setting struct { + Name string `json:"name"` + Description string `json:"description"` + Required bool `json:"required"` + RequiresRestart bool `json:"requires_restart"` + Type string `json:"type"` // Type (string, number, bool, etc.) + Value interface{} `json:"value"` + Options []string `json:"options,omitempty"` + DependsTrue string `json:"depends_true,omitempty"` // If specified, this field is enabled when the specified bool setting is enabled. + DependsFalse string `json:"depends_false,omitempty"` // If specified, opposite behaviour of DependsTrue. +} + +type section struct { + Meta meta `json:"meta"` + Order []string `json:"order"` + Settings map[string]setting `json:"settings"` +} + +type settings struct { + Order []string `json:"order"` + Sections map[string]section `json:"sections"` +}