def init_app(app, user_datastore, LoginForm): def load_user(user_id): return user_datastore.get_user(user_id) def load_user_from_request(request): apikey = request.headers.environ.get("HTTP_X_API_KEY", None) if apikey: user = user_datastore.find_user(apikey=apikey) if not user: return None else: auth = request.headers.get("Authorization") if not auth or auth.count(":") != 1: return None login, password = auth.split(":") user = user_datastore.find_user(email=login.strip()) if user is None: return None if not verify_and_update_password(password.strip(), user): return None return user if login_user(user) else None security = Security() security.init_app(app, user_datastore, login_form=LoginForm) app.login_manager.request_loader(load_user_from_request) app.login_manager.user_loader(load_user) user_logged_out.connect(invalidate_user)
def _enable_session_activity(self, app): """Enable session activity.""" user_logged_in.connect(login_listener, app) user_logged_out.connect(logout_listener, app) from .views.settings import blueprint from .views.security import security, revoke_session blueprint.route('/security/', methods=['GET'])(security) blueprint.route('/sessions/revoke/', methods=['POST'])(revoke_session)
def _enable_logger_activity(self, app): """ Enable session activity. :param app: The flask application. """ user_logged_in.connect(login_listener, app) user_logged_out.connect(logout_listener, app)
def _enable_session_activity(self, app): """Enable session activity.""" user_logged_in.connect(login_listener, app) user_logged_in.connect(csrf_token_reset, app) user_logged_out.connect(logout_listener, app) user_logged_out.connect(csrf_token_reset, app) from .views.security import revoke_session, security from .views.settings import blueprint blueprint.route("/security/", methods=["GET"])(security) blueprint.route("/sessions/revoke/", methods=["POST"])(revoke_session)
def init_app(self, app): login_manager.init_app(app) login_manager.login_view = 'login.login_form' Service.init_app(self, app) self.login_url_prefix = app.config.get('LOGIN_URL', '/user') app.before_request(self.do_access_control) app.before_request(self.update_user_session_data) user_logged_in.connect(self.user_logged_in, sender=app) user_logged_out.connect(self.user_logged_out, sender=app) app.register_blueprint(login_views, url_prefix=self.login_url_prefix) with app.app_context(): actions.register(*_ACTIONS)
def setUp(self): super().setUp() self.flask_app = self._create_app() self.client = self.flask_app.test_client() self._ctx = self.flask_app.test_request_context() self._ctx.push() self.json_mod = json self.templates = [] self.current_user = None template_rendered.connect(self._add_template) if HAVE_FLASK_LOGIN: user_logged_in.connect(self._signal_login) user_logged_out.connect(self._signal_logout)
def init_app(self, app: Flask) -> None: login_manager.init_app(app) login_manager.login_view = "login.login_form" super().init_app(app) self.login_url_prefix = app.config.get("LOGIN_URL", "/user") app.before_request(self.do_access_control) app.before_request(self.update_user_session_data) user_logged_in.connect(self.user_logged_in, sender=app) user_logged_out.connect(self.user_logged_out, sender=app) app.register_blueprint(login_views, url_prefix=self.login_url_prefix) with app.app_context(): actions.register(*_ACTIONS)
def create_app(db_connection_string=None, testing=None): class CustomFlask(Flask): SKIP_RULES = [ # These endpoints will be removed for v3 '/v3/ws/<workspace_name>/hosts/bulk_delete/', '/v3/ws/<workspace_name>/vulns/bulk_delete/', '/v3/ws/<workspace_id>/change_readonly/', '/v3/ws/<workspace_id>/deactivate/', '/v3/ws/<workspace_id>/activate/', ] def add_url_rule(self, rule, endpoint=None, view_func=None, **options): # Flask registers views when an application starts # do not add view from SKIP_VIEWS for rule_ in CustomFlask.SKIP_RULES: if rule_ == rule: return return super().add_url_rule(rule, endpoint, view_func, **options) app = CustomFlask(__name__, static_folder=None) try: secret_key = faraday.server.config.faraday_server.secret_key except Exception: # Now when the config file does not exist it doesn't enter in this # condition, but it could happen in the future. TODO check save_new_secret_key(app) else: if secret_key is None: # This is what happens now when the config file doesn't exist. # TODO check save_new_secret_key(app) else: app.config['SECRET_KEY'] = secret_key if faraday.server.config.faraday_server.agent_registration_secret is None: save_new_agent_creation_token_secret() login_failed_message = ("Invalid username or password", 'error') app.config.update({ 'SECURITY_BACKWARDS_COMPAT_AUTH_TOKEN': True, 'SECURITY_PASSWORD_SINGLE_HASH': True, 'WTF_CSRF_ENABLED': False, 'SECURITY_USER_IDENTITY_ATTRIBUTES': [{ 'username': { 'mapper': uia_username_mapper } }], 'SECURITY_POST_LOGIN_VIEW': '/_api/session', 'SECURITY_POST_CHANGE_VIEW': '/_api/change', 'SECURITY_RESET_PASSWORD_TEMPLATE': '/security/reset.html', 'SECURITY_POST_RESET_VIEW': '/', 'SECURITY_SEND_PASSWORD_RESET_EMAIL': True, # For testing porpouse 'SECURITY_EMAIL_SENDER': "*****@*****.**", 'SECURITY_CHANGEABLE': True, 'SECURITY_SEND_PASSWORD_CHANGE_EMAIL': False, 'SECURITY_MSG_USER_DOES_NOT_EXIST': login_failed_message, 'SECURITY_TOKEN_AUTHENTICATION_HEADER': 'Authorization', # The line bellow should not be necessary because of the # CustomLoginForm, but i'll include it anyway. 'SECURITY_MSG_INVALID_PASSWORD': login_failed_message, 'SESSION_TYPE': 'filesystem', 'SESSION_FILE_DIR': faraday.server.config.FARADAY_SERVER_SESSIONS_DIR, 'SQLALCHEMY_TRACK_MODIFICATIONS': False, 'SQLALCHEMY_RECORD_QUERIES': True, # app.config['SQLALCHEMY_ECHO'] = True 'SECURITY_PASSWORD_SCHEMES': [ 'bcrypt', # This should be the default value # 'des_crypt', # 'pbkdf2_sha256', # 'pbkdf2_sha512', # 'sha256_crypt', # 'sha512_crypt', ], 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(hours=int( faraday.server.config.faraday_server.session_timeout or 12)), 'SESSION_COOKIE_NAME': 'faraday_session_2', 'SESSION_COOKIE_SAMESITE': 'Lax', }) store = FilesystemStore(app.config['SESSION_FILE_DIR']) prefixed_store = PrefixDecorator('sessions_', store) KVSessionExtension(prefixed_store, app) user_logged_in.connect(user_logged_in_succesfull, app) user_logged_out.connect(expire_session, app) storage_path = faraday.server.config.storage.path if not storage_path: logger.warn( 'No storage section or path in the .faraday/config/server.ini. Setting the default value to .faraday/storage' ) storage_path = setup_storage_path() if not DepotManager.get('default'): if testing: DepotManager.configure( 'default', { 'depot.storage_path': '/tmp' # nosec }) else: DepotManager.configure('default', {'depot.storage_path': storage_path}) check_testing_configuration(testing, app) try: app.config[ 'SQLALCHEMY_DATABASE_URI'] = db_connection_string or faraday.server.config.database.connection_string.strip( "'") except AttributeError: logger.info( 'Missing [database] section on server.ini. Please configure the database before running the server.' ) except NoOptionError: logger.info( 'Missing connection_string on [database] section on server.ini. Please configure the database before running the server.' ) from faraday.server.models import db # pylint:disable=import-outside-toplevel db.init_app(app) # Session(app) # Setup Flask-Security app.user_datastore = SQLAlchemyUserDatastore( db, user_model=User, role_model=None) # We won't use flask security roles feature from faraday.server.api.modules.agent import agent_creation_api # pylint: disable=import-outside-toplevel app.limiter = Limiter(app, key_func=get_remote_address, default_limits=[]) if not testing: app.limiter.limit(faraday.server.config.limiter_config.login_limit)( agent_creation_api) app.register_blueprint(agent_creation_api) Security(app, app.user_datastore, login_form=CustomLoginForm) # Make API endpoints require a login user by default. Based on # https://stackoverflow.com/questions/13428708/best-way-to-make-flask-logins-login-required-the-default app.view_functions['security.login'].is_public = True app.view_functions['security.logout'].is_public = True app.debug = faraday.server.config.is_debug_mode() minify_json_output(app) for handler in LOGGING_HANDLERS: app.logger.addHandler(handler) app.logger.propagate = False register_blueprints(app) register_handlers(app) app.view_functions[ 'agent_creation_api.AgentCreationView:post'].is_public = True app.view_functions[ 'agent_creation_api.AgentCreationV3View:post'].is_public = True return app
from flask import current_app from flask_mail import email_dispatched from flask_login import user_logged_in, user_logged_out from app.logger import log_user_operation, log_email_operation def _after_sending_email_hook(message, app): log_email_operation(message, 'sent') email_dispatched.connect(_after_sending_email_hook) # @user_logged_in.connect_via(current_app) def _after_user_logged_in_hook(sender, user, **extra): log_user_operation(user, 'logged in') user_logged_in.connect(_after_user_logged_in_hook) # @user_logged_out.connect_via(current_app) def _after_user_logged_out_hook(sender, user, **extra): log_user_operation(user, 'logged out') user_logged_out.connect(_after_user_logged_out_hook)
def __init__(self, app, entry_point_group=None): """Initialize state.""" self.app = app self.handlers = {} self.disconnect_handlers = {} self.signup_handlers = {} # Connect signal to remove access tokens on logout user_logged_out.connect(oauth_logout_handler) oauth = app.extensions['oauthlib.client'] # Add remote applications oauth.init_app(app) for remote_app, conf in app.config[ 'OAUTHCLIENT_REMOTE_APPS'].items(): # Prevent double creation problems if remote_app not in oauth.remote_apps: remote = oauth.remote_app( remote_app, **conf['params'] ) remote = oauth.remote_apps[remote_app] # Set token getter for remote remote.tokengetter(make_token_getter(remote)) # Register authorized handler self.handlers[remote_app] = remote.authorized_handler(make_handler( conf.get('authorized_handler', authorized_default_handler), remote, )) # Register disconnect handler self.disconnect_handlers[remote_app] = make_handler( conf.get('disconnect_handler', disconnect_handler), remote, with_response=False, ) # Register sign-up handlers def dummy_handler(remote, *args, **kargs): pass signup_handler = conf.get('signup_handler', dict()) account_info_handler = make_handler( signup_handler.get('info', dummy_handler), remote, with_response=False ) account_setup_handler = make_handler( signup_handler.get('setup', dummy_handler), remote, with_response=False ) account_view_handler = make_handler( signup_handler.get('view', dummy_handler), remote, with_response=False ) self.signup_handlers[remote_app] = dict( info=account_info_handler, setup=account_setup_handler, view=account_view_handler, )
def setup_app(): """Setup OAuth clients.""" # Connect signal to remove access tokens on logout user_logged_out.connect(oauth_logout_handler) # Add remote applications oauth.init_app(current_app) for remote_app, conf in cfg['OAUTHCLIENT_REMOTE_APPS'].items(): # Prevent double creation problems if remote_app not in oauth.remote_apps: remote = oauth.remote_app( remote_app, **conf['params'] ) remote = oauth.remote_apps[remote_app] # Set token getter for remote remote.tokengetter(make_token_getter(remote)) # Register authorized handler handlers.register( remote_app, remote.authorized_handler(make_handler( conf.get('authorized_handler', authorized_default_handler), remote, )) ) # Register disconnect handler disconnect_handlers.register( remote_app, make_handler( conf.get('disconnect_handler', disconnect_handler), remote, with_response=False, ) ) # Register sign-up handlers def dummy_handler(remote, *args, **kargs): pass signup_handler = conf.get('signup_handler', dict()) account_info_handler = make_handler( signup_handler.get('info', dummy_handler), remote, with_response=False ) account_setup_handler = make_handler( signup_handler.get('setup', dummy_handler), remote, with_response=False ) account_view_handler = make_handler( signup_handler.get('view', dummy_handler), remote, with_response=False ) signup_handlers.register( remote_app, dict( info=account_info_handler, setup=account_setup_handler, view=account_view_handler, ) )
def __init__(self, app): """Initialize state.""" self.app = app self.handlers = {} self.disconnect_handlers = {} self.signup_handlers = {} # Connect signal to remove access tokens on logout user_logged_out.connect(oauth_logout_handler) self.oauth = app.extensions.get('oauthlib.client') or FlaskOAuth() # Add remote applications self.oauth.init_app(app) for remote_app, conf in app.config['OAUTHCLIENT_REMOTE_APPS'].items(): # Prevent double creation problems if remote_app not in self.oauth.remote_apps: remote = self.oauth.remote_app(remote_app, **conf['params']) remote = self.oauth.remote_apps[remote_app] # Set token getter for remote remote.tokengetter(make_token_getter(remote)) # Register authorized handler self.handlers[remote_app] = remote.authorized_handler( make_handler( conf.get('authorized_handler', authorized_default_handler), remote, )) # Register disconnect handler self.disconnect_handlers[remote_app] = make_handler( conf.get('disconnect_handler', disconnect_handler), remote, with_response=False, ) # Register sign-up handlers def dummy_handler(remote, *args, **kargs): pass signup_handler = conf.get('signup_handler', dict()) account_info_handler = make_handler(signup_handler.get( 'info', dummy_handler), remote, with_response=False) account_setup_handler = make_handler(signup_handler.get( 'setup', dummy_handler), remote, with_response=False) account_view_handler = make_handler(signup_handler.get( 'view', dummy_handler), remote, with_response=False) self.signup_handlers[remote_app] = dict( info=account_info_handler, setup=account_setup_handler, view=account_view_handler, )
session['lang'] = reqlang else: reqlang = session.get('lang') if not reqlang: if current_user.is_authenticated: reqlang = current_user.language session['lang'] = reqlang return reqlang from flask_login import user_logged_in, user_logged_out from models import syslog def log_user_logged_in(sender, user, **extra): syslog.log(type="user logged in") session['lang'] = current_user.language def log_user_logged_out(sender, user, **extra): syslog.log(type="user logged out") syslog.syslog_init() syslog.log(type="application initialized") user_logged_in.connect(log_user_logged_in, shareds.app) user_logged_out.connect(log_user_logged_out, shareds.app) import setups
def init_security_logging(): user_logged_in.connect(log_user_logged_in) user_logged_out.connect(log_user_logged_out) user_registered.connect(log_user_registered) user_confirmed.connect(log_user_confirmed)
def __init__(self, app, remote_app_config_key, default_disconnect_handler, default_authorized_handler, default_remote_app_response_handler=None, default_response_handler=None): """Initialize state.""" self.app = app self.handlers = {} self.disconnect_handlers = {} self.signup_handlers = {} self.remote_app_response_handler = {} # Connect signal to remove access tokens on logout user_logged_out.connect(handlers.oauth_logout_handler) self.oauth = app.extensions.get('oauthlib.client') or FlaskOAuth() # Init config self.init_config(app) # Add remote applications self.oauth.init_app(app) remote_app_class = load_or_import_from_config( 'OAUTHCLIENT_REMOTE_APP', app, default=OAuthRemoteApp ) def dummy_handler(remote, *args, **kargs): pass self.default_response_handler = default_response_handler or \ dummy_handler for remote_app, conf in app.config[ remote_app_config_key].items(): # Prevent double creation problems if remote_app not in self.oauth.remote_apps: # use this app's specific remote app class if there is one. current_remote_app_class = obj_or_import_string( conf.get('remote_app'), default=remote_app_class ) # Register the remote app. We are doing this because the # current version of OAuth.remote_app does not allow to specify # the remote app class. Use it once it is fixed. self.oauth.remote_apps[remote_app] = current_remote_app_class( self.oauth, remote_app, **conf['params'] ) remote = self.oauth.remote_apps[remote_app] # Set token getter for remote remote.tokengetter(handlers.make_token_getter(remote)) # Register authorized handler self.handlers[remote_app] = handlers.authorized_handler( handlers.make_handler( conf.get( 'authorized_handler', default_authorized_handler), remote ), remote.authorized_response ) # Register disconnect handler self.disconnect_handlers[remote_app] = handlers.make_handler( conf.get('disconnect_handler', default_disconnect_handler), remote, with_response=False, ) self.remote_app_response_handler[ remote_app] = obj_or_import_string( conf.get( 'response_handler', default_remote_app_response_handler or dummy_handler)) # Register sign-up handlers signup_handler = conf.get('signup_handler', dict()) account_info_handler = handlers.make_handler( signup_handler.get('info', dummy_handler), remote, with_response=False ) account_setup_handler = handlers.make_handler( signup_handler.get('setup', dummy_handler), remote, with_response=False ) account_view_handler = handlers.make_handler( signup_handler.get('view', dummy_handler), remote, with_response=False ) self.signup_handlers[remote_app] = dict( info=account_info_handler, setup=account_setup_handler, view=account_view_handler, ) if 'cern' in self.oauth.remote_apps: warnings.warn( "CERN Remote app is deprecated, use CERN OpenID instead.", DeprecationWarning )
# def log_session_start(app, user): session = LoginSession.new() db.session.add(session) db.session.commit() def log_session_end(app, user): session = LoginSession.query.get_active_for(user) if session: session.ended_at = datetime.utcnow() db.session.commit() user_logged_in.connect(log_session_start) user_logged_out.connect(log_session_end) # login redirect utilities # from http://flask.pocoo.org/snippets/62/ def is_safe_url(target): ref_url = urlparse(request.host_url) test_url = urlparse(urljoin(request.url_root, target)) return test_url.scheme in ('http', 'https') and \ ref_url.netloc == test_url.netloc def check_for_redirect(target): target = urljoin(request.url_root, target) url = urlparse(target) reqctx = _request_ctx_stack.top
def __init__(self, app): """Initialize state.""" self.app = app self.handlers = {} self.disconnect_handlers = {} self.signup_handlers = {} # Connect signal to remove access tokens on logout user_logged_out.connect(oauth_logout_handler) self.oauth = app.extensions.get('oauthlib.client') or FlaskOAuth() # Add remote applications self.oauth.init_app(app) remote_app_class = load_or_import_from_config( 'OAUTHCLIENT_REMOTE_APP', app, default=OAuthRemoteApp ) for remote_app, conf in app.config[ 'OAUTHCLIENT_REMOTE_APPS'].items(): # Prevent double creation problems if remote_app not in self.oauth.remote_apps: # use this app's specific remote app class if there is one. current_remote_app_class = obj_or_import_string( conf.get('remote_app'), default=remote_app_class ) # Register the remote app. We are doing this because the # current version of OAuth.remote_app does not allow to specify # the remote app class. Use it once it is fixed. self.oauth.remote_apps[remote_app] = current_remote_app_class( self.oauth, remote_app, **conf['params'] ) remote = self.oauth.remote_apps[remote_app] # Set token getter for remote remote.tokengetter(make_token_getter(remote)) # Register authorized handler self.handlers[remote_app] = remote.authorized_handler(make_handler( conf.get('authorized_handler', authorized_default_handler), remote, )) # Register disconnect handler self.disconnect_handlers[remote_app] = make_handler( conf.get('disconnect_handler', disconnect_handler), remote, with_response=False, ) # Register sign-up handlers def dummy_handler(remote, *args, **kargs): pass signup_handler = conf.get('signup_handler', dict()) account_info_handler = make_handler( signup_handler.get('info', dummy_handler), remote, with_response=False ) account_setup_handler = make_handler( signup_handler.get('setup', dummy_handler), remote, with_response=False ) account_view_handler = make_handler( signup_handler.get('view', dummy_handler), remote, with_response=False ) self.signup_handlers[remote_app] = dict( info=account_info_handler, setup=account_setup_handler, view=account_view_handler, )
def init_signals(app): user_logged_in.connect(on_user_logged_in, app) user_logged_out.connect(on_user_logged_out, app) voucher_generated.connect(on_voucher_generated, app) voucher_logged_in.connect(on_voucher_logged_in, app)
def create_app(db_connection_string=None, testing=None): app = Flask(__name__) try: secret_key = faraday.server.config.faraday_server.secret_key except Exception: # Now when the config file does not exist it doesn't enter in this # condition, but it could happen in the future. TODO check save_new_secret_key(app) else: if secret_key is None: # This is what happens now when the config file doesn't exist. # TODO check save_new_secret_key(app) else: app.config['SECRET_KEY'] = secret_key if faraday.server.config.faraday_server.agent_token is None: save_new_agent_creation_token() login_failed_message = ("Invalid username or password", 'error') app.config.update({ 'SECURITY_PASSWORD_SINGLE_HASH': True, 'WTF_CSRF_ENABLED': False, 'SECURITY_USER_IDENTITY_ATTRIBUTES': ['username'], 'SECURITY_POST_LOGIN_VIEW': '/_api/session', 'SECURITY_POST_LOGOUT_VIEW': '/_api/login', 'SECURITY_POST_CHANGE_VIEW': '/_api/change', 'SECURITY_CHANGEABLE': True, 'SECURITY_SEND_PASSWORD_CHANGE_EMAIL': False, 'SECURITY_MSG_USER_DOES_NOT_EXIST': login_failed_message, 'SECURITY_TOKEN_AUTHENTICATION_HEADER': 'Authorization', # The line bellow should not be necessary because of the # CustomLoginForm, but i'll include it anyway. 'SECURITY_MSG_INVALID_PASSWORD': login_failed_message, 'SESSION_TYPE': 'filesystem', 'SESSION_FILE_DIR': faraday.server.config.FARADAY_SERVER_SESSIONS_DIR, 'SQLALCHEMY_TRACK_MODIFICATIONS': False, 'SQLALCHEMY_RECORD_QUERIES': True, # app.config['SQLALCHEMY_ECHO'] = True 'SECURITY_PASSWORD_SCHEMES': [ 'bcrypt', # This should be the default value # 'des_crypt', 'pbkdf2_sha1', # Used by CouchDB passwords # 'pbkdf2_sha256', # 'pbkdf2_sha512', # 'sha256_crypt', # 'sha512_crypt', 'plaintext', # TODO: remove it ], 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(hours=12), 'SESSION_COOKIE_NAME': 'faraday_session_2', 'SESSION_COOKIE_SAMESITE': 'Lax', }) store = FilesystemStore(app.config['SESSION_FILE_DIR']) prefixed_store = PrefixDecorator('sessions_', store) KVSessionExtension(prefixed_store, app) user_logged_out.connect(expire_session, app) storage_path = faraday.server.config.storage.path if not storage_path: logger.warn('No storage section or path in the .faraday/config/server.ini. Setting the default value to .faraday/storage') storage_path = setup_storage_path() if not DepotManager.get('default'): if testing: DepotManager.configure('default', { 'depot.storage_path': '/tmp' }) else: DepotManager.configure('default', { 'depot.storage_path': storage_path }) check_testing_configuration(testing, app) try: app.config['SQLALCHEMY_DATABASE_URI'] = db_connection_string or faraday.server.config.database.connection_string.strip("'") except AttributeError: logger.info('Missing [database] section on server.ini. Please configure the database before running the server.') except NoOptionError: logger.info('Missing connection_string on [database] section on server.ini. Please configure the database before running the server.') from faraday.server.models import db # pylint:disable=import-outside-toplevel db.init_app(app) #Session(app) # Setup Flask-Security app.user_datastore = SQLAlchemyUserDatastore( db, user_model=User, role_model=None) # We won't use flask security roles feature Security(app, app.user_datastore, login_form=CustomLoginForm) # Make API endpoints require a login user by default. Based on # https://stackoverflow.com/questions/13428708/best-way-to-make-flask-logins-login-required-the-default app.view_functions['security.login'].is_public = True app.view_functions['security.logout'].is_public = True app.debug = faraday.server.config.is_debug_mode() minify_json_output(app) for handler in LOGGING_HANDLERS: app.logger.addHandler(handler) register_blueprints(app) register_handlers(app) app.view_functions['agent_api.AgentCreationView:post'].is_public = True return app
def create_app(settings_override=None, register_security_blueprint=True): """Returns the frontend application instance""" app = factory.create_app(__name__, __path__, settings_override) app.wsgi_app = WhiteNoise(app.wsgi_app, root=app.static_folder, prefix='static/') # Init assets assets.init_app(app) webpack.init_app(app) oauth.init_app(app) menu.init_app(app) gravatar.init_app(app) userdatastore = SQLAlchemyUserDatastore(db, models.User, models.Role) security_ctx = security.init_app( app, userdatastore, login_form=DeploymentLoginForm, register_blueprint=register_security_blueprint) @security_ctx.send_mail_task def delay_flask_security_mail(msg): send_email.delay(subject=msg.subject, sender=msg.sender, recipients=msg.recipients, body=msg.body) # initialize the OpenAPI extension spec = APISpec(title='Apollo', version='1.0.0', openapi_version='3.0.2', plugins=[MarshmallowPlugin()]) app.config.update({'APISPEC_SPEC': spec}) docs.init_app(app) csrf.init_app(app) init_admin(admin, app) monitor(app) # Register custom error handlers if not app.debug: for e in [500, 404, 403]: app.register_error_handler(e, handle_error) # register deployment selection middleware app.before_request(set_request_presets) # add Jinja2 filters app.jinja_env.filters.update(custom_filters) # Login and logout signal handlers user_logged_out.connect(clear_session) @identity_loaded.connect_via(app) def on_identity_loaded(sender, identity): if current_user.is_authenticated: user = current_user._get_current_object() needs = services.users.get_permissions_cache(user) for need in needs: identity.provides.add(need) @app.context_processor def inject_permissions(): ga_key = app.config.get('GOOGLE_ANALYTICS_KEY') gtm_key = app.config.get('GOOGLE_TAG_MANAGER_KEY') return dict(perms=permissions, ga_key=ga_key, gtm_key=gtm_key) # clickjacking protection @app.after_request def frame_buster(response): response.headers['X-Frame-Options'] = app.config.get( 'X_FRAME_OPTIONS', 'DENY') return response # content security policy @app.after_request def content_security_policy(response): response.headers['Content-Security-Policy'] = "default-src 'self' " + \ "*.googlecode.com *.google-analytics.com fonts.gstatic.com fonts.googleapis.com " + \ "*.googletagmanager.com " + \ "cdn.heapanalytics.com heapanalytics.com " + \ "'unsafe-inline' 'unsafe-eval' data:; img-src * data:" return response def handle_authorize(remote, token, user_info): if user_info and 'email' in user_info: user = models.User.query.filter_by( email=user_info['email']).first() if user: login_user(user) userdatastore.commit() return redirect(app.config.get('SECURITY_POST_LOGIN_VIEW')) return redirect(url_for_security('login')) @app.template_global() def modify_query(**values): args = request.args.copy() for k, v in values.items(): if not v: _ = args.pop(k, None) else: args[k] = v return '{}?{}'.format(request.path, url_encode(args)) facebook_bp = create_flask_blueprint(Facebook, oauth, handle_authorize) google_bp = create_flask_blueprint(Google, oauth, handle_authorize) if app.config.get('ENABLE_SOCIAL_LOGIN', False): app.register_blueprint(facebook_bp, url_prefix='/facebook') app.register_blueprint(google_bp, url_prefix='/google') return app
def setUp(self): self.clean_db() self.current_user = None user_logged_in.connect(self._signal_login) user_logged_out.connect(self._signal_logout)