flaschengeist/flaschengeist/__init__.py

84 lines
2.7 KiB
Python

""" Server-package
Initialize app, CORS, database and add it to the application.
Initialize also a singleton for the AccessTokenController and start the Thread.
"""
import yaml
import logging
import pkg_resources
from flask import Flask
from pathlib import Path
from flask.json import JSONEncoder, jsonify
from flask_cors import CORS
from logging.config import dictConfig
from werkzeug.exceptions import HTTPException
from werkzeug.local import LocalProxy
_module_path = Path(__file__).parent
logger = LocalProxy(lambda: logging.getLogger(__name__))
with (_module_path / 'logging.yml').open(mode='rb') as file:
config = yaml.safe_load(file.read())
logging.config.dictConfig(config)
class CustomJSONEncoder(JSONEncoder):
def default(self, o):
# Check if custom model
try:
return o.serialize()
except AttributeError:
pass
# Check if iterable
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
return JSONEncoder.default(self, o)
def create_app():
app = Flask(__name__)
app.json_encoder = CustomJSONEncoder
CORS(app)
with app.app_context():
from .system.database import db
from .system.config import configure_app, config
configure_app(app)
db.init_app(app)
for entry_point in pkg_resources.iter_entry_points('flaschengeist.auth'):
logger.debug('Found authentication plugin: %s', entry_point.name)
if entry_point.name == config['FLASCHENGEIST']['AUTH']:
app.config['FG_AUTH_BACKEND'] = entry_point.load()()
app.config['FG_AUTH_BACKEND'].configure(
config[entry_point.name] if config.has_section(entry_point.name) else {})
logger.info('Loaded authentication plugin > %s <', entry_point.name)
break
if not app.config['FG_AUTH_BACKEND']:
logger.error('No authentication plugin configured or authentication plugin not found')
logger.info('Search for plugins')
for entry_point in pkg_resources.iter_entry_points('flaschengeist.plugin'):
logger.debug("Found plugin: %s", entry_point.name)
if config.get(entry_point.name, 'enabled', fallback=False):
logger.info('Loaded plugin > %s <', entry_point.name)
app.register_blueprint(entry_point.load()())
@app.errorhandler(Exception)
def handle_exception(e):
if isinstance(e, HTTPException):
logger.debug(e.description, exc_info=True)
return jsonify({"error": e.name}), e.code
logger.error(str(e), exc_info=True)
return jsonify({"error": "Internal server error occurred"}), 500
return app