commit
260366fb01
@ -6,7 +6,6 @@ out/
|
|||||||
data/uploads/*
|
data/uploads/*
|
||||||
!data/uploads/sample.jpg
|
!data/uploads/sample.jpg
|
||||||
data/db/*
|
data/db/*
|
||||||
!data/db/slideshow.json.dist
|
|
||||||
/plugins/user/*
|
/plugins/user/*
|
||||||
!/plugins/user/.gitkeep
|
!/plugins/user/.gitkeep
|
||||||
*.lock
|
*.lock
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,7 +6,6 @@ out/
|
|||||||
data/uploads/*
|
data/uploads/*
|
||||||
!data/uploads/sample.jpg
|
!data/uploads/sample.jpg
|
||||||
data/db/*
|
data/db/*
|
||||||
!data/db/slideshow.json.dist
|
|
||||||
/plugins/user/*
|
/plugins/user/*
|
||||||
!/plugins/user/.gitkeep
|
!/plugins/user/.gitkeep
|
||||||
*.lock
|
*.lock
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
FROM python:3.9.17-alpine3.17
|
FROM python:3.9.17-alpine3.17
|
||||||
|
|
||||||
|
RUN apk add --no-cache --virtual .build-deps gcc musl-dev sqlite-dev
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt && apk del .build-deps gcc musl-dev sqlite-dev
|
||||||
|
|
||||||
ENTRYPOINT ["python", "/app/obscreen.py"]
|
ENTRYPOINT ["python", "/app/obscreen.py"]
|
||||||
|
|||||||
@ -15,7 +15,7 @@ Use a RaspberryPi (Lite OS) to show a full-screen slideshow (Kiosk-mode)
|
|||||||
- Clear GUI
|
- Clear GUI
|
||||||
- Fleet view to manage many devices easily
|
- Fleet view to manage many devices easily
|
||||||
- Very few dependencies
|
- Very few dependencies
|
||||||
- JSON database files
|
- SQLite database
|
||||||
- Plugin system
|
- Plugin system
|
||||||
- No stupid pricing plan
|
- No stupid pricing plan
|
||||||
- No cloud
|
- No cloud
|
||||||
|
|||||||
@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"keys": [
|
|
||||||
"duration",
|
|
||||||
"enabled",
|
|
||||||
"location",
|
|
||||||
"name",
|
|
||||||
"position",
|
|
||||||
"type",
|
|
||||||
"cron_schedule",
|
|
||||||
"cron_schedule_end",
|
|
||||||
"created_by",
|
|
||||||
"updated_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"data": {
|
|
||||||
"0": {
|
|
||||||
"location": "data/uploads/sample.jpg",
|
|
||||||
"duration": 10,
|
|
||||||
"type": "picture",
|
|
||||||
"enabled": true,
|
|
||||||
"name": "Picture Sample",
|
|
||||||
"position": 0,
|
|
||||||
"cron_schedule": null
|
|
||||||
},
|
|
||||||
"1": {
|
|
||||||
"location": "https://unix.org",
|
|
||||||
"duration": 20,
|
|
||||||
"type": "url",
|
|
||||||
"enabled": true,
|
|
||||||
"name": "URL Sample",
|
|
||||||
"position": 1,
|
|
||||||
"cron_schedule": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,7 +9,7 @@ jQuery(document).ready(function ($) {
|
|||||||
if (confirm(l.js_sysinfo_restart_confirmation)) {
|
if (confirm(l.js_sysinfo_restart_confirmation)) {
|
||||||
$('body').html(l.js_sysinfo_restart_loading).css({margin:200});
|
$('body').html(l.js_sysinfo_restart_loading).css({margin:200});
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/sysinfo/restart',
|
url: '/sysinfo/restart?secret_key='+secret_key,
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
data: '',
|
data: '',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@ -53,10 +53,10 @@ cd ~ && git clone https://github.com/jr-k/obscreen.git && cd obscreen
|
|||||||
# Install application dependencies
|
# Install application dependencies
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Add some sample data
|
# 🚨For MacOS users, requirements installation may cause an error but it's ok if only for pysqlite3 package
|
||||||
cp data/db/slideshow.json.dist data/db/slideshow.json
|
# you'll need to install brew and execute command `brew install sqlite3`
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
# Customize server default values
|
# Customize server default values
|
||||||
cp .env.dist .env
|
cp .env.dist .env
|
||||||
|
|||||||
@ -72,9 +72,6 @@ python3 -m venv venv
|
|||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
# Add some sample data
|
|
||||||
cp data/db/slideshow.json.dist data/db/slideshow.json
|
|
||||||
|
|
||||||
# Customize server default values
|
# Customize server default values
|
||||||
cp .env.dist .env
|
cp .env.dist .env
|
||||||
```
|
```
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
flask==2.3.3
|
flask==2.3.3
|
||||||
pysondb-v2==2.1.0
|
|
||||||
python-dotenv
|
python-dotenv
|
||||||
cron-descriptor
|
cron-descriptor
|
||||||
waitress
|
waitress
|
||||||
flask-login
|
flask-login
|
||||||
|
pysqlite3
|
||||||
|
|||||||
@ -18,8 +18,9 @@ class Application:
|
|||||||
self._model_store = ModelStore()
|
self._model_store = ModelStore()
|
||||||
self._template_renderer = TemplateRenderer(project_dir=project_dir, model_store=self._model_store, render_hook=self.render_hook)
|
self._template_renderer = TemplateRenderer(project_dir=project_dir, model_store=self._model_store, render_hook=self.render_hook)
|
||||||
self._web_server = WebServer(project_dir=project_dir, model_store=self._model_store, template_renderer=self._template_renderer)
|
self._web_server = WebServer(project_dir=project_dir, model_store=self._model_store, template_renderer=self._template_renderer)
|
||||||
self._plugin_store = PluginStore(project_dir=project_dir, model_store=self._model_store, template_renderer=self._template_renderer, web_server=self._web_server)
|
|
||||||
|
|
||||||
|
logging.info("[Obscreen] Starting...")
|
||||||
|
self._plugin_store = PluginStore(project_dir=project_dir, model_store=self._model_store, template_renderer=self._template_renderer, web_server=self._web_server)
|
||||||
signal.signal(signal.SIGINT, self.signal_handler)
|
signal.signal(signal.SIGINT, self.signal_handler)
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
@ -27,6 +28,7 @@ class Application:
|
|||||||
|
|
||||||
def signal_handler(self, signal, frame) -> None:
|
def signal_handler(self, signal, frame) -> None:
|
||||||
logging.info("Shutting down...")
|
logging.info("Shutting down...")
|
||||||
|
self._model_store.database().close()
|
||||||
self._stop_event.set()
|
self._stop_event.set()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,9 @@ class AuthController(ObController):
|
|||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
return redirect(url_for('slideshow_slide_list'))
|
return redirect(url_for('slideshow_slide_list'))
|
||||||
|
|
||||||
|
if not self._model_store.variable().map().get('auth_enabled').as_bool():
|
||||||
|
return redirect(url_for('slideshow_slide_list'))
|
||||||
|
|
||||||
if len(request.form):
|
if len(request.form):
|
||||||
user = self._model_store.user().get_one_by_username(request.form['username'], enabled=True)
|
user = self._model_store.user().get_one_by_username(request.form['username'], enabled=True)
|
||||||
if user:
|
if user:
|
||||||
@ -42,6 +45,13 @@ class AuthController(ObController):
|
|||||||
|
|
||||||
def logout(self):
|
def logout(self):
|
||||||
logout_user()
|
logout_user()
|
||||||
|
|
||||||
|
if request.args.get('restart'):
|
||||||
|
return redirect(url_for(
|
||||||
|
'sysinfo_restart',
|
||||||
|
secret_key=self._model_store.config().map().get('secret_key')
|
||||||
|
))
|
||||||
|
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
def auth_user_list(self):
|
def auth_user_list(self):
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class SettingsController(ObController):
|
|||||||
forward = self._post_update(request.form['id'])
|
forward = self._post_update(request.form['id'])
|
||||||
return forward if forward is not None else redirect(url_for('settings_variable_list'))
|
return forward if forward is not None else redirect(url_for('settings_variable_list'))
|
||||||
|
|
||||||
def _post_update(self, id: str):
|
def _post_update(self, id: int):
|
||||||
variable = self._model_store.variable().get(id)
|
variable = self._model_store.variable().get(id)
|
||||||
|
|
||||||
if variable.refresh_player:
|
if variable.refresh_player:
|
||||||
@ -39,7 +39,10 @@ class SettingsController(ObController):
|
|||||||
if variable.name == 'auth_enabled':
|
if variable.name == 'auth_enabled':
|
||||||
self.reload_web_server()
|
self.reload_web_server()
|
||||||
if variable.as_bool():
|
if variable.as_bool():
|
||||||
return redirect(url_for('logout'))
|
return redirect(url_for(
|
||||||
|
'logout',
|
||||||
|
restart=1
|
||||||
|
))
|
||||||
|
|
||||||
if variable.name == 'lang':
|
if variable.name == 'lang':
|
||||||
self._model_store.lang().set_lang(variable.value)
|
self._model_store.lang().set_lang(variable.value)
|
||||||
|
|||||||
@ -2,21 +2,23 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
from flask import Flask, render_template, jsonify
|
from flask import Flask, render_template, jsonify, request, url_for, redirect
|
||||||
from src.manager.VariableManager import VariableManager
|
from src.manager.VariableManager import VariableManager
|
||||||
from src.manager.ConfigManager import ConfigManager
|
from src.manager.ConfigManager import ConfigManager
|
||||||
from src.service.ModelStore import ModelStore
|
from src.service.ModelStore import ModelStore
|
||||||
|
|
||||||
from src.interface.ObController import ObController
|
from src.interface.ObController import ObController
|
||||||
from src.utils import get_ip_address
|
from src.utils import get_ip_address, am_i_in_docker
|
||||||
|
|
||||||
|
|
||||||
class SysinfoController(ObController):
|
class SysinfoController(ObController):
|
||||||
|
|
||||||
def register(self):
|
def register(self):
|
||||||
self._app.add_url_rule('/sysinfo', 'sysinfo_attribute_list', self._auth(self.sysinfo), methods=['GET'])
|
self._app.add_url_rule('/sysinfo', 'sysinfo_attribute_list', self._auth(self.sysinfo), methods=['GET'])
|
||||||
self._app.add_url_rule('/sysinfo/restart', 'sysinfo_restart', self._auth(self.sysinfo_restart), methods=['POST'])
|
self._app.add_url_rule('/sysinfo/restart', 'sysinfo_restart', self.sysinfo_restart, methods=['GET', 'POST'])
|
||||||
self._app.add_url_rule('/sysinfo/restart/needed', 'sysinfo_restart_needed', self._auth(self.sysinfo_restart_needed), methods=['GET'])
|
self._app.add_url_rule('/sysinfo/restart/needed', 'sysinfo_restart_needed', self._auth(self.sysinfo_restart_needed), methods=['GET'])
|
||||||
|
|
||||||
def sysinfo(self):
|
def sysinfo(self):
|
||||||
@ -29,20 +31,13 @@ class SysinfoController(ObController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def sysinfo_restart(self):
|
def sysinfo_restart(self):
|
||||||
if platform.system().lower() == 'darwin':
|
secret = self._model_store.config().map().get('secret_key')
|
||||||
if self._model_store.config().map().get('debug'):
|
challenge = request.args.get('secret_key')
|
||||||
python = sys.executable
|
thread = threading.Thread(target=self.restart, args=(secret, challenge))
|
||||||
os.execl(python, python, *sys.argv)
|
thread.daemon = True
|
||||||
else:
|
thread.start()
|
||||||
try:
|
|
||||||
subprocess.run(["sudo", "systemctl", "restart", 'obscreen'], check=True, timeout=10, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
pass
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
pass
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return jsonify({'status': 'ok'})
|
return redirect(url_for('manage'))
|
||||||
|
|
||||||
def sysinfo_restart_needed(self):
|
def sysinfo_restart_needed(self):
|
||||||
var_last_slide_update = self._model_store.variable().get_one_by_name('last_slide_update')
|
var_last_slide_update = self._model_store.variable().get_one_by_name('last_slide_update')
|
||||||
@ -53,3 +48,24 @@ class SysinfoController(ObController):
|
|||||||
|
|
||||||
return jsonify({'status': True})
|
return jsonify({'status': True})
|
||||||
|
|
||||||
|
def restart(self, secret: str, challenge: str) -> None:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
if secret != challenge:
|
||||||
|
return jsonify({'status': 'error'})
|
||||||
|
|
||||||
|
if platform.system().lower() == 'darwin':
|
||||||
|
if self._model_store.config().map().get('debug'):
|
||||||
|
python = sys.executable
|
||||||
|
os.execl(python, python, *sys.argv)
|
||||||
|
elif am_i_in_docker:
|
||||||
|
python = sys.executable
|
||||||
|
os.execl(python, python, *sys.argv)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.run(["sudo", "systemctl", "restart", 'obscreen-manager'], check=True, timeout=10, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
pass
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
pass
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
pass
|
||||||
|
|||||||
@ -1,33 +1,144 @@
|
|||||||
|
import os
|
||||||
import json
|
import json
|
||||||
import sys
|
import sqlite3
|
||||||
|
import logging
|
||||||
from pysondb import PysonDB
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
|
from sqlite3 import Cursor
|
||||||
|
from src.utils import wrap_if, is_wrapped_by
|
||||||
|
from typing import Optional, Dict
|
||||||
|
|
||||||
class DatabaseManager:
|
class DatabaseManager:
|
||||||
|
|
||||||
DB_DIR = 'data/db'
|
DB_FILE: str = "data/db/obscreen.db"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
self._conn = None
|
||||||
|
self._enabled = True
|
||||||
|
self.init()
|
||||||
|
|
||||||
def open(self, table_name: str, table_model: list) -> PysonDB:
|
def init(self):
|
||||||
db_file = "{}/{}.json".format(self.DB_DIR, table_name)
|
logging.info('Using DB engine {}'.format(self.__class__.__name__))
|
||||||
db = PysonDB(db_file)
|
self._open()
|
||||||
db = self._update_model(db_file, table_model)
|
|
||||||
return db
|
def _open(self, flush: bool = False) -> None:
|
||||||
|
if flush and os.path.isfile(self.DB_FILE):
|
||||||
|
os.unlink(self.DB_FILE)
|
||||||
|
|
||||||
|
self._conn = sqlite3.connect(self.DB_FILE, check_same_thread=False)
|
||||||
|
self._conn.row_factory = sqlite3.Row
|
||||||
|
|
||||||
|
def open(self, table_name: str, table_model: list):
|
||||||
|
self.execute_write_query('''CREATE TABLE IF NOT EXISTS {} (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
{}
|
||||||
|
)'''.format(table_name, ", ".join(table_model)))
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
self._conn.close()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def get_connection(self):
|
||||||
|
return self._conn
|
||||||
|
|
||||||
|
def execute_write_query(self, query, params=()) -> None:
|
||||||
|
logging.debug(query)
|
||||||
|
cur = None
|
||||||
|
sanitized_params = []
|
||||||
|
|
||||||
|
for param in params:
|
||||||
|
if isinstance(param, bool):
|
||||||
|
sanitized_params.append(int(param))
|
||||||
|
elif isinstance(param, dict) or isinstance(param, list):
|
||||||
|
sanitized_params.append(json.dumps(param))
|
||||||
|
else:
|
||||||
|
sanitized_params.append(param)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _update_model(db_file: str, table_model: list) -> Optional[PysonDB]:
|
|
||||||
try:
|
try:
|
||||||
with open(db_file, 'r') as file:
|
with self._conn:
|
||||||
db_model = file.read()
|
cur = self._conn.cursor()
|
||||||
db_model = json.loads(db_model)
|
cur.execute(query, tuple(sanitized_params))
|
||||||
db_model['keys'] = table_model
|
except sqlite3.Error as e:
|
||||||
with open(db_file, 'w') as file:
|
logging.error("SQL query execution error while writing '{}': {}".format(query, e))
|
||||||
file.write(json.dumps(db_model, indent=4))
|
self._conn.rollback()
|
||||||
return PysonDB(db_file)
|
finally:
|
||||||
except FileNotFoundError:
|
if cur is not None:
|
||||||
logging.error("Database file {} not found".format(db_file))
|
cur.close()
|
||||||
return None
|
|
||||||
|
def execute_read_query(self, query, params=()) -> list:
|
||||||
|
logging.debug(query)
|
||||||
|
cur = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
with self._conn:
|
||||||
|
cur = self._conn.cursor()
|
||||||
|
cur.execute(query, params)
|
||||||
|
rows = cur.fetchall()
|
||||||
|
result = [dict(row) for row in rows]
|
||||||
|
except sqlite3.Error as e:
|
||||||
|
logging.error("SQL query execution error while reading '{}': {}".format(query, e))
|
||||||
|
result = []
|
||||||
|
finally:
|
||||||
|
if cur is not None:
|
||||||
|
cur.close()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_all(self, table_name: str, sort: Optional[str] = None) -> list:
|
||||||
|
return self.execute_read_query(
|
||||||
|
query="select * from {} {}".format(table_name, "ORDER BY {} ASC".format(sort) if sort else "")
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_by_query(self, table_name: str, query: str = "1=1", sort: Optional[str] = None) -> list:
|
||||||
|
return self.execute_read_query(
|
||||||
|
query="select * from {} where {} {}".format(
|
||||||
|
table_name,
|
||||||
|
query,
|
||||||
|
"ORDER BY {} ASC".format(sort) if sort else ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_one_by_query(self, table_name: str, query: str = "1=1", sort: Optional[str] = None) -> list:
|
||||||
|
query = "select * from {} where {} {}".format(table_name, query, "ORDER BY {} ASC".format(sort) if sort else "")
|
||||||
|
lines = self.execute_read_query(query=query)
|
||||||
|
count = len(lines)
|
||||||
|
|
||||||
|
if count > 1:
|
||||||
|
raise Error("More than one line returned by query '{}'".format(query))
|
||||||
|
|
||||||
|
return lines[0] if count == 1 else None
|
||||||
|
|
||||||
|
def update_by_query(self, table_name: str, query: str = "1=1", values: dict = {}) -> list:
|
||||||
|
return self.execute_write_query(
|
||||||
|
query="UPDATE {} SET {} where {}".format(
|
||||||
|
table_name,
|
||||||
|
" , ".join(["{} = ?".format(k, v) for k, v in values.items()]),
|
||||||
|
query
|
||||||
|
),
|
||||||
|
params=tuple(v for v in values.values())
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_by_id(self, table_name: str, id: int, values: dict = {}) -> list:
|
||||||
|
return self.update_by_query(table_name, "id = {}".format(id), values)
|
||||||
|
|
||||||
|
def get_by_id(self, table_name: str, id: int) -> Optional[Dict]:
|
||||||
|
return self.get_one_by_query(table_name, "id = {}".format(id))
|
||||||
|
|
||||||
|
def add(self, table_name: str, values: dict) -> None:
|
||||||
|
self.execute_write_query(
|
||||||
|
query="INSERT INTO {} ({}) VALUES ({})".format(
|
||||||
|
table_name,
|
||||||
|
", ".join(["{}".format(key) for key in values.keys()]),
|
||||||
|
", ".join(["?" for _ in values.keys()]),
|
||||||
|
),
|
||||||
|
params=tuple(v for v in values.values())
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_by_id(self, table_name: str, id: int) -> None:
|
||||||
|
self.execute_write_query("DELETE FROM {} WHERE id = ?".format(table_name), params=(id,))
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
from pysondb.errors import IdDoesNotExistError
|
|
||||||
from typing import Dict, Optional, List, Tuple, Union
|
from typing import Dict, Optional, List, Tuple, Union
|
||||||
|
|
||||||
from src.model.entity.Screen import Screen
|
from src.model.entity.Screen import Screen
|
||||||
@ -12,71 +11,59 @@ class ScreenManager(ModelManager):
|
|||||||
|
|
||||||
TABLE_NAME = "fleet"
|
TABLE_NAME = "fleet"
|
||||||
TABLE_MODEL = [
|
TABLE_MODEL = [
|
||||||
"name",
|
"name CHAR(255)",
|
||||||
"enabled",
|
"enabled INTEGER",
|
||||||
"position",
|
"position INTEGER",
|
||||||
"host",
|
"host CHAR(255)",
|
||||||
"port"
|
"port INTEGER"
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, user_manager: UserManager):
|
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, user_manager: UserManager):
|
||||||
super().__init__(lang_manager, database_manager, user_manager)
|
super().__init__(lang_manager, database_manager, user_manager)
|
||||||
self._db = database_manager.open(self.TABLE_NAME, self.TABLE_MODEL)
|
self._db = database_manager.open(self.TABLE_NAME, self.TABLE_MODEL)
|
||||||
|
|
||||||
def hydrate_object(self, raw_screen: dict, id: Optional[str] = None) -> Screen:
|
def hydrate_object(self, raw_screen: dict, id: Optional[int] = None) -> Screen:
|
||||||
if id:
|
if id:
|
||||||
raw_screen['id'] = id
|
raw_screen['id'] = id
|
||||||
|
|
||||||
return Screen(**raw_screen)
|
return Screen(**raw_screen)
|
||||||
|
|
||||||
def hydrate_dict(self, raw_screens: dict) -> List[Screen]:
|
|
||||||
return [self.hydrate_object(raw_screen, raw_id) for raw_id, raw_screen in raw_screens.items()]
|
|
||||||
|
|
||||||
def hydrate_list(self, raw_screens: list) -> List[Screen]:
|
def hydrate_list(self, raw_screens: list) -> List[Screen]:
|
||||||
return [self.hydrate_object(raw_screen) for raw_screen in raw_screens]
|
return [self.hydrate_object(raw_screen) for raw_screen in raw_screens]
|
||||||
|
|
||||||
def get(self, id: str) -> Optional[Screen]:
|
def get(self, id: int) -> Optional[Screen]:
|
||||||
try:
|
object = self._db.get_by_id(self.TABLE_NAME, id)
|
||||||
return self.hydrate_object(self._db.get_by_id(id), id)
|
return self.hydrate_object(object, id) if object else None
|
||||||
except IdDoesNotExistError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_by(self, query) -> List[Screen]:
|
def get_by(self, query, sort: Optional[str] = None) -> List[Screen]:
|
||||||
return self.hydrate_dict(self._db.get_by_query(query=query))
|
return self.hydrate_list(self._db.get_by_query(self.TABLE_NAME, query=query, sort=sort))
|
||||||
|
|
||||||
def get_one_by(self, query) -> Optional[Screen]:
|
def get_one_by(self, query) -> Optional[Screen]:
|
||||||
screens = self.hydrate_dict(self._db.get_by_query(query=query))
|
object = self._db.get_one_by_query(self.TABLE_NAME, query=query)
|
||||||
if len(screens) == 1:
|
|
||||||
return screens[0]
|
if not object:
|
||||||
elif len(screens) > 1:
|
return None
|
||||||
raise Error("More than one result for query")
|
|
||||||
return None
|
return self.hydrate_object(object)
|
||||||
|
|
||||||
def get_all(self, sort: bool = False) -> List[Screen]:
|
def get_all(self, sort: bool = False) -> List[Screen]:
|
||||||
raw_screens = self._db.get_all()
|
return self.hydrate_list(self._db.get_all(self.TABLE_NAME, "position" if sort else None))
|
||||||
|
|
||||||
if isinstance(raw_screens, dict):
|
|
||||||
if sort:
|
|
||||||
return sorted(self.hydrate_dict(raw_screens), key=lambda x: x.position)
|
|
||||||
return self.hydrate_dict(raw_screens)
|
|
||||||
|
|
||||||
return self.hydrate_list(sorted(raw_screens, key=lambda x: x['position']) if sort else raw_screens)
|
|
||||||
|
|
||||||
def get_enabled_screens(self) -> List[Screen]:
|
def get_enabled_screens(self) -> List[Screen]:
|
||||||
return [screen for screen in self.get_all(sort=True) if screen.enabled]
|
return self.get_by(query="enabled = 1", sort="position")
|
||||||
|
|
||||||
def get_disabled_screens(self) -> List[Screen]:
|
def get_disabled_screens(self) -> List[Screen]:
|
||||||
return [screen for screen in self.get_all(sort=True) if not screen.enabled]
|
return self.get_by(query="enabled = 0", sort="position")
|
||||||
|
|
||||||
def update_enabled(self, id: str, enabled: bool) -> None:
|
def update_enabled(self, id: int, enabled: bool) -> None:
|
||||||
self._db.update_by_id(id, {"enabled": enabled, "position": 999})
|
self._db.update_by_id(self.TABLE_NAME, id, {"enabled": enabled, "position": 999})
|
||||||
|
|
||||||
def update_positions(self, positions: list) -> None:
|
def update_positions(self, positions: list) -> None:
|
||||||
for screen_id, screen_position in positions.items():
|
for screen_id, screen_position in positions.items():
|
||||||
self._db.update_by_id(screen_id, {"position": screen_position})
|
self._db.update_by_id(self.TABLE_NAME, screen_id, {"position": screen_position})
|
||||||
|
|
||||||
def update_form(self, id: str, name: str, host: str, port: int) -> None:
|
def update_form(self, id: int, name: str, host: str, port: int) -> None:
|
||||||
self._db.update_by_id(id, {"name": name, "host": host, "port": port})
|
self._db.update_by_id(self.TABLE_NAME, id, {"name": name, "host": host, "port": port})
|
||||||
|
|
||||||
def add_form(self, screen: Union[Screen, Dict]) -> None:
|
def add_form(self, screen: Union[Screen, Dict]) -> None:
|
||||||
form = screen
|
form = screen
|
||||||
@ -85,10 +72,10 @@ class ScreenManager(ModelManager):
|
|||||||
form = screen.to_dict()
|
form = screen.to_dict()
|
||||||
del form['id']
|
del form['id']
|
||||||
|
|
||||||
self._db.add(form)
|
self._db.add(self.TABLE_NAME, form)
|
||||||
|
|
||||||
def delete(self, id: str) -> None:
|
def delete(self, id: int) -> None:
|
||||||
self._db.delete_by_id(id)
|
self._db.delete_by_id(self.TABLE_NAME, id)
|
||||||
|
|
||||||
def to_dict(self, screens: List[Screen]) -> List[Dict]:
|
def to_dict(self, screens: List[Screen]) -> List[Dict]:
|
||||||
return [screen.to_dict() for screen in screens]
|
return [screen.to_dict() for screen in screens]
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from typing import Dict, Optional, List, Tuple, Union
|
from typing import Dict, Optional, List, Tuple, Union
|
||||||
from pysondb.errors import IdDoesNotExistError
|
|
||||||
|
|
||||||
from src.model.entity.Slide import Slide
|
from src.model.entity.Slide import Slide
|
||||||
from src.model.enum.SlideType import SlideType
|
from src.model.enum.SlideType import SlideType
|
||||||
@ -16,80 +15,68 @@ class SlideManager(ModelManager):
|
|||||||
|
|
||||||
TABLE_NAME = "slideshow"
|
TABLE_NAME = "slideshow"
|
||||||
TABLE_MODEL = [
|
TABLE_MODEL = [
|
||||||
"name",
|
"name CHAR(255)",
|
||||||
"type",
|
"type CHAR(30)",
|
||||||
"enabled",
|
"enabled INTEGER",
|
||||||
"duration",
|
"duration INTEGER",
|
||||||
"position",
|
"position INTEGER",
|
||||||
"location",
|
"location TEXT",
|
||||||
"cron_schedule",
|
"cron_schedule CHAR(255)",
|
||||||
"cron_schedule_end",
|
"cron_schedule_end CHAR(255)",
|
||||||
"created_by",
|
"created_by CHAR(255)",
|
||||||
"updated_by",
|
"updated_by CHAR(255)",
|
||||||
"created_at",
|
"created_at INTEGER",
|
||||||
"updated_at"
|
"updated_at INTEGER"
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, user_manager: UserManager):
|
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, user_manager: UserManager):
|
||||||
super().__init__(lang_manager, database_manager, user_manager)
|
super().__init__(lang_manager, database_manager, user_manager)
|
||||||
self._db = database_manager.open(self.TABLE_NAME, self.TABLE_MODEL)
|
self._db = database_manager.open(self.TABLE_NAME, self.TABLE_MODEL)
|
||||||
|
|
||||||
def hydrate_object(self, raw_slide: dict, id: str = None) -> Slide:
|
def hydrate_object(self, raw_slide: dict, id: int = None) -> Slide:
|
||||||
if id:
|
if id:
|
||||||
raw_slide['id'] = id
|
raw_slide['id'] = id
|
||||||
|
|
||||||
[raw_slide, user_tracker_edits] = self.user_manager.initialize_user_trackers(raw_slide)
|
[raw_slide, user_tracker_edits] = self.user_manager.initialize_user_trackers(raw_slide)
|
||||||
|
|
||||||
if len(user_tracker_edits) > 0:
|
if len(user_tracker_edits) > 0:
|
||||||
self._db.update_by_id(raw_slide['id'], user_tracker_edits)
|
self._db.update_by_id(self.TABLE_NAME, raw_slide['id'], user_tracker_edits)
|
||||||
|
|
||||||
return Slide(**raw_slide)
|
return Slide(**raw_slide)
|
||||||
|
|
||||||
def hydrate_dict(self, raw_slides: dict) -> List[Slide]:
|
|
||||||
return [self.hydrate_object(raw_slide, raw_id) for raw_id, raw_slide in raw_slides.items()]
|
|
||||||
|
|
||||||
def hydrate_list(self, raw_slides: list) -> List[Slide]:
|
def hydrate_list(self, raw_slides: list) -> List[Slide]:
|
||||||
return [self.hydrate_object(raw_slide) for raw_slide in raw_slides]
|
return [self.hydrate_object(raw_slide) for raw_slide in raw_slides]
|
||||||
|
|
||||||
def get(self, id: str) -> Optional[Slide]:
|
def get(self, id: int) -> Optional[Slide]:
|
||||||
try:
|
object = self._db.get_by_id(self.TABLE_NAME, id)
|
||||||
return self.hydrate_object(self._db.get_by_id(id), id)
|
return self.hydrate_object(object, id) if object else None
|
||||||
except IdDoesNotExistError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_by(self, query) -> List[Slide]:
|
def get_by(self, query, sort: Optional[str] = None) -> List[Slide]:
|
||||||
return self.hydrate_dict(self._db.get_by_query(query=query))
|
return self.hydrate_list(self._db.get_by_query(self.TABLE_NAME, query=query, sort=sort))
|
||||||
|
|
||||||
def get_one_by(self, query) -> Optional[Slide]:
|
def get_one_by(self, query) -> Optional[Slide]:
|
||||||
slides = self.hydrate_dict(self._db.get_by_query(query=query))
|
object = self._db.get_one_by_query(self.TABLE_NAME, query=query)
|
||||||
if len(slides) == 1:
|
|
||||||
return slides[0]
|
if not object:
|
||||||
elif len(slides) > 1:
|
return None
|
||||||
raise Error("More than one result for query")
|
|
||||||
return None
|
return self.hydrate_object(object)
|
||||||
|
|
||||||
def get_all(self, sort: bool = False) -> List[Slide]:
|
def get_all(self, sort: bool = False) -> List[Slide]:
|
||||||
raw_slides = self._db.get_all()
|
return self.hydrate_list(self._db.get_all(self.TABLE_NAME, sort="position" if sort else None))
|
||||||
|
|
||||||
if isinstance(raw_slides, dict):
|
def forget_user(self, user_id: int):
|
||||||
if sort:
|
slides = self.get_by("created_by = '{}' or updated_by = '{}'".format(user_id, user_id))
|
||||||
return sorted(self.hydrate_dict(raw_slides), key=lambda x: x.position)
|
|
||||||
return self.hydrate_dict(raw_slides)
|
|
||||||
|
|
||||||
return self.hydrate_list(sorted(raw_slides, key=lambda x: x['position']) if sort else raw_slides)
|
|
||||||
|
|
||||||
def forget_user(self, user_id: str):
|
|
||||||
slides = self.hydrate_dict(self._db.get_by_query(query=lambda s: s['created_by'] == user_id or s['updated_by'] == user_id))
|
|
||||||
edits_slides = self.user_manager.forget_user(slides, user_id)
|
edits_slides = self.user_manager.forget_user(slides, user_id)
|
||||||
|
|
||||||
for slide_id, edits in edits_slides.items():
|
for slide_id, edits in edits_slides.items():
|
||||||
self._db.update_by_id(slide_id, edits)
|
self._db.update_by_id(self.TABLE_NAME, slide_id, edits)
|
||||||
|
|
||||||
def get_enabled_slides(self) -> List[Slide]:
|
def get_enabled_slides(self) -> List[Slide]:
|
||||||
return [slide for slide in self.get_all(sort=True) if slide.enabled]
|
return self.get_by(query="enabled = 1", sort="position")
|
||||||
|
|
||||||
def get_disabled_slides(self) -> List[Slide]:
|
def get_disabled_slides(self) -> List[Slide]:
|
||||||
return [slide for slide in self.get_all(sort=True) if not slide.enabled]
|
return self.get_by(query="enabled = 0", sort="position")
|
||||||
|
|
||||||
def pre_add(self, slide: Dict) -> Dict:
|
def pre_add(self, slide: Dict) -> Dict:
|
||||||
self.user_manager.track_user_on_create(slide)
|
self.user_manager.track_user_on_create(slide)
|
||||||
@ -115,15 +102,15 @@ class SlideManager(ModelManager):
|
|||||||
def post_delete(self, slide_id: str) -> str:
|
def post_delete(self, slide_id: str) -> str:
|
||||||
return slide_id
|
return slide_id
|
||||||
|
|
||||||
def update_enabled(self, id: str, enabled: bool) -> None:
|
def update_enabled(self, id: int, enabled: bool) -> None:
|
||||||
self._db.update_by_id(id, self.pre_update({"enabled": enabled, "position": 999}))
|
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update({"enabled": enabled, "position": 999}))
|
||||||
self.post_update(id)
|
self.post_update(id)
|
||||||
|
|
||||||
def update_positions(self, positions: list) -> None:
|
def update_positions(self, positions: list) -> None:
|
||||||
for slide_id, slide_position in positions.items():
|
for slide_id, slide_position in positions.items():
|
||||||
self._db.update_by_id(slide_id, {"position": slide_position})
|
self._db.update_by_id(self.TABLE_NAME, slide_id, {"position": slide_position})
|
||||||
|
|
||||||
def update_form(self, id: str, name: str, duration: int, cron_schedule: Optional[str] = '', cron_schedule_end: Optional[str] = '', location: Optional[str] = None) -> None:
|
def update_form(self, id: int, name: str, duration: int, cron_schedule: Optional[str] = '', cron_schedule_end: Optional[str] = '', location: Optional[str] = None) -> None:
|
||||||
slide = self.get(id)
|
slide = self.get(id)
|
||||||
|
|
||||||
if not slide:
|
if not slide:
|
||||||
@ -142,7 +129,7 @@ class SlideManager(ModelManager):
|
|||||||
if slide.type == SlideType.YOUTUBE:
|
if slide.type == SlideType.YOUTUBE:
|
||||||
form['location'] = get_yt_video_id(form['location'])
|
form['location'] = get_yt_video_id(form['location'])
|
||||||
|
|
||||||
self._db.update_by_id(id, self.pre_update(form))
|
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update(form))
|
||||||
self.post_update(id)
|
self.post_update(id)
|
||||||
|
|
||||||
def add_form(self, slide: Union[Slide, Dict]) -> None:
|
def add_form(self, slide: Union[Slide, Dict]) -> None:
|
||||||
@ -155,10 +142,10 @@ class SlideManager(ModelManager):
|
|||||||
if form['type'] == SlideType.YOUTUBE.value:
|
if form['type'] == SlideType.YOUTUBE.value:
|
||||||
form['location'] = get_yt_video_id(form['location'])
|
form['location'] = get_yt_video_id(form['location'])
|
||||||
|
|
||||||
self._db.add(self.pre_add(form))
|
self._db.add(self.TABLE_NAME, self.pre_add(form))
|
||||||
self.post_add(slide.id)
|
self.post_add(slide.id)
|
||||||
|
|
||||||
def delete(self, id: str) -> None:
|
def delete(self, id: int) -> None:
|
||||||
slide = self.get(id)
|
slide = self.get(id)
|
||||||
|
|
||||||
if slide:
|
if slide:
|
||||||
@ -169,7 +156,7 @@ class SlideManager(ModelManager):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
self.pre_delete(id)
|
self.pre_delete(id)
|
||||||
self._db.delete_by_id(id)
|
self._db.delete_by_id(self.TABLE_NAME, id)
|
||||||
self.post_delete(id)
|
self.post_delete(id)
|
||||||
|
|
||||||
def to_dict(self, slides: List[Slide]) -> List[Dict]:
|
def to_dict(self, slides: List[Slide]) -> List[Dict]:
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import time
|
import time
|
||||||
from pysondb.errors import IdDoesNotExistError
|
|
||||||
from typing import Dict, Optional, List, Tuple, Union
|
from typing import Dict, Optional, List, Tuple, Union
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
@ -14,9 +13,9 @@ class UserManager:
|
|||||||
|
|
||||||
TABLE_NAME = "user"
|
TABLE_NAME = "user"
|
||||||
TABLE_MODEL = [
|
TABLE_MODEL = [
|
||||||
"username",
|
"username CHAR(255)",
|
||||||
"password",
|
"password CHAR(255)",
|
||||||
"enabled"
|
"enabled INTEGER"
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, on_user_delete):
|
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, on_user_delete):
|
||||||
@ -44,37 +43,32 @@ class UserManager:
|
|||||||
|
|
||||||
return user_map
|
return user_map
|
||||||
|
|
||||||
def hydrate_object(self, raw_user: dict, id: Optional[str] = None) -> User:
|
def hydrate_object(self, raw_user: dict, id: Optional[int] = None) -> User:
|
||||||
if id:
|
if id:
|
||||||
raw_user['id'] = id
|
raw_user['id'] = id
|
||||||
|
|
||||||
return User(**raw_user)
|
return User(**raw_user)
|
||||||
|
|
||||||
def hydrate_dict(self, raw_users: dict) -> List[User]:
|
|
||||||
return [self.hydrate_object(raw_user, raw_id) for raw_id, raw_user in raw_users.items()]
|
|
||||||
|
|
||||||
def hydrate_list(self, raw_users: list) -> List[User]:
|
def hydrate_list(self, raw_users: list) -> List[User]:
|
||||||
return [self.hydrate_object(raw_user) for raw_user in raw_users]
|
return [self.hydrate_object(raw_user) for raw_user in raw_users]
|
||||||
|
|
||||||
def get(self, id: str) -> Optional[User]:
|
def get(self, id: int) -> Optional[User]:
|
||||||
try:
|
object = self._db.get_by_id(self.TABLE_NAME, id)
|
||||||
return self.hydrate_object(self._db.get_by_id(id), id)
|
return self.hydrate_object(object, id) if object else None
|
||||||
except IdDoesNotExistError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_by(self, query) -> List[User]:
|
def get_by(self, query, sort: Optional[str] = None) -> List[User]:
|
||||||
return self.hydrate_dict(self._db.get_by_query(query=query))
|
return self.hydrate_list(self._db.get_by_query(self.TABLE_NAME, query=query, sort=sort))
|
||||||
|
|
||||||
def get_one_by(self, query) -> Optional[User]:
|
def get_one_by(self, query) -> Optional[User]:
|
||||||
users = self.hydrate_dict(self._db.get_by_query(query=query))
|
object = self._db.get_one_by_query(self.TABLE_NAME, query=query)
|
||||||
if len(users) == 1:
|
|
||||||
return users[0]
|
if not object:
|
||||||
elif len(users) > 1:
|
return None
|
||||||
raise Error("More than one result for query")
|
|
||||||
return None
|
return self.hydrate_object(object)
|
||||||
|
|
||||||
def get_one_by_username(self, username: str, enabled: bool = None) -> Optional[User]:
|
def get_one_by_username(self, username: str, enabled: bool = None) -> Optional[User]:
|
||||||
return self.get_one_by(query=lambda v: v['username'] == username and (enabled is None or v['enabled'] == enabled))
|
return self.get_one_by("username = '{}' and (enabled is null or enabled = {})".format(username, int(enabled)))
|
||||||
|
|
||||||
def count_all_enabled(self):
|
def count_all_enabled(self):
|
||||||
return len(self.get_enabled_users())
|
return len(self.get_enabled_users())
|
||||||
@ -85,12 +79,16 @@ class UserManager:
|
|||||||
def track_user_updated(self, id_or_entity: Optional[str]) -> User:
|
def track_user_updated(self, id_or_entity: Optional[str]) -> User:
|
||||||
return self.track_user_action(id_or_entity, 'updated_by')
|
return self.track_user_action(id_or_entity, 'updated_by')
|
||||||
|
|
||||||
def track_user_action(self, id_or_entity: Optional[str], attribute: Optional[str] = 'created_by') -> User:
|
def track_user_action(self, id_or_entity: Optional[int], attribute: Optional[str] = 'created_by') -> User:
|
||||||
if not isinstance(id_or_entity, str):
|
if not isinstance(id_or_entity, int):
|
||||||
id_or_entity = getattr(id_or_entity, attribute)
|
id_or_entity = getattr(id_or_entity, attribute)
|
||||||
id_or_entity = str(id_or_entity)
|
|
||||||
|
|
||||||
user_map = self.map()
|
try:
|
||||||
|
id_or_entity = int(id_or_entity)
|
||||||
|
except ValueError:
|
||||||
|
return User(username=id_or_entity, enabled=False)
|
||||||
|
|
||||||
|
user_map = self.prepare_map()
|
||||||
|
|
||||||
if id_or_entity in user_map:
|
if id_or_entity in user_map:
|
||||||
return user_map[id_or_entity]
|
return user_map[id_or_entity]
|
||||||
@ -101,20 +99,13 @@ class UserManager:
|
|||||||
return User(username=self._lang_manager.translate('anonymous'), enabled=False)
|
return User(username=self._lang_manager.translate('anonymous'), enabled=False)
|
||||||
|
|
||||||
def get_all(self, sort: bool = False) -> List[User]:
|
def get_all(self, sort: bool = False) -> List[User]:
|
||||||
raw_users = self._db.get_all()
|
return self.hydrate_list(self._db.get_all(self.TABLE_NAME, "username" if sort else None))
|
||||||
|
|
||||||
if isinstance(raw_users, dict):
|
|
||||||
if sort:
|
|
||||||
return sorted(self.hydrate_dict(raw_users), key=lambda x: x.username)
|
|
||||||
return self.hydrate_dict(raw_users)
|
|
||||||
|
|
||||||
return self.hydrate_list(sorted(raw_users, key=lambda x: x['username']) if sort else raw_users)
|
|
||||||
|
|
||||||
def get_enabled_users(self) -> List[User]:
|
def get_enabled_users(self) -> List[User]:
|
||||||
return [user for user in self.get_all(sort=True) if user.enabled]
|
return self.get_by(query="enabled = 1", sort="username")
|
||||||
|
|
||||||
def get_disabled_users(self) -> List[User]:
|
def get_disabled_users(self) -> List[User]:
|
||||||
return [user for user in self.get_all(sort=True) if not user.enabled]
|
return self.get_by(query="enabled = 0", sort="username")
|
||||||
|
|
||||||
def pre_add(self, user: Dict) -> Dict:
|
def pre_add(self, user: Dict) -> Dict:
|
||||||
return user
|
return user
|
||||||
@ -122,33 +113,33 @@ class UserManager:
|
|||||||
def pre_update(self, user: Dict) -> Dict:
|
def pre_update(self, user: Dict) -> Dict:
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def pre_delete(self, user_id: str) -> str:
|
def pre_delete(self, user_id: int) -> int:
|
||||||
self._on_user_delete(user_id)
|
self._on_user_delete(user_id)
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
def post_add(self, user_id: str) -> str:
|
def post_add(self, user_id: int) -> int:
|
||||||
self.reload()
|
self.reload()
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
def post_update(self, user_id: str) -> str:
|
def post_update(self, user_id: int) -> int:
|
||||||
self.reload()
|
self.reload()
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
def post_delete(self, user_id: str) -> str:
|
def post_delete(self, user_id: int) -> int:
|
||||||
self.reload()
|
self.reload()
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
def update_enabled(self, id: str, enabled: bool) -> None:
|
def update_enabled(self, id: int, enabled: bool) -> None:
|
||||||
self._db.update_by_id(id, self.pre_update({"enabled": enabled}))
|
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update({"enabled": enabled}))
|
||||||
self.post_update(id)
|
self.post_update(id)
|
||||||
|
|
||||||
def update_form(self, id: str, username: str, password: Optional[str]) -> None:
|
def update_form(self, id: int, username: str, password: Optional[str]) -> None:
|
||||||
form = {"username": username}
|
form = {"username": username}
|
||||||
|
|
||||||
if password is not None and password:
|
if password is not None and password:
|
||||||
form['password'] = self.encode_password(password)
|
form['password'] = self.encode_password(password)
|
||||||
|
|
||||||
self._db.update_by_id(id, self.pre_update(form))
|
self._db.update_by_id(self.TABLE_NAME, id, self.pre_update(form))
|
||||||
self.post_update(id)
|
self.post_update(id)
|
||||||
|
|
||||||
def add_form(self, user: Union[User, Dict]) -> None:
|
def add_form(self, user: Union[User, Dict]) -> None:
|
||||||
@ -160,12 +151,12 @@ class UserManager:
|
|||||||
|
|
||||||
form['password'] = self.encode_password(form['password'])
|
form['password'] = self.encode_password(form['password'])
|
||||||
|
|
||||||
self._db.add(self.pre_add(form))
|
self._db.add(self.TABLE_NAME, self.pre_add(form))
|
||||||
self.post_add(user.id)
|
self.post_add(user.id)
|
||||||
|
|
||||||
def delete(self, id: str) -> None:
|
def delete(self, id: int) -> None:
|
||||||
self.pre_delete(id)
|
self.pre_delete(id)
|
||||||
self._db.delete_by_id(id)
|
self._db.delete_by_id(self.TABLE_NAME, id)
|
||||||
self.post_delete(id)
|
self.post_delete(id)
|
||||||
|
|
||||||
def to_dict(self, users: List[User]) -> List[Dict]:
|
def to_dict(self, users: List[User]) -> List[Dict]:
|
||||||
@ -215,18 +206,18 @@ class UserManager:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def forget_user(self, objects: List, user_id: str) -> Dict:
|
def forget_user(self, objects: List, user_id: int) -> Dict:
|
||||||
user_map = self.map()
|
user_map = self.prepare_map()
|
||||||
user_id = str(user_id)
|
user_id = int(user_id)
|
||||||
edits = {}
|
edits = {}
|
||||||
|
|
||||||
for object in objects:
|
for object in objects:
|
||||||
edits = {object.id: {}}
|
edits[object.id] = {}
|
||||||
|
|
||||||
if str(object.created_by) == user_id and user_id in user_map:
|
if int(object.created_by) == user_id and user_id in user_map:
|
||||||
edits[object.id]['created_by'] = user_map[user_id].username
|
edits[object.id]['created_by'] = user_map[user_id].username
|
||||||
|
|
||||||
if str(object.updated_by) == user_id and user_id in user_map:
|
if int(object.updated_by) == user_id and user_id in user_map:
|
||||||
edits[object.id]['updated_by'] = user_map[user_id].username
|
edits[object.id]['updated_by'] = user_map[user_id].username
|
||||||
|
|
||||||
return edits
|
return edits
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
import json
|
||||||
import time
|
import time
|
||||||
from typing import Dict, Optional, List, Tuple, Union
|
from typing import Dict, Optional, List, Tuple, Union
|
||||||
from pysondb.errors import IdDoesNotExistError
|
|
||||||
|
|
||||||
from src.manager.DatabaseManager import DatabaseManager
|
from src.manager.DatabaseManager import DatabaseManager
|
||||||
from src.manager.LangManager import LangManager
|
from src.manager.LangManager import LangManager
|
||||||
@ -24,17 +24,17 @@ class VariableManager(ModelManager):
|
|||||||
|
|
||||||
TABLE_NAME = "settings"
|
TABLE_NAME = "settings"
|
||||||
TABLE_MODEL = [
|
TABLE_MODEL = [
|
||||||
"description",
|
"description TEXT",
|
||||||
"description_edition",
|
"description_edition TEXT",
|
||||||
"editable",
|
"editable INTEGER",
|
||||||
"name",
|
"name CHAR(255)",
|
||||||
"section",
|
"section CHAR(255)",
|
||||||
"plugin",
|
"plugin CHAR(255)",
|
||||||
"selectables",
|
"selectables TEXT",
|
||||||
"type",
|
"type CHAR(255)",
|
||||||
"unit",
|
"unit CHAR(255)",
|
||||||
"refresh_player",
|
"refresh_player INTEGER",
|
||||||
"value"
|
"value TEXT"
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, user_manager: UserManager):
|
def __init__(self, lang_manager: LangManager, database_manager: DatabaseManager, user_manager: UserManager):
|
||||||
@ -75,25 +75,25 @@ class VariableManager(ModelManager):
|
|||||||
same_selectables_label = get_keys(default_var, 'selectables', 'label') == get_keys(variable, 'selectables', 'label')
|
same_selectables_label = get_keys(default_var, 'selectables', 'label') == get_keys(variable, 'selectables', 'label')
|
||||||
|
|
||||||
if variable.description != default_var['description']:
|
if variable.description != default_var['description']:
|
||||||
self._db.update_by_id(variable.id, {"description": default_var['description']})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"description": default_var['description']})
|
||||||
|
|
||||||
if variable.description_edition != default_var['description_edition']:
|
if variable.description_edition != default_var['description_edition']:
|
||||||
self._db.update_by_id(variable.id, {"description_edition": default_var['description_edition']})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"description_edition": default_var['description_edition']})
|
||||||
|
|
||||||
if variable.unit != default_var['unit']:
|
if variable.unit != default_var['unit']:
|
||||||
self._db.update_by_id(variable.id, {"unit": default_var['unit']})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"unit": default_var['unit']})
|
||||||
|
|
||||||
if variable.section != default_var['section']:
|
if variable.section != default_var['section']:
|
||||||
self._db.update_by_id(variable.id, {"section": default_var['section']})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"section": default_var['section']})
|
||||||
|
|
||||||
if variable.refresh_player != default_var['refresh_player']:
|
if variable.refresh_player != default_var['refresh_player']:
|
||||||
self._db.update_by_id(variable.id, {"refresh_player": default_var['refresh_player']})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"refresh_player": default_var['refresh_player']})
|
||||||
|
|
||||||
if not same_selectables_keys or not same_selectables_label:
|
if not same_selectables_keys or not same_selectables_label:
|
||||||
self._db.update_by_id(variable.id, {"selectables": default_var['selectables']})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"selectables": default_var['selectables']})
|
||||||
|
|
||||||
if variable.name == 'last_restart':
|
if variable.name == 'last_restart':
|
||||||
self._db.update_by_id(variable.id, {"value": time.time()})
|
self._db.update_by_id(self.TABLE_NAME, variable.id, {"value": time.time()})
|
||||||
|
|
||||||
return variable
|
return variable
|
||||||
|
|
||||||
@ -144,75 +144,60 @@ class VariableManager(ModelManager):
|
|||||||
|
|
||||||
return var_map
|
return var_map
|
||||||
|
|
||||||
def hydrate_object(self, raw_variable: dict, id: Optional[str] = None) -> Variable:
|
def hydrate_object(self, raw_variable: dict, id: Optional[int] = None) -> Variable:
|
||||||
if id:
|
if id:
|
||||||
raw_variable['id'] = id
|
raw_variable['id'] = id
|
||||||
|
|
||||||
if 'selectables' in raw_variable and raw_variable['selectables']:
|
if 'selectables' in raw_variable and raw_variable['selectables']:
|
||||||
raw_variable['selectables'] = [Selectable(**selectable) for selectable in raw_variable['selectables']]
|
raw_variable['selectables'] = [Selectable(**selectable) for selectable in json.loads(raw_variable['selectables'])]
|
||||||
|
|
||||||
return Variable(**raw_variable)
|
return Variable(**raw_variable)
|
||||||
|
|
||||||
def hydrate_dict(self, raw_variables: dict) -> List[Variable]:
|
|
||||||
return [self.hydrate_object(raw_variable, raw_id) for raw_id, raw_variable in raw_variables.items()]
|
|
||||||
|
|
||||||
def hydrate_list(self, raw_variables: list) -> List[Variable]:
|
def hydrate_list(self, raw_variables: list) -> List[Variable]:
|
||||||
return [self.hydrate_object(raw_variable) for raw_variable in raw_variables]
|
return [self.hydrate_object(raw_variable) for raw_variable in raw_variables]
|
||||||
|
|
||||||
def get(self, id: str) -> Optional[Variable]:
|
def get(self, id: int) -> Optional[Variable]:
|
||||||
try:
|
object = self._db.get_by_id(self.TABLE_NAME, id)
|
||||||
return self.hydrate_object(self._db.get_by_id(id), id)
|
return self.hydrate_object(object, id) if object else None
|
||||||
except IdDoesNotExistError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_by(self, query) -> List[Variable]:
|
def get_by(self, query, sort: Optional[str] = None) -> List[Variable]:
|
||||||
return self.hydrate_dict(self._db.get_by_query(query=query))
|
return self.hydrate_list(self._db.get_by_query(self.TABLE_NAME, query=query, sort=sort))
|
||||||
|
|
||||||
def get_by_prefix(self, prefix: str) -> List[Variable]:
|
def get_by_prefix(self, prefix: str) -> List[Variable]:
|
||||||
return self.hydrate_dict(self._db.get_by_query(query=lambda v: v['name'].startswith(prefix)))
|
return self.get_by(query="name like '{}%'".format(prefix))
|
||||||
|
|
||||||
def get_by_plugin(self, plugin: str) -> List[Variable]:
|
def get_by_plugin(self, plugin: str) -> List[Variable]:
|
||||||
return self.hydrate_dict(self._db.get_by_query(query=lambda v: v['plugin'] == plugin))
|
return self.get_by(query="plugin = '{}'".format(plugin))
|
||||||
|
|
||||||
def get_one_by_name(self, name: str) -> Optional[Variable]:
|
def get_one_by_name(self, name: str) -> Optional[Variable]:
|
||||||
return self.get_one_by(query=lambda v: v['name'] == name)
|
return self.get_one_by("name = '{}'".format(name))
|
||||||
|
|
||||||
def get_one_by(self, query) -> Optional[Variable]:
|
def get_one_by(self, query) -> Optional[Variable]:
|
||||||
object = self._db.get_by_query(query=query)
|
object = self._db.get_one_by_query(self.TABLE_NAME, query=query)
|
||||||
variables = self.hydrate_dict(object)
|
|
||||||
if len(variables) == 1:
|
if not object:
|
||||||
return variables[0]
|
return None
|
||||||
elif len(variables) > 1:
|
|
||||||
raise Error("More than one result for query")
|
return self.hydrate_object(object)
|
||||||
return None
|
|
||||||
|
|
||||||
def get_all(self) -> List[Variable]:
|
def get_all(self) -> List[Variable]:
|
||||||
raw_variables = self._db.get_all()
|
return self.hydrate_list(self._db.get_all(self.TABLE_NAME))
|
||||||
|
|
||||||
if isinstance(raw_variables, dict):
|
|
||||||
return self.hydrate_dict(raw_variables)
|
|
||||||
|
|
||||||
return self.hydrate_list(raw_variables)
|
|
||||||
|
|
||||||
def get_editable_variables(self, plugin: bool = True, sort: Optional[str] = None) -> List[Variable]:
|
def get_editable_variables(self, plugin: bool = True, sort: Optional[str] = None) -> List[Variable]:
|
||||||
query = lambda v: (not plugin and not isinstance(v['plugin'], str)) or (plugin and isinstance(v['plugin'], str))
|
query = "plugin is null and editable = 1" if not plugin else "plugin is not null and length(plugin) > 0 and editable = 1"
|
||||||
variables = [variable for variable in self.get_by(query=query) if variable.editable]
|
return self.get_by(query=query, sort=sort)
|
||||||
if sort is not None and sort:
|
|
||||||
return sorted(variables, key=lambda x: getattr(x, sort))
|
|
||||||
return variables
|
|
||||||
|
|
||||||
def get_readonly_variables(self) -> List[Variable]:
|
def get_readonly_variables(self) -> List[Variable]:
|
||||||
return [variable for variable in self.get_all() if not variable.editable]
|
return self.get_by(query="editable = 0", sort="name")
|
||||||
|
|
||||||
def update_form(self, id: str, value: Union[int, bool, str]) -> None:
|
def update_form(self, id: int, value: Union[int, bool, str]) -> None:
|
||||||
var_dict = self._db.update_by_id(id, {"value": value})
|
self._db.update_by_id(self.TABLE_NAME, id, {"value": value})
|
||||||
var = self.hydrate_object(var_dict, id)
|
var = self.get_one_by("id = {}".format(id))
|
||||||
self._var_map[var.name] = var
|
self._var_map[var.name] = var
|
||||||
|
|
||||||
def update_by_name(self, name: str, value) -> Optional[Variable]:
|
def update_by_name(self, name: str, value) -> Optional[Variable]:
|
||||||
[var_id] = self._db.update_by_query(query=lambda v: v['name'] == name, new_data={"value": value})
|
self._db.update_by_query(self.TABLE_NAME, query="name = '{}'".format(name), values={"value": value})
|
||||||
var_dict = self._db.get_by_id(var_id)
|
var = self.get_one_by_name(name)
|
||||||
var = self.hydrate_object(var_dict, id)
|
|
||||||
self._var_map[name] = var
|
self._var_map[name] = var
|
||||||
|
|
||||||
def add_form(self, variable: Union[Variable, Dict]) -> None:
|
def add_form(self, variable: Union[Variable, Dict]) -> None:
|
||||||
@ -222,10 +207,10 @@ class VariableManager(ModelManager):
|
|||||||
form = variable.to_dict()
|
form = variable.to_dict()
|
||||||
del form['id']
|
del form['id']
|
||||||
|
|
||||||
self._db.add(form)
|
self._db.add(self.TABLE_NAME, form)
|
||||||
|
|
||||||
def delete(self, id: str) -> None:
|
def delete(self, id: int) -> None:
|
||||||
self._db.delete_by_id(id)
|
self._db.delete_by_id(self.TABLE_NAME, id)
|
||||||
|
|
||||||
def to_dict(self, variables: List[Variable]) -> List[Dict]:
|
def to_dict(self, variables: List[Variable]) -> List[Dict]:
|
||||||
return [variable.to_dict() for variable in variables]
|
return [variable.to_dict() for variable in variables]
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from typing import Optional, Union
|
|||||||
|
|
||||||
class Screen:
|
class Screen:
|
||||||
|
|
||||||
def __init__(self, host: str = '', port: int = 5000, enabled: bool = False, name: str = 'Untitled', position: int = 999, id: Optional[str] = None):
|
def __init__(self, host: str = '', port: int = 5000, enabled: bool = False, name: str = 'Untitled', position: int = 999, id: Optional[int] = None):
|
||||||
self._id = id if id else None
|
self._id = id if id else None
|
||||||
self._host = host
|
self._host = host
|
||||||
self._port = port
|
self._port = port
|
||||||
@ -14,7 +14,7 @@ class Screen:
|
|||||||
self._position = position
|
self._position = position
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> Union[int, str]:
|
def id(self) -> Optional[int]:
|
||||||
return self._id
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -35,11 +35,11 @@ class Screen:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def enabled(self) -> bool:
|
def enabled(self) -> bool:
|
||||||
return self._enabled
|
return bool(self._enabled)
|
||||||
|
|
||||||
@enabled.setter
|
@enabled.setter
|
||||||
def enabled(self, value: bool):
|
def enabled(self, value: bool):
|
||||||
self._enabled = value
|
self._enabled = bool(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from src.utils import str_to_enum
|
|||||||
|
|
||||||
class Slide:
|
class Slide:
|
||||||
|
|
||||||
def __init__(self, location: str = '', duration: int = 3, type: Union[SlideType, str] = SlideType.URL, enabled: bool = False, name: str = 'Untitled', position: int = 999, id: Optional[str] = None, cron_schedule: Optional[str] = None, cron_schedule_end: Optional[str] = None, created_by: Optional[str] = None, updated_by: Optional[str] = None, created_at: Optional[int] = None, updated_at: Optional[int] = None):
|
def __init__(self, location: str = '', duration: int = 3, type: Union[SlideType, str] = SlideType.URL, enabled: bool = False, name: str = 'Untitled', position: int = 999, id: Optional[int] = None, cron_schedule: Optional[str] = None, cron_schedule_end: Optional[str] = None, created_by: Optional[str] = None, updated_by: Optional[str] = None, created_at: Optional[int] = None, updated_at: Optional[int] = None):
|
||||||
self._id = id if id else None
|
self._id = id if id else None
|
||||||
self._location = location
|
self._location = location
|
||||||
self._duration = duration
|
self._duration = duration
|
||||||
@ -24,7 +24,7 @@ class Slide:
|
|||||||
self._updated_at = int(updated_at if updated_at else time.time())
|
self._updated_at = int(updated_at if updated_at else time.time())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> Optional[str]:
|
def id(self) -> Optional[int]:
|
||||||
return self._id
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -101,11 +101,11 @@ class Slide:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def enabled(self) -> bool:
|
def enabled(self) -> bool:
|
||||||
return self._enabled
|
return bool(self._enabled)
|
||||||
|
|
||||||
@enabled.setter
|
@enabled.setter
|
||||||
def enabled(self, value: bool):
|
def enabled(self, value: bool):
|
||||||
self._enabled = value
|
self._enabled = bool(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
|||||||
@ -5,14 +5,14 @@ from typing import Optional, Union
|
|||||||
|
|
||||||
class User:
|
class User:
|
||||||
|
|
||||||
def __init__(self, username: str = '', password: str = '', enabled: bool = True, id: Optional[str] = None):
|
def __init__(self, username: str = '', password: str = '', enabled: bool = True, id: Optional[int] = None):
|
||||||
self._id = id if id else None
|
self._id = id if id else None
|
||||||
self._username = username
|
self._username = username
|
||||||
self._password = password
|
self._password = password
|
||||||
self._enabled = enabled
|
self._enabled = enabled
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> Union[int, str]:
|
def id(self) -> Optional[int]:
|
||||||
return self._id
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -33,11 +33,11 @@ class User:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def enabled(self) -> bool:
|
def enabled(self) -> bool:
|
||||||
return self._enabled
|
return bool(self._enabled)
|
||||||
|
|
||||||
@enabled.setter
|
@enabled.setter
|
||||||
def enabled(self, value: bool):
|
def enabled(self, value: bool):
|
||||||
self._enabled = value
|
self._enabled = bool(value)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"User(" \
|
return f"User(" \
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from src.utils import str_to_enum
|
|||||||
class Variable:
|
class Variable:
|
||||||
|
|
||||||
def __init__(self, name: str = '', section: str = '', description: str = '', description_edition: str = '', type: Union[VariableType, str] = VariableType.STRING,
|
def __init__(self, name: str = '', section: str = '', description: str = '', description_edition: str = '', type: Union[VariableType, str] = VariableType.STRING,
|
||||||
value: Union[int, bool, str] = '', editable: bool = True, id: Optional[str] = None,
|
value: Union[int, bool, str] = '', editable: bool = True, id: Optional[int] = None,
|
||||||
plugin: Optional[str] = None, selectables: Optional[List[Selectable]] = None, unit: Optional[VariableUnit] = None,
|
plugin: Optional[str] = None, selectables: Optional[List[Selectable]] = None, unit: Optional[VariableUnit] = None,
|
||||||
refresh_player: bool = False):
|
refresh_player: bool = False):
|
||||||
self._id = id if id else None
|
self._id = id if id else None
|
||||||
@ -32,7 +32,7 @@ class Variable:
|
|||||||
self._unit = None
|
self._unit = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> Union[int, str]:
|
def id(self) -> Optional[int]:
|
||||||
return self._id
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -96,19 +96,19 @@ class Variable:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def editable(self) -> bool:
|
def editable(self) -> bool:
|
||||||
return self._editable
|
return bool(self._editable)
|
||||||
|
|
||||||
@editable.setter
|
@editable.setter
|
||||||
def editable(self, value: bool):
|
def editable(self, value: bool):
|
||||||
self._editable = value
|
self._editable = bool(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def refresh_player(self) -> bool:
|
def refresh_player(self) -> bool:
|
||||||
return self._refresh_player
|
return bool(self._refresh_player)
|
||||||
|
|
||||||
@refresh_player.setter
|
@refresh_player.setter
|
||||||
def refresh_player(self, value: bool):
|
def refresh_player(self, value: bool):
|
||||||
self._refresh_player = value
|
self._refresh_player = bool(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> Union[int, bool, str]:
|
def value(self) -> Union[int, bool, str]:
|
||||||
@ -171,10 +171,10 @@ class Variable:
|
|||||||
return str(self._value)
|
return str(self._value)
|
||||||
|
|
||||||
def as_int(self) -> int:
|
def as_int(self) -> int:
|
||||||
return int(self._value)
|
return int(float(self._value))
|
||||||
|
|
||||||
def as_ctime(self) -> int:
|
def as_ctime(self) -> int:
|
||||||
return time.ctime(self._value)
|
return time.ctime(int(float(self._value)))
|
||||||
|
|
||||||
def display(self) -> Union[int, bool, str]:
|
def display(self) -> Union[int, bool, str]:
|
||||||
value = self.eval()
|
value = self.eval()
|
||||||
|
|||||||
@ -53,5 +53,5 @@ class ModelStore:
|
|||||||
def user(self) -> UserManager:
|
def user(self) -> UserManager:
|
||||||
return self._user_manager
|
return self._user_manager
|
||||||
|
|
||||||
def on_user_delete(self, user_id: str):
|
def on_user_delete(self, user_id: int) -> None:
|
||||||
self._slide_manager.forget_user(user_id)
|
self._slide_manager.forget_user(user_id)
|
||||||
|
|||||||
@ -156,6 +156,9 @@ class PluginStore:
|
|||||||
|
|
||||||
def is_plugin_enabled(self, plugin: ObPlugin) -> bool:
|
def is_plugin_enabled(self, plugin: ObPlugin) -> bool:
|
||||||
var = self._model_store.variable().get_one_by_name(plugin.get_plugin_variable_name(self.DEFAULT_PLUGIN_ENABLED_VARIABLE))
|
var = self._model_store.variable().get_one_by_name(plugin.get_plugin_variable_name(self.DEFAULT_PLUGIN_ENABLED_VARIABLE))
|
||||||
|
if var.as_bool:
|
||||||
|
logging.info("[Plugin] {} enabled".format(plugin.use_title()))
|
||||||
|
|
||||||
return var.as_bool() if var else False
|
return var.as_bool() if var else False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class TemplateRenderer:
|
|||||||
def get_view_globals(self) -> dict:
|
def get_view_globals(self) -> dict:
|
||||||
globals = dict(
|
globals = dict(
|
||||||
STATIC_PREFIX="/{}/{}/".format(WebDirConstant.FOLDER_STATIC, WebDirConstant.FOLDER_STATIC_WEB_ASSETS),
|
STATIC_PREFIX="/{}/{}/".format(WebDirConstant.FOLDER_STATIC, WebDirConstant.FOLDER_STATIC_WEB_ASSETS),
|
||||||
|
SECRET_KEY=self._model_store.config().map().get('secret_key'),
|
||||||
FLEET_ENABLED=self._model_store.variable().map().get('fleet_enabled').as_bool(),
|
FLEET_ENABLED=self._model_store.variable().map().get('fleet_enabled').as_bool(),
|
||||||
AUTH_ENABLED=self._model_store.variable().map().get('auth_enabled').as_bool(),
|
AUTH_ENABLED=self._model_store.variable().map().get('auth_enabled').as_bool(),
|
||||||
track_created=self._model_store.user().track_user_created,
|
track_created=self._model_store.user().track_user_created,
|
||||||
|
|||||||
14
src/utils.py
14
src/utils.py
@ -13,6 +13,20 @@ from cron_descriptor.Exception import FormatException, WrongArgumentException, M
|
|||||||
CAMEL_CASE_TO_SNAKE_CASE_PATTERN = re.compile(r'(?<!^)(?=[A-Z])')
|
CAMEL_CASE_TO_SNAKE_CASE_PATTERN = re.compile(r'(?<!^)(?=[A-Z])')
|
||||||
|
|
||||||
|
|
||||||
|
def is_wrapped_by(s: str, head: str = '', tail: str = '') -> bool:
|
||||||
|
return s[0] == head and s[-1] == tail if len(s) > 0 else None
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_if(s: str, condition: bool = True, quote_type: str = "'") -> str:
|
||||||
|
if not condition or is_wrapped_by(s, quote_type, quote_type):
|
||||||
|
return s
|
||||||
|
return "{}{}{}".format(
|
||||||
|
quote_type,
|
||||||
|
s,
|
||||||
|
quote_type
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def am_i_in_docker():
|
def am_i_in_docker():
|
||||||
docker_env = os.path.exists('/.dockerenv')
|
docker_env = os.path.exists('/.dockerenv')
|
||||||
docker_cgroup = False
|
docker_cgroup = False
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
1.14
|
1.15
|
||||||
|
|||||||
@ -113,6 +113,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
var secret_key = '{{ SECRET_KEY }}';
|
||||||
var l = {
|
var l = {
|
||||||
'js_slideshow_slide_delete_confirmation': '{{ l.slideshow_slide_delete_confirmation }}',
|
'js_slideshow_slide_delete_confirmation': '{{ l.slideshow_slide_delete_confirmation }}',
|
||||||
'js_fleet_screen_delete_confirmation': '{{ l.js_fleet_screen_delete_confirmation }}',
|
'js_fleet_screen_delete_confirmation': '{{ l.js_fleet_screen_delete_confirmation }}',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user