import json import logging import boto3 from authlib.integrations.flask_client import OAuth from flask import Flask, session from flask_admin import Admin from flask_admin.menu import MenuLink from flask_sqlalchemy import SQLAlchemy from smelog.entities import LoggerConfig, SentryConfig from smelog.factory import LoggerFactory from delphi_slz_admin.const import APP_NAME, VERSION from delphi_slz_admin.modelviews.apps_content_status import AppsContentStatusModelView from delphi_slz_admin.modelviews.apps_dbx_execution import AppsDbxExecutionModelView from delphi_slz_admin.modelviews.apps_failure_log import AppsFailureLogModelView from delphi_slz_admin.modelviews.apps_unit_of_work import AppsUnitOfWorkModelView from delphi_slz_admin.modelviews.audit_log import AuditLogModelView from delphi_slz_admin.modelviews.backfill_progress import ( BackfillProgressYearDspModelView, BackfillProgressYearDspReportModelView, ) from delphi_slz_admin.modelviews.content_failure_log import ContentFailureLogModelView from delphi_slz_admin.modelviews.content_status import ContentStatusModelView from delphi_slz_admin.modelviews.snapshot import SnapshotModelView from delphi_slz_admin.services.config import ConfigService from delphi_slz_admin.views import auth as auth_views from delphi_slz_admin.views import health as health_views logger = None # pylint: disable=invalid-name class LoginMenuLink(MenuLink): def is_accessible(self) -> bool: return 'profile' not in session class LogoutMenuLink(MenuLink): def is_accessible(self) -> bool: return 'profile' in session def setup_app() -> Flask: config = ConfigService().load_config() global logger # pylint: disable=global-statement,invalid-name log_config = LoggerConfig( name=APP_NAME, version=VERSION, level=logging.DEBUG, environment=config.env, is_local=config.is_local, ) if not config.is_local and config.sentry_secret_key: secrets_manager = boto3.client('secretsmanager') sentry_dsn = json.loads( secrets_manager.get_secret_value(SecretId=config.sentry_secret_key, )['SecretString'] )[APP_NAME] log_config.sentry = SentryConfig( level=logging.ERROR, dsn=sentry_dsn, ) logger = LoggerFactory(log_config).get_logger(APP_NAME) app = Flask(__name__) app.secret_key = 'super secret key' app.config['CONFIG'] = config app.config['FLASK_ADMIN_SWATCH'] = 'cerulean' app.config['SQLALCHEMY_DATABASE_URI'] = config.db_url app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False if not config.fake_login_enabled: oauth = OAuth(app) auth0 = oauth.register( 'auth0', client_id=config.auth0_client_id, client_secret=config.auth0_client_secret, api_base_url=config.auth0_base_url, access_token_url=f'{config.auth0_base_url}/oauth/token', authorize_url=f'{config.auth0_base_url}/authorize', client_kwargs={ 'scope': 'openid profile email', }, ) app.auth0 = auth0 db = SQLAlchemy(app) if not config.fake_login_enabled: app.add_url_rule('/login', 'login', view_func=auth_views.login) app.add_url_rule('/logout', 'logout', view_func=auth_views.logout) app.add_url_rule('/callback', 'callback', view_func=auth_views.callback) app.add_url_rule('/health', 'health', view_func=health_views.health) admin = Admin( app, url='/', index_view=ContentStatusModelView(db.session, url='/', endpoint='admin'), name='Admin', template_mode='bootstrap3', base_template='master.html', ) if not config.fake_login_enabled: admin.add_link(LoginMenuLink(name='Login', category='', url='/login')) admin.add_link(LogoutMenuLink(name='Logout', category='', url='/logout')) admin.add_view(ContentFailureLogModelView(db.session)) admin.add_view(BackfillProgressYearDspModelView(db.session)) admin.add_view(BackfillProgressYearDspReportModelView(db.session)) admin.add_view(AppsUnitOfWorkModelView(db.session)) admin.add_view(AppsContentStatusModelView(db.session)) admin.add_view(SnapshotModelView(db.session)) admin.add_view(AppsDbxExecutionModelView(db.session)) admin.add_view(AppsFailureLogModelView(db.session)) admin.add_view(AuditLogModelView(db.session)) return app