2026-04-02 17:48:27 +02:00
|
|
|
/**
|
|
|
|
|
* Helpdesk settings page — auth mode toggle and connection test.
|
|
|
|
|
*/
|
2026-04-02 21:05:54 +02:00
|
|
|
import { showAsyncFlash } from '/js/components/app-async-flash.js';
|
2026-04-02 17:48:27 +02:00
|
|
|
|
2026-04-04 18:34:03 +02:00
|
|
|
const settingsForm = document.getElementById('helpdesk-settings-form');
|
|
|
|
|
|
|
|
|
|
const getMessage = (key, fallback) => {
|
|
|
|
|
if (!settingsForm || !settingsForm.dataset) {
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return settingsForm.dataset[key] || fallback;
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-02 17:48:27 +02:00
|
|
|
// Toggle OAuth2 vs Basic Auth field visibility
|
|
|
|
|
const authModeSelect = document.getElementById('auth_mode');
|
|
|
|
|
const basicFields = document.getElementById('helpdesk-basic-auth-fields');
|
|
|
|
|
const oauth2Fields = document.getElementById('helpdesk-oauth2-fields');
|
|
|
|
|
|
|
|
|
|
const toggleAuthFields = () => {
|
|
|
|
|
if (!authModeSelect || !basicFields || !oauth2Fields) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-04-04 18:34:03 +02:00
|
|
|
|
2026-04-02 17:48:27 +02:00
|
|
|
const isOAuth2 = authModeSelect.value === 'oauth2';
|
2026-04-04 18:34:03 +02:00
|
|
|
basicFields.toggleAttribute('hidden', isOAuth2);
|
|
|
|
|
oauth2Fields.toggleAttribute('hidden', !isOAuth2);
|
2026-04-02 17:48:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (authModeSelect) {
|
|
|
|
|
authModeSelect.addEventListener('change', toggleAuthFields);
|
|
|
|
|
toggleAuthFields();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Connection test button
|
|
|
|
|
const testButton = document.getElementById('helpdesk-test-connection-button');
|
2026-04-04 18:34:03 +02:00
|
|
|
const testResult = document.getElementById('helpdesk-connection-test-result');
|
|
|
|
|
|
|
|
|
|
const setTestResult = (variant, message) => {
|
|
|
|
|
if (!testResult) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
testResult.textContent = message;
|
|
|
|
|
testResult.dataset.variant = variant;
|
|
|
|
|
testResult.hidden = !message;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const setButtonLoadingState = (isLoading) => {
|
|
|
|
|
if (!testButton) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const defaultLabel = testButton.dataset.labelDefault || getMessage('testDefaultLabel', 'Test connection');
|
|
|
|
|
const loadingLabel = testButton.dataset.labelLoading || getMessage('testLoadingLabel', 'Testing...');
|
|
|
|
|
|
|
|
|
|
testButton.disabled = isLoading;
|
|
|
|
|
testButton.toggleAttribute('aria-busy', isLoading);
|
|
|
|
|
testButton.textContent = isLoading ? loadingLabel : defaultLabel;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const parseJsonSafely = async (response) => {
|
|
|
|
|
try {
|
|
|
|
|
return await response.json();
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
2026-04-02 17:48:27 +02:00
|
|
|
|
2026-04-06 10:29:59 +02:00
|
|
|
// Tenant override toggle — show/hide tenant fields + set save_target
|
|
|
|
|
const overrideToggle = document.getElementById('helpdesk-override-toggle');
|
|
|
|
|
const tenantFields = document.getElementById('helpdesk-tenant-fields');
|
|
|
|
|
const saveTargetInput = document.getElementById('helpdesk-settings-save-target');
|
|
|
|
|
|
|
|
|
|
const tenantAuthModeSelect = document.getElementById('tenant_auth_mode');
|
|
|
|
|
const tenantBasicFields = document.getElementById('helpdesk-tenant-basic-auth-fields');
|
|
|
|
|
const tenantOauth2Fields = document.getElementById('helpdesk-tenant-oauth2-fields');
|
|
|
|
|
|
|
|
|
|
if (overrideToggle && tenantFields) {
|
|
|
|
|
overrideToggle.addEventListener('change', () => {
|
|
|
|
|
tenantFields.hidden = !overrideToggle.checked;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// On form submit, set save_target based on active tab
|
|
|
|
|
if (settingsForm && saveTargetInput) {
|
|
|
|
|
settingsForm.addEventListener('submit', () => {
|
|
|
|
|
const tenantPanel = settingsForm.querySelector('[data-tab-panel="tenant"]:not([hidden])');
|
|
|
|
|
saveTargetInput.value = tenantPanel ? 'tenant' : 'global';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tenant auth mode toggle
|
|
|
|
|
if (tenantAuthModeSelect && tenantBasicFields && tenantOauth2Fields) {
|
|
|
|
|
tenantAuthModeSelect.addEventListener('change', () => {
|
|
|
|
|
const isOAuth2 = tenantAuthModeSelect.value === 'oauth2';
|
|
|
|
|
tenantBasicFields.hidden = isOAuth2;
|
|
|
|
|
tenantOauth2Fields.hidden = !isOAuth2;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 21:05:54 +02:00
|
|
|
if (testButton) {
|
2026-04-02 17:48:27 +02:00
|
|
|
testButton.addEventListener('click', async () => {
|
2026-04-04 18:34:03 +02:00
|
|
|
setButtonLoadingState(true);
|
|
|
|
|
setTestResult('info', getMessage('testLoadingLabel', 'Testing...'));
|
2026-04-02 17:48:27 +02:00
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const csrfMeta = document.querySelector('meta[name="csrf-token"]');
|
|
|
|
|
const csrfInput = document.querySelector('input[name="csrf_token"]');
|
|
|
|
|
const csrfToken = csrfInput?.value || csrfMeta?.content || '';
|
|
|
|
|
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
if (csrfToken) {
|
|
|
|
|
formData.append('csrf_token', csrfToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const response = await fetch(
|
|
|
|
|
new URL('helpdesk/settings/test-connection-data', document.baseURI).href,
|
|
|
|
|
{
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: formData,
|
|
|
|
|
credentials: 'same-origin',
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-04 18:34:03 +02:00
|
|
|
const data = await parseJsonSafely(response);
|
|
|
|
|
const successMessage = getMessage('testSuccessMessage', 'Connection successful');
|
|
|
|
|
const defaultErrorMessage = getMessage('testErrorMessage', 'Connection failed');
|
2026-04-02 17:48:27 +02:00
|
|
|
|
2026-04-04 18:34:03 +02:00
|
|
|
if (response.ok && data?.ok) {
|
|
|
|
|
const message = data.message || successMessage;
|
|
|
|
|
setTestResult('success', message);
|
|
|
|
|
showAsyncFlash('success', message);
|
2026-04-02 17:48:27 +02:00
|
|
|
} else {
|
2026-04-04 18:34:03 +02:00
|
|
|
let message = defaultErrorMessage;
|
|
|
|
|
if (data?.error) {
|
|
|
|
|
message = data.error;
|
|
|
|
|
} else if (!response.ok) {
|
|
|
|
|
message = `${defaultErrorMessage} (HTTP ${response.status})`;
|
2026-04-02 17:48:27 +02:00
|
|
|
}
|
2026-04-04 18:34:03 +02:00
|
|
|
|
|
|
|
|
if (data?.debug?.http_code) {
|
|
|
|
|
message += ` (HTTP ${data.debug.http_code})`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setTestResult('warning', message);
|
|
|
|
|
showAsyncFlash('error', message);
|
2026-04-02 17:48:27 +02:00
|
|
|
}
|
|
|
|
|
} catch {
|
2026-04-04 18:34:03 +02:00
|
|
|
const message = getMessage('testErrorMessage', 'Connection failed');
|
|
|
|
|
setTestResult('warning', message);
|
|
|
|
|
showAsyncFlash('error', message);
|
2026-04-02 17:48:27 +02:00
|
|
|
} finally {
|
2026-04-04 18:34:03 +02:00
|
|
|
setButtonLoadingState(false);
|
2026-04-02 17:48:27 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|