Skip to content

Commit 2db9654

Browse files
committed
feat: handle safe list noop and delete appropriately
Conversation with jacksonlauren indicated that if the ExtensionSiteSettings safe list is None, no safeList element should be included in the request. If the ExtensionSiteSettings.safe_list is a non-None Iterable that yields 0 items, an empty safeList element will be included in the request, having the effect of deleting the safe list on the site.
1 parent 4e2c01b commit 2db9654

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

tableauserverclient/server/request_factory.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,8 +1671,11 @@ def update_site_extensions(self, xml_request: ET.Element, extensions_site_settin
16711671
include_partner_built_element = ET.SubElement(ext_element, "includePartnerBuilt")
16721672
include_partner_built_element.text = str(extensions_site_settings.include_partner_built).lower()
16731673

1674-
for safe in extensions_site_settings.safe_list or []:
1675-
safe_element = ET.SubElement(ext_element, "safeList")
1674+
if extensions_site_settings.safe_list is None:
1675+
return
1676+
1677+
safe_element = ET.SubElement(ext_element, "safeList")
1678+
for safe in extensions_site_settings.safe_list:
16761679
if safe.url is not None:
16771680
url_element = ET.SubElement(safe_element, "url")
16781681
url_element.text = safe.url

test/test_extensions.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,66 @@ def test_update_site_settings(server: TSC.Server) -> None:
131131
prompt_needed_elem = safe_extension_elem.find("promptNeeded")
132132
assert prompt_needed_elem is not None
133133
assert prompt_needed_elem.text == "true"
134+
135+
136+
def test_update_safe_list_none(server: TSC.Server) -> None:
137+
with requests_mock.mock() as m:
138+
m.put(server.extensions.baseurl, text=GET_SITE_SETTINGS.read_text())
139+
140+
site_settings = TSC.ExtensionsSiteSettings()
141+
site_settings.enabled = True
142+
site_settings.use_default_setting = False
143+
144+
updated_settings = server.extensions.update(site_settings)
145+
history = m.request_history
146+
147+
assert isinstance(updated_settings, TSC.ExtensionsSiteSettings)
148+
assert updated_settings.enabled is True
149+
assert updated_settings.use_default_setting is False
150+
assert updated_settings.safe_list is not None
151+
assert len(updated_settings.safe_list) == 1
152+
first_safe = updated_settings.safe_list[0]
153+
assert first_safe.url == "http://localhost:9123/Dynamic.html"
154+
assert first_safe.full_data_allowed is True
155+
assert first_safe.prompt_needed is True
156+
157+
# Verify that the request body was as expected
158+
assert len(history) == 1
159+
xml_payload = fromstring(history[0].body)
160+
extensions_site_settings_elem = xml_payload.find(".//extensionsSiteSettings")
161+
assert extensions_site_settings_elem is not None
162+
safe_list_element = extensions_site_settings_elem.find("safeList")
163+
assert safe_list_element is None
164+
165+
166+
def test_update_safe_list_empty(server: TSC.Server) -> None:
167+
with requests_mock.mock() as m:
168+
m.put(server.extensions.baseurl, text=GET_SITE_SETTINGS.read_text())
169+
170+
site_settings = TSC.ExtensionsSiteSettings()
171+
site_settings.enabled = True
172+
site_settings.use_default_setting = False
173+
site_settings.safe_list = []
174+
175+
updated_settings = server.extensions.update(site_settings)
176+
history = m.request_history
177+
178+
assert isinstance(updated_settings, TSC.ExtensionsSiteSettings)
179+
assert updated_settings.enabled is True
180+
assert updated_settings.use_default_setting is False
181+
assert updated_settings.safe_list is not None
182+
assert len(updated_settings.safe_list) == 1
183+
first_safe = updated_settings.safe_list[0]
184+
assert first_safe.url == "http://localhost:9123/Dynamic.html"
185+
assert first_safe.full_data_allowed is True
186+
assert first_safe.prompt_needed is True
187+
188+
# Verify that the request body was as expected
189+
assert len(history) == 1
190+
xml_payload = fromstring(history[0].body)
191+
extensions_site_settings_elem = xml_payload.find(".//extensionsSiteSettings")
192+
assert extensions_site_settings_elem is not None
193+
safe_list_element = extensions_site_settings_elem.find("safeList")
194+
assert safe_list_element is not None
195+
assert len(safe_list_element) == 0
196+

0 commit comments

Comments
 (0)