diff --git a/mellon/adapters.py b/mellon/adapters.py index 8f3f93a..6970936 100644 --- a/mellon/adapters.py +++ b/mellon/adapters.py @@ -36,7 +36,7 @@ class DefaultAdapter(object): else: for extra_idp in self.get_identity_providers_setting(): if extra_idp.get('ENTITY_ID') == entity_id or \ - idp_metadata_extract_entity_id(extra_idp) == entity_id: + idp_metadata_extract_entity_id(extra_idp.get('METADATA')) == entity_id: idp = extra_idp.copy() extra_idp_settings = idp_settings_load(entity_id) diff --git a/mellon/federation_utils.py b/mellon/federation_utils.py index 2484c1a..83e89f9 100644 --- a/mellon/federation_utils.py +++ b/mellon/federation_utils.py @@ -38,8 +38,9 @@ def load_federation_cache(url): path = os.path.join('metadata-cache', filename) unix_path = default_storage.path(path) - if not os.path.exists('metadata-cache'): - os.makedirs('metadata-cache') + dirname = os.path.dirname(unix_path) + if not os.path.exists(dirname): + os.makedirs(dirname) f = open(unix_path, 'w') try: fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB) @@ -74,23 +75,25 @@ def load_federation_cache(url): def get_federation_from_url(url, update_cache=False): logger = logging.getLogger(__name__) filename = url2filename(url) - path = os.path.join('metadata-cache', filename) - if not default_storage.exists(path) or update_cache or \ - default_storage.created_time(path) < datetime.now() - timedelta(days=1): + filepath = os.path.join('metadata-cache', filename) + if not default_storage.exists(filepath) or update_cache or \ + default_storage.created_time(filepath) < datetime.now() - timedelta(days=1): load_federation_cache(url) else: logger.warning('federation %s has not been loaded', url) - return path + return default_storage.path(filepath) def idp_metadata_filepath(entity_id): filename = url2filename(entity_id) - return os.path.join('./metadata-cache', filename) + filepath = os.path.join('./metadata-cache', filename) + return filepath def idp_settings_filepath(entity_id): filename = url2filename(entity_id) + "_settings.json" - return os.path.join('./metadata-cache', filename) + filepath = os.path.join('./metadata-cache', filename) + return filepath def idp_metadata_is_cached(entity_id): @@ -132,8 +135,13 @@ def idp_metadata_store(metadata_content): return logger = logging.getLogger(__name__) filepath = idp_metadata_filepath(entity_id) + + dirname = os.path.dirname(filepath) + if not default_storage.exists(dirname): + os.makedirs(default_storage.path(dirname)) + if idp_metadata_needs_refresh(entity_id): - with open(filepath, 'w') as f: + with open(default_storage.path(filepath), 'w') as f: try: fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB) f.write(metadata_content) @@ -142,7 +150,7 @@ def idp_metadata_store(metadata_content): logger.error('Couldn\'t store metadata for EntityID %r', entity_id) return - return filepath + return default_storage.path(filepath) def idp_metadata_load(entity_id): @@ -150,7 +158,7 @@ def idp_metadata_load(entity_id): filepath = idp_metadata_filepath(entity_id) if default_storage.exists(filepath): logger.info('Loading metadata for EntityID %r', entity_id) - with open(filepath, 'r') as f: + with open(default_storage.path(filepath), 'r') as f: return f.read() else: logger.warning('No metadata file for EntityID %r', entity_id) @@ -168,12 +176,16 @@ def idp_settings_store(idp): if not entity_id: return + dirname = os.path.dirname(filepath) + if not default_storage.exists(dirname): + os.makedirs(default_storage.path(dirname)) + for key, value in idp.items(): if key not in ('METADATA', 'ENTITY_ID'): idp_settings.update({key: value}) if idp_settings_needs_refresh(entity_id) and idp_settings: - with open(filepath, 'w') as f: + with open(default_storage.path(filepath), 'w') as f: try: fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB) f.write(json.dumps(idp_settings)) @@ -181,8 +193,6 @@ def idp_settings_store(idp): except: logger.error('Couldn\'t store settings for EntityID %r', entity_id) - return - return filepath def idp_settings_load(entity_id): @@ -190,7 +200,7 @@ def idp_settings_load(entity_id): filepath = idp_settings_filepath(entity_id) if default_storage.exists(filepath): logger.info('Loading JSON settings for EntityID %r', entity_id) - with open(filepath, 'r') as f: + with open(default_storage.path(filepath), 'r') as f: try: idp_settings = json.loads(f.read()) except: diff --git a/tests/conftest.py b/tests/conftest.py index bfa8788..82a7fb9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -42,3 +42,10 @@ def caplog(caplog): caplog.handler.stream = py.io.TextIO() caplog.handler.records = [] return caplog + + +# XXX temporary workaround +# non-federated IdPs shouldn't have their MD cached +@pytest.fixture(autouse=True) +def mellon_settings(settings, tmpdir): + settings.MEDIA_ROOT = str(tmpdir) diff --git a/tests/test_default_adapter.py b/tests/test_default_adapter.py index e2a6088..78ca071 100644 --- a/tests/test_default_adapter.py +++ b/tests/test_default_adapter.py @@ -89,7 +89,7 @@ def test_provision_user_attributes(settings, django_user_model, caplog): assert user.email == 'test@example.net' assert user.is_superuser is False assert user.is_staff is False - assert len(caplog.records) == 6 + assert len(caplog.records) == 5 assert 'created new user' in caplog.text assert 'set field first_name' in caplog.text assert 'set field last_name' in caplog.text @@ -102,7 +102,7 @@ def test_provision_user_groups(settings, django_user_model, caplog): user = SAMLBackend().authenticate(saml_attributes=saml_attributes) assert user.groups.count() == 3 assert set(user.groups.values_list('name', flat=True)) == set(saml_attributes['group']) - assert len(caplog.records) == 6 + assert len(caplog.records) == 5 assert 'created new user' in caplog.text assert 'adding group GroupA' in caplog.text assert 'adding group GroupB' in caplog.text @@ -112,7 +112,7 @@ def test_provision_user_groups(settings, django_user_model, caplog): user = SAMLBackend().authenticate(saml_attributes=saml_attributes2) assert user.groups.count() == 2 assert set(user.groups.values_list('name', flat=True)) == set(saml_attributes2['group']) - assert len(caplog.records) == 9 + assert len(caplog.records) == 7 assert 'removing group GroupA' in caplog.records[-1].message @@ -142,7 +142,7 @@ def test_provision_absent_attribute(settings, django_user_model, caplog): del local_saml_attributes['email'] user = SAMLBackend().authenticate(saml_attributes=local_saml_attributes) assert not user.email - assert len(caplog.records) == 6 + assert len(caplog.records) == 5 assert 'created new user' in caplog.text assert re.search(r'invalid reference.*email', caplog.text) assert 'set field first_name' in caplog.text @@ -160,7 +160,7 @@ def test_provision_long_attribute(settings, django_user_model, caplog): local_saml_attributes['first_name'] = [('y' * 32)] user = SAMLBackend().authenticate(saml_attributes=local_saml_attributes) assert user.first_name == 'y' * 30 - assert len(caplog.records) == 6 + assert len(caplog.records) == 5 assert 'created new user' in caplog.text assert 'set field first_name' in caplog.text assert 'to value %r ' % (u'y' * 30) in caplog.text diff --git a/tests/test_federations_utils.py b/tests/test_federations_utils.py index 5a101e0..f939c70 100644 --- a/tests/test_federations_utils.py +++ b/tests/test_federations_utils.py @@ -1,6 +1,7 @@ import os import time +from django.core.files.storage import default_storage from django.utils.text import slugify from httmock import HTTMock @@ -10,15 +11,12 @@ from utils import sample_federation_response def test_mock_fedmd_caching(): url = u'https://dummy.mdserver/metadata.xml' - filepath = os.path.join('metadata-cache/', truncate_unique(slugify(url))) - - if os.path.isfile(filepath): - os.remove(filepath) + filepath = default_storage.path(os.path.join('metadata-cache/', truncate_unique(slugify(url)))) with HTTMock(sample_federation_response): tmp = get_federation_from_url(url) - assert tmp == filepath + assert default_storage.path(tmp) == filepath st = os.stat(filepath) @@ -35,5 +33,3 @@ def test_mock_fedmd_caching(): storig = os.stat(os.path.join('tests', 'federation-sample.xml')) assert storig.st_size == st.st_size - - os.remove(filepath)