Added route for getting API version and installed plugins + some cleanup
This commit is contained in:
parent
7f6ff3f001
commit
ad3e2a34b8
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
||||||
|
|
52
setup.py
52
setup.py
|
@ -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",
|
||||||
|
],
|
||||||
|
extras_require={"ldap": ["flask_ldapconn", "ldap3"]},
|
||||||
entry_points={
|
entry_points={
|
||||||
'flaschengeist.plugin': [
|
"flaschengeist.plugin": [
|
||||||
'auth = flaschengeist.modules.auth:register',
|
"auth = flaschengeist.modules.auth:register",
|
||||||
'users = flaschengeist.modules.users:register',
|
"users = flaschengeist.modules.users:register",
|
||||||
'schedule = flaschengeist.modules.schedule:register'
|
"schedule = flaschengeist.modules.schedule:register",
|
||||||
],
|
],
|
||||||
'flaschengeist.auth': [
|
"flaschengeist.auth": [
|
||||||
'auth_plain = flaschengeist.modules.auth_plain:AuthPlain',
|
"auth_plain = flaschengeist.modules.auth_plain:AuthPlain",
|
||||||
'auth_ldap = flaschengeist.modules.auth_ldap:AuthLDAP [ldap]'
|
"auth_ldap = flaschengeist.modules.auth_ldap:AuthLDAP [ldap]",
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue