Skip to content
Snippets Groups Projects
factory.py 3.33 KiB
Newer Older
Benjamin Bertrand's avatar
Benjamin Bertrand committed
# -*- coding: utf-8 -*-
"""
app.factory
~~~~~~~~~~~

Create the WSGI application.

:copyright: (c) 2017 European Spallation Source ERIC
:license: BSD 2-Clause, see LICENSE for more details.

"""
import sqlalchemy as sa
from flask import Flask
from flask_admin.contrib.sqla import ModelView
from . import settings
from .extensions import db, migrate, login_manager, ldap_manager, bootstrap, admin, mail
from .models import User, Role, Action, Vendor, Model, Location, Status, Item
from .main.views import bp as main
from .users.views import bp as users
from .defaults import defaults


def register_cli(app):
    @app.cli.command()
    def initdb():
        """Create the database tables and initialize them with default values"""
        db.create_all()
        for instance in defaults:
            db.session.add(instance)
            try:
                db.session.commit()
            except sa.exc.IntegrityError as e:
                db.session.rollback()
                app.logger.debug(f'{instance} already exists')


def create_app():
    app = Flask(__name__)

    app.config.from_object(settings)
    app.config.from_envvar('LOCAL_SETTINGS', silent=True)

    if not app.debug:
        import logging
        # Send ERROR via mail
        from logging.handlers import SMTPHandler
        mail_handler = SMTPHandler(app.config['MAIL_SERVER'],
                                   app.config['EMAIL_SENDER'],
                                   app.config['ADMIN_EMAILS'],
                                   'Inventory: ERROR raised')
        mail_handler.setFormatter(logging.Formatter("""
            Message type:       %(levelname)s
            Location:           %(pathname)s:%(lineno)d
            Module:             %(module)s
            Function:           %(funcName)s
            Time:               %(asctime)s

            Message:

            %(message)s
        """))
        mail_handler.setLevel(logging.ERROR)
        app.logger.addHandler(mail_handler)
        # Log to stderr
        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s '
            '[in %(pathname)s:%(lineno)d]'
        ))
        # Set app logger level to DEBUG
        # otherwise only WARNING and above are propagated
        app.logger.setLevel(logging.DEBUG)
        handler.setLevel(logging.DEBUG)
        app.logger.addHandler(handler)
    app.logger.info('Inventory created!')
    app.logger.info('Settings:\n{}'.format(
        '\n'.join(['{}: {}'.format(key, value) for key, value in app.config.items()
                   if key not in ('SECRET_KEY', 'LDAP_BIND_USER_PASSWORD')])))

    bootstrap.init_app(app)
    db.init_app(app)
    migrate.init_app(app)
    login_manager.init_app(app)
    login_manager.login_view = 'users.login'
    ldap_manager.init_app(app)
    mail.init_app(app)

    admin.init_app(app)
    admin.add_view(ModelView(Role, db.session))
    admin.add_view(ModelView(User, db.session))
    admin.add_view(ModelView(Action, db.session))
    admin.add_view(ModelView(Vendor, db.session))
    admin.add_view(ModelView(Model, db.session))
    admin.add_view(ModelView(Location, db.session))
    admin.add_view(ModelView(Status, db.session))
    admin.add_view(ModelView(Item, db.session))

    app.register_blueprint(main)
    app.register_blueprint(users)

    register_cli(app)

    return app