Skip to content
Snippets Groups Projects
factory.py 5.05 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 whitenoise import WhiteNoise
Benjamin Bertrand's avatar
Benjamin Bertrand committed
from . import settings, models
from .extensions import (db, migrate, login_manager, ldap_manager, bootstrap,
                         admin, mail, jwt, toolbar, redis_store, fsession, cache)
Benjamin Bertrand's avatar
Benjamin Bertrand committed
from .admin.views import (AdminModelView, ItemAdmin, UserAdmin, TokenAdmin,
                          NetworkAdmin)
from .main.views import bp as main
Benjamin Bertrand's avatar
Benjamin Bertrand committed
from .inventory.views import bp as inventory
from .network.views import bp as network
from .user.views import bp as user
from .api.user import bp as user_api
Benjamin Bertrand's avatar
Benjamin Bertrand committed
from .api.inventory import bp as inventory_api
from .api.network import bp as network_api
from .commands import register_cli
def create_app(config=None):
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    app = Flask(__name__)

    app.config.from_object(settings)
    app.config.from_envvar('LOCAL_SETTINGS', silent=True)
    app.config.update(config or {})
Benjamin Bertrand's avatar
Benjamin Bertrand committed

    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'])
Benjamin Bertrand's avatar
Benjamin Bertrand committed
        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!')
    # Remove variables that contain a password
    settings_to_display = [f'{key}: {value}' for key, value in app.config.items()
                           if key not in ('SECRET_KEY', 'LDAP_BIND_USER_PASSWORD',
                                          'MAIL_CREDENTIALS', 'SQLALCHEMY_DATABASE_URI')]
    # The repr() of make_url hides the password
    settings_to_display.append(f'SQLALCHEMY_DATABASE_URI: {sa.engine.url.make_url(app.config["SQLALCHEMY_DATABASE_URI"])!r}')
    settings_string = '\n'.join(settings_to_display)
    app.logger.info(f'Settings:\n{settings_string}')
Benjamin Bertrand's avatar
Benjamin Bertrand committed

    bootstrap.init_app(app)
    db.init_app(app)
    migrate.init_app(app)
    login_manager.init_app(app)
    login_manager.login_view = 'user.login'
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    ldap_manager.init_app(app)
    mail.init_app(app)
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    jwt.init_app(app)
    toolbar.init_app(app)
    redis_store.init_app(app)
    app.config['SESSION_REDIS'] = redis_store
    fsession.init_app(app)
    cache.init_app(app)
Benjamin Bertrand's avatar
Benjamin Bertrand committed

    admin.init_app(app)
    admin.add_view(UserAdmin(models.User, db.session, endpoint='users'))
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    admin.add_view(TokenAdmin(models.Token, db.session))
    admin.add_view(AdminModelView(models.Action, db.session))
    admin.add_view(AdminModelView(models.Manufacturer, db.session))
    admin.add_view(AdminModelView(models.Model, db.session))
    admin.add_view(AdminModelView(models.Location, db.session))
    admin.add_view(AdminModelView(models.Status, db.session))
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    admin.add_view(ItemAdmin(models.Item, db.session))
    admin.add_view(AdminModelView(models.ItemComment, db.session))
    admin.add_view(AdminModelView(models.NetworkScope, db.session))
    admin.add_view(NetworkAdmin(models.Network, db.session, endpoint='networks'))
    admin.add_view(AdminModelView(models.Host, db.session))
    admin.add_view(AdminModelView(models.Interface, db.session))
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    admin.add_view(AdminModelView(models.Mac, db.session))
    admin.add_view(AdminModelView(models.Cname, db.session))
    admin.add_view(AdminModelView(models.Tag, db.session))
Benjamin Bertrand's avatar
Benjamin Bertrand committed

    app.register_blueprint(main)
    app.register_blueprint(inventory, url_prefix='/inventory')
    app.register_blueprint(network, url_prefix='/network')
    app.register_blueprint(user, url_prefix='/user')
    app.register_blueprint(user_api, url_prefix='/api/v1/user')
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    app.register_blueprint(inventory_api, url_prefix='/api/v1/inventory')
    app.register_blueprint(network_api, url_prefix='/api/v1/network')
Benjamin Bertrand's avatar
Benjamin Bertrand committed

    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/',
Benjamin Bertrand's avatar
Benjamin Bertrand committed
    register_cli(app)

    return app