Added better debugging

This commit is contained in:
Kevin Veen-Birkenbach 2025-07-22 19:14:40 +02:00
parent 3bc64023af
commit c2f83abb60
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
6 changed files with 95 additions and 10 deletions

View File

@ -0,0 +1,28 @@
---
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: "Injects a catcher, which catches the actions of all logout elements and redirects them to the central logout."
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl"
min_ansible_version: "2.9"
platforms:
- name: Archlinux
versions:
- rolling
galaxy_tags:
- nginx
- javascript
- csp
- sub_filter
- injection
- global
repository: "https://s.veen.world/cymais"
documentation: "https://s.veen.world/cymais"
issue_tracker_url: "https://s.veen.world/cymaisissues"
dependencies:
- srv-web-7-4-core

View File

@ -0,0 +1,13 @@
# run_once_srv_web_7_7_inj_javascript: deactivated
- name: "Load JavaScript code for '{{ application_id }}'"
set_fact:
javascript_code: "{{ lookup('template', modifier_javascript_template_file) }}"
- name: "Collapse Javascript code into one-liner for '{{application_id}}'"
set_fact:
javascript_code_one_liner: "{{ javascript_code | to_one_liner }}"
- name: "Append Javascript CSP hash for '{{application_id}}'"
set_fact:
applications: "{{ applications | append_csp_hash(application_id, javascript_code_one_liner) }}"
changed_when: false

View File

@ -0,0 +1 @@
<script>{{ javascript_code_one_liner | replace("'", "\\'") }}</script>

View File

@ -0,0 +1,38 @@
(function() {
const logoutUrlBase = 'https://auth.cymais.cloud/realms/cymais.cloud/protocol/openid-connect/logout';
const redirectUri = encodeURIComponent('https://cymais.cloud');
const logoutUrl = `${logoutUrlBase}?redirect_uri=${redirectUri}`;
// Check if a string matches logout keywords
function matchesLogout(str) {
return str && /logout|log\s*out|abmelden/i.test(str);
}
// Check if any attribute name contains "logout" (case-insensitive)
function hasLogoutAttribute(el) {
for (let attr of el.attributes) {
if (/logout/i.test(attr.name)) {
return true;
}
}
return false;
}
// Find all elements
const allElements = document.querySelectorAll('*');
allElements.forEach(el => {
if (
matchesLogout(el.getAttribute('name')) ||
matchesLogout(el.id) ||
matchesLogout(el.className) ||
matchesLogout(el.innerText) ||
hasLogoutAttribute(el)
) {
el.style.cursor = 'pointer';
el.addEventListener('click', function(event) {
event.preventDefault();
window.location.href = logoutUrl;
});
}
});
})();

View File

@ -0,0 +1 @@
modifier_javascript_template_file: "{{ application_id | abs_role_path_by_application_id }}/templates/javascript.js.j2"

View File

@ -2,7 +2,7 @@ import unittest
import yaml
import subprocess
from pathlib import Path
from collections import Counter
from collections import Counter, defaultdict
class TestDomainUniqueness(unittest.TestCase):
def test_no_duplicate_domains(self):
@ -22,7 +22,8 @@ class TestDomainUniqueness(unittest.TestCase):
cfg = yaml.safe_load(yaml_file.read_text(encoding='utf-8')) or {}
apps = cfg.get('defaults_applications', {})
all_domains = []
domain_to_apps = defaultdict(set)
for app_name, app_cfg in apps.items():
domains_cfg = app_cfg.get('domains', {})
@ -32,7 +33,10 @@ class TestDomainUniqueness(unittest.TestCase):
values = list(canonical.values())
else:
values = canonical or []
all_domains.extend(values)
for d in values:
if isinstance(d, str) and d.strip():
domain_to_apps[d].add(app_name)
# aliases entries may be a list or a mapping
aliases = domains_cfg.get('aliases', [])
@ -40,16 +44,16 @@ class TestDomainUniqueness(unittest.TestCase):
values = list(aliases.values())
else:
values = aliases or []
all_domains.extend(values)
# Filter out any empty or non-string entries
domain_list = [d for d in all_domains if isinstance(d, str) and d.strip()]
counts = Counter(domain_list)
for d in values:
if isinstance(d, str) and d.strip():
domain_to_apps[d].add(app_name)
# Find duplicates
duplicates = [domain for domain, count in counts.items() if count > 1]
# Find duplicates: domains that appear in more than one app
duplicates = {domain: list(apps) for domain, apps in domain_to_apps.items() if len(apps) > 1}
if duplicates:
self.fail(f"Duplicate domain entries found: {duplicates}\n (May 'make build' solves this issue.)")
details = "\n".join(f"Domain '{domain}' is used in applications: {apps}" for domain, apps in duplicates.items())
self.fail(f"Duplicate domain entries found:\n{details}\n(Maybe 'make build' solves this issue.)")
if __name__ == "__main__":
unittest.main()