mirror of
https://github.com/hrfee/jellyfin-accounts.git
synced 2024-12-22 09:00:14 +00:00
Proper dynamic config reload
A bunch of options can now be changed without a restart as the config is now guaranteed to be reloaded on change through the use of a RELOADCONFIG environment variable.
This commit is contained in:
parent
27169e4e0d
commit
d615b21c7d
@ -9,9 +9,9 @@ server = http://jellyfin.local:8096
|
|||||||
public_server = https://jellyf.in:443
|
public_server = https://jellyf.in:443
|
||||||
; this and below settings will show on the jellyfin dashboard when the program connects. you may as well leave them alone.
|
; this and below settings will show on the jellyfin dashboard when the program connects. you may as well leave them alone.
|
||||||
client = jf-accounts
|
client = jf-accounts
|
||||||
version = 0.3.2
|
version = 0.3.6
|
||||||
device = jf-accounts
|
device = jf-accounts
|
||||||
device_id = jf-accounts-0.3.2
|
device_id = jf-accounts-0.3.6
|
||||||
|
|
||||||
[ui]
|
[ui]
|
||||||
; settings related to the ui and program functionality.
|
; settings related to the ui and program functionality.
|
||||||
@ -31,7 +31,7 @@ password = your password
|
|||||||
debug = false
|
debug = false
|
||||||
; displayed at bottom of all pages except admin
|
; displayed at bottom of all pages except admin
|
||||||
contact_message = Need help? contact me.
|
contact_message = Need help? contact me.
|
||||||
; display at top of invite form.
|
; displayed at top of invite form.
|
||||||
help_message = Enter your details to create an account.
|
help_message = Enter your details to create an account.
|
||||||
; displayed when a user creates an account
|
; displayed when a user creates an account
|
||||||
success_message = Your account has been created. Click below to continue to Jellyfin.
|
success_message = Your account has been created. Click below to continue to Jellyfin.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
# Runs it!
|
||||||
__version__ = "0.3.6"
|
__version__ = "0.3.6"
|
||||||
|
|
||||||
import secrets
|
import secrets
|
||||||
@ -13,6 +13,7 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from flask import Flask, jsonify, g
|
from flask import Flask, jsonify, g
|
||||||
from jellyfin_accounts.data_store import JSONStorage
|
from jellyfin_accounts.data_store import JSONStorage
|
||||||
|
from jellyfin_accounts.config import Config
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="jellyfin-accounts")
|
parser = argparse.ArgumentParser(description="jellyfin-accounts")
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ if data_dir.exists() is False or (data_dir / "config.ini").exists() is False:
|
|||||||
else:
|
else:
|
||||||
config_path = data_dir / "config.ini"
|
config_path = data_dir / "config.ini"
|
||||||
|
|
||||||
|
# Temp config so logger knows whether to use debug mode or not
|
||||||
temp_config = configparser.RawConfigParser()
|
temp_config = configparser.RawConfigParser()
|
||||||
temp_config.read(config_path)
|
temp_config.read(config_path)
|
||||||
|
|
||||||
@ -93,61 +94,7 @@ def create_log(name):
|
|||||||
|
|
||||||
log = create_log("main")
|
log = create_log("main")
|
||||||
|
|
||||||
|
config = Config(config_path, secrets.token_urlsafe(16), data_dir, local_dir, log)
|
||||||
def load_config(config_path, data_dir):
|
|
||||||
config = configparser.RawConfigParser()
|
|
||||||
config.read(config_path)
|
|
||||||
global log
|
|
||||||
for key in config["files"]:
|
|
||||||
if config["files"][key] == "":
|
|
||||||
if key != "custom_css":
|
|
||||||
log.debug(f"Using default {key}")
|
|
||||||
config["files"][key] = str(data_dir / (key + ".json"))
|
|
||||||
|
|
||||||
for key in ["user_configuration", "user_displayprefs"]:
|
|
||||||
if key not in config["files"]:
|
|
||||||
log.debug(f"Using default {key}")
|
|
||||||
config["files"][key] = str(data_dir / (key + ".json"))
|
|
||||||
|
|
||||||
if "no_username" not in config["email"]:
|
|
||||||
config["email"]["no_username"] = "false"
|
|
||||||
log.debug("Set no_username to false")
|
|
||||||
if (
|
|
||||||
"email_html" not in config["password_resets"]
|
|
||||||
or config["password_resets"]["email_html"] == ""
|
|
||||||
):
|
|
||||||
log.debug("Using default password reset email HTML template")
|
|
||||||
config["password_resets"]["email_html"] = str(local_dir / "email.html")
|
|
||||||
if (
|
|
||||||
"email_text" not in config["password_resets"]
|
|
||||||
or config["password_resets"]["email_text"] == ""
|
|
||||||
):
|
|
||||||
log.debug("Using default password reset email plaintext template")
|
|
||||||
config["password_resets"]["email_text"] = str(local_dir / "email.txt")
|
|
||||||
|
|
||||||
if (
|
|
||||||
"email_html" not in config["invite_emails"]
|
|
||||||
or config["invite_emails"]["email_html"] == ""
|
|
||||||
):
|
|
||||||
log.debug("Using default invite email HTML template")
|
|
||||||
config["invite_emails"]["email_html"] = str(local_dir / "invite-email.html")
|
|
||||||
if (
|
|
||||||
"email_text" not in config["invite_emails"]
|
|
||||||
or config["invite_emails"]["email_text"] == ""
|
|
||||||
):
|
|
||||||
log.debug("Using default invite email plaintext template")
|
|
||||||
config["invite_emails"]["email_text"] = str(local_dir / "invite-email.txt")
|
|
||||||
if (
|
|
||||||
"public_server" not in config["jellyfin"]
|
|
||||||
or config["jellyfin"]["public_server"] == ""
|
|
||||||
):
|
|
||||||
config["jellyfin"]["public_server"] = config["jellyfin"]["server"]
|
|
||||||
if "bs5" not in config["ui"] or config["ui"]["bs5"] == "":
|
|
||||||
config["ui"]["bs5"] = "false"
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
config = load_config(config_path, data_dir)
|
|
||||||
|
|
||||||
web_log = create_log("waitress")
|
web_log = create_log("waitress")
|
||||||
if not first_run:
|
if not first_run:
|
||||||
|
95
jellyfin_accounts/config.py
Normal file
95
jellyfin_accounts/config.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import os
|
||||||
|
import configparser
|
||||||
|
import secrets
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
"""
|
||||||
|
Configuration object that can automatically reload modified settings.
|
||||||
|
Behaves mostly like a dictionary.
|
||||||
|
:param file: Path to config.ini, where parameters are set.
|
||||||
|
:param instance: Used to identify specific jf-accounts instances in environment variables.
|
||||||
|
:param data_dir: Path to directory with config, invites, templates, etc.
|
||||||
|
:param local_dir: Path to internally stored config base, emails, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_config(config_path, data_dir, local_dir, log):
|
||||||
|
config = configparser.RawConfigParser()
|
||||||
|
config.read(config_path)
|
||||||
|
for key in config["files"]:
|
||||||
|
if config["files"][key] == "":
|
||||||
|
if key != "custom_css":
|
||||||
|
log.debug(f"Using default {key}")
|
||||||
|
config["files"][key] = str(data_dir / (key + ".json"))
|
||||||
|
|
||||||
|
for key in ["user_configuration", "user_displayprefs"]:
|
||||||
|
if key not in config["files"]:
|
||||||
|
log.debug(f"Using default {key}")
|
||||||
|
config["files"][key] = str(data_dir / (key + ".json"))
|
||||||
|
|
||||||
|
if "no_username" not in config["email"]:
|
||||||
|
config["email"]["no_username"] = "false"
|
||||||
|
log.debug("Set no_username to false")
|
||||||
|
if (
|
||||||
|
"email_html" not in config["password_resets"]
|
||||||
|
or config["password_resets"]["email_html"] == ""
|
||||||
|
):
|
||||||
|
log.debug("Using default password reset email HTML template")
|
||||||
|
config["password_resets"]["email_html"] = str(local_dir / "email.html")
|
||||||
|
if (
|
||||||
|
"email_text" not in config["password_resets"]
|
||||||
|
or config["password_resets"]["email_text"] == ""
|
||||||
|
):
|
||||||
|
log.debug("Using default password reset email plaintext template")
|
||||||
|
config["password_resets"]["email_text"] = str(local_dir / "email.txt")
|
||||||
|
|
||||||
|
if (
|
||||||
|
"email_html" not in config["invite_emails"]
|
||||||
|
or config["invite_emails"]["email_html"] == ""
|
||||||
|
):
|
||||||
|
log.debug("Using default invite email HTML template")
|
||||||
|
config["invite_emails"]["email_html"] = str(local_dir / "invite-email.html")
|
||||||
|
if (
|
||||||
|
"email_text" not in config["invite_emails"]
|
||||||
|
or config["invite_emails"]["email_text"] == ""
|
||||||
|
):
|
||||||
|
log.debug("Using default invite email plaintext template")
|
||||||
|
config["invite_emails"]["email_text"] = str(local_dir / "invite-email.txt")
|
||||||
|
if (
|
||||||
|
"public_server" not in config["jellyfin"]
|
||||||
|
or config["jellyfin"]["public_server"] == ""
|
||||||
|
):
|
||||||
|
config["jellyfin"]["public_server"] = config["jellyfin"]["server"]
|
||||||
|
if "bs5" not in config["ui"] or config["ui"]["bs5"] == "":
|
||||||
|
config["ui"]["bs5"] = "false"
|
||||||
|
return config
|
||||||
|
|
||||||
|
def __init__(self, file, instance, data_dir, local_dir, log):
|
||||||
|
self.config_path = Path(file)
|
||||||
|
self.data_dir = data_dir
|
||||||
|
self.local_dir = local_dir
|
||||||
|
self.instance = instance
|
||||||
|
self.log = log
|
||||||
|
self.varname = f"JFA_{self.instance}_RELOADCONFIG"
|
||||||
|
os.environ[self.varname] = "true"
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if os.environ[self.varname] == "true":
|
||||||
|
self.config = Config.load_config(
|
||||||
|
self.config_path, self.data_dir, self.local_dir, self.log
|
||||||
|
)
|
||||||
|
os.environ[self.varname] = "false"
|
||||||
|
return self.config.__getitem__(key)
|
||||||
|
|
||||||
|
def getboolean(self, sect, key):
|
||||||
|
if os.environ[self.varname] == "true":
|
||||||
|
self.config = Config.load_config(
|
||||||
|
self.config_path, self.data_dir, self.local_dir, self.log
|
||||||
|
)
|
||||||
|
os.environ[self.varname] = "false"
|
||||||
|
return self.config.getboolean(sect, key)
|
||||||
|
|
||||||
|
def trigger_reload(self):
|
||||||
|
os.environ[self.varname] = "true"
|
@ -143,7 +143,7 @@
|
|||||||
"contact_message": {
|
"contact_message": {
|
||||||
"name": "Contact message",
|
"name": "Contact message",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "Need help? contact me.",
|
"value": "Need help? contact me.",
|
||||||
"description": "Displayed at bottom of all pages except admin"
|
"description": "Displayed at bottom of all pages except admin"
|
||||||
@ -151,15 +151,15 @@
|
|||||||
"help_message": {
|
"help_message": {
|
||||||
"name": "Help message",
|
"name": "Help message",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "Enter your details to create an account.",
|
"value": "Enter your details to create an account.",
|
||||||
"description": "Display at top of invite form."
|
"description": "Displayed at top of invite form."
|
||||||
},
|
},
|
||||||
"success_message": {
|
"success_message": {
|
||||||
"name": "Success message",
|
"name": "Success message",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "Your account has been created. Click below to continue to Jellyfin.",
|
"value": "Your account has been created. Click below to continue to Jellyfin.",
|
||||||
"description": "Displayed when a user creates an account"
|
"description": "Displayed when a user creates an account"
|
||||||
@ -167,7 +167,7 @@
|
|||||||
"bs5": {
|
"bs5": {
|
||||||
"name": "Use Bootstrap 5",
|
"name": "Use Bootstrap 5",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": false,
|
"value": false,
|
||||||
"description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster."
|
"description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster."
|
||||||
@ -181,41 +181,41 @@
|
|||||||
"enabled": {
|
"enabled": {
|
||||||
"name": "Enabled",
|
"name": "Enabled",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": true
|
"value": true
|
||||||
},
|
},
|
||||||
"min_length": {
|
"min_length": {
|
||||||
"name": "Minimum Length",
|
"name": "Minimum Length",
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "8"
|
"value": "8"
|
||||||
},
|
},
|
||||||
"upper": {
|
"upper": {
|
||||||
"name": "Minimum uppercase characters",
|
"name": "Minimum uppercase characters",
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "1"
|
"value": "1"
|
||||||
},
|
},
|
||||||
"lower": {
|
"lower": {
|
||||||
"name": "Minimum lowercase characters",
|
"name": "Minimum lowercase characters",
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "0"
|
"value": "0"
|
||||||
},
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"name": "Minimum number count",
|
"name": "Minimum number count",
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "1"
|
"value": "1"
|
||||||
},
|
},
|
||||||
"special": {
|
"special": {
|
||||||
"name": "Minimum number of special characters",
|
"name": "Minimum number of special characters",
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "0"
|
"value": "0"
|
||||||
@ -229,7 +229,7 @@
|
|||||||
"no_username": {
|
"no_username": {
|
||||||
"name": "Use email addresses as username",
|
"name": "Use email addresses as username",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"depends_true": "method",
|
"depends_true": "method",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": false,
|
"value": false,
|
||||||
@ -350,7 +350,7 @@
|
|||||||
"enabled": {
|
"enabled": {
|
||||||
"name": "Enabled",
|
"name": "Enabled",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": true,
|
"requires_restart": false,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": true
|
"value": true
|
||||||
},
|
},
|
||||||
|
@ -35,19 +35,15 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
const bsVersion = 4;
|
const bsVersion = 4;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
console.log('create');
|
|
||||||
var css = document.createElement('link');
|
var css = document.createElement('link');
|
||||||
css.setAttribute('rel', 'stylesheet');
|
css.setAttribute('rel', 'stylesheet');
|
||||||
css.setAttribute('type', 'text/css');
|
css.setAttribute('type', 'text/css');
|
||||||
var cssCookie = getCookie("css");
|
var cssCookie = getCookie("css");
|
||||||
if (cssCookie.includes('bs' + bsVersion)) {
|
if (cssCookie.includes('bs' + bsVersion)) {
|
||||||
console.log('href');
|
|
||||||
css.setAttribute('href', cssCookie);
|
css.setAttribute('href', cssCookie);
|
||||||
} else {
|
} else {
|
||||||
console.log('href');
|
|
||||||
css.setAttribute('href', '{{ css_file }}');
|
css.setAttribute('href', '{{ css_file }}');
|
||||||
};
|
};
|
||||||
console.log('append');
|
|
||||||
document.head.appendChild(css);
|
document.head.appendChild(css);
|
||||||
</script>
|
</script>
|
||||||
{% if not bs5 %}
|
{% if not bs5 %}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Automatic storage of everything except the config
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Handles everything related to emails
|
||||||
import datetime
|
import datetime
|
||||||
import pytz
|
import pytz
|
||||||
import requests
|
import requests
|
||||||
@ -43,9 +44,7 @@ class Email:
|
|||||||
if expires_in["hours"] == 0:
|
if expires_in["hours"] == 0:
|
||||||
expires_in = f'{str(expires_in["minutes"])}m'
|
expires_in = f'{str(expires_in["minutes"])}m'
|
||||||
else:
|
else:
|
||||||
expires_in = (
|
expires_in = f'{str(expires_in["hours"])}h {str(expires_in["minutes"])}m'
|
||||||
f'{str(expires_in["hours"])}h ' + f'{str(expires_in["minutes"])}m'
|
|
||||||
)
|
|
||||||
log.debug(f"{self.address}: Expires in {expires_in}")
|
log.debug(f"{self.address}: Expires in {expires_in}")
|
||||||
return {"date": date, "time": time, "expires_in": expires_in}
|
return {"date": date, "time": time, "expires_in": expires_in}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Generates config file
|
||||||
import configparser
|
import configparser
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
# Jellyfin API client
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
# Handles authentication
|
||||||
|
|
||||||
from flask_httpauth import HTTPBasicAuth
|
from flask_httpauth import HTTPBasicAuth
|
||||||
from itsdangerous import (
|
from itsdangerous import (
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Watches Jellyfin for password resets and sends emails.
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Views and endpoints for the initial setup
|
||||||
from flask import request, jsonify, render_template
|
from flask import request, jsonify, render_template
|
||||||
from configparser import RawConfigParser
|
from configparser import RawConfigParser
|
||||||
from jellyfin_accounts.jf_api import Jellyfin
|
from jellyfin_accounts.jf_api import Jellyfin
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# Password validation
|
||||||
specials = ['[', '@', '_', '!', '#', '$', '%', '^', '&', '*', '(', ')',
|
specials = ['[', '@', '_', '!', '#', '$', '%', '^', '&', '*', '(', ')',
|
||||||
'<', '>', '?', '/', '\\', '|', '}', '{', '~', ':', ']']
|
'<', '>', '?', '/', '\\', '|', '}', '{', '~', ':', ']']
|
||||||
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
# Web views
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from flask import Flask, send_from_directory, render_template
|
from flask import Flask, send_from_directory, render_template
|
||||||
|
|
||||||
from jellyfin_accounts import app, g, css_file, data_store
|
from jellyfin_accounts import config, app, g, css_file, data_store
|
||||||
from jellyfin_accounts import web_log as log
|
from jellyfin_accounts import web_log as log
|
||||||
from jellyfin_accounts.web_api import config, checkInvite, validator
|
from jellyfin_accounts.web_api import checkInvite, validator
|
||||||
|
|
||||||
|
|
||||||
if config.getboolean("ui", "bs5"):
|
def bsVersion():
|
||||||
bsVersion = 5
|
if config.getboolean("ui", "bs5"):
|
||||||
else:
|
return 5
|
||||||
bsVersion = 4
|
return 4
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
@ -42,7 +43,7 @@ def static_proxy(path):
|
|||||||
if "html" not in path:
|
if "html" not in path:
|
||||||
if "admin.js" in path:
|
if "admin.js" in path:
|
||||||
return (
|
return (
|
||||||
render_template("admin.js", bsVersion=bsVersion, css_file=css_file),
|
render_template("admin.js", bsVersion=bsVersion(), css_file=css_file),
|
||||||
200,
|
200,
|
||||||
{"Content-Type": "text/javascript"},
|
{"Content-Type": "text/javascript"},
|
||||||
)
|
)
|
||||||
@ -75,7 +76,7 @@ def inviteProxy(path):
|
|||||||
successMessage=config["ui"]["success_message"],
|
successMessage=config["ui"]["success_message"],
|
||||||
jfLink=config["jellyfin"]["public_server"],
|
jfLink=config["jellyfin"]["public_server"],
|
||||||
validate=config.getboolean("password_validation", "enabled"),
|
validate=config.getboolean("password_validation", "enabled"),
|
||||||
requirements=validator.getCriteria(),
|
requirements=validator().getCriteria(),
|
||||||
email=email,
|
email=email,
|
||||||
username=(not config.getboolean("email", "no_username")),
|
username=(not config.getboolean("email", "no_username")),
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# A bit of a mess, but mostly does API endpoints and a couple compatability fixes
|
||||||
from flask import request, jsonify
|
from flask import request, jsonify
|
||||||
from jellyfin_accounts.jf_api import Jellyfin
|
from jellyfin_accounts.jf_api import Jellyfin
|
||||||
import json
|
import json
|
||||||
@ -7,8 +8,6 @@ import time
|
|||||||
from jellyfin_accounts import (
|
from jellyfin_accounts import (
|
||||||
config,
|
config,
|
||||||
config_path,
|
config_path,
|
||||||
load_config,
|
|
||||||
data_dir,
|
|
||||||
app,
|
app,
|
||||||
g,
|
g,
|
||||||
data_store,
|
data_store,
|
||||||
@ -136,11 +135,11 @@ if (
|
|||||||
version.parse(jf.info["Version"]) >= version.parse("10.6.0")
|
version.parse(jf.info["Version"]) >= version.parse("10.6.0")
|
||||||
and bool(data_store.user_template) is not False
|
and bool(data_store.user_template) is not False
|
||||||
):
|
):
|
||||||
log.info("Updating user_template for Jellyfin >= 10.6.0")
|
|
||||||
if (
|
if (
|
||||||
data_store.user_template["AuthenticationProviderId"]
|
data_store.user_template["AuthenticationProviderId"]
|
||||||
== "Emby.Server.Implementations.Library.DefaultAuthenticationProvider"
|
== "Emby.Server.Implementations.Library.DefaultAuthenticationProvider"
|
||||||
):
|
):
|
||||||
|
log.info("Updating user_template for Jellyfin >= 10.6.0")
|
||||||
data_store.user_template[
|
data_store.user_template[
|
||||||
"AuthenticationProviderId"
|
"AuthenticationProviderId"
|
||||||
] = "Jellyfin.Server.Implementations.Users.DefaultAuthenticationProvider"
|
] = "Jellyfin.Server.Implementations.Users.DefaultAuthenticationProvider"
|
||||||
@ -153,16 +152,16 @@ if (
|
|||||||
] = "Jellyfin.Server.Implementations.Users.DefaultPasswordResetProvider"
|
] = "Jellyfin.Server.Implementations.Users.DefaultPasswordResetProvider"
|
||||||
|
|
||||||
|
|
||||||
if config.getboolean("password_validation", "enabled"):
|
def validator():
|
||||||
validator = PasswordValidator(
|
if config.getboolean("password_validation", "enabled"):
|
||||||
|
return PasswordValidator(
|
||||||
config["password_validation"]["min_length"],
|
config["password_validation"]["min_length"],
|
||||||
config["password_validation"]["upper"],
|
config["password_validation"]["upper"],
|
||||||
config["password_validation"]["lower"],
|
config["password_validation"]["lower"],
|
||||||
config["password_validation"]["number"],
|
config["password_validation"]["number"],
|
||||||
config["password_validation"]["special"],
|
config["password_validation"]["special"],
|
||||||
)
|
)
|
||||||
else:
|
return PasswordValidator(0, 0, 0, 0, 0)
|
||||||
validator = PasswordValidator(0, 0, 0, 0, 0)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/newUser", methods=["POST"])
|
@app.route("/newUser", methods=["POST"])
|
||||||
@ -170,7 +169,7 @@ def newUser():
|
|||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
log.debug("Attempted newUser")
|
log.debug("Attempted newUser")
|
||||||
if checkInvite(data["code"]):
|
if checkInvite(data["code"]):
|
||||||
validation = validator.validate(data["password"])
|
validation = validator().validate(data["password"])
|
||||||
valid = True
|
valid = True
|
||||||
for criterion in validation:
|
for criterion in validation:
|
||||||
if validation[criterion] is False:
|
if validation[criterion] is False:
|
||||||
@ -203,9 +202,7 @@ def newUser():
|
|||||||
jf.setDisplayPreferences(user.json()["Id"], displayprefs)
|
jf.setDisplayPreferences(user.json()["Id"], displayprefs)
|
||||||
log.debug("Set homescreen layout.")
|
log.debug("Set homescreen layout.")
|
||||||
else:
|
else:
|
||||||
log.debug(
|
log.debug("user configuration and/or displayprefs were blank")
|
||||||
"user configuration and/or " + "displayprefs were blank"
|
|
||||||
)
|
|
||||||
except:
|
except:
|
||||||
log.error("Failed to set new user homescreen layout")
|
log.error("Failed to set new user homescreen layout")
|
||||||
if config.getboolean("password_resets", "enabled"):
|
if config.getboolean("password_resets", "enabled"):
|
||||||
@ -392,18 +389,11 @@ def modifyConfig():
|
|||||||
log.debug(f"{section}/{item} modified")
|
log.debug(f"{section}/{item} modified")
|
||||||
with open(config_path, "w") as config_file:
|
with open(config_path, "w") as config_file:
|
||||||
temp_config.write(config_file)
|
temp_config.write(config_file)
|
||||||
config = load_config(config_path, data_dir)
|
config.trigger_reload()
|
||||||
log.info("Config written. Restart may be needed to load settings.")
|
log.info("Config written. Restart may be needed to load settings.")
|
||||||
return resp()
|
return resp()
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/getConfig', methods=["GET"])
|
|
||||||
# @auth.login_required
|
|
||||||
# def getConfig():
|
|
||||||
# log.debug('Config requested')
|
|
||||||
# return jsonify(config._sections), 200
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/getConfig", methods=["GET"])
|
@app.route("/getConfig", methods=["GET"])
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
def getConfig():
|
def getConfig():
|
||||||
|
Loading…
Reference in New Issue
Block a user