From 024c0b56aafdaf92b4618b6f82fe93f55967bad7 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Fri, 31 Jul 2020 16:09:30 +0100 Subject: [PATCH] Display settings with hacky solution to retain order Python utility included to convert config-base.json into a new version which includes lists that define the order settings should be displayed. admin.js edited to recognize this. --- api.go | 33 +++ data/config-base.json | 95 ++++++- data/static/admin.js | 8 +- fixconfig/README.md | 5 + fixconfig/config-base.json | 567 +++++++++++++++++++++++++++++++++++++ fixconfig/fixconfig.py | 21 ++ go.mod | 2 + go.sum | 61 ++++ main.go | 39 ++- 9 files changed, 811 insertions(+), 20 deletions(-) create mode 100644 fixconfig/README.md create mode 100644 fixconfig/config-base.json create mode 100644 fixconfig/fixconfig.py diff --git a/api.go b/api.go index e0cab13..d944534 100644 --- a/api.go +++ b/api.go @@ -461,3 +461,36 @@ func (ctx *appContext) SetDefaults(gc *gin.Context) { } gc.JSON(200, map[string]bool{"success": true}) } + +func (ctx *appContext) GetConfig(gc *gin.Context) { + resp := map[string]interface{}{} + for section, settings := range ctx.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" { + fmt.Println(resp[section].(map[string]interface{})[key].(map[string]interface{})) + dataType := resp[section].(map[string]interface{})[key].(map[string]interface{})["type"].(string) + configKey := ctx.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 { + resp[section].(map[string]interface{})[key].(map[string]interface{})["value"] = configKey.String() + } + } + } + } + } + } + gc.JSON(200, resp) +} diff --git a/data/config-base.json b/data/config-base.json index 08dd0e2..e471b08 100644 --- a/data/config-base.json +++ b/data/config-base.json @@ -1,5 +1,27 @@ { + "order": [ + "jellyfin", + "ui", + "password_validation", + "email", + "password_resets", + "invite_emails", + "notifications", + "mailgun", + "smtp", + "files" + ], "jellyfin": { + "order": [ + "username", + "password", + "server", + "public_server", + "client", + "version", + "device", + "device_id" + ], "meta": { "name": "Jellyfin", "description": "Settings for connecting to Jellyfin" @@ -66,6 +88,21 @@ } }, "ui": { + "order": [ + "theme", + "host", + "port", + "jellyfin_login", + "admin_only", + "username", + "password", + "email", + "debug", + "contact_message", + "help_message", + "success_message", + "bs5" + ], "meta": { "name": "General", "description": "Settings related to the UI and program functionality." @@ -183,6 +220,14 @@ } }, "password_validation": { + "order": [ + "enabled", + "min_length", + "upper", + "lower", + "number", + "special" + ], "meta": { "name": "Password Validation", "description": "Password validation (minimum length, etc.)" @@ -231,6 +276,15 @@ } }, "email": { + "order": [ + "no_username", + "use_24h", + "date_format", + "message", + "method", + "address", + "from" + ], "meta": { "name": "Email", "description": "General email settings. Ignore if not using email features." @@ -302,6 +356,13 @@ } }, "password_resets": { + "order": [ + "enabled", + "watch_directory", + "email_html", + "email_text", + "subject" + ], "meta": { "name": "Password Resets", "description": "Settings for the password reset handler." @@ -352,6 +413,13 @@ } }, "invite_emails": { + "order": [ + "enabled", + "email_html", + "email_text", + "subject", + "url_base" + ], "meta": { "name": "Invite emails", "description": "Settings for sending invites directly to users." @@ -401,6 +469,13 @@ } }, "notifications": { + "order": [ + "enabled", + "expiry_html", + "expiry_text", + "created_html", + "created_text" + ], "meta": { "name": "Notifications", "description": "Notification related settings." @@ -451,6 +526,10 @@ } }, "mailgun": { + "order": [ + "api_url", + "api_key" + ], "meta": { "name": "Mailgun (Email)", "description": "Mailgun API connection settings" @@ -471,6 +550,12 @@ } }, "smtp": { + "order": [ + "encryption", + "server", + "port", + "password" + ], "meta": { "name": "SMTP (Email)", "description": "SMTP Server connection settings." @@ -511,6 +596,14 @@ } }, "files": { + "order": [ + "invites", + "emails", + "user_template", + "user_configuration", + "user_displayprefs", + "custom_css" + ], "meta": { "name": "File Storage", "description": "Optional settings for changing storage locations." @@ -564,4 +657,4 @@ "description": "Location of custom bootstrap CSS." } } -} +} \ No newline at end of file diff --git a/data/static/admin.js b/data/static/admin.js index 77a09ea..139edef 100644 --- a/data/static/admin.js +++ b/data/static/admin.js @@ -776,7 +776,7 @@ document.getElementById('openSettings').onclick = function () { let settingsList = document.getElementById('settingsList'); settingsList.textContent = ''; config = this.response; - for (let section of Object.keys(config)) { + for (let section of config["order"]) { let sectionCollapse = document.createElement('div'); sectionCollapse.classList.add('collapse'); sectionCollapse.id = section; @@ -796,7 +796,7 @@ document.getElementById('openSettings').onclick = function () { sectionCollapse.innerHTML = innerCollapse; - for (var entry of Object.keys(config[section])) { + for (var entry of config[section]["order"]) { if (entry != 'meta') { let entryName = config[section][entry]['name']; let required = false; @@ -923,8 +923,8 @@ document.getElementById('settingsSave').onclick = function() { var restart_setting_changed = false; var settings_changed = false; - for (let section of Object.keys(config)) { - for (let entry of Object.keys(config[section])) { + for (let section of config["order"]) { + for (let entry of config[section]["order"]) { if (entry != 'meta') { let entryID = section + '_' + entry; let el = document.getElementById(entryID); diff --git a/fixconfig/README.md b/fixconfig/README.md new file mode 100644 index 0000000..060a44d --- /dev/null +++ b/fixconfig/README.md @@ -0,0 +1,5 @@ +## fixconfig + +Python's `json` library retains the order of data in a JSON file, which meant settings sent to the web page would be in the right order. Go's `encoding/json` and maps do not retain order, so this script opens the json file, and for each section, adds an "order" list which tells the web page in which order to display settings. + +Place the config base at `./config-base.json`, run `python fixconfig.py`, and the new config base will be stored at `./ordered-config-base.json`. diff --git a/fixconfig/config-base.json b/fixconfig/config-base.json new file mode 100644 index 0000000..08dd0e2 --- /dev/null +++ b/fixconfig/config-base.json @@ -0,0 +1,567 @@ +{ + "jellyfin": { + "meta": { + "name": "Jellyfin", + "description": "Settings for connecting to Jellyfin" + }, + "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": "jf-accounts", + "description": "This and below settings will show on the Jellyfin dashboard when the program connects. You may as well leave them alone." + }, + "version": { + "name": "Version Number", + "required": true, + "requires_restart": true, + "type": "text", + "value": "{version}" + }, + "device": { + "name": "Device Name", + "required": true, + "requires_restart": true, + "type": "text", + "value": "jf-accounts" + }, + "device_id": { + "name": "Device ID", + "required": true, + "requires_restart": true, + "type": "text", + "value": "jf-accounts-{version}" + } + }, + "ui": { + "meta": { + "name": "General", + "description": "Settings related to the UI and program functionality." + }, + "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 + }, + "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": false, + "type": "bool", + "value": false, + "description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster." + } + }, + "password_validation": { + "meta": { + "name": "Password Validation", + "description": "Password validation (minimum length, etc.)" + }, + "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": { + "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 jf-accounts. 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." + }, + "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" + } + }, + "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)." + }, + "user_template": { + "name": "User Template", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of stored user policy template (json)." + }, + "user_configuration": { + "name": "userConfiguration", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of stored user configuration template (used for setting homescreen layout) (json)" + }, + "user_displayprefs": { + "name": "displayPreferences", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of stored displayPreferences template (also used for homescreen layout) (json)" + }, + "custom_css": { + "name": "Custom CSS", + "required": false, + "requires_restart": true, + "type": "text", + "value": "", + "description": "Location of custom bootstrap CSS." + } + } +} diff --git a/fixconfig/fixconfig.py b/fixconfig/fixconfig.py new file mode 100644 index 0000000..65f3d5a --- /dev/null +++ b/fixconfig/fixconfig.py @@ -0,0 +1,21 @@ +import json + +with open('config-base.json', 'r') as f: + config = json.load(f) + +newconfig = {"order": []} + +for sect in config: + 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] + +with open('ordered-config-base.json', 'w') as f: + f.write(json.dumps(newconfig, indent=4)) + + diff --git a/go.mod b/go.mod index d481cc3..a4aadc5 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,9 @@ require ( github.com/spf13/cast v1.3.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + gitlab.com/c0b/go-ordered-json v0.0.0-20171130231205-49bbdab258c2 gitlab.com/go-box/pongo2gin v0.0.0-20180611101114-fb2c4f0fe00f + go.mongodb.org/mongo-driver v1.4.0 go.starlark.net v0.0.0-20200723213555-f21d2f77688f // indirect golang.org/x/arch v0.0.0-20200511175325-f7c78586839d // indirect golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 // indirect diff --git a/go.sum b/go.sum index fe9df9d..95dc098 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/astaxie/beego v1.12.1/go.mod h1:kPBWpSANNbSdIqOc8SUL9h+1oyBMZhROeYsXQDbidWQ= github.com/astaxie/beego v1.12.2 h1:CajUexhSX5ONWDiSCpeQBNVfTzOtPb9e9d+3vuU5FuU= github.com/astaxie/beego v1.12.2/go.mod h1:TMcqhsbhN3UFpN+RCfysaxPAbrhox6QSS3NIAEp/uzE= +github.com/aws/aws-sdk-go v1.29.15/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/beego/bee v1.12.0 h1:8KkeTxJSAJpC7mKPAI/jrMChgo2W82WZBawO/yp08qE= github.com/beego/bee v1.12.0/go.mod h1:JzjsS3OVzIYTJUmApBIOPmvV+LSS3WsYyObCNQlYsno= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= @@ -124,9 +125,34 @@ github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobuffalo/envy v1.9.0 h1:eZR0DuEgVLfeIb1zIKt3bT4YovIMf9O9LXQeCZLXpqE= github.com/gobuffalo/envy v1.9.0/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -148,6 +174,7 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -197,6 +224,7 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -212,11 +240,15 @@ github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9/go.mod h1:W54LbzXuIE0b github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/knz/strtime v0.0.0-20200318182718-be999391ffa9 h1:GQE1iatYDRrIidq4Zf/9ZzKWyrTk2sXOYc1JADbkAjQ= github.com/knz/strtime v0.0.0-20200318182718-be999391ffa9/go.mod h1:4ZxfWkxwtc7dBeifERVVWRy9F9rTU9p0yCDgeCtlius= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -255,6 +287,8 @@ github.com/mailgun/mailgun-go/v4 v4.1.3 h1:KLa5EZaOMMeyvY/lfAhWxv9ealB3mtUsMz0O9 github.com/mailgun/mailgun-go/v4 v4.1.3/go.mod h1:R9kHUQBptF4iSEjhriCQizplCDwrnDShy8w/iPiOfaM= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -293,6 +327,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -303,6 +338,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= @@ -313,6 +349,8 @@ github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -340,6 +378,8 @@ github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFB github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.2 h1:XU784Pr0wdahMY2bYcyK6N1KuaRAdLtqD4qd8D18Bfs= github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -354,6 +394,8 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg= github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -372,6 +414,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= @@ -393,6 +436,7 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= @@ -405,11 +449,17 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU= +gitlab.com/c0b/go-ordered-json v0.0.0-20171130231205-49bbdab258c2 h1:M+r1hdmjZc4L4SCn0ZIq/5YQIRxprV+kOf7n7f04l5o= +gitlab.com/c0b/go-ordered-json v0.0.0-20171130231205-49bbdab258c2/go.mod h1:NREvu3a57BaK0R1+ztrEzHWiZAihohNLQ6trPxlIqZI= gitlab.com/go-box/pongo2gin v0.0.0-20180611101114-fb2c4f0fe00f h1:BIsEj1psDbt911E2Zv2h8E+eATWEFi3QMTCpyExpSHo= gitlab.com/go-box/pongo2gin v0.0.0-20180611101114-fb2c4f0fe00f/go.mod h1:uarWX64Mu2b7B8sCSP0yZuf4aKEIQQYKaGHf9Jw0Epw= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.mongodb.org/mongo-driver v1.4.0 h1:C8rFn1VF4GVEM/rG+dSoMmlm2pyQ9cs2/oRtUATejRU= +go.mongodb.org/mongo-driver v1.4.0/go.mod h1:llVBH2pkj9HywK0Dtdt6lDikOjFLbceHVu/Rc0iMKLs= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.starlark.net v0.0.0-20190702223751-32f345186213 h1:lkYv5AKwvvduv5XWP6szk/bvvgO6aDeUujhZQXIFTes= @@ -426,7 +476,9 @@ golang.org/x/arch v0.0.0-20200511175325-f7c78586839d/go.mod h1:flIaEI6LNU6xOCD5P golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -470,6 +522,7 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= @@ -481,6 +534,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -493,10 +547,13 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -530,9 +587,13 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= diff --git a/main.go b/main.go index ce71cfd..d946ada 100644 --- a/main.go +++ b/main.go @@ -3,11 +3,13 @@ package main import ( "crypto/rand" "encoding/base64" + "encoding/json" "fmt" "github.com/gin-contrib/static" "github.com/gin-gonic/gin" "github.com/google/uuid" "gopkg.in/ini.v1" + "io/ioutil" "os" "path/filepath" ) @@ -20,21 +22,23 @@ type User struct { } type appContext struct { - config *ini.File - config_path string - data_path string - local_path string - cssFile string - bsVersion int - jellyfinLogin bool - users []User - jf Jellyfin - authJf Jellyfin - datePattern string - timePattern string - storage Storage - validator Validator - email Emailer + config *ini.File + config_path string + configBase_path string + configBase map[string]interface{} + data_path string + local_path string + cssFile string + bsVersion int + jellyfinLogin bool + users []User + jf Jellyfin + authJf Jellyfin + datePattern string + timePattern string + storage Storage + validator Validator + email Emailer } func GenerateSecret(length int) (string, error) { @@ -89,6 +93,10 @@ func main() { ctx.storage.displayprefs_path = filepath.Join(ctx.data_path, "user_displayprefs.json") ctx.storage.loadDisplayprefs() + ctx.configBase_path = filepath.Join(ctx.local_path, "config-base.json") + config_base, _ := ioutil.ReadFile(ctx.configBase_path) + json.Unmarshal(config_base, &ctx.configBase) + //bson.UnmarshalExtJSON(config_base, true, &ctx.configBase) themes := map[string]string{ "Jellyfin (Dark)": fmt.Sprintf("bs%d-jf.css", ctx.bsVersion), "Bootstrap (Light)": fmt.Sprintf("bs%d.css", ctx.bsVersion), @@ -152,6 +160,7 @@ func main() { api.GET("/getUsers", ctx.GetUsers) api.POST("/modifyUsers", ctx.ModifyEmails) api.POST("/setDefaults", ctx.SetDefaults) + api.GET("/getConfig", ctx.GetConfig) router.Run(":8080") }