105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
from flask import Flask, Blueprint
|
|
|
|
from . import commands, login, target_exchange, target, registration, webhook
|
|
from .exceptions import ApiException
|
|
from .extensions import db, migrate, jwt, apispec, rabbit
|
|
from .settings import ProdConfig, Config
|
|
|
|
|
|
def create_app(config: Config = ProdConfig) -> Flask:
|
|
"""An application factory, as explained here:
|
|
http://flask.pocoo.org/docs/patterns/appfactories/.
|
|
|
|
:param config: The configuration object to use.
|
|
"""
|
|
app = Flask(__name__.split('.')[0])
|
|
app.url_map.strict_slashes = False
|
|
app.config.from_object(config)
|
|
register_extensions(app)
|
|
register_blueprints(app)
|
|
register_apispecs(app)
|
|
register_errorhandlers(app)
|
|
register_shellcontext(app)
|
|
register_commands(app)
|
|
|
|
return app
|
|
|
|
|
|
def register_extensions(app: Flask):
|
|
"""Register Flask extensions."""
|
|
db.init_app(app)
|
|
migrate.init_app(app, db)
|
|
jwt.init_app(app)
|
|
apispec.init_app(app)
|
|
rabbit.init_app(app)
|
|
|
|
|
|
def register_blueprints(app: Flask):
|
|
"""Register Flask blueprints."""
|
|
api_blueprint = Blueprint('api', __name__, url_prefix='/api')
|
|
|
|
api_blueprint.register_blueprint(login.views.blueprint, url_prefix='/login')
|
|
api_blueprint.register_blueprint(target_exchange.views.blueprint, url_prefix='/target-exchange')
|
|
api_blueprint.register_blueprint(target.views.blueprint, url_prefix='/target')
|
|
api_blueprint.register_blueprint(registration.views.blueprint, url_prefix='/registration')
|
|
|
|
app.register_blueprint(api_blueprint)
|
|
app.register_blueprint(webhook.views.blueprint)
|
|
|
|
|
|
def register_apispecs(app: Flask):
|
|
"""Register routes for apispec
|
|
|
|
Extended from FlaskApiSpec::register_existing_resources
|
|
that one doesn't handle the static routes or blueprints in blueprints well
|
|
"""
|
|
|
|
apispec.spec.components.security_scheme('api_key', {"type": "apiKey", "in": "query", "name": "apikey"})
|
|
apispec.spec.components.security_scheme('jwt', {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"})
|
|
|
|
for name, rule in app.view_functions.items():
|
|
if name == 'static':
|
|
continue
|
|
|
|
try:
|
|
blueprint_name, _ = name.rsplit('.', 1)
|
|
except ValueError:
|
|
blueprint_name = None
|
|
|
|
try:
|
|
apispec.register(rule, blueprint=blueprint_name)
|
|
except TypeError:
|
|
pass
|
|
|
|
|
|
def register_errorhandlers(app: Flask):
|
|
def errorHandler(error: ApiException):
|
|
return error.to_response()
|
|
|
|
app.errorhandler(ApiException)(errorHandler)
|
|
pass
|
|
|
|
|
|
def register_shellcontext(app: Flask):
|
|
"""Register shell context objects."""
|
|
|
|
def shell_context():
|
|
"""Shell context objects."""
|
|
return {
|
|
'db': db,
|
|
'rabbit': rabbit,
|
|
'TargetExchange': target_exchange.models.TargetExchange,
|
|
'Target': target.models.Target,
|
|
'Registration': registration.models.Registration,
|
|
}
|
|
|
|
app.shell_context_processor(shell_context)
|
|
|
|
|
|
def register_commands(app: Flask):
|
|
"""Register Click commands."""
|
|
app.cli.add_command(commands.clean)
|
|
app.cli.add_command(commands.urls)
|
|
app.cli.add_command(commands.seed)
|
|
app.cli.add_command(commands.setup_rabmq)
|