Added route for getting API version and installed plugins + some cleanup

This commit is contained in:
Ferdinand Thiessen 2020-09-07 16:07:35 +02:00
parent 7f6ff3f001
commit ad3e2a34b8
4 changed files with 114 additions and 91 deletions

View File

@ -7,78 +7,15 @@
import yaml import yaml
import logging import logging
import pkg_resources import pkg_resources
from flask import Flask
from pathlib import Path from pathlib import Path
from flask.json import JSONEncoder, jsonify
from flask_cors import CORS
from logging.config import dictConfig from logging.config import dictConfig
from werkzeug.exceptions import HTTPException
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
_module_path = Path(__file__).parent _module_path = Path(__file__).parent
logger = LocalProxy(lambda: logging.getLogger(__name__)) logger = LocalProxy(lambda: logging.getLogger(__name__))
__version__ = pkg_resources.get_distribution('flaschengeist').version
with (_module_path / 'logging.yml').open(mode='rb') as file: with (_module_path / 'logging.yml').open(mode='rb') as file:
config = yaml.safe_load(file.read()) config = yaml.safe_load(file.read())
logging.config.dictConfig(config) 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 >{}<".format(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

84
flaschengeist/app.py Normal file
View File

@ -0,0 +1,84 @@
from datetime import datetime
import pkg_resources
from flask import Flask
from flask.json import JSONEncoder, jsonify
from flask_cors import CORS
from werkzeug.exceptions import HTTPException
from . import logger
from .system.config import config, configure_app
class CustomJSONEncoder(JSONEncoder):
def default(self, o):
# Check if custom model
try:
return o.serialize()
except AttributeError:
pass
if isinstance(o, datetime):
return o.isoformat()
# Check if iterable
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
return JSONEncoder.default(self, o)
def __load_auth(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')
def __load_plugins(app):
logger.info('Search for plugins')
app.config['FG_PLUGINS'] = {}
for entry_point in pkg_resources.iter_entry_points('flaschengeist.plugin'):
logger.debug("Found plugin: >{}<".format(entry_point.name))
if config.get(entry_point.name, 'enabled', fallback=False):
logger.info("Loaded plugin >{}<".format(entry_point.name))
app.config["FG_PLUGINS"][entry_point.name] = True
app.register_blueprint(entry_point.load()())
else:
app.config["FG_PLUGINS"][entry_point.name] = False
def create_app():
app = Flask(__name__)
app.json_encoder = CustomJSONEncoder
CORS(app)
with app.app_context():
from .system.database import db
configure_app(app)
db.init_app(app)
__load_auth(app)
__load_plugins(app)
@app.route("/", methods=["GET"])
def __get_state():
from . import __version__ as version
return jsonify({"plugins": app.config["FG_PLUGINS"], "version": version})
@app.errorhandler(Exception)
def handle_exception(e):
if isinstance(e, HTTPException):
logger.debug(e.description, exc_info=True)
return jsonify({"error": e.description}), e.code
logger.error(str(e), exc_info=True)
return jsonify({"error": "Internal server error occurred"}), 500
return app

View File

@ -1,5 +1,5 @@
#!/usr/bin/python3 #!/usr/bin/python3
from flaschengeist import create_app from flaschengeist.app import create_app
import bjoern import bjoern
import argparse import argparse

View File

@ -1,32 +1,34 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
setup( setup(
name='flaschengeist', name="flaschengeist",
version='0.0.1', version="2.0.0-dev",
url='https://wu5.de/redmine/projects/geruecht', url="https://wu5.de/redmine/projects/geruecht",
author='WU5 + Friends', author="WU5 + Friends",
author_email='tim@groeger-clan.de', author_email="tim@groeger-clan.de",
description='Does things', description="Does things",
packages=find_packages(), packages=find_packages(),
package_data={'': ['*.yml']}, package_data={"": ["*.yml"]},
scripts=['run_flaschengeist'], scripts=["run_flaschengeist"],
install_requires=['Flask >= 1.1', 'PyYAML>=5.3.1', 'sqlalchemy>=1.3', "flask_sqlalchemy", install_requires=[
"flask_cors", "werkzeug", "bjoern"], "Flask >= 1.1",
extras_require={ "PyYAML>=5.3.1",
'ldap': [ "sqlalchemy>=1.3",
'flask_ldapconn', "flask_sqlalchemy",
'ldap3' "flask_cors",
] "werkzeug",
}, "bjoern",
entry_points={
'flaschengeist.plugin': [
'auth = flaschengeist.modules.auth:register',
'users = flaschengeist.modules.users:register',
'schedule = flaschengeist.modules.schedule:register'
], ],
'flaschengeist.auth': [ extras_require={"ldap": ["flask_ldapconn", "ldap3"]},
'auth_plain = flaschengeist.modules.auth_plain:AuthPlain', entry_points={
'auth_ldap = flaschengeist.modules.auth_ldap:AuthLDAP [ldap]' "flaschengeist.plugin": [
] "auth = flaschengeist.modules.auth:register",
} "users = flaschengeist.modules.users:register",
"schedule = flaschengeist.modules.schedule:register",
],
"flaschengeist.auth": [
"auth_plain = flaschengeist.modules.auth_plain:AuthPlain",
"auth_ldap = flaschengeist.modules.auth_ldap:AuthLDAP [ldap]",
],
},
) )