Skip to content

Commit fd893c6

Browse files
committed
fix problem with non-standard OA ScopedUIInfo, close #287
1 parent f733b10 commit fd893c6

File tree

5 files changed

+109
-16
lines changed

5 files changed

+109
-16
lines changed

src/pyff/builtins.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -844,14 +844,14 @@ def select(req: Plumbing.Request, *opts):
844844
def _strings(elt):
845845
lst = []
846846
for attr in [
847-
'{%s}DisplayName' % NS['mdui'],
847+
'.//{%s}UIInfo/{%s}DisplayName' % (NS['mdui'], NS['mdui']),
848848
'{%s}ServiceName' % NS['md'],
849849
'{%s}OrganizationDisplayName' % NS['md'],
850850
'{%s}OrganizationName' % NS['md'],
851-
'{%s}Keywords' % NS['mdui'],
851+
'.//{%s}UIInfo/{%s}Keywords' % (NS['mdui'], NS['mdui']),
852852
'{%s}Scope' % NS['shibmd'],
853853
]:
854-
lst.extend([s.text for s in elt.iter(attr)])
854+
lst.extend([s.text for s in elt.iterfind(attr)])
855855
lst.append(elt.get('entityID'))
856856
return [item for item in lst if item is not None]
857857

src/pyff/samlmd.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -698,12 +698,12 @@ def gen_icon(e):
698698

699699

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

704704

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

709709

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

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

743743
return name_dict, desc_dict
@@ -825,7 +825,7 @@ def entity_extended_display(entity, langs=None):
825825
display = serviceName.text
826826
break
827827

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

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

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

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

949-
keywords = filter_lang(e.iter("{%s}Keywords" % NS['mdui']), langs=langs)
949+
keywords = filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Keywords" % (NS['mdui'], NS['mdui'])), langs=langs)
950950
if keywords is not None:
951951
lst = [elt.text for elt in keywords]
952952
if len(lst) > 0:
@@ -1214,7 +1214,7 @@ def entity_simple_info(e, langs=None):
12141214
d['service_name'] = entity_service_name(e, langs)
12151215
d['service_descr'] = entity_service_description(e, langs)
12161216
d['entity_attributes'] = entity_attribute_dict(e)
1217-
keywords = filter_lang(e.iter("{%s}Keywords" % NS['mdui']), langs=langs)
1217+
keywords = filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Keywords" % (NS['mdui'], NS['mdui'])), langs=langs)
12181218
if keywords is not None:
12191219
lst = [elt.text for elt in keywords]
12201220
if len(lst) > 0:
@@ -1224,7 +1224,7 @@ def entity_simple_info(e, langs=None):
12241224

12251225
def entity_info(e, langs=None):
12261226
d = entity_simple_summary(e)
1227-
keywords = filter_lang(e.iter("{%s}Keywords" % NS['mdui']), langs=langs)
1227+
keywords = filter_lang(e.iterfind(".//{%s}UIInfo/{%s}Keywords" % (NS['mdui'], NS['mdui'])), langs=langs)
12281228
if keywords is not None:
12291229
lst = [elt.text for elt in keywords]
12301230
if len(lst) > 0:

src/pyff/store.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,14 @@ def search(self, query=None, path=None, entity_filter=None, related=None):
413413
def _strings(elt):
414414
lst = []
415415
for attr in [
416-
'{%s}DisplayName' % NS['mdui'],
416+
'.//{%s}UIInfo/{%s}DisplayName' % (NS['mdui'], NS['mdui']),
417417
'{%s}ServiceName' % NS['md'],
418418
'{%s}OrganizationDisplayName' % NS['md'],
419419
'{%s}OrganizationName' % NS['md'],
420-
'{%s}Keywords' % NS['mdui'],
420+
'.//{%s}UIInfo/{%s}Keywords' % (NS['mdui'], NS['mdui']),
421421
'{%s}Scope' % NS['shibmd'],
422422
]:
423-
lst.extend([s.text for s in elt.iter(attr)])
423+
lst.extend([s.text for s in elt.iterfind(attr)])
424424
lst.append(elt.get('entityID'))
425425
return [item for item in lst if item is not None]
426426

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
3+
entityID="https://idp.example.com/saml2/idp/metadata.php"
4+
xmlns:oaf="http://schemas.eduserv.org.uk/openathens-federation/1.0" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
5+
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
6+
<md:Extensions>
7+
<shibmd:Scope regexp="false">example.com</shibmd:Scope>
8+
<shibmd:Scope regexp="false">81098135.example.com</shibmd:Scope>
9+
<oaf:ScopedUIInfo scope="81098135.example.com">
10+
<mdui:DisplayName xml:lang="sv">Scoped Example Universitet</mdui:DisplayName>
11+
<mdui:DisplayName xml:lang="en">Scoped Example University</mdui:DisplayName>
12+
</oaf:ScopedUIInfo>
13+
<mdui:UIInfo>
14+
<mdui:DisplayName xml:lang="sv">Example universitet</mdui:DisplayName>
15+
<mdui:DisplayName xml:lang="en">Example University</mdui:DisplayName>
16+
<mdui:Description xml:lang="sv">Identity Provider för Example universitet</mdui:Description>
17+
<mdui:Description xml:lang="en">Identity Provider for Example University</mdui:Description>
18+
<mdui:InformationURL xml:lang="sv">http://www.example.com/</mdui:InformationURL>
19+
<mdui:InformationURL xml:lang="en">http://www.example.com/english/</mdui:InformationURL>
20+
<mdui:Logo height="63" width="358">https://www.example.com/static/images/umu_logo.jpg</mdui:Logo>
21+
<mdui:Logo xml:lang="sv" height="63" width="358">https://www.example.com/static/images/logo.jpg</mdui:Logo>
22+
<mdui:Logo xml:lang="en" height="63" width="350">https://www.example.com/static/images/logo_eng.jpg</mdui:Logo>
23+
<mdui:Keywords xml:lang="sv">exempel</mdui:Keywords>
24+
<mdui:Keywords xml:lang="en">example</mdui:Keywords>
25+
</mdui:UIInfo>
26+
<mdui:DiscoHints xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
27+
<mdui:DomainHint>example.com</mdui:DomainHint>
28+
<mdui:DomainHint>example.net</mdui:DomainHint>
29+
<mdui:IPHint>10.0.0.0/8</mdui:IPHint>
30+
</mdui:DiscoHints>
31+
</md:Extensions>
32+
<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.com/saml2/idp/ArtifactResolutionService.php" index="0"/>
33+
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.com/saml2/idp/SingleLogoutService.php"/>
34+
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
35+
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.com/saml2/idp/SSOService.php"/>
36+
</md:IDPSSODescriptor>
37+
<md:Organization>
38+
<md:OrganizationName xml:lang="sv">ExempelU</md:OrganizationName>
39+
<md:OrganizationName xml:lang="en">ExampleU</md:OrganizationName>
40+
<md:OrganizationDisplayName xml:lang="sv">Exempel Universitetet</md:OrganizationDisplayName>
41+
<md:OrganizationDisplayName xml:lang="en">The Example University</md:OrganizationDisplayName>
42+
<md:OrganizationURL xml:lang="sv">http://www.example.com</md:OrganizationURL>
43+
<md:OrganizationURL xml:lang="en">http://www.example.com/english</md:OrganizationURL>
44+
</md:Organization>
45+
<md:ContactPerson contactType="administrative">
46+
<md:Company>Example University</md:Company>
47+
<md:SurName>Example helpdesk</md:SurName>
48+
<md:EmailAddress>[email protected]</md:EmailAddress>
49+
</md:ContactPerson>
50+
<md:ContactPerson contactType="technical">
51+
<md:Company>Example University</md:Company>
52+
<md:SurName>Example helpdesk</md:SurName>
53+
<md:EmailAddress>[email protected]</md:EmailAddress>
54+
</md:ContactPerson>
55+
<md:ContactPerson contactType="support">
56+
<md:Company>Example University</md:Company>
57+
<md:SurName>Servicedesk Example universitet</md:SurName>
58+
<md:EmailAddress>[email protected]</md:EmailAddress>
59+
</md:ContactPerson>
60+
</md:EntityDescriptor>

src/pyff/test/test_pipeline.py

+33
Original file line numberDiff line numberDiff line change
@@ -795,3 +795,36 @@ def test_discojson_sp_trustinfo_in_attr(self):
795795
pass
796796
finally:
797797
shutil.rmtree(tmpdir)
798+
799+
def test_discojson_scoped_display_name(self):
800+
with patch.multiple("sys", exit=self.sys_exit):
801+
tmpdir = tempfile.mkdtemp()
802+
os.rmdir(tmpdir) # lets make sure 'store' can recreate it
803+
try:
804+
self.exec_pipeline("""
805+
- load:
806+
- file://%s/metadata/test-scoped-display-name.xml
807+
- select
808+
- discojson
809+
- publish:
810+
output: %s/disco.json
811+
raw: true
812+
update_store: false
813+
""" % (self.datadir, tmpdir))
814+
fn = "%s/disco.json" % tmpdir
815+
assert os.path.exists(fn)
816+
with open(fn, 'r') as f:
817+
idps_json = json.load(f)
818+
819+
idp_json = idps_json[0]
820+
assert idp_json['title'] == 'Example University'
821+
assert idp_json['title_langs']['sv'] == 'Example universitet'
822+
assert idp_json['title_langs']['en'] == 'Example University'
823+
assert idp_json['descr'] == 'Identity Provider for Example University'
824+
assert idp_json['descr_langs']['sv'] == 'Identity Provider för Example universitet'
825+
assert idp_json['descr_langs']['en'] == 'Identity Provider for Example University'
826+
assert idp_json['keywords'] == 'example'
827+
except IOError:
828+
pass
829+
finally:
830+
shutil.rmtree(tmpdir)

0 commit comments

Comments
 (0)