import os import time from waitress import serve from flask import Flask, send_from_directory, redirect, url_for from flask_login import LoginManager, current_user from src.model.entity.User import User from src.manager.UserManager import UserManager from src.service.ModelStore import ModelStore from src.service.TemplateRenderer import TemplateRenderer from src.controller.PlayerController import PlayerController from src.controller.SlideshowController import SlideshowController from src.controller.FleetController import FleetController from src.controller.AuthController import AuthController from src.controller.SysinfoController import SysinfoController from src.controller.SettingsController import SettingsController from src.constant.WebDirConstant import WebDirConstant class WebServer: def __init__(self, project_dir: str, model_store: ModelStore, template_renderer: TemplateRenderer): self._app = None self._login_manager = None self._project_dir = project_dir self._model_store = model_store self._template_renderer = template_renderer self._debug = self._model_store.config().map().get('debug') self.setup() def run(self) -> None: serve( self._app, host=self._model_store.config().map().get('bind'), port=self._model_store.config().map().get('port') ) def reload(self) -> None: self.setup() def setup(self) -> None: self._setup_flask_app() self._setup_web_globals() self._setup_web_errors() self._setup_web_controllers() def get_app(self): return self._app def _get_template_folder(self) -> str: return "{}/{}".format(self._project_dir, WebDirConstant.FOLDER_TEMPLATES) def _get_static_folder(self) -> str: return "{}/{}".format(self._project_dir, WebDirConstant.FOLDER_STATIC) def _setup_flask_app(self) -> None: self._app = Flask( __name__, template_folder=self._get_template_folder(), static_folder=self._get_static_folder(), ) self._app.config['UPLOAD_FOLDER'] = "{}/{}".format(WebDirConstant.FOLDER_STATIC, WebDirConstant.FOLDER_STATIC_WEB_UPLOADS) self._app.config['MAX_CONTENT_LENGTH'] = self._model_store.variable().map().get('slide_upload_limit').as_int() * 1024 * 1024 self._setup_flask_login() if self._debug: self._app.config['TEMPLATES_AUTO_RELOAD'] = True def _setup_flask_login(self) -> bool: auth_module = self._model_store.variable().map().get('auth_enabled').as_bool() if not auth_module: return auth_module self._app.config['SECRET_KEY'] = self._model_store.config().map().get('secret_key') self._login_manager = LoginManager() self._login_manager.init_app(self._app) self._login_manager.login_view = 'login' if self._model_store.user().count_all() == 0: self._model_store.user().add_form(User(username="admin", password="admin", enabled=True)) @self._login_manager.user_loader def load_user(user_id): return self._model_store.user().get(user_id) return auth_module def _setup_web_controllers(self) -> None: def auth_required(f): if not self._login_manager: return f def decorated_function(*args, **kwargs): if not current_user.is_authenticated: return redirect(url_for('login')) return f(*args, **kwargs) return decorated_function PlayerController(self, self._app, auth_required, self._model_store, self._template_renderer) SlideshowController(self, self._app, auth_required, self._model_store, self._template_renderer) SettingsController(self, self._app, auth_required, self._model_store, self._template_renderer) SysinfoController(self, self._app, auth_required, self._model_store, self._template_renderer) FleetController(self, self._app, auth_required, self._model_store, self._template_renderer) AuthController(self, self._app, auth_required, self._model_store, self._template_renderer) def _setup_web_globals(self) -> None: @self._app.context_processor def inject_global_vars() -> dict: return self._template_renderer.get_view_globals() def _setup_web_errors(self) -> None: @self._app.errorhandler(404) def not_found(e): return send_from_directory(self._get_template_folder(), 'core/error404.html'), 404