Esempio n. 1
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration files
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'default_config.py'
    ))
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'consul_config.py'
    ), silent=True)
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'custom_config.py'
    ), silent=True)
    if config_path:
        app.config.from_pyfile(config_path)
    if debug is not None:
        app.debug = debug

    # Error handling
    from critiquebrainz.ws.errors import init_error_handlers
    init_error_handlers(app)

    app.init_loggers(
        file_config=app.config.get("LOG_FILE"),
        email_config=app.config.get("LOG_EMAIL"),
        sentry_config=app.config.get("LOG_SENTRY"),
    )

    # Database
    from critiquebrainz.db import init_db_engine
    init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))

    # Redis (cache)
    from brainzutils import cache
    if "REDIS_HOST" in app.config and \
       "REDIS_PORT" in app.config and \
       "REDIS_NAMESPACE" in app.config:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    else:
        logging.warning("Redis is not defined in config file. Skipping initialization.")

    # OAuth
    from critiquebrainz.ws.oauth import oauth
    oauth.init_app(app)

    app.config["JSONIFY_PRETTYPRINT_REGULAR"] = False

    _register_blueprints(app)

    return app
 def setUp(self):
     cache.init(
         host=self.host,
         port=self.port,
         namespace=self.namespace,
     )
     # Making sure there are no items in cache before we run each test
     cache.flush_all()
 def test_key_expire(self, mock_redis):
     cache.init(host='host', port=2, namespace=self.namespace)
     cache.set('key', u'value'.encode('utf-8'), time=30)
     expected_key = 'NS_TEST:a62f2225bf70bfaccbc7f1ef2a397836717377de'.encode('utf-8')
     # msgpack encoded value
     expected_value = b'\xc4\x05value'
     mock_redis.return_value.mset.assert_called_with({expected_key: expected_value})
     mock_redis.return_value.pexpire.assert_called_with(expected_key, 30000)
Esempio n. 4
0
 def setUp(self):
     cache.init(
         host=self.host,
         port=self.port,
         namespace=self.namespace,
     )
     # Making sure there are no items in cache before we run each test
     cache.flush_all()
Esempio n. 5
0
 def test_key_expire(self, mock_redis):
     cache.init(host='host', port=2, namespace=self.namespace)
     cache.set('key', u'value'.encode('utf-8'), time=30)
     expected_key = 'NS_TEST:a62f2225bf70bfaccbc7f1ef2a397836717377de'.encode(
         'utf-8')
     # msgpack encoded value
     expected_value = b'\xc4\x05value'
     mock_redis.return_value.mset.assert_called_with(
         {expected_key: expected_value})
     mock_redis.return_value.pexpire.assert_called_with(expected_key, 30000)
    def test_set_key_unicode(self, mock_redis):
        """Test setting a unicode value"""
        cache.init(host='host', port=2, namespace=self.namespace)
        cache.set('key', u'value')

        expected_key = 'NS_TEST:a62f2225bf70bfaccbc7f1ef2a397836717377de'.encode('utf-8')
        # msgpack encoded value
        expected_value = b'\xa5value'
        mock_redis.return_value.mset.assert_called_with({expected_key: expected_value})
        mock_redis.return_value.pexpire.assert_not_called()
def create_app():
    app = Flask(__name__)

    # Configuration
    sys.path.append(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
    import config
    app.config.from_object(config)

    # Redis (cache)
    from brainzutils import cache
    try:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    except KeyError as e:
        logging.error(
            "Redis is not defined in config file. Error: {}".format(e))
        raise

    # Logging
    from webserver.loggers import init_loggers
    init_loggers(app)

    # Extensions
    from flask_uuid import FlaskUUID
    FlaskUUID(app)

    # Error handling
    from webserver.errors import init_error_handlers
    init_error_handlers(app)

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime

    # Blueprints
    from webserver.views.index import index_bp
    from webserver.views.api import api_bp
    app.register_blueprint(index_bp)
    app.register_blueprint(api_bp)

    @app.before_request
    def before_request():
        db.init_db_engine(app.config['SQLALCHEMY_DATABASE_URI'])

    @app.teardown_request
    def teardown_request(exception):
        pass

    return app
Esempio n. 8
0
    def test_set_key_unicode(self, mock_redis):
        """Test setting a unicode value"""
        cache.init(host='host', port=2, namespace=self.namespace)
        cache.set('key', u'value')

        expected_key = 'NS_TEST:a62f2225bf70bfaccbc7f1ef2a397836717377de'.encode(
            'utf-8')
        # msgpack encoded value
        expected_value = b'\xa5value'
        mock_redis.return_value.mset.assert_called_with(
            {expected_key: expected_value})
        mock_redis.return_value.pexpire.assert_not_called()
def incremental_update_release_color_table():
    """ Incrementally update the cover art mapping. This is designed to run hourly
        and save a last_updated timestamp in the cache. If the cache value cannot be
        found, a complete sync is run instead and the cache value is set. """

    cache.init(host=config.REDIS_HOST, port=config.REDIS_PORT,
               namespace=config.REDIS_NAMESPACE)

    try:
        last_updated = cache.get(LAST_UPDATED_CACHE_KEY, decode=True) or None
    except Exception:
        last_updated = None

    if not last_updated:
        log("No timestamp found, performing full sync")
        sync_release_color_table()
        last_updated = get_last_updated_from_caa()
        cache.set(LAST_UPDATED_CACHE_KEY, last_updated,
                  expirein=0, encode=True)
        return

    log("cover art incremental update starting...")
    mb_query = """SELECT caa.id AS caa_id
                       , release AS release_id
                       , release.gid AS release_mbid
                       , mime_type
                       , date_uploaded
                    FROM cover_art_archive.cover_art caa
                    JOIN cover_art_archive.cover_art_type cat
                      ON cat.id = caa.id
                    JOIN musicbrainz.release
                      ON caa.release = release.id
                   WHERE type_id = 1
                     AND caa.date_uploaded > %s
                ORDER BY caa.date_uploaded
                   LIMIT %s"""

    compare_coverart(mb_query, None, last_updated, None,
                     "date_uploaded", "last_updated")

    last_updated = get_last_updated_from_caa()
    cache.set(LAST_UPDATED_CACHE_KEY, last_updated, expirein=0, encode=True)
Esempio n. 10
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration files
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..',
                     'default_config.py'))

    config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                               '..', '..', 'consul_config.py')
    if deploy_env:
        print("Checking if consul template generated config file exists: {}".
              format(config_file))
        for _ in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(config_file):
                sleep(1)

        if not os.path.exists(config_file):
            print(
                "No configuration file generated yet. Retried {} times, exiting."
                .format(CONSUL_CONFIG_FILE_RETRY_COUNT))
            sys.exit(-1)

        print("Loading consul config file {}".format(config_file))
    app.config.from_pyfile(config_file, silent=True)

    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', '..',
        'custom_config.py'),
                           silent=True)
    if config_path:
        app.config.from_pyfile(config_path)
    if debug is not None:
        app.debug = debug
    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Error handling
    from critiquebrainz.frontend.error_handlers import init_error_handlers
    init_error_handlers(app)

    # Static files
    from critiquebrainz.frontend import static_manager
    static_manager.read_manifest()

    app.init_loggers(
        file_config=app.config.get("LOG_FILE"),
        email_config=app.config.get("LOG_EMAIL"),
        sentry_config=app.config.get("LOG_SENTRY"),
    )

    # CritiqueBrainz Database
    from critiquebrainz import db as critiquebrainz_db
    critiquebrainz_db.init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))

    add_robots(app)

    # MusicBrainz Database
    from brainzutils import musicbrainz_db
    musicbrainz_db.init_db_engine(app.config.get("MB_DATABASE_URI"))

    # Redis (cache)
    from brainzutils import cache
    if "REDIS_HOST" in app.config and \
            "REDIS_PORT" in app.config and \
            "REDIS_NAMESPACE" in app.config:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    else:
        logging.warning(
            "Redis is not defined in config file. Skipping initialization.")

    from critiquebrainz.frontend import babel
    babel.init_app(app)

    from critiquebrainz.frontend import login
    login.login_manager.init_app(app)
    from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication
    login.mb_auth = MusicBrainzAuthentication(
        name='musicbrainz',
        client_id=app.config['MUSICBRAINZ_CLIENT_ID'],
        client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'],
        authorize_url="https://musicbrainz.org/oauth2/authorize",
        access_token_url="https://musicbrainz.org/oauth2/token",
        base_url="https://musicbrainz.org/",
    )

    # APIs
    from critiquebrainz.frontend.external import mbspotify
    mbspotify.init(app.config['MBSPOTIFY_BASE_URI'],
                   app.config['MBSPOTIFY_ACCESS_KEY'])
    from critiquebrainz.frontend.external import musicbrainz
    musicbrainz.init(
        app_name=app.config['MUSICBRAINZ_USERAGENT']
        or "CritiqueBrainz Custom",
        app_version="1.0",
        hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org",
    )

    # Template utilities
    # TODO (code-master5): disabled no-member warnings just as a workaround to deal with failing tests till the
    # issue [https://github.com/PyCQA/pylint/issues/2563] with pylint is resolved
    app.jinja_env.add_extension('jinja2.ext.do')
    from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, track_length_ms, parameterize
    from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id
    from critiquebrainz.frontend.forms.utils import get_language_name
    app.jinja_env.filters['date'] = reformat_date
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['track_length'] = track_length
    app.jinja_env.filters['track_length_ms'] = track_length_ms
    app.jinja_env.filters['parameterize'] = parameterize
    app.jinja_env.filters['entity_details'] = get_entity_by_id
    app.jinja_env.filters['language_name'] = get_language_name
    app.context_processor(
        lambda: dict(get_static_path=static_manager.get_static_path))

    # Blueprints
    from critiquebrainz.frontend.views.index import frontend_bp
    from critiquebrainz.frontend.views.review import review_bp
    from critiquebrainz.frontend.views.search import search_bp
    from critiquebrainz.frontend.views.artist import artist_bp
    from critiquebrainz.frontend.views.label import label_bp
    from critiquebrainz.frontend.views.release_group import release_group_bp
    from critiquebrainz.frontend.views.release import release_bp
    from critiquebrainz.frontend.views.work import work_bp
    from critiquebrainz.frontend.views.event import event_bp
    from critiquebrainz.frontend.views.mapping import mapping_bp
    from critiquebrainz.frontend.views.user import user_bp
    from critiquebrainz.frontend.views.profile import profile_bp
    from critiquebrainz.frontend.views.place import place_bp
    from critiquebrainz.frontend.views.profile_apps import profile_apps_bp
    from critiquebrainz.frontend.views.login import login_bp
    from critiquebrainz.frontend.views.oauth import oauth_bp
    from critiquebrainz.frontend.views.reports import reports_bp
    from critiquebrainz.frontend.views.moderators import moderators_bp
    from critiquebrainz.frontend.views.log import log_bp
    from critiquebrainz.frontend.views.comment import comment_bp
    from critiquebrainz.frontend.views.rate import rate_bp
    from critiquebrainz.frontend.views.statistics import statistics_bp

    app.register_blueprint(frontend_bp)
    app.register_blueprint(review_bp, url_prefix='/review')
    app.register_blueprint(search_bp, url_prefix='/search')
    app.register_blueprint(artist_bp, url_prefix='/artist')
    app.register_blueprint(label_bp, url_prefix='/label')
    app.register_blueprint(release_group_bp, url_prefix='/release-group')
    app.register_blueprint(release_bp, url_prefix='/release')
    app.register_blueprint(work_bp, url_prefix='/work')
    app.register_blueprint(event_bp, url_prefix='/event')
    app.register_blueprint(place_bp, url_prefix='/place')
    app.register_blueprint(mapping_bp, url_prefix='/mapping')
    app.register_blueprint(user_bp, url_prefix='/user')
    app.register_blueprint(profile_bp, url_prefix='/profile')
    app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications')
    app.register_blueprint(login_bp, url_prefix='/login')
    app.register_blueprint(oauth_bp, url_prefix='/oauth')
    app.register_blueprint(reports_bp, url_prefix='/reports')
    app.register_blueprint(log_bp, url_prefix='/log')
    app.register_blueprint(moderators_bp, url_prefix='/moderators')
    app.register_blueprint(comment_bp, url_prefix='/comments')
    app.register_blueprint(rate_bp, url_prefix='/rate')
    app.register_blueprint(statistics_bp, url_prefix='/statistics')

    return app
Esempio n. 11
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    print("Starting metabrainz service with %s environment." % deploy_env)

    # Now load other bits of configuration
    print("loading %s" %
          os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                       'default_config.py'))
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                     'default_config.py'))
    print("loading %s" % os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', 'custom_config.py'))
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', 'custom_config.py'),
                           silent=True)

    if config_path:
        print("loading custom %s" % config_path)
        app.config.from_pyfile(config_path)

    # Load configuration files: If we're running under a docker deployment, wait until
    # the consul configuration is available.
    if deploy_env:
        consul_config = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), '..',
            'consul_config.py')

        print("loading consul %s" % consul_config)
        for i in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(consul_config):
                sleep(1)

        if not os.path.exists(consul_config):
            print(
                "No configuration file generated yet. Retried %d times, exiting."
                % CONSUL_CONFIG_FILE_RETRY_COUNT)
            sys.exit(-1)

        app.config.from_pyfile(consul_config, silent=True)

    if debug is not None:
        app.debug = debug

    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Printing out some debug values such as config and git commit
    try:
        with open(".git-version") as f:
            git_version = f.read()
        print('Running on git commit %s' % git_version.strip())
    except IOError:
        print(
            "Unable to retrieve git commit. Use docker/push.sh to push images for production."
        )

    print('Configuration values are as follows: ')
    print(pprint.pformat(app.config, indent=4))

    app.init_loggers(
        file_config=app.config.get('LOG_FILE'),
        email_config=app.config.get('LOG_EMAIL'),
        sentry_config=app.config.get('LOG_SENTRY'),
    )

    # Database
    from metabrainz import db
    db.init_db_engine(app.config["SQLALCHEMY_DATABASE_URI"])
    from metabrainz import model
    model.db.init_app(app)

    # Redis (cache)
    from brainzutils import cache
    cache.init(**app.config['REDIS'])

    # MusicBrainz OAuth
    from metabrainz.users import login_manager, musicbrainz_login
    login_manager.init_app(app)
    musicbrainz_login.init(app.config['MUSICBRAINZ_BASE_URL'],
                           app.config['MUSICBRAINZ_CLIENT_ID'],
                           app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Templates
    from metabrainz.utils import reformat_datetime
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['nl2br'] = lambda val: val.replace('\n', '<br />'
                                                             ) if val else ''

    # Error handling
    from metabrainz.errors import init_error_handlers
    init_error_handlers(app)

    add_robots(app)

    from metabrainz import babel
    babel.init_app(app)

    from flask_uploads import configure_uploads
    from metabrainz.admin.forms import LOGO_UPLOAD_SET
    configure_uploads(app, upload_sets=[
        LOGO_UPLOAD_SET,
    ])

    # Blueprints
    _register_blueprints(app)

    # ADMIN SECTION

    from flask_admin import Admin
    from metabrainz.admin.views import HomeView
    admin = Admin(app,
                  index_view=HomeView(name='Pending users'),
                  template_mode='bootstrap3')

    # Models
    from metabrainz.model.user import UserAdminView
    from metabrainz.model.payment import PaymentAdminView
    from metabrainz.model.tier import TierAdminView
    admin.add_view(
        UserAdminView(model.db.session,
                      category='Users',
                      endpoint="user_model"))
    admin.add_view(
        PaymentAdminView(model.db.session,
                         category='Payments',
                         endpoint="payment_model"))
    admin.add_view(TierAdminView(model.db.session, endpoint="tier_model"))

    # Custom stuff
    from metabrainz.admin.views import CommercialUsersView
    from metabrainz.admin.views import UsersView
    from metabrainz.admin.views import PaymentsView
    from metabrainz.admin.views import TokensView
    from metabrainz.admin.views import StatsView
    admin.add_view(
        CommercialUsersView(name='Commercial users', category='Users'))
    admin.add_view(UsersView(name='Search', category='Users'))
    admin.add_view(PaymentsView(name='All', category='Payments'))
    admin.add_view(TokensView(name='Access tokens', category='Users'))
    admin.add_view(StatsView(name='Statistics'))

    return app
def gen_app(debug=None):
    """ Generate a Flask app for LB with all configurations done and connections established.

    In the Flask app returned, blueprints are not registered.
    """
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    load_config(app)
    if debug is not None:
        app.debug = debug

    # initialize Flask-DebugToolbar if the debug option is True
    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Logging
    app.init_loggers(file_config=app.config.get('LOG_FILE'),
                     sentry_config=app.config.get('LOG_SENTRY'))

    # Initialize BU cache and metrics
    cache.init(host=app.config['REDIS_HOST'],
               port=app.config['REDIS_PORT'],
               namespace=app.config['REDIS_NAMESPACE'])
    metrics.init("listenbrainz")

    # Redis connection
    create_redis(app)

    # Timescale connection
    create_timescale(app)

    # RabbitMQ connection
    try:
        create_rabbitmq(app)
    except ConnectionError:
        app.logger.critical("RabbitMQ service is not up!", exc_info=True)

    # Database connections
    from listenbrainz import db
    from listenbrainz.db import timescale as ts
    from listenbrainz import messybrainz as msb
    db.init_db_connection(app.config['SQLALCHEMY_DATABASE_URI'])
    ts.init_db_connection(app.config['SQLALCHEMY_TIMESCALE_URI'])
    msb.init_db_connection(app.config['MESSYBRAINZ_SQLALCHEMY_DATABASE_URI'])

    if app.config['MB_DATABASE_URI']:
        from brainzutils import musicbrainz_db
        musicbrainz_db.init_db_engine(app.config['MB_DATABASE_URI'])

    # OAuth
    from listenbrainz.webserver.login import login_manager, provider
    login_manager.init_app(app)
    provider.init(app.config['MUSICBRAINZ_CLIENT_ID'],
                  app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Error handling
    from listenbrainz.webserver.errors import init_error_handlers
    init_error_handlers(app)

    from brainzutils.ratelimit import inject_x_rate_headers

    @app.after_request
    def after_request_callbacks(response):
        return inject_x_rate_headers(response)

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from listenbrainz.webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime

    return app
Esempio n. 13
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration files
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'default_config.py'
    ))

    config_file = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'consul_config.py'
    )
    if deploy_env:
        print("Checking if consul template generated config file exists: {}".format(config_file))
        for _ in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(config_file):
                sleep(1)

        if not os.path.exists(config_file):
            print("No configuration file generated yet. Retried {} times, exiting.".format(CONSUL_CONFIG_FILE_RETRY_COUNT))
            sys.exit(-1)

        print("Loading consul config file {}".format(config_file))
    app.config.from_pyfile(config_file, silent=True)

    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'custom_config.py'
    ), silent=True)
    if config_path:
        app.config.from_pyfile(config_path)
    if debug is not None:
        app.debug = debug

    # Error handling
    from critiquebrainz.ws.errors import init_error_handlers
    init_error_handlers(app)

    app.init_loggers(
        file_config=app.config.get("LOG_FILE"),
        email_config=app.config.get("LOG_EMAIL"),
        sentry_config=app.config.get("LOG_SENTRY"),
    )

    # Database
    from critiquebrainz.db import init_db_engine
    init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))

    # Redis (cache)
    from brainzutils import cache
    if "REDIS_HOST" in app.config and \
       "REDIS_PORT" in app.config and \
       "REDIS_NAMESPACE" in app.config:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    else:
        logging.warning("Redis is not defined in config file. Skipping initialization.")

    # OAuth
    from critiquebrainz.ws.oauth import oauth
    oauth.init_app(app)

    app.config["JSONIFY_PRETTYPRINT_REGULAR"] = False

    _register_blueprints(app)

    return app
Esempio n. 14
0
def create_app(config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
        use_debug_toolbar=True,
    )

    # Configuration files
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', 'default_config.py'
    ))
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', 'consul_config.py'
    ), silent=True)
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', 'custom_config.py'
    ), silent=True)
    if config_path:
        app.config.from_pyfile(config_path)

    app.init_loggers(
        file_config=app.config.get('LOG_FILE'),
        email_config=app.config.get('LOG_EMAIL'),
        sentry_config=app.config.get('LOG_SENTRY'),
    )

    # Database
    from metabrainz import db
    db.init_db_engine(app.config["SQLALCHEMY_DATABASE_URI"])
    from metabrainz import model
    model.db.init_app(app)

    # Redis (cache)
    from brainzutils import cache
    cache.init(**app.config['REDIS'])

    # MusicBrainz OAuth
    from metabrainz.users import login_manager, musicbrainz_login
    login_manager.init_app(app)
    musicbrainz_login.init(
        app.config['MUSICBRAINZ_BASE_URL'],
        app.config['MUSICBRAINZ_CLIENT_ID'],
        app.config['MUSICBRAINZ_CLIENT_SECRET']
    )

    # Templates
    from metabrainz.utils import reformat_datetime
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['nl2br'] = lambda val: val.replace('\n', '<br />') if val else ''

    # Error handling
    from metabrainz.errors import init_error_handlers
    init_error_handlers(app)

    add_robots(app)

    # Blueprints
    _register_blueprints(app)

    # ADMIN SECTION

    from flask_admin import Admin
    from metabrainz.admin.views import HomeView
    admin = Admin(app, index_view=HomeView(name='Pending users'))

    # Models
    from metabrainz.model.user import UserAdminView
    from metabrainz.model.payment import PaymentAdminView
    from metabrainz.model.tier import TierAdminView
    admin.add_view(UserAdminView(model.db.session, category='Users', endpoint="user_model"))
    admin.add_view(PaymentAdminView(model.db.session, endpoint="donation_model"))
    admin.add_view(TierAdminView(model.db.session, endpoint="tier_model"))

    # Custom stuff
    from metabrainz.admin.views import CommercialUsersView
    from metabrainz.admin.views import UsersView
    from metabrainz.admin.views import TokensView
    from metabrainz.admin.views import StatsView
    admin.add_view(CommercialUsersView(name='Commercial users', category='Users'))
    admin.add_view(UsersView(name='Search', category='Users'))
    admin.add_view(TokensView(name='Access tokens', category='Users'))
    admin.add_view(StatsView(name='Statistics'))

    return app
Esempio n. 15
0
 def setUp(self):
     cache.init('redis')
Esempio n. 16
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration files
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..',
                     'default_config.py'))
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', '..',
        'consul_config.py'),
                           silent=True)
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', '..',
        'custom_config.py'),
                           silent=True)
    if config_path:
        app.config.from_pyfile(config_path)
    if debug is not None:
        app.debug = debug
    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Error handling
    from critiquebrainz.frontend.error_handlers import init_error_handlers
    init_error_handlers(app)

    # Static files
    from critiquebrainz.frontend import static_manager
    static_manager.read_manifest()

    app.init_loggers(
        file_config=app.config.get("LOG_FILE"),
        email_config=app.config.get("LOG_EMAIL"),
        sentry_config=app.config.get("LOG_SENTRY"),
    )

    # Database
    from critiquebrainz.db import init_db_engine
    init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))

    add_robots(app)

    # MusicBrainz Database
    from critiquebrainz.frontend.external import musicbrainz_db
    musicbrainz_db.init_db_engine(app.config.get('MB_DATABASE_URI'))

    # Redis (cache)
    from brainzutils import cache
    if "REDIS_HOST" in app.config and \
       "REDIS_PORT" in app.config and \
       "REDIS_NAMESPACE" in app.config:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    else:
        logging.warning(
            "Redis is not defined in config file. Skipping initialization.")

    from critiquebrainz.frontend import babel
    babel.init_app(app)

    from critiquebrainz.frontend import login
    login.login_manager.init_app(app)
    from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication
    login.mb_auth = MusicBrainzAuthentication(
        name='musicbrainz',
        client_id=app.config['MUSICBRAINZ_CLIENT_ID'],
        client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'],
        authorize_url="https://musicbrainz.org/oauth2/authorize",
        access_token_url="https://musicbrainz.org/oauth2/token",
        base_url="https://musicbrainz.org/",
    )

    # APIs
    from critiquebrainz.frontend.external import mbspotify
    mbspotify.init(app.config['MBSPOTIFY_BASE_URI'],
                   app.config['MBSPOTIFY_ACCESS_KEY'])
    from critiquebrainz.frontend.external import musicbrainz
    musicbrainz.init(
        app_name=app.config['MUSICBRAINZ_USERAGENT']
        or "CritiqueBrainz Custom",
        app_version="1.0",
        hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org",
    )

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, parameterize
    from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id
    app.jinja_env.filters['date'] = reformat_date
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['track_length'] = track_length
    app.jinja_env.filters['parameterize'] = parameterize
    app.jinja_env.filters['entity_details'] = get_entity_by_id
    from flask_babel import Locale, get_locale
    app.jinja_env.filters['language_name'] = lambda language_code: Locale(
        language_code).get_language_name(get_locale())
    app.context_processor(
        lambda: dict(get_static_path=static_manager.get_static_path))

    # Blueprints
    from critiquebrainz.frontend.views.index import frontend_bp
    from critiquebrainz.frontend.views.review import review_bp
    from critiquebrainz.frontend.views.search import search_bp
    from critiquebrainz.frontend.views.artist import artist_bp
    from critiquebrainz.frontend.views.release_group import release_group_bp
    from critiquebrainz.frontend.views.release import release_bp
    from critiquebrainz.frontend.views.event import event_bp
    from critiquebrainz.frontend.views.mapping import mapping_bp
    from critiquebrainz.frontend.views.user import user_bp
    from critiquebrainz.frontend.views.profile import profile_bp
    from critiquebrainz.frontend.views.place import place_bp
    from critiquebrainz.frontend.views.profile_apps import profile_apps_bp
    from critiquebrainz.frontend.views.login import login_bp
    from critiquebrainz.frontend.views.oauth import oauth_bp
    from critiquebrainz.frontend.views.reports import reports_bp
    from critiquebrainz.frontend.views.moderators import moderators_bp
    from critiquebrainz.frontend.views.log import log_bp

    app.register_blueprint(frontend_bp)
    app.register_blueprint(review_bp, url_prefix='/review')
    app.register_blueprint(search_bp, url_prefix='/search')
    app.register_blueprint(artist_bp, url_prefix='/artist')
    app.register_blueprint(release_group_bp, url_prefix='/release-group')
    app.register_blueprint(release_bp, url_prefix='/release')
    app.register_blueprint(event_bp, url_prefix='/event')
    app.register_blueprint(place_bp, url_prefix='/place')
    app.register_blueprint(mapping_bp, url_prefix='/mapping')
    app.register_blueprint(user_bp, url_prefix='/user')
    app.register_blueprint(profile_bp, url_prefix='/profile')
    app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications')
    app.register_blueprint(login_bp, url_prefix='/login')
    app.register_blueprint(oauth_bp, url_prefix='/oauth')
    app.register_blueprint(reports_bp, url_prefix='/reports')
    app.register_blueprint(log_bp, url_prefix='/log')
    app.register_blueprint(moderators_bp, url_prefix='/moderators')

    return app
Esempio n. 17
0
def init_cache(host, port, namespace):
    """ Initializes brainzutils cache. """
    from brainzutils import cache
    cache.init(host=host, port=port, namespace=namespace)
Esempio n. 18
0
def create_app(debug=None, config_path = None):

    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # get rid of some really pesky warning. Remove this in April 2020, when it shouldn't be needed anymore.
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

    print("Starting metabrainz service with %s environment." % deploy_env);

    # This is used to run tests, but not for dev or deployment
    if config_path:
        print("loading %s" % config_path)
        app.config.from_pyfile(config_path)
    else:
        print("loading %s" % os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', 'config.py'))
        app.config.from_pyfile(os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            '..', 'config.py'
        ))

    # Load configuration files: If we're running under a docker deployment, wait until 
    # the consul configuration is available.
    if deploy_env:
        consul_config = os.path.join( os.path.dirname(os.path.realpath(__file__)), 
            '..', 'consul_config.py')

        print("loading consul %s" % consul_config)
        for i in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(consul_config):
                sleep(1)
                    
        if not os.path.exists(consul_config):
            print("No configuration file generated yet. Retried %d times, exiting." % CONSUL_CONFIG_FILE_RETRY_COUNT);
            sys.exit(-1)

        app.config.from_pyfile(consul_config, silent=True)

    if debug is not None:
        app.debug = debug

    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Printing out some debug values such as config and git commit
    try:
        with open(".git-version") as f:
            git_version = f.read()
        print('Running on git commit %s' % git_version.strip())
    except IOError:
        print("Unable to retrieve git commit. Use docker/push.sh to push images for production.")

    print('Configuration values are as follows: ')
    print(pprint.pformat(app.config, indent=4))

    app.init_loggers(
        file_config=app.config.get('LOG_FILE'),
        email_config=app.config.get('LOG_EMAIL'),
        sentry_config=app.config.get('LOG_SENTRY'),
    )

    # Database
    from metabrainz import db
    db.init_db_engine(app.config["SQLALCHEMY_DATABASE_URI"])
    from metabrainz import model
    model.db.init_app(app)

    # Redis (cache)
    from brainzutils import cache
    cache.init(**app.config['REDIS'])

    # MusicBrainz OAuth
    from metabrainz.users import login_manager, musicbrainz_login
    login_manager.init_app(app)
    musicbrainz_login.init(
        app.config['MUSICBRAINZ_BASE_URL'],
        app.config['MUSICBRAINZ_CLIENT_ID'],
        app.config['MUSICBRAINZ_CLIENT_SECRET']
    )

    # Templates
    from metabrainz.utils import reformat_datetime
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['nl2br'] = lambda val: val.replace('\n', '<br />') if val else ''

    # Error handling
    from metabrainz.errors import init_error_handlers
    init_error_handlers(app)

    add_robots(app)

    from metabrainz import babel
    babel.init_app(app)

    from flask_uploads import configure_uploads
    from metabrainz.admin.forms import LOGO_UPLOAD_SET
    configure_uploads(app, upload_sets=[
        LOGO_UPLOAD_SET,
    ])

    # Blueprints
    _register_blueprints(app)

    # ADMIN SECTION

    from flask_admin import Admin
    from metabrainz.admin.views import HomeView
    admin = Admin(app, index_view=HomeView(name='Pending users'), template_mode='bootstrap3')

    # Models
    from metabrainz.model.user import UserAdminView
    from metabrainz.model.payment import PaymentAdminView
    from metabrainz.model.tier import TierAdminView
    admin.add_view(UserAdminView(model.db.session, category='Users', endpoint="user_model"))
    admin.add_view(PaymentAdminView(model.db.session, category='Payments', endpoint="payment_model"))
    admin.add_view(TierAdminView(model.db.session, endpoint="tier_model"))

    # Custom stuff
    from metabrainz.admin.views import CommercialUsersView
    from metabrainz.admin.views import UsersView
    from metabrainz.admin.views import PaymentsView
    from metabrainz.admin.views import TokensView
    from metabrainz.admin.views import StatsView
    admin.add_view(CommercialUsersView(name='Commercial users', category='Users'))
    admin.add_view(UsersView(name='Search', category='Users'))
    admin.add_view(PaymentsView(name='All', category='Payments'))
    admin.add_view(TokensView(name='Access tokens', category='Users'))
    admin.add_view(StatsView(name='Statistics', category='Statistics'))
    admin.add_view(StatsView(name='Top IPs', endpoint="statsview/top-ips", category='Statistics'))
    admin.add_view(StatsView(name='Top Tokens', endpoint="statsview/top-tokens", category='Statistics'))

    return app
Esempio n. 19
0
def create_app(config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
        use_debug_toolbar=True,
    )

    # Configuration files
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                     'default_config.py'))
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', 'consul_config.py'),
                           silent=True)
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', 'custom_config.py'),
                           silent=True)
    if config_path:
        app.config.from_pyfile(config_path)

    app.init_loggers(
        file_config=app.config.get('LOG_FILE'),
        email_config=app.config.get('LOG_EMAIL'),
        sentry_config=app.config.get('LOG_SENTRY'),
    )

    # Database
    from metabrainz import db
    db.init_db_engine(app.config["SQLALCHEMY_DATABASE_URI"])
    from metabrainz import model
    model.db.init_app(app)

    # Redis (cache)
    from brainzutils import cache
    cache.init(**app.config['REDIS'])

    # MusicBrainz OAuth
    from metabrainz.users import login_manager, musicbrainz_login
    login_manager.init_app(app)
    musicbrainz_login.init(app.config['MUSICBRAINZ_BASE_URL'],
                           app.config['MUSICBRAINZ_CLIENT_ID'],
                           app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Templates
    from metabrainz.utils import reformat_datetime
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['nl2br'] = lambda val: val.replace('\n', '<br />'
                                                             ) if val else ''

    # Error handling
    from metabrainz.errors import init_error_handlers
    init_error_handlers(app)

    add_robots(app)

    from metabrainz import babel
    babel.init_app(app)

    from flask_uploads import configure_uploads
    from metabrainz.admin.forms import LOGO_UPLOAD_SET
    configure_uploads(app, upload_sets=[
        LOGO_UPLOAD_SET,
    ])

    # Blueprints
    _register_blueprints(app)

    # ADMIN SECTION

    from flask_admin import Admin
    from metabrainz.admin.views import HomeView
    admin = Admin(app,
                  index_view=HomeView(name='Pending users'),
                  template_mode='bootstrap3')

    # Models
    from metabrainz.model.user import UserAdminView
    from metabrainz.model.payment import PaymentAdminView
    from metabrainz.model.tier import TierAdminView
    admin.add_view(
        UserAdminView(model.db.session,
                      category='Users',
                      endpoint="user_model"))
    admin.add_view(
        PaymentAdminView(model.db.session,
                         category='Payments',
                         endpoint="payment_model"))
    admin.add_view(TierAdminView(model.db.session, endpoint="tier_model"))

    # Custom stuff
    from metabrainz.admin.views import CommercialUsersView
    from metabrainz.admin.views import UsersView
    from metabrainz.admin.views import PaymentsView
    from metabrainz.admin.views import TokensView
    from metabrainz.admin.views import StatsView
    admin.add_view(
        CommercialUsersView(name='Commercial users', category='Users'))
    admin.add_view(UsersView(name='Search', category='Users'))
    admin.add_view(PaymentsView(name='All', category='Payments'))
    admin.add_view(TokensView(name='Access tokens', category='Users'))
    admin.add_view(StatsView(name='Statistics'))

    return app
Esempio n. 20
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                     'default_config.py'))
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', 'custom_config.py'),
                           silent=True)

    if config_path:
        app.config.from_pyfile(config_path)

    if debug is not None:
        app.debug = debug

    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Redis (cache)
    from brainzutils import cache
    try:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    except KeyError as e:
        logging.error(
            "Redis is not defined in config file. Error: {}".format(e))
        raise

    # Logging
    app.init_loggers(file_config=app.config.get('LOG_FILE'),
                     sentry_config=app.config.get('LOG_SENTRY'))

    # Extensions
    from flask_uuid import FlaskUUID
    FlaskUUID(app)

    # Error handling
    from messybrainz.webserver.errors import init_error_handlers
    init_error_handlers(app)

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from messybrainz.webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime

    # Blueprints
    from messybrainz.webserver.views.index import index_bp
    from messybrainz.webserver.views.api import api_bp
    app.register_blueprint(index_bp)
    app.register_blueprint(api_bp)

    db.init_db_engine(app.config['SQLALCHEMY_DATABASE_URI'])

    return app
Esempio n. 21
0
def setup_cache():
    cache.init(
        host=REDIS_HOST,
        port=REDIS_PORT,
        namespace=REDIS_NAMESPACE,
    )
def gen_app(config_path=None, debug=None):
    """ Generate a Flask app for LB with all configurations done and connections established.

    In the Flask app returned, blueprints are not registered.
    """
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
        use_debug_toolbar=True,
    )

    print("Starting metabrainz service with %s environment." % deploy_env)

    # Configuration
    print("loading %s" %
          os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                       'default_config.py'))
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                     'default_config.py'))

    # Load configuration files: If we're running under a docker deployment, wait until
    # the consul configuration has been copied to custom_config.py
    custom_config = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                 '..', 'custom_config.py')
    if deploy_env:
        print("Checking if consul template generated config file exists: %s" %
              custom_config)
        for i in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(custom_config):
                sleep(1)

        if not os.path.exists(custom_config):
            print(
                "No configuration file generated yet. Retried %d times, exiting."
                % CONSUL_CONFIG_FILE_RETRY_COUNT)
            sys.exit(-1)

        print("loading consul config file %s)" %
              os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                           'custom_config.py'))
        app.config.from_pyfile(custom_config)

    else:
        print("loading custom config %s" % custom_config)
        app.config.from_pyfile(custom_config, silent=True)

    if config_path:
        print("loading additional config %s" % config_path)
        app.config.from_pyfile(config_path)

    if debug is not None:
        app.debug = debug

    # Output config values and some other info
    print('Configuration values are as follows: ')
    print(pprint.pformat(app.config, indent=4))
    try:
        with open('.git-version') as git_version_file:
            print('Running on git commit: %s', git_version_file.read().strip())
    except IOError as e:
        print('Unable to retrieve git commit. Error: %s', str(e))

    # Logging
    app.init_loggers(file_config=app.config.get('LOG_FILE'),
                     email_config=app.config.get('LOG_EMAIL'),
                     sentry_config=app.config.get('LOG_SENTRY'))

    # Redis connection
    create_redis(app)

    # Cache
    if 'REDIS_HOST' in app.config and\
       'REDIS_PORT' in app.config and\
       'REDIS_NAMESPACE' in app.config:

        from brainzutils import cache
        cache.init(host=app.config['REDIS_HOST'],
                   port=app.config['REDIS_PORT'],
                   namespace=app.config['REDIS_NAMESPACE'])
    else:
        raise Exception(
            'One or more redis cache configuration options are missing from custom_config.py'
        )

    # Influx connection
    create_influx(app)

    # RabbitMQ connection
    create_rabbitmq(app)

    # Database connection
    from listenbrainz import db
    db.init_db_connection(app.config['SQLALCHEMY_DATABASE_URI'])
    from listenbrainz.webserver.external import messybrainz
    messybrainz.init_db_connection(
        app.config['MESSYBRAINZ_SQLALCHEMY_DATABASE_URI'])

    # OAuth
    from listenbrainz.webserver.login import login_manager, provider
    login_manager.init_app(app)
    provider.init(app.config['MUSICBRAINZ_CLIENT_ID'],
                  app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Error handling
    from listenbrainz.webserver.errors import init_error_handlers
    init_error_handlers(app)

    from listenbrainz.webserver import rate_limiter

    @app.after_request
    def after_request_callbacks(response):
        return rate_limiter.inject_x_rate_headers(response)

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from listenbrainz.webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime

    return app
Esempio n. 23
0
def create_app(debug=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration
    load_config(app)

    if debug is not None:
        app.debug = debug

    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Logging
    app.init_loggers(file_config=app.config.get('LOG_FILE'),
                     email_config=app.config.get('LOG_EMAIL'),
                     sentry_config=app.config.get('LOG_SENTRY')
                     )

    # Database connection
    from db import init_db_engine
    init_db_engine(app.config['SQLALCHEMY_DATABASE_URI'])

    # Cache
    if 'REDIS_HOST' in app.config and\
       'REDIS_PORT' in app.config and\
       'REDIS_NAMESPACE' in app.config and\
       'REDIS_NS_VERSIONS_LOCATION' in app.config:
        if not os.path.exists(app.config['REDIS_NS_VERSIONS_LOCATION']):
            os.makedirs(app.config['REDIS_NS_VERSIONS_LOCATION'])

        from brainzutils import cache
        cache.init(
            host=app.config['REDIS_HOST'],
            port=app.config['REDIS_PORT'],
            namespace=app.config['REDIS_NAMESPACE'],
            ns_versions_loc=app.config['REDIS_NS_VERSIONS_LOCATION'])
    else:
        raise Exception('One or more redis cache configuration options are missing from config.py')

    # Add rate limiting support
    @app.after_request
    def after_request_callbacks(response):
        return inject_x_rate_headers(response)

    # check for ratelimit config values and set them if present
    if 'RATELIMIT_PER_IP' in app.config and 'RATELIMIT_WINDOW' in app.config:
        set_rate_limits(app.config['RATELIMIT_PER_IP'], app.config['RATELIMIT_PER_IP'], app.config['RATELIMIT_WINDOW'])

    # MusicBrainz
    import musicbrainzngs
    from db import SCHEMA_VERSION
    musicbrainzngs.set_useragent(app.config['MUSICBRAINZ_USERAGENT'], SCHEMA_VERSION)
    if app.config['MUSICBRAINZ_HOSTNAME']:
        musicbrainzngs.set_hostname(app.config['MUSICBRAINZ_HOSTNAME'])

    # OAuth
    from webserver.login import login_manager, provider
    login_manager.init_app(app)
    provider.init(app.config['MUSICBRAINZ_CLIENT_ID'],
                  app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Error handling
    from webserver.errors import init_error_handlers
    init_error_handlers(app)

    # Static files
    import static_manager

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime
    # During development, built js and css assets don't have a hash, but in production we use
    # a manifest to map a name to name.hash.extension for caching/cache busting
    if app.debug:
        app.context_processor(lambda: dict(get_static_path=static_manager.development_get_static_path))
    else:
        static_manager.read_manifest()
        app.context_processor(lambda: dict(get_static_path=static_manager.manifest_get_static_path))

    _register_blueprints(app)

    # Admin section
    from flask_admin import Admin
    from webserver.admin import views as admin_views
    admin = Admin(app, index_view=admin_views.HomeView(name='Admin'))
    admin.add_view(admin_views.AdminsView(name='Admins'))

    @app.before_request
    def prod_https_login_redirect():
        """ Redirect to HTTPS in production except for the API endpoints
        """
        if urlparse.urlsplit(request.url).scheme == 'http' \
                and app.config['DEBUG'] == False \
                and app.config['TESTING'] == False \
                and request.blueprint not in ('api', 'api_v1_core', 'api_v1_datasets', 'api_v1_dataset_eval'):
            url = request.url[7:] # remove http:// from url
            return redirect('https://{}'.format(url), 301)


    @app.before_request
    def before_request_gdpr_check():
        # skip certain pages, static content and the API
        if request.path == url_for('index.gdpr_notice') \
          or request.path == url_for('login.logout') \
          or request.path.startswith('/_debug') \
          or request.path.startswith('/static') \
          or request.path.startswith(API_PREFIX):
            return
        # otherwise if user is logged in and hasn't agreed to gdpr,
        # redirect them to agree to terms page.
        elif current_user.is_authenticated and current_user.gdpr_agreed is None:
            return redirect(url_for('index.gdpr_notice', next=request.full_path))

    return app
Esempio n. 24
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration files
    app.config.from_pyfile(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..',
                     'default_config.py'))

    config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                               '..', '..', 'consul_config.py')
    if deploy_env:
        print("Checking if consul template generated config file exists: {}".
              format(config_file))
        for _ in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(config_file):
                sleep(1)

        if not os.path.exists(config_file):
            print(
                "No configuration file generated yet. Retried {} times, exiting."
                .format(CONSUL_CONFIG_FILE_RETRY_COUNT))
            sys.exit(-1)

        print("Loading consul config file {}".format(config_file))
    app.config.from_pyfile(config_file, silent=True)

    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)), '..', '..',
        'custom_config.py'),
                           silent=True)
    if config_path:
        app.config.from_pyfile(config_path)
    if debug is not None:
        app.debug = debug

    # Error handling
    from critiquebrainz.ws.errors import init_error_handlers
    init_error_handlers(app)

    app.init_loggers(
        file_config=app.config.get("LOG_FILE"),
        email_config=app.config.get("LOG_EMAIL"),
        sentry_config=app.config.get("LOG_SENTRY"),
    )

    # CritiqueBrainz Database
    from critiquebrainz import db as critiquebrainz_db
    critiquebrainz_db.init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))

    # MusicBrainz Database
    from brainzutils import musicbrainz_db
    musicbrainz_db.init_db_engine(app.config.get("MB_DATABASE_URI"))

    # Redis (cache)
    from brainzutils import cache
    if "REDIS_HOST" in app.config and \
       "REDIS_PORT" in app.config and \
       "REDIS_NAMESPACE" in app.config:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    else:
        logging.warning(
            "Redis is not defined in config file. Skipping initialization.")

    # OAuth
    from critiquebrainz.ws.oauth import oauth
    oauth.init_app(app)

    app.config["JSONIFY_PRETTYPRINT_REGULAR"] = False

    _register_blueprints(app)

    return app
Esempio n. 25
0
def create_app(debug=None, config_path=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration files
    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'default_config.py'
    ))

    config_file = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'consul_config.py'
    )
    if deploy_env:
        print("Checking if consul template generated config file exists: {}".format(config_file))
        for _ in range(CONSUL_CONFIG_FILE_RETRY_COUNT):
            if not os.path.exists(config_file):
                sleep(1)

        if not os.path.exists(config_file):
            print("No configuration file generated yet. Retried {} times, exiting.".format(CONSUL_CONFIG_FILE_RETRY_COUNT))
            sys.exit(-1)

        print("Loading consul config file {}".format(config_file))
    app.config.from_pyfile(config_file, silent=True)

    app.config.from_pyfile(os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        '..', '..', 'custom_config.py'
    ), silent=True)
    if config_path:
        app.config.from_pyfile(config_path)
    if debug is not None:
        app.debug = debug
    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Error handling
    from critiquebrainz.frontend.error_handlers import init_error_handlers
    init_error_handlers(app)

    # Static files
    from critiquebrainz.frontend import static_manager
    static_manager.read_manifest()

    app.init_loggers(
        file_config=app.config.get("LOG_FILE"),
        email_config=app.config.get("LOG_EMAIL"),
        sentry_config=app.config.get("LOG_SENTRY"),
    )

    # Database
    from critiquebrainz.db import init_db_engine
    init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))

    add_robots(app)

    # MusicBrainz Database
    from critiquebrainz.frontend.external import musicbrainz_db
    musicbrainz_db.init_db_engine(app.config.get('MB_DATABASE_URI'))

    # Redis (cache)
    from brainzutils import cache
    if "REDIS_HOST" in app.config and \
       "REDIS_PORT" in app.config and \
       "REDIS_NAMESPACE" in app.config:
        cache.init(
            host=app.config["REDIS_HOST"],
            port=app.config["REDIS_PORT"],
            namespace=app.config["REDIS_NAMESPACE"],
        )
    else:
        logging.warning("Redis is not defined in config file. Skipping initialization.")

    from critiquebrainz.frontend import babel
    babel.init_app(app)

    from critiquebrainz.frontend import login
    login.login_manager.init_app(app)
    from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication
    login.mb_auth = MusicBrainzAuthentication(
        name='musicbrainz',
        client_id=app.config['MUSICBRAINZ_CLIENT_ID'],
        client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'],
        authorize_url="https://musicbrainz.org/oauth2/authorize",
        access_token_url="https://musicbrainz.org/oauth2/token",
        base_url="https://musicbrainz.org/",
    )

    # APIs
    from critiquebrainz.frontend.external import mbspotify
    mbspotify.init(app.config['MBSPOTIFY_BASE_URI'], app.config['MBSPOTIFY_ACCESS_KEY'])
    from critiquebrainz.frontend.external import musicbrainz
    musicbrainz.init(
        app_name=app.config['MUSICBRAINZ_USERAGENT'] or "CritiqueBrainz Custom",
        app_version="1.0",
        hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org",
    )

    # Template utilities
    # TODO (code-master5): disabled no-member warnings just as a workaround to deal with failing tests till the
    # issue [https://github.com/PyCQA/pylint/issues/2563] with pylint is resolved
    app.jinja_env.add_extension('jinja2.ext.do')
    from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, parameterize
    from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id
    app.jinja_env.filters['date'] = reformat_date
    app.jinja_env.filters['datetime'] = reformat_datetime
    app.jinja_env.filters['track_length'] = track_length
    app.jinja_env.filters['parameterize'] = parameterize
    app.jinja_env.filters['entity_details'] = get_entity_by_id
    from flask_babel import Locale, get_locale
    app.jinja_env.filters['language_name'] = lambda language_code: Locale(language_code).get_language_name(get_locale())
    app.context_processor(lambda: dict(get_static_path=static_manager.get_static_path))

    # Blueprints
    from critiquebrainz.frontend.views.index import frontend_bp
    from critiquebrainz.frontend.views.review import review_bp
    from critiquebrainz.frontend.views.search import search_bp
    from critiquebrainz.frontend.views.artist import artist_bp
    from critiquebrainz.frontend.views.release_group import release_group_bp
    from critiquebrainz.frontend.views.release import release_bp
    from critiquebrainz.frontend.views.event import event_bp
    from critiquebrainz.frontend.views.mapping import mapping_bp
    from critiquebrainz.frontend.views.user import user_bp
    from critiquebrainz.frontend.views.profile import profile_bp
    from critiquebrainz.frontend.views.place import place_bp
    from critiquebrainz.frontend.views.profile_apps import profile_apps_bp
    from critiquebrainz.frontend.views.login import login_bp
    from critiquebrainz.frontend.views.oauth import oauth_bp
    from critiquebrainz.frontend.views.reports import reports_bp
    from critiquebrainz.frontend.views.moderators import moderators_bp
    from critiquebrainz.frontend.views.log import log_bp
    from critiquebrainz.frontend.views.comment import comment_bp
    from critiquebrainz.frontend.views.rate import rate_bp

    app.register_blueprint(frontend_bp)
    app.register_blueprint(review_bp, url_prefix='/review')
    app.register_blueprint(search_bp, url_prefix='/search')
    app.register_blueprint(artist_bp, url_prefix='/artist')
    app.register_blueprint(release_group_bp, url_prefix='/release-group')
    app.register_blueprint(release_bp, url_prefix='/release')
    app.register_blueprint(event_bp, url_prefix='/event')
    app.register_blueprint(place_bp, url_prefix='/place')
    app.register_blueprint(mapping_bp, url_prefix='/mapping')
    app.register_blueprint(user_bp, url_prefix='/user')
    app.register_blueprint(profile_bp, url_prefix='/profile')
    app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications')
    app.register_blueprint(login_bp, url_prefix='/login')
    app.register_blueprint(oauth_bp, url_prefix='/oauth')
    app.register_blueprint(reports_bp, url_prefix='/reports')
    app.register_blueprint(log_bp, url_prefix='/log')
    app.register_blueprint(moderators_bp, url_prefix='/moderators')
    app.register_blueprint(comment_bp, url_prefix='/comments')
    app.register_blueprint(rate_bp, url_prefix='/rate')

    return app
Esempio n. 26
0
def create_app(debug=None):
    app = CustomFlask(
        import_name=__name__,
        use_flask_uuid=True,
    )

    # Configuration
    load_config(app)

    if debug is not None:
        app.debug = debug

    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Logging
    app.init_loggers(file_config=app.config.get('LOG_FILE'),
                     email_config=app.config.get('LOG_EMAIL'),
                     sentry_config=app.config.get('LOG_SENTRY')
                     )

    # Database connection
    from db import init_db_engine
    init_db_engine(app.config['SQLALCHEMY_DATABASE_URI'])

    # Cache
    if 'REDIS_HOST' in app.config and\
       'REDIS_PORT' in app.config and\
       'REDIS_NAMESPACE' in app.config and\
       'REDIS_NS_VERSIONS_LOCATION' in app.config:
        if not os.path.exists(app.config['REDIS_NS_VERSIONS_LOCATION']):
            os.makedirs(app.config['REDIS_NS_VERSIONS_LOCATION'])

        from brainzutils import cache
        cache.init(
            host=app.config['REDIS_HOST'],
            port=app.config['REDIS_PORT'],
            namespace=app.config['REDIS_NAMESPACE'],
            ns_versions_loc=app.config['REDIS_NS_VERSIONS_LOCATION'])
    else:
        raise Exception('One or more redis cache configuration options are missing from config.py')

    # Extensions
    from flask_uuid import FlaskUUID
    FlaskUUID(app)

    # MusicBrainz
    import musicbrainzngs
    from db import SCHEMA_VERSION
    musicbrainzngs.set_useragent(app.config['MUSICBRAINZ_USERAGENT'], SCHEMA_VERSION)
    if app.config['MUSICBRAINZ_HOSTNAME']:
        musicbrainzngs.set_hostname(app.config['MUSICBRAINZ_HOSTNAME'])

    # OAuth
    from webserver.login import login_manager, provider
    login_manager.init_app(app)
    provider.init(app.config['MUSICBRAINZ_CLIENT_ID'],
                  app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Error handling
    from webserver.errors import init_error_handlers
    init_error_handlers(app)

    # Static files
    import static_manager
    static_manager.read_manifest()

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime
    app.context_processor(lambda: dict(get_static_path=static_manager.get_static_path))

    _register_blueprints(app)

    # Admin section
    from flask_admin import Admin
    from webserver.admin import views as admin_views
    admin = Admin(app, index_view=admin_views.HomeView(name='Admin'))
    admin.add_view(admin_views.AdminsView(name='Admins'))

    @ app.before_request
    def before_request_gdpr_check():
        # skip certain pages, static content and the API
        if request.path == url_for('index.gdpr_notice') \
          or request.path == url_for('login.logout') \
          or request.path.startswith('/_debug') \
          or request.path.startswith('/static') \
          or request.path.startswith(API_PREFIX):
            return
        # otherwise if user is logged in and hasn't agreed to gdpr,
        # redirect them to agree to terms page.
        elif current_user.is_authenticated and current_user.gdpr_agreed is None:
            return redirect(url_for('index.gdpr_notice', next=request.full_path))

    return app
Esempio n. 27
0
def init_cache(host, port, namespace):
    """ Initializes brainzutils cache. """
    from brainzutils import cache
    cache.init(host=host, port=port, namespace=namespace)
Esempio n. 28
0
def create_app(debug=None, config_path=None):
    app = create_app_with_configuration(config_path)

    if debug is not None:
        app.debug = debug

    if app.debug and app.config['SECRET_KEY']:
        app.init_debug_toolbar()

    # Logging
    from webserver.loggers import init_loggers
    init_loggers(app)

    # Database connection
    from db import init_db_engine
    init_db_engine(app.config['SQLALCHEMY_DATABASE_URI'])

    # Cache
    if 'REDIS_HOST' in app.config and\
       'REDIS_PORT' in app.config and\
       'REDIS_NAMESPACE' in app.config and\
       'REDIS_NS_VERSIONS_LOCATION' in app.config:
        if not os.path.exists(app.config['REDIS_NS_VERSIONS_LOCATION']):
            os.makedirs(app.config['REDIS_NS_VERSIONS_LOCATION'])

        from brainzutils import cache
        cache.init(host=app.config['REDIS_HOST'],
                   port=app.config['REDIS_PORT'],
                   namespace=app.config['REDIS_NAMESPACE'],
                   ns_versions_loc=app.config['REDIS_NS_VERSIONS_LOCATION'])
    else:
        raise Exception(
            'One or more redis cache configuration options are missing from custom_config.py'
        )

    # Extensions
    from flask_uuid import FlaskUUID
    FlaskUUID(app)

    # MusicBrainz
    import musicbrainzngs
    from db import SCHEMA_VERSION
    musicbrainzngs.set_useragent(app.config['MUSICBRAINZ_USERAGENT'],
                                 SCHEMA_VERSION)
    if app.config['MUSICBRAINZ_HOSTNAME']:
        musicbrainzngs.set_hostname(app.config['MUSICBRAINZ_HOSTNAME'])

    # OAuth
    from webserver.login import login_manager, provider
    login_manager.init_app(app)
    provider.init(app.config['MUSICBRAINZ_CLIENT_ID'],
                  app.config['MUSICBRAINZ_CLIENT_SECRET'])

    # Error handling
    from webserver.errors import init_error_handlers
    init_error_handlers(app)

    # Static files
    import static_manager
    static_manager.read_manifest()

    # Template utilities
    app.jinja_env.add_extension('jinja2.ext.do')
    from webserver import utils
    app.jinja_env.filters['date'] = utils.reformat_date
    app.jinja_env.filters['datetime'] = utils.reformat_datetime
    app.context_processor(
        lambda: dict(get_static_path=static_manager.get_static_path))

    _register_blueprints(app)

    # Admin section
    from flask_admin import Admin
    from webserver.admin import views as admin_views
    admin = Admin(app, index_view=admin_views.HomeView(name='Admin'))
    admin.add_view(admin_views.AdminsView(name='Admins'))

    return app