Skip to content

Commit

Permalink
fix problem with non-standard OA ScopedUIInfo, close #287
Browse files Browse the repository at this point in the history
  • Loading branch information
enriquepablo committed Jan 13, 2025
1 parent b392203 commit f939db3
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 16 deletions.
6 changes: 3 additions & 3 deletions src/pyff/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,14 +844,14 @@ def select(req: Plumbing.Request, *opts):
def _strings(elt):
lst = []
for attr in [
'{%s}DisplayName' % NS['mdui'],
'.//{%s}UIInfo/{%s}DisplayName' % (NS['mdui'], NS['mdui']),
'{%s}ServiceName' % NS['md'],
'{%s}OrganizationDisplayName' % NS['md'],
'{%s}OrganizationName' % NS['md'],
'{%s}Keywords' % NS['mdui'],
'.//{%s}UIInfo/{%s}Keywords' % (NS['mdui'], NS['mdui']),
'{%s}Scope' % NS['shibmd'],
]:
lst.extend([s.text for s in elt.iter(attr)])
lst.extend([s.text for s in elt.iterfind(attr)])
lst.append(elt.get('entityID'))
return [item for item in lst if item is not None]

Expand Down
20 changes: 10 additions & 10 deletions src/pyff/samlmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,12 +698,12 @@ def gen_icon(e):


def entity_icon_url(e, langs=None):
for ico in filter_lang(e.iter("{%s}Logo" % NS['mdui']), langs=langs):
for ico in filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Logo" % (NS['mdui'], NS['mdui'])), langs=langs):
return dict(url=ico.text, width=ico.get('width'), height=ico.get('height'))


def privacy_statement_url(entity, langs):
for url in filter_lang(entity.iter("{%s}PrivacyStatementURL" % NS['mdui']), langs=langs):
for url in filter_lang(entity.iterfind(".//{%s}UIInfo/{%s}PrivacyStatementURL" % (NS['mdui'], NS['mdui'])), langs=langs):
return url.text


Expand Down Expand Up @@ -732,12 +732,12 @@ def entity_extended_display_i18n(entity, default_lang=None):
)
name_dict.update(lang_dict(entity.iter("{%s}ServiceName" % NS['md']), lambda e: e.text, default_lang=default_lang))
name_dict.update(
lang_dict(entity.iter("{%s}DisplayName" % NS['mdui']), lambda e: e.text, default_lang=default_lang)
lang_dict(entity.iterfind(".//{%s}UIInfo/{%s}DisplayName" % (NS['mdui'], NS['mdui'])), lambda e: e.text, default_lang=default_lang)
)

desc_dict = lang_dict(entity.iter("{%s}OrganizationURL" % NS['md']), lambda e: e.text, default_lang=default_lang)
desc_dict.update(
lang_dict(entity.iter("{%s}Description" % NS['mdui']), lambda e: e.text, default_lang=default_lang)
lang_dict(entity.iterfind(".//{%s}UIInfo/{%s}Description" % (NS['mdui'], NS['mdui'])), lambda e: e.text, default_lang=default_lang)
)

return name_dict, desc_dict
Expand Down Expand Up @@ -825,7 +825,7 @@ def entity_extended_display(entity, langs=None):
display = serviceName.text
break

for displayName in filter_lang(entity.iter("{%s}DisplayName" % NS['mdui']), langs=langs):
for displayName in filter_lang(entity.iterfind(".//{%s}UIInfo/{%s}DisplayName" % (NS['mdui'], NS['mdui'])), langs=langs):
info = display
display = displayName.text
break
Expand All @@ -834,7 +834,7 @@ def entity_extended_display(entity, langs=None):
info = organizationUrl.text
break

for description in filter_lang(entity.iter("{%s}Description" % NS['mdui']), langs=langs):
for description in filter_lang(entity.iterfind(".//{%s}UIInfo/{%s}Description" % (NS['mdui'], NS['mdui'])), langs=langs):
info = description.text
break

Expand All @@ -850,7 +850,7 @@ def entity_display_name(entity: Element, langs=None) -> str:
:param entity: An EntityDescriptor element
:param langs: The list of languages to search in priority order
"""
for displayName in filter_lang(entity.iter("{%s}DisplayName" % NS['mdui']), langs=langs):
for displayName in filter_lang(entity.iterfind(".//{%s}UIInfo/{%s}DisplayName" % (NS['mdui'], NS['mdui'])), langs=langs):
return displayName.text.strip()

for serviceName in filter_lang(entity.iter("{%s}ServiceName" % NS['md']), langs=langs):
Expand Down Expand Up @@ -946,7 +946,7 @@ def discojson(e, sources=None, langs=None, fallback_to_favicon=False, icon_store
icon_info['url'] = ico
d['entity_icon_url'] = icon_info

keywords = filter_lang(e.iter("{%s}Keywords" % NS['mdui']), langs=langs)
keywords = filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Keywords" % (NS['mdui'], NS['mdui'])), langs=langs)
if keywords is not None:
lst = [elt.text for elt in keywords]
if len(lst) > 0:
Expand Down Expand Up @@ -1223,7 +1223,7 @@ def entity_simple_info(e, langs=None):
d['service_name'] = entity_service_name(e, langs)
d['service_descr'] = entity_service_description(e, langs)
d['entity_attributes'] = entity_attribute_dict(e)
keywords = filter_lang(e.iter("{%s}Keywords" % NS['mdui']), langs=langs)
keywords = filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Keywords" % (NS['mdui'], NS['mdui'])), langs=langs)
if keywords is not None:
lst = [elt.text for elt in keywords]
if len(lst) > 0:
Expand All @@ -1233,7 +1233,7 @@ def entity_simple_info(e, langs=None):

def entity_info(e, langs=None):
d = entity_simple_summary(e)
keywords = filter_lang(e.iter("{%s}Keywords" % NS['mdui']), langs=langs)
keywords = filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Keywords" % (NS['mdui'], NS['mdui'])), langs=langs)
if keywords is not None:
lst = [elt.text for elt in keywords]
if len(lst) > 0:
Expand Down
6 changes: 3 additions & 3 deletions src/pyff/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,14 +413,14 @@ def search(self, query=None, path=None, entity_filter=None, related=None):
def _strings(elt):
lst = []
for attr in [
'{%s}DisplayName' % NS['mdui'],
'.//{%s}UIInfo/{%s}DisplayName' % (NS['mdui'], NS['mdui']),
'{%s}ServiceName' % NS['md'],
'{%s}OrganizationDisplayName' % NS['md'],
'{%s}OrganizationName' % NS['md'],
'{%s}Keywords' % NS['mdui'],
'.//{%s}UIInfo/{%s}Keywords' % (NS['mdui'], NS['mdui']),
'{%s}Scope' % NS['shibmd'],
]:
lst.extend([s.text for s in elt.iter(attr)])
lst.extend([s.text for s in elt.iterfind(attr)])
lst.append(elt.get('entityID'))
return [item for item in lst if item is not None]

Expand Down
60 changes: 60 additions & 0 deletions src/pyff/test/data/metadata/test-scoped-display-name.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
entityID="https://idp.example.com/saml2/idp/metadata.php"
xmlns:oaf="http://schemas.eduserv.org.uk/openathens-federation/1.0" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:Extensions>
<shibmd:Scope regexp="false">example.com</shibmd:Scope>
<shibmd:Scope regexp="false">81098135.example.com</shibmd:Scope>
<oaf:ScopedUIInfo scope="81098135.example.com">
<mdui:DisplayName xml:lang="sv">Scoped Example Universitet</mdui:DisplayName>
<mdui:DisplayName xml:lang="en">Scoped Example University</mdui:DisplayName>
</oaf:ScopedUIInfo>
<mdui:UIInfo>
<mdui:DisplayName xml:lang="sv">Example universitet</mdui:DisplayName>
<mdui:DisplayName xml:lang="en">Example University</mdui:DisplayName>
<mdui:Description xml:lang="sv">Identity Provider för Example universitet</mdui:Description>
<mdui:Description xml:lang="en">Identity Provider for Example University</mdui:Description>
<mdui:InformationURL xml:lang="sv">http://www.example.com/</mdui:InformationURL>
<mdui:InformationURL xml:lang="en">http://www.example.com/english/</mdui:InformationURL>
<mdui:Logo height="63" width="358">https://www.example.com/static/images/umu_logo.jpg</mdui:Logo>
<mdui:Logo xml:lang="sv" height="63" width="358">https://www.example.com/static/images/logo.jpg</mdui:Logo>
<mdui:Logo xml:lang="en" height="63" width="350">https://www.example.com/static/images/logo_eng.jpg</mdui:Logo>
<mdui:Keywords xml:lang="sv">exempel</mdui:Keywords>
<mdui:Keywords xml:lang="en">example</mdui:Keywords>
</mdui:UIInfo>
<mdui:DiscoHints xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
<mdui:DomainHint>example.com</mdui:DomainHint>
<mdui:DomainHint>example.net</mdui:DomainHint>
<mdui:IPHint>10.0.0.0/8</mdui:IPHint>
</mdui:DiscoHints>
</md:Extensions>
<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.com/saml2/idp/ArtifactResolutionService.php" index="0"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.com/saml2/idp/SingleLogoutService.php"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.com/saml2/idp/SSOService.php"/>
</md:IDPSSODescriptor>
<md:Organization>
<md:OrganizationName xml:lang="sv">ExempelU</md:OrganizationName>
<md:OrganizationName xml:lang="en">ExampleU</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="sv">Exempel Universitetet</md:OrganizationDisplayName>
<md:OrganizationDisplayName xml:lang="en">The Example University</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="sv">http://www.example.com</md:OrganizationURL>
<md:OrganizationURL xml:lang="en">http://www.example.com/english</md:OrganizationURL>
</md:Organization>
<md:ContactPerson contactType="administrative">
<md:Company>Example University</md:Company>
<md:SurName>Example helpdesk</md:SurName>
<md:EmailAddress>[email protected]</md:EmailAddress>
</md:ContactPerson>
<md:ContactPerson contactType="technical">
<md:Company>Example University</md:Company>
<md:SurName>Example helpdesk</md:SurName>
<md:EmailAddress>[email protected]</md:EmailAddress>
</md:ContactPerson>
<md:ContactPerson contactType="support">
<md:Company>Example University</md:Company>
<md:SurName>Servicedesk Example universitet</md:SurName>
<md:EmailAddress>[email protected]</md:EmailAddress>
</md:ContactPerson>
</md:EntityDescriptor>
33 changes: 33 additions & 0 deletions src/pyff/test/test_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,3 +795,36 @@ def test_discojson_sp_trustinfo_in_attr(self):
pass
finally:
shutil.rmtree(tmpdir)

def test_discojson_scoped_display_name(self):
with patch.multiple("sys", exit=self.sys_exit):
tmpdir = tempfile.mkdtemp()
os.rmdir(tmpdir) # lets make sure 'store' can recreate it
try:
self.exec_pipeline("""
- load:
- file://%s/metadata/test-scoped-display-name.xml
- select
- discojson
- publish:
output: %s/disco.json
raw: true
update_store: false
""" % (self.datadir, tmpdir))
fn = "%s/disco.json" % tmpdir
assert os.path.exists(fn)
with open(fn, 'r') as f:
idps_json = json.load(f)

idp_json = idps_json[0]
assert idp_json['title'] == 'Example University'
assert idp_json['title_langs']['sv'] == 'Example universitet'
assert idp_json['title_langs']['en'] == 'Example University'
assert idp_json['descr'] == 'Identity Provider for Example University'
assert idp_json['descr_langs']['sv'] == 'Identity Provider för Example universitet'
assert idp_json['descr_langs']['en'] == 'Identity Provider for Example University'
assert idp_json['keywords'] == 'example'
except IOError:
pass
finally:
shutil.rmtree(tmpdir)

0 comments on commit f939db3

Please sign in to comment.