mirror of
https://github.com/Casvt/MIND.git
synced 2026-02-19 11:54:46 -05:00
When the value of the URL prefix would be changed, if the resulting json would be smaller than the current json, it would create invalid json. Now we wipe the contents before writing to avoid this.
242 lines
5.1 KiB
Python
242 lines
5.1 KiB
Python
#-*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Getting and setting settings
|
|
"""
|
|
|
|
import logging
|
|
from json import dump, load
|
|
from typing import Any
|
|
|
|
from backend.custom_exceptions import InvalidKeyValue, KeyNotFound
|
|
from backend.db import __DATABASE_VERSION__, get_db
|
|
from backend.helpers import folder_path
|
|
from backend.logging import set_log_level
|
|
|
|
default_settings = {
|
|
'allow_new_accounts': True,
|
|
'login_time': 3600,
|
|
'login_time_reset': True,
|
|
|
|
'database_version': __DATABASE_VERSION__,
|
|
|
|
'host': '0.0.0.0',
|
|
'port': 8080,
|
|
'url_prefix': '',
|
|
|
|
'log_level': logging.INFO
|
|
}
|
|
|
|
def _format_setting(key: str, value):
|
|
"""Turn python value in to database value.
|
|
|
|
Args:
|
|
key (str): The key of the value.
|
|
value (Any): The value itself.
|
|
|
|
Raises:
|
|
InvalidKeyValue: The value is not valid.
|
|
|
|
Returns:
|
|
Any: The converted value.
|
|
"""
|
|
if key == 'database_version':
|
|
try:
|
|
value = int(value)
|
|
except ValueError:
|
|
raise InvalidKeyValue(key, value)
|
|
|
|
elif key in ('allow_new_accounts', 'login_time_reset'):
|
|
if not isinstance(value, bool):
|
|
raise InvalidKeyValue(key, value)
|
|
value = int(value)
|
|
|
|
elif key == 'login_time':
|
|
if not isinstance(value, int) or not 60 <= value <= 2592000:
|
|
raise InvalidKeyValue(key, value)
|
|
|
|
elif key == 'host':
|
|
if not isinstance(value, str):
|
|
raise InvalidKeyValue(key, value)
|
|
|
|
elif key == 'port':
|
|
if not isinstance(value, int) or not 1 <= value <= 65535:
|
|
raise InvalidKeyValue(key, value)
|
|
|
|
elif key == 'url_prefix':
|
|
if not isinstance(value, str):
|
|
raise InvalidKeyValue(key, value)
|
|
|
|
if value == '/':
|
|
value = ''
|
|
|
|
elif value:
|
|
value = '/' + value.strip('/')
|
|
|
|
elif key == 'log_level' and not value in (logging.INFO, logging.DEBUG):
|
|
raise InvalidKeyValue(key, value)
|
|
|
|
return value
|
|
|
|
def _reverse_format_setting(key: str, value: Any) -> Any:
|
|
"""Turn database value in to python value.
|
|
|
|
Args:
|
|
key (str): The key of the value.
|
|
value (Any): The value itself.
|
|
|
|
Returns:
|
|
Any: The converted value.
|
|
"""
|
|
if key in ('allow_new_accounts', 'login_time_reset'):
|
|
value = value == 1
|
|
return value
|
|
|
|
def get_setting(key: str) -> Any:
|
|
"""Get a value from the config.
|
|
|
|
Args:
|
|
key (str): The key of which to get the value.
|
|
|
|
Raises:
|
|
KeyNotFound: Key is not in config.
|
|
|
|
Returns:
|
|
Any: The value of the key.
|
|
"""
|
|
result = get_db().execute(
|
|
"SELECT value FROM config WHERE key = ? LIMIT 1;",
|
|
(key,)
|
|
).fetchone()
|
|
if result is None:
|
|
raise KeyNotFound(key)
|
|
|
|
result = _reverse_format_setting(key, result[0])
|
|
|
|
return result
|
|
|
|
def get_admin_settings() -> dict:
|
|
"""Get all admin settings
|
|
|
|
Returns:
|
|
dict: The admin settings
|
|
"""
|
|
return dict((
|
|
(key, _reverse_format_setting(key, value))
|
|
for key, value in get_db().execute("""
|
|
SELECT key, value
|
|
FROM config
|
|
WHERE
|
|
key = 'allow_new_accounts'
|
|
OR key = 'login_time'
|
|
OR key = 'login_time_reset'
|
|
OR key = 'host'
|
|
OR key = 'port'
|
|
OR key = 'url_prefix'
|
|
OR key = 'log_level';
|
|
"""
|
|
)
|
|
))
|
|
|
|
def set_setting(key: str, value: Any) -> None:
|
|
"""Set a value in the config
|
|
|
|
Args:
|
|
key (str): The key for which to set the value
|
|
value (Any): The value to give to the key
|
|
|
|
Raises:
|
|
KeyNotFound: The key is not in the config
|
|
InvalidKeyValue: The value is not allowed for the key
|
|
"""
|
|
if not key in (*default_settings, 'database_version'):
|
|
raise KeyNotFound(key)
|
|
|
|
value = _format_setting(key, value)
|
|
|
|
get_db().execute(
|
|
"UPDATE config SET value = ? WHERE key = ?;",
|
|
(value, key)
|
|
)
|
|
|
|
if key == 'url_prefix':
|
|
update_manifest(value)
|
|
|
|
elif key == 'log_level':
|
|
set_log_level(value)
|
|
|
|
return
|
|
|
|
def update_manifest(url_base: str) -> None:
|
|
"""Update the url's in the manifest file.
|
|
Needs to happen when url base changes.
|
|
|
|
Args:
|
|
url_base (str): The url base to use in the file.
|
|
"""
|
|
filename = folder_path('frontend', 'static', 'json', 'pwa_manifest.json')
|
|
|
|
with open(filename, 'r') as f:
|
|
manifest = load(f)
|
|
manifest['start_url'] = url_base + '/'
|
|
manifest['icons'][0]['src'] = f'{url_base}/static/img/favicon.svg'
|
|
|
|
with open(filename, 'w') as f:
|
|
dump(manifest, f, indent=4)
|
|
|
|
return
|
|
|
|
def backup_hosting_settings() -> None:
|
|
"""Copy current hosting settings to backup values.
|
|
"""
|
|
cursor = get_db()
|
|
hosting_settings = dict(cursor.execute("""
|
|
SELECT key, value
|
|
FROM config
|
|
WHERE key = 'host'
|
|
OR key = 'port'
|
|
OR key = 'url_prefix'
|
|
LIMIT 3;
|
|
"""
|
|
))
|
|
hosting_settings = {f'{k}_backup': v for k, v in hosting_settings.items()}
|
|
|
|
cursor.executemany("""
|
|
INSERT INTO config(key, value)
|
|
VALUES (?, ?)
|
|
ON CONFLICT(key) DO
|
|
UPDATE
|
|
SET value = ?;
|
|
""",
|
|
((k, v, v) for k, v in hosting_settings.items())
|
|
)
|
|
|
|
return
|
|
|
|
def restore_hosting_settings() -> None:
|
|
"""Copy the hosting settings from the backup over to the main keys.
|
|
"""
|
|
cursor = get_db()
|
|
hosting_settings = dict(cursor.execute("""
|
|
SELECT key, value
|
|
FROM config
|
|
WHERE key = 'host_backup'
|
|
OR key = 'port_backup'
|
|
OR key = 'url_prefix_backup'
|
|
LIMIT 3;
|
|
"""
|
|
))
|
|
if len(hosting_settings) < 3:
|
|
return
|
|
|
|
hosting_settings = {k.split('_backup')[0]: v for k, v in hosting_settings.items()}
|
|
|
|
cursor.executemany(
|
|
"UPDATE config SET value = ? WHERE key = ?",
|
|
((v, k) for k, v in hosting_settings.items())
|
|
)
|
|
|
|
update_manifest(hosting_settings['url_prefix'])
|
|
|
|
return
|