Source code for server

import server.serverlogging as serverlogging
import logging

from flask import Flask
from flask_socketio import SocketIO
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager

from server.resources import TempdirManager, SocketioConnections
from server.proxy_helpers import behind_proxy_options
import time

slacklog = logging.getLogger("slack")
# Info: slacklog sends messages to a specified Slack channel. Usage:
#
#   slacklog.info("Hello Slack")
#   slacklog.info("Sending log file", extra=dict(file=serverlogging.LOG_DIR / "server.log"))
#

socketio = SocketIO(async_mode="eventlet")
db = SQLAlchemy()
jwt = JWTManager()


tempdirs_devices = TempdirManager()

connections_users = SocketioConnections(multiple_connections=True)
connections_devices = SocketioConnections(multiple_connections=False)

start_time = time.time()


[docs] def create_app(config_override={}): warnings = serverlogging.configure() app = Flask( "server", static_folder="../plasmafront/build/static", template_folder="../plasmafront/build", ) # Configuration: Load from different sources in a specific order app.config.from_pyfile("config.py") app.config.from_prefixed_env(prefix="FLASK") app.config.update(config_override) # Configuration: Override with contents of a file specified by a *_FILE var for var_from_file in ["SECRET_KEY_FILE"]: if var_from_file in app.config: with open(app.config[var_from_file]) as file: app.config[var_from_file[:-len("_FILE")]] = file.read() # Start message and verify that the configuration is ok if app.env == "production": app.logger.info(16 * "=" + " New instance started " + 16 * "=") for w in warnings: app.logger.warning(w) slacklog.info("*Server has started* %s", time.strftime("%d.%m.%Y %H:%M:%S")) check_secrets(app) if app.config.get("BEHIND_PROXY") not in behind_proxy_options: raise KeyError("Unknown proxy service set in the BEHIND_PROXY config") # Register all blueprints from .views_main import blueprints as main_blueprints for bp in main_blueprints: app.register_blueprint(bp) from .views_api import blueprints as api_blueprints for bp in api_blueprints: app.register_blueprint(bp) from .events import blueprints as events_blueprints for bp in events_blueprints: app.register_blueprint(bp) # Init everything (app, database, ...) app.logger.info("Database: %s", app.config["SQLALCHEMY_DATABASE_URI"]) socketio.init_app(app) db.init_app(app) jwt.init_app(app) with app.app_context(): from .models import User from .blacklist_helpers import prune_database db.create_all() # If database is empty, create user "admin" and more if not User.query.all(): populate_database() prune_database() return app
[docs] def check_secrets(app): if app.config["SECRET_KEY"] is None: app.logger.fatal("Missing SECRET_KEY env variable.") raise RuntimeError("Missing SECRET_KEY env variable.") for key in ["SECRET_KEY", "JWT_SECRET_KEY"]: if app.config.get(key) == "secret!": app.logger.fatal("Cannot use default value of %s in production." " Please set a %s env variable.", key, key) raise RuntimeError(f"Using default {key} when in production mode!")
[docs] def populate_database(): """Initial commits to a new empty database.""" import time from .models import Device from .functions import submit_user, submit_device, submit_experiment, submit_session admin = submit_user("admin", "admin", "admin", "") submit_user("student", "student", "user", "") submit_device("test", "test", "127.0.0.1") devices = Device.query.all() exper = submit_experiment("All", devices) now_ms = int(time.time()) * 1e3 submit_session("All", now_ms, now_ms + 3600*24*30*1e3, exper, [admin]) # 1 month
[docs] def run_server(config={}, server_kwargs={}): app = create_app(config) host = {"production": "0.0.0.0", "development": "127.0.0.1"}[app.env] socketio.run( app, host=app.config["LISTEN_HOST"] or host, port=app.config["LISTEN_PORT"] or 5000, **server_kwargs )