def test_handle_auth_error(mocker): flash = mocker.patch("flask_multipass.core.flash") app = Flask("test") app.config["SECRET_KEY"] = "testing" multipass = Multipass(app) with app.test_request_context(): multipass.handle_auth_error(AuthenticationFailed()) assert flash.called assert session["_multipass_auth_failed"]
def test_handle_auth_error(mocker): flash = mocker.patch('flask_multipass.core.flash') app = Flask('test') app.config['SECRET_KEY'] = 'testing' multipass = Multipass(app) with app.test_request_context(): multipass.handle_auth_error(AuthenticationFailed()) assert flash.called assert session['_multipass_auth_failed']
def test_multiple_apps(): apps = Flask('test'), Flask('test') multipass = Multipass() for app in apps: multipass.init_app(app) # The separate loop here is on purpose as the extension needs to # be present on all apps after initializing them for app in apps: assert app.extensions['multipass'].multipass is multipass
def test_multiple_apps(): apps = Flask("test"), Flask("test") multipass = Multipass() for app in apps: multipass.init_app(app) # The separate loop here is on purpose as the extension needs to # be present on all apps after initializing them for app in apps: assert app.extensions["multipass"].multipass is multipass
def test_handle_auth_error_with_redirect(mocker): flash = mocker.patch('flask_multipass.core.flash') redirect = mocker.patch('flask_multipass.core.redirect') app = Flask('test') app.config['SECRET_KEY'] = 'testing' multipass = Multipass(app) with app.test_request_context(): multipass.handle_auth_error(AuthenticationFailed(), redirect_to_login=True) assert flash.called redirect.assert_called_with(app.config['MULTIPASS_LOGIN_URLS'][0])
def test_handle_auth_error_with_redirect(mocker): flash = mocker.patch("flask_multipass.core.flash") redirect = mocker.patch("flask_multipass.core.redirect") app = Flask("test") app.config["SECRET_KEY"] = "testing" multipass = Multipass(app) with app.test_request_context(): multipass.handle_auth_error(AuthenticationFailed(), redirect_to_login=True) assert flash.called redirect.assert_called_with(app.config["MULTIPASS_LOGIN_URLS"][0])
def test_next_url_invalid(): app = Flask('test') app.add_url_rule('/success', 'success') app.config['SECRET_KEY'] = 'testing' app.config['MULTIPASS_SUCCESS_ENDPOINT'] = 'success' multipass = Multipass(app) with app.test_request_context(): request.args = {'next': '//evil.com'} multipass.set_next_url() assert multipass._get_next_url() == '/success'
def test_render_template(mocker): render_template = mocker.patch('flask_multipass.core.render_template') app = Flask('test') app.config['MULTIPASS_FOO_TEMPLATE'] = None app.config['MULTIPASS_BAR_TEMPLATE'] = 'bar.html' multipass = Multipass(app) with app.app_context(): with pytest.raises(RuntimeError): multipass.render_template('FOO', foo='bar') multipass.render_template('BAR', foo='bar') render_template.assert_called_with('bar.html', foo='bar')
def test_render_template(mocker): render_template = mocker.patch("flask_multipass.core.render_template") app = Flask("test") app.config["MULTIPASS_FOO_TEMPLATE"] = None app.config["MULTIPASS_BAR_TEMPLATE"] = "bar.html" multipass = Multipass(app) with app.app_context(): with pytest.raises(RuntimeError): multipass.render_template("FOO", foo="bar") multipass.render_template("BAR", foo="bar") render_template.assert_called_with("bar.html", foo="bar")
def test_get_state_explicit(): app = Flask('test') app2 = Flask('test2') multipass = Multipass() multipass.init_app(app) multipass.init_app(app2) # outside app ctx with pytest.raises(RuntimeError): assert get_state().app # explicit app assert get_state(app2).app is app2 # explicit app inside other app context (unlikely) with app.app_context(): assert get_state(app2).app is app2
def test_login_finished(): multipass = Multipass() with pytest.raises(AssertionError): multipass.login_finished(None) callback = Mock() multipass.identity_handler(callback) multipass.login_finished('foo') callback.assert_called_with('foo')
def test_get_members(mocker, settings, group_dn, mock_data, expected): mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject') mocker.patch( 'flask_multipass.providers.ldap.providers.build_group_search_filter', side_effect=MagicMock(side_effect=mock_data['groups'])) mocker.patch( 'flask_multipass.providers.ldap.providers.build_user_search_filter', side_effect=MagicMock(side_effect=mock_data['groups'])) app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', settings) idp._search_groups = MagicMock( side_effect=lambda x: mock_data['subgroups'].get(x, [])) idp._search_users = MagicMock( side_effect=lambda x: mock_data['users'].get(x, [])) group = LDAPGroup(idp, 'LDAP test group', group_dn) with pytest.raises(StopIteration): members = group.get_members() while True: member = next(members) assert member.provider.name == idp.name assert member.identifier == expected.pop(0)
def test_map_search_criteria(criteria, mapping, result): app = Flask('test') Multipass(app) with app.app_context(): settings = {'mapping': mapping} provider = IdentityProvider(None, 'foo', settings) assert provider.map_search_criteria(criteria) == result
def test_login_view(mocker): handle_auth_error = mocker.patch.object(Multipass, 'handle_auth_error') app = Flask('test') e = AuthenticationFailed() @app.route('/ok') @login_view def ok(): return '' @app.route('/err') @login_view def err(): raise Exception @app.route('/fail') @login_view def fail(): raise e Multipass(app) with app.test_client() as c: c.get('/ok') assert not handle_auth_error.called c.get('/err') assert not handle_auth_error.called c.get('/fail') handle_auth_error.assert_called_with(e, True)
def test_create_login_rule(mocker): process_login = mocker.patch.object(Multipass, 'process_login') app = Flask('test') Multipass(app) with app.test_client() as c: for url in app.config['MULTIPASS_LOGIN_URLS']: c.get(url) assert process_login.call_count == 2
def test_get_state(): app = Flask('test') multipass = Multipass(app) with app.app_context(): state = get_state(app) assert state.multipass is multipass assert state.app is app assert get_state(app) is state
def test_settings_copied(): app = Flask('test') Multipass(app) with app.app_context(): settings = {'foo': 'bar'} provider = IdentityProvider(None, None, settings) provider.settings['foo'] = 'foobar' assert settings['foo'] == 'bar'
def test_create_login_rule_disabled(mocker): process_login = mocker.patch.object(Multipass, 'process_login') app = Flask('test') app.config['MULTIPASS_LOGIN_URLS'] = None Multipass(app) with app.test_client() as c: for url in ('/login/', '/login/<provider>'): assert c.get(url).status_code == 404 assert not process_login.called
def test_default_idp_settings(mocker, required_settings, expected_settings): certifi = mocker.patch('flask_multipass.providers.ldap.providers.certifi') certifi.where.return_value = '/default/ca-certs-file' app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', {'ldap': required_settings}) assert idp.ldap_settings == expected_settings
def test_initialize_providers_unique(): app = Flask('test') app.config['MULTIPASS_AUTH_PROVIDERS'] = { 'test': {'type': 'unique', 'foo': 'bar'}, 'test2': {'type': 'unique', 'hello': 'world'}, } multipass = Multipass() multipass.register_provider(FooProvider, 'foo') multipass.register_provider(UniqueProvider, 'unique') with pytest.raises(RuntimeError): multipass.init_app(app)
def test_login_finished(): multipass = Multipass() with pytest.raises(AssertionError): multipass.login_finished(None) callback = Mock() multipass.identity_handler(callback) multipass.login_finished("foo") callback.assert_called_with("foo")
def test_has_member_bad_identifier(mocker, settings): mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject') app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', settings) group = LDAPGroup(idp, 'LDAP test group', 'group_dn') with pytest.raises(IdentityRetrievalFailed): group.has_member(None)
def test_next_url(): app = Flask('test') app.add_url_rule('/success', 'success') app.config['SECRET_KEY'] = 'testing' app.config['MULTIPASS_SUCCESS_ENDPOINT'] = 'success' multipass = Multipass(app) with app.test_request_context(): # default url - not in session assert multipass._get_next_url() == '/success' multipass.set_next_url() # default url - in session assert multipass._get_next_url() == '/success' request.args = {'next': '/private'} # next url specified, but not in session yet assert multipass._get_next_url() == '/success' multipass.set_next_url() # removed from session after retrieving it once assert multipass._get_next_url() == '/private' assert multipass._get_next_url() == '/success'
def test_has_member_slapd(mocker, settings, group_dn, user_mock, expected): mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject') mocker.patch('flask_multipass.providers.ldap.providers.get_user_by_id', return_value=(user_mock['dn'], user_mock['data'])) app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', settings) group = LDAPGroup(idp, 'LDAP test group', group_dn) assert group.has_member(user_mock['data']['uid'][0]) == expected
def test_has_member_unknown_user(mocker, settings): mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject') mocker.patch('flask_multipass.providers.ldap.providers.get_user_by_id', return_value=(None, { 'cn': ['Configuration'] })) app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', settings) group = LDAPGroup(idp, 'LDAP test group', 'group_dn') assert not group.has_member('unknown_user')
def test_initialize_providers_unique(): app = Flask("test") app.config["MULTIPASS_AUTH_PROVIDERS"] = { "test": {"type": "unique", "foo": "bar"}, "test2": {"type": "unique", "hello": "world"}, } multipass = Multipass() multipass.register_provider(FooProvider, "foo") multipass.register_provider(UniqueProvider, "unique") with pytest.raises(RuntimeError): multipass.init_app(app)
def test_next_url(): app = Flask('test') app.add_url_rule('/success', 'success') app.config['SECRET_KEY'] = 'testing' app.config['MULTIPASS_SUCCESS_ENDPOINT'] = 'success' multipass = Multipass(app) with app.test_request_context(): # default url - not in session assert multipass._get_next_url() == '/success' multipass._set_next_url() # default url - in session assert multipass._get_next_url() == '/success' request.args = {'next': '/private'} # next url specified, but not in session yet assert multipass._get_next_url() == '/success' multipass._set_next_url() # removed from session after retrieving it once assert multipass._get_next_url() == '/private' assert multipass._get_next_url() == '/success'
def test_next_url(): app = Flask("test") app.add_url_rule("/success", "success") app.config["SECRET_KEY"] = "testing" app.config["MULTIPASS_SUCCESS_ENDPOINT"] = "success" multipass = Multipass(app) with app.test_request_context(): # default url - not in session assert multipass._get_next_url() == "/success" multipass.set_next_url() # default url - in session assert multipass._get_next_url() == "/success" request.args = {"next": "/private"} # next url specified, but not in session yet assert multipass._get_next_url() == "/success" multipass.set_next_url() # removed from session after retrieving it once assert multipass._get_next_url() == "/private" assert multipass._get_next_url() == "/success"
def test_initialize_providers(): app = Flask('test') app.config['MULTIPASS_AUTH_PROVIDERS'] = { 'test': {'type': 'foo', 'foo': 'bar'}, 'test2': {'type': 'unique', 'hello': 'world'}, } multipass = Multipass() multipass.register_provider(FooProvider, 'foo') multipass.register_provider(UniqueProvider, 'unique') with app.app_context(): auth_providers = multipass._create_providers('AUTH', AuthProvider) assert auth_providers['test'].settings == {'foo': 'bar'} assert auth_providers['test2'].settings == {'hello': 'world'}
def test_iter_group(mocker, settings, group_dn, subgroups, expected): app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', settings) group = LDAPGroup(idp, 'LDAP test group', group_dn) visited_groups = [] iter_group = group._iter_group() # should not throw StopIteration as the initial group dn must be returned first current_dn = next(iter_group) with pytest.raises(StopIteration): while current_dn: visited_groups.append(current_dn) current_dn = iter_group.send(subgroups.get(current_dn, [])) assert len(visited_groups) == len(expected) assert set(visited_groups) == expected
def test_initialize_providers(): app = Flask("test") app.config["MULTIPASS_AUTH_PROVIDERS"] = { "test": {"type": "foo", "foo": "bar"}, "test2": {"type": "unique", "hello": "world"}, } multipass = Multipass() multipass.register_provider(FooProvider, "foo") multipass.register_provider(UniqueProvider, "unique") with app.app_context(): auth_providers = multipass._create_providers("AUTH", AuthProvider) assert auth_providers["test"].settings == {"foo": "bar"} assert auth_providers["test2"].settings == {"hello": "world"}
def test_has_member_ad(mocker, settings, group_mock, user_mock, expected): def get_token_groups(user_dn): if user_mock['dn'] != user_dn: pytest.fail('expected {0}, got {1}'.format(user_mock['dn'], user_dn)) return user_mock['token_groups'] mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject') mocker.patch('flask_multipass.providers.ldap.providers.get_user_by_id', return_value=(user_mock['dn'], user_mock['data'])) mocker.patch('flask_multipass.providers.ldap.providers.get_group_by_id', return_value=(group_mock['dn'], group_mock['data'])) mocker.patch( 'flask_multipass.providers.ldap.providers.get_token_groups_from_user_dn', side_effect=get_token_groups) app = Flask('test') multipass = Multipass(app) with app.app_context(): idp = LDAPIdentityProvider(multipass, 'LDAP test idp', settings) group = LDAPGroup(idp, 'LDAP test group', group_mock['dn']) assert group.has_member(user_mock['data']['uid'][0]) == expected
def test_login_finished_returns(): multipass = Multipass() multipass.identity_handler(Mock(return_value='bar')) assert multipass.login_finished('foo') == 'bar'
def test_login_check(): multipass = Multipass() callback = Mock() assert multipass.login_check(callback) is callback
def test_identity_handler(): multipass = Multipass() callback = Mock() assert multipass.identity_handler(callback) is callback
def test_init_app_twice(): multipass = Multipass() app = Flask("test") multipass.init_app(app) with pytest.raises(RuntimeError): multipass.init_app(app)
def test_validate_next_url(url, valid): app = Flask('test') multipass = Multipass(app) with app.test_request_context(): assert multipass.validate_next_url(url) == valid
from __future__ import unicode_literals import json from flask import Flask, render_template, flash, session, url_for, redirect, request, g from flask_sqlalchemy import SQLAlchemy from flask_multipass import Multipass from flask_multipass.providers.sqlalchemy import SQLAlchemyAuthProviderBase, SQLAlchemyIdentityProviderBase application = app = Flask(__name__) app.debug = True app.secret_key = 'fma-example' db = SQLAlchemy() multipass = Multipass() class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String) email = db.Column(db.String) affiliation = db.Column(db.String) class Identity(db.Model): __tablename__ = 'identities' id = db.Column(db.Integer, primary_key=True)
def test_init_app_twice(): multipass = Multipass() app = Flask('test') multipass.init_app(app) with pytest.raises(RuntimeError): multipass.init_app(app)
def test_init_app_late(): app = Flask('text') multipass = Multipass() multipass.init_app(app) assert app.extensions['multipass'].multipass is multipass
def test_init_app_late(): app = Flask("text") multipass = Multipass() multipass.init_app(app) assert app.extensions["multipass"].multipass is multipass
def test_login_finished_returns(): multipass = Multipass() multipass.identity_handler(Mock(return_value="bar")) assert multipass.login_finished("foo") == "bar"
def test_init_app_immediately(): app = Flask('test') multipass = Multipass(app) assert app.extensions['multipass'].multipass is multipass