Skip to content
Snippets Groups Projects
  • Benjamin Bertrand's avatar
    107bba8d
    Cleaning · 107bba8d
    Benjamin Bertrand authored
    Don't override the Admin view __init__ method for consistency.
    Avoid having to import models in admin/views.py
    107bba8d
    History
    Cleaning
    Benjamin Bertrand authored
    Don't override the Admin view __init__ method for consistency.
    Avoid having to import models in admin/views.py
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
factory.py 4.14 KiB
# -*- 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 whitenoise import WhiteNoise
from . import settings, models
from .extensions import db, migrate, login_manager, ldap_manager, bootstrap, admin, mail, jwt, toolbar
from .admin.views import AdminModelView, ItemAdmin, UserAdmin, GroupAdmin, QRCodeAdmin
from .main.views import bp as main
from .users.views import bp as users
from .api.main import bp as api
from .defaults import defaults


def register_cli(app):
    @app.cli.command()
    def initdb():
        """Create the database tables and initialize them with default values"""
        db.engine.execute('CREATE EXTENSION IF NOT EXISTS citext')
        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(config=None):
    app = Flask(__name__)

    app.config.from_object(settings)
    app.config.from_envvar('LOCAL_SETTINGS', silent=True)
    app.config.update(config or {})

    if not app.debug:
        import logging
        # Send ERROR via mail
        from logging.handlers import SMTPHandler
        mail_handler = SMTPHandler(app.config['MAIL_SERVER'],
                                   fromaddr=app.config['EMAIL_SENDER'],
                                   toaddrs=app.config['ADMIN_EMAILS'],
                                   subject='CSEntry: ERROR raised',
                                   credentials=app.config['MAIL_CREDENTIALS'])
        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('CSEntry 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)
    jwt.init_app(app)
    toolbar.init_app(app)

    admin.init_app(app)
    admin.add_view(GroupAdmin(models.Group, db.session))
    admin.add_view(UserAdmin(models.User, db.session))
    admin.add_view(QRCodeAdmin(models.Action, db.session))
    admin.add_view(QRCodeAdmin(models.Manufacturer, db.session))
    admin.add_view(QRCodeAdmin(models.Model, db.session))
    admin.add_view(QRCodeAdmin(models.Location, db.session))
    admin.add_view(QRCodeAdmin(models.Status, db.session))
    admin.add_view(ItemAdmin(models.Item, db.session))
    admin.add_view(AdminModelView(models.Network, db.session))
    admin.add_view(AdminModelView(models.Host, db.session))
    admin.add_view(AdminModelView(models.Mac, db.session))

    app.register_blueprint(main)
    app.register_blueprint(users)
    app.register_blueprint(api, url_prefix='/api')

    app.wsgi_app = WhiteNoise(app.wsgi_app, root='static/')
    app.wsgi_app.add_files(
        root='/opt/conda/envs/csentry/lib/python3.6/site-packages/flask_bootstrap/static/',
        prefix='bootstrap/'
    )

    register_cli(app)

    return app