mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-05-18 10:40:33 +02:00
Optimized safe options
This commit is contained in:
parent
2506065142
commit
ad51597e2e
29
filter_plugins/safe_join.py
Normal file
29
filter_plugins/safe_join.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# file: filter_plugins/safe_join.py
|
||||||
|
"""
|
||||||
|
Ansible filter plugin that joins a base string and a tail path safely.
|
||||||
|
If the base is falsy (None, empty, etc.), returns an empty string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def safe_join(base, tail):
|
||||||
|
"""
|
||||||
|
Safely join base and tail into a path or URL.
|
||||||
|
|
||||||
|
- base: the base string. If falsy, returns ''.
|
||||||
|
- tail: the string to append. Leading/trailing slashes are handled.
|
||||||
|
- On any exception, returns ''.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not base:
|
||||||
|
return ''
|
||||||
|
base_str = str(base).rstrip('/')
|
||||||
|
tail_str = str(tail).lstrip('/')
|
||||||
|
return f"{base_str}/{tail_str}"
|
||||||
|
except Exception:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'safe_join': safe_join,
|
||||||
|
}
|
@ -9,18 +9,12 @@ defaults_service_provider:
|
|||||||
city: "Cybertown"
|
city: "Cybertown"
|
||||||
postal_code: "00001"
|
postal_code: "00001"
|
||||||
country: "Nexusland"
|
country: "Nexusland"
|
||||||
logo: >-
|
logo: "{{ applications.assets_server.url | safe_var | safe_join('logo.png') }}"
|
||||||
{{ (applications.assets_server.url | safe_var ~ '/logo.png')
|
|
||||||
if applications.assets_server.url | safe_var else '' }}
|
|
||||||
platform:
|
platform:
|
||||||
titel: "CyMaIS Demo"
|
titel: "CyMaIS Demo"
|
||||||
subtitel: "The Future of Self-Hosted Infrastructure. Secure. Automated. Sovereign."
|
subtitel: "The Future of Self-Hosted Infrastructure. Secure. Automated. Sovereign."
|
||||||
logo: >-
|
logo: "{{ applications.assets_server.url | safe_var | safe_join('logo.png') }}"
|
||||||
{{ (applications.assets_server.url | safe_var ~ '/logo.png')
|
favicon: "{{ applications.assets_server.url | safe_var | safe_join('favicon.ico') }}"
|
||||||
if applications.assets_server.url | safe_var else '' }}
|
|
||||||
favicon: >-
|
|
||||||
{{ (applications.assets_server.url | safe_var ~ '/favicon.ico')
|
|
||||||
if applications.assets_server.url | safe_var else '' }}
|
|
||||||
contact:
|
contact:
|
||||||
bluesky: >-
|
bluesky: >-
|
||||||
{{ ('@' ~ users.administrator.username ~ '.' ~ domains[application_id]['api'])
|
{{ ('@' ~ users.administrator.username ~ '.' ~ domains[application_id]['api'])
|
||||||
@ -36,4 +30,10 @@ defaults_service_provider:
|
|||||||
legal:
|
legal:
|
||||||
editorial_responsible: "Johannes Gutenberg"
|
editorial_responsible: "Johannes Gutenberg"
|
||||||
source_code: "https://github.com/kevinveenbirkenbach/cymais"
|
source_code: "https://github.com/kevinveenbirkenbach/cymais"
|
||||||
imprint: "{{ web_protocol }}://{{domains.html_server}}/imprint.html"
|
imprint: >-
|
||||||
|
{{ "{protocol}://{domain}/imprint.html"
|
||||||
|
| safe_placeholders({
|
||||||
|
'protocol': web_protocol,
|
||||||
|
'domain': domains.html_server
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
@ -51,8 +51,10 @@ env:
|
|||||||
DISCOURSE_DEVELOPER_EMAILS: {{users.administrator.email}}
|
DISCOURSE_DEVELOPER_EMAILS: {{users.administrator.email}}
|
||||||
|
|
||||||
# Set Logo
|
# Set Logo
|
||||||
|
{% if service_provider.platform.logo | bool %}
|
||||||
DISCOURSE_LOGO_URL: "{{ service_provider.platform.logo }}"
|
DISCOURSE_LOGO_URL: "{{ service_provider.platform.logo }}"
|
||||||
DISCOURSE_LOGO_SMALL_URL: "{{ service_provider.platform.logo }}"
|
DISCOURSE_LOGO_SMALL_URL: "{{ service_provider.platform.logo }}"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
# SMTP ADDRESS, username, and password are required
|
# SMTP ADDRESS, username, and password are required
|
||||||
# WARNING the char '#' in SMTP password can cause problems!
|
# WARNING the char '#' in SMTP password can cause problems!
|
||||||
|
@ -67,6 +67,7 @@ listmonk_settings:
|
|||||||
|
|
||||||
- key: "app.logo_url"
|
- key: "app.logo_url"
|
||||||
value: '"{{ service_provider.platform.logo }}"'
|
value: '"{{ service_provider.platform.logo }}"'
|
||||||
|
when: service_provider.platform.logo | bool
|
||||||
|
|
||||||
- key: "app.site_name"
|
- key: "app.site_name"
|
||||||
value: '"{{ service_provider.company.titel }} Mailing list"'
|
value: '"{{ service_provider.company.titel }} Mailing list"'
|
||||||
@ -117,6 +118,7 @@ listmonk_settings:
|
|||||||
|
|
||||||
- key: "app.favicon_url"
|
- key: "app.favicon_url"
|
||||||
value: '"{{ service_provider.platform.favicon }}"'
|
value: '"{{ service_provider.platform.favicon }}"'
|
||||||
|
when: service_provider.platform.favicon | bool
|
||||||
|
|
||||||
# - key: "bounce.postmark"
|
# - key: "bounce.postmark"
|
||||||
# value: '{"enabled": false, "password": "", "username": ""}'
|
# value: '{"enabled": false, "password": "", "username": ""}'
|
||||||
|
51
tests/unit/test_safe_join.py
Normal file
51
tests/unit/test_safe_join.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Ensure filter_plugins directory is on the path
|
||||||
|
sys.path.insert(
|
||||||
|
0,
|
||||||
|
os.path.abspath(os.path.join(os.path.dirname(__file__), '../../filter_plugins'))
|
||||||
|
)
|
||||||
|
|
||||||
|
from safe_join import safe_join
|
||||||
|
|
||||||
|
class TestSafeJoinFilter(unittest.TestCase):
|
||||||
|
def test_join_with_trailing_slashes(self):
|
||||||
|
self.assertEqual(
|
||||||
|
safe_join('http://example.com/', '/path/to'),
|
||||||
|
'http://example.com/path/to'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_join_without_slashes(self):
|
||||||
|
self.assertEqual(
|
||||||
|
safe_join('http://example.com', 'path/to'),
|
||||||
|
'http://example.com/path/to'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_base_none(self):
|
||||||
|
self.assertEqual(safe_join(None, 'path'), '')
|
||||||
|
|
||||||
|
def test_base_empty(self):
|
||||||
|
self.assertEqual(safe_join('', 'path'), '')
|
||||||
|
|
||||||
|
def test_tail_empty(self):
|
||||||
|
# joining with empty tail should yield base with trailing slash
|
||||||
|
self.assertEqual(
|
||||||
|
safe_join('http://example.com', ''),
|
||||||
|
'http://example.com/'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_numeric_base(self):
|
||||||
|
# numeric base is cast to string
|
||||||
|
self.assertEqual(safe_join(123, 'path'), '123/path')
|
||||||
|
|
||||||
|
def test_exception_in_str(self):
|
||||||
|
class Bad:
|
||||||
|
def __str__(self):
|
||||||
|
raise ValueError('bad')
|
||||||
|
# on exception, safe_join returns ''
|
||||||
|
self.assertEqual(safe_join(Bad(), 'x'), '')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user