Files
CDN-APP-INSIDER/public/js/paramadminsettingsetup.script.js
Dinawo 51d11a6c36
Some checks failed
continuous-integration/drone/push Build is failing
Update v1.1.0-beta.1
2024-12-21 18:16:25 +01:00

683 lines
24 KiB
JavaScript

const body = document.body;
const themeSwitcher = document.getElementById('themeSwitcher');
// Gestion du thème
function setTheme(theme) {
if (theme === 'dark') {
body.classList.add('dark');
} else {
body.classList.remove('dark');
}
localStorage.setItem('theme', theme);
}
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
setTheme(savedTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
setTheme('dark');
}
themeSwitcher.addEventListener('click', function() {
if (body.classList.contains('dark')) {
setTheme('light');
} else {
setTheme('dark');
}
});
// Gestion des formulaires LDAP et Discord
function toggleForm(formId, checkbox) {
const form = document.getElementById(formId);
form.style.display = checkbox.checked ? 'block' : 'none';
}
// Fonctions pour la gestion des IPs
function addIpField() {
const ipList = document.getElementById('ipList');
const newField = document.createElement('div');
newField.className = 'flex items-center space-x-2 animate';
newField.innerHTML = `
<input type="text" name="allowedIps[]" class="form-control flex-1"
placeholder="ex: 10.20.0.34 ou 10.20.0.0/24">
<button type="button" class="btn btn-secondary p-2" onclick="removeIpField(this)">
<i class="fas fa-trash"></i>
</button>
`;
ipList.appendChild(newField);
}
function removeIpField(button) {
const fieldContainer = button.parentElement;
fieldContainer.classList.add('fade-out');
setTimeout(() => {
fieldContainer.remove();
}, 300);
}
// Fonctions de validation IP
function validateIP(ip) {
if (!ip) return false;
if (ip.includes('/')) {
const [addr, bits] = ip.split('/');
const bitsNum = parseInt(bits);
if (isIPv4(addr)) {
return bitsNum >= 0 && bitsNum <= 32;
} else if (isIPv6(addr)) {
return bitsNum >= 0 && bitsNum <= 128;
}
return false;
}
return isIPv4(ip) || isIPv6(ip);
}
function isIPv4(ip) {
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
if (!ipv4Regex.test(ip)) return false;
const parts = ip.split('.');
return parts.every(part => {
const num = parseInt(part);
return num >= 0 && num <= 255;
});
}
function isIPv6(ip) {
const ipv6Regex = /^(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
return ipv6Regex.test(ip);
}
// Gestionnaire pour le switch des logs et les niveaux
document.addEventListener('DOMContentLoaded', function() {
const logsSwitch = document.getElementById('logsEnabled');
const logsLevelsSection = document.getElementById('logsLevelsSection');
const logsPathsSection = document.getElementById('logsPathsSection');
if (logsSwitch) {
logsSwitch.addEventListener('change', function() {
const isEnabled = this.checked;
// Activer/désactiver visuellement les sections
if (logsLevelsSection) logsLevelsSection.style.opacity = isEnabled ? '1' : '0.5';
if (logsPathsSection) logsPathsSection.style.opacity = isEnabled ? '1' : '0.5';
if (!isEnabled) {
// Décocher tous les niveaux de log
document.querySelectorAll('input[name="logs[levels][]"]').forEach(checkbox => {
checkbox.checked = false;
checkbox.parentElement.classList.remove('bg-blue-600');
checkbox.parentElement.classList.add('bg-gray-700');
});
}
});
}
});
function toggleLogLevel(button) {
if (!document.getElementById('logsEnabled').checked) {
return; // Ne rien faire si les logs sont désactivés
}
button.classList.toggle('bg-blue-600');
button.classList.toggle('bg-gray-700');
const checkbox = button.querySelector('input[type="checkbox"]');
checkbox.checked = !checkbox.checked;
}
// Gestion du formulaire principal
async function handleFormSubmit(e) {
e.preventDefault();
// Validation des IPs
const ipInputs = document.querySelectorAll('input[name="allowedIps[]"]');
let hasError = false;
ipInputs.forEach(input => {
input.classList.remove('ip-error');
const value = input.value.trim();
if (value && !validateIP(value)) {
input.classList.add('ip-error');
hasError = true;
}
});
if (hasError) {
Swal.fire({
icon: 'error',
title: 'Erreur de validation',
text: 'Veuillez vérifier le format des IPs saisies'
});
return;
}
try {
const formData = new FormData(this);
const formObject = {};
// Traitement des données du formulaire
formData.forEach((value, key) => {
if (key.includes('[') && key.includes(']')) {
const parts = key.split('[');
const mainKey = parts[0];
const subKey = parts[1].replace(']', '');
if (!formObject[mainKey]) {
formObject[mainKey] = {};
}
if (key.endsWith('[]')) {
if (!formObject[mainKey][subKey.replace('[]', '')]) {
formObject[mainKey][subKey.replace('[]', '')] = [];
}
formObject[mainKey][subKey.replace('[]', '')].push(value);
} else {
formObject[mainKey][subKey] = value;
}
} else {
formObject[key] = value;
}
});
// Gestion de l'état enabled/disabled des logs
formObject.logs.enabled = document.getElementById('logsEnabled')?.checked ? 'on' : 'off';
// Si les logs sont désactivés
if (formObject.logs.enabled === 'off') {
formObject.logs = {
enabled: 'off',
levels: [],
excludePaths: [],
includeOnly: []
};
} else {
// Si les logs sont activés, on s'assure d'avoir tous les champs
if (!formObject.logs.levels) formObject.logs.levels = [];
if (!formObject.logs.excludePaths) formObject.logs.excludePaths = [];
if (!formObject.logs.includeOnly) formObject.logs.includeOnly = [];
}
// Gérer l'état des services
if (!formObject.services) formObject.services = {};
// Service de nettoyage de fichiers
formObject.services.fileCleanup = {
enabled: document.getElementById('fileCleanupEnabled')?.checked ? 'on' : 'off',
...(document.getElementById('fileCleanupEnabled')?.checked && {
schedule: document.getElementById('fileCleanupSchedule')?.value
})
};
// Service de gestion des rapports
formObject.services.reportManager = {
enabled: document.getElementById('reportManagerEnabled')?.checked ? 'on' : 'off',
...(document.getElementById('reportManagerEnabled')?.checked && {
schedule: document.getElementById('reportSchedule')?.value,
endpoint: document.getElementById('reportEndpoint')?.value
})
};
// Gérer l'état de LDAP
if (!formObject.ldap) formObject.ldap = {};
formObject.ldap.enabled = document.getElementById('ldapEnabled').checked ? 'on' : 'off';
if (formObject.ldap.enabled === 'off') {
delete formObject.ldap.url;
delete formObject.ldap.baseDN;
delete formObject.ldap.username;
delete formObject.ldap.password;
}
// Gérer l'état de Discord
if (!formObject.discord) formObject.discord = {};
formObject.discord.enabled = document.getElementById('discordEnabled').checked ? 'on' : 'off';
if (formObject.discord.enabled === 'off') {
delete formObject.discord.clientID;
delete formObject.discord.clientSecret;
delete formObject.discord.identifyURL;
delete formObject.discord.authorizedIDs;
}
console.log('Form data to be sent:', formObject);
const response = await fetch('/api/dpanel/dashboard/admin/update-setup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formObject)
});
const result = await response.json();
if (result.success) {
Swal.fire({
icon: 'success',
title: 'Configuration mise à jour',
text: result.message
}).then(() => {
window.location.reload();
});
} else {
throw new Error(result.message || 'Erreur lors de la mise à jour');
}
} catch (error) {
console.error('Erreur:', error);
Swal.fire({
icon: 'error',
title: 'Erreur',
text: error.message || 'Une erreur est survenue lors de la mise à jour'
});
}
}
function showCommonPaths(type) {
const paths = [
'/api/',
'/auth/',
'/public/',
'/build-metadata',
'/attachments/',
'/favicon.ico',
'/dpanel/'
];
const modalContent = `
<div class="modal-common-paths">
<h3 class="text-xl mb-4">Chemins communs</h3>
<div class="space-y-2">
${paths.map(path => `
<div class="path-option">
<input type="checkbox" id="path-${path}" value="${path}" class="mr-3">
<label for="path-${path}" class="flex-1">${path}</label>
</div>
`).join('')}
</div>
<div class="flex justify-end gap-2 mt-4">
<button onclick="Swal.close()" class="px-4 py-2 bg-gray-600 rounded">Annuler</button>
<button onclick="addSelectedPaths('${type}')" class="px-4 py-2 bg-blue-600 rounded">Ajouter</button>
</div>
</div>
`;
Swal.fire({
html: modalContent,
showConfirmButton: false,
showCancelButton: false,
background: '#1a1a1a',
padding: 0
});
}
function addPath(type) {
const input = document.getElementById(`${type}PathInput`);
const value = input.value.trim();
if (!value) return;
const list = document.getElementById(`${type}PathsList`);
const div = document.createElement('div');
div.className = 'flex items-center space-x-2 py-2 px-3 bg-gray-800 rounded-lg animate';
div.innerHTML = `
<span class="flex-1">${value}</span>
<button type="button" onclick="removePath(this)" class="text-gray-400 hover:text-red-500">
<i class="fas fa-times"></i>
</button>
<input type="hidden" name="logs[${type === 'exclude' ? 'excludePaths' : 'includeOnly'}][]" value="${value}">
`;
list.appendChild(div);
input.value = '';
}
function addSelectedPaths(type) {
const checkboxes = document.querySelectorAll('.path-option input[type="checkbox"]:checked');
checkboxes.forEach(checkbox => {
const input = document.getElementById(`${type}PathInput`);
input.value = checkbox.value;
addPath(type);
});
Swal.close();
}
function removePath(button) {
const div = button.closest('div');
div.classList.add('fade-out');
setTimeout(() => div.remove(), 300);
}
// Fonction pour basculer l'affichage du formulaire de service
function toggleService(serviceName) {
const checkbox = document.getElementById(`${serviceName}Enabled`);
const form = document.getElementById(`${serviceName}Form`);
if (form) {
form.style.display = checkbox.checked ? 'block' : 'none';
}
}
// Validation du format cron
function validateCron(schedule) {
const cronPattern = /^(\*|\d{1,2})(\s+(\*|\d{1,2})){4}$/;
return cronPattern.test(schedule);
}
// Validation de l'URL
function validateUrl(url) {
try {
new URL(url);
return true;
} catch {
return false;
}
}
// Initialisation au chargement de la page
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('setupForm');
if (form) {
form.addEventListener('submit', async function(e) {
e.preventDefault();
// Validation des IPs
const ipInputs = document.querySelectorAll('input[name="allowedIps[]"]');
let hasError = false;
ipInputs.forEach(input => {
input.classList.remove('ip-error');
const value = input.value.trim();
if (value && !validateIP(value)) {
input.classList.add('ip-error');
hasError = true;
}
});
if (hasError) {
Swal.fire({
icon: 'error',
title: 'Erreur de validation',
text: 'Veuillez vérifier le format des IPs saisies'
});
return;
}
try {
// Création de l'objet de données
const formObject = {
domain: document.getElementById('domain').value,
webhooks_discord: document.getElementById('webhooksDiscord').value,
// Configuration LDAP
ldap: {
enabled: document.getElementById('ldapEnabled').checked ? 'on' : 'off'
},
// Configuration Discord
discord: {
enabled: document.getElementById('discordEnabled').checked ? 'on' : 'off'
},
// Configuration des services
services: {
fileCleanup: {
enabled: document.getElementById('fileCleanupEnabled')?.checked ? 'on' : 'off',
schedule: document.getElementById('fileCleanupSchedule')?.value || ''
},
reportManager: {
enabled: document.getElementById('reportManagerEnabled')?.checked ? 'on' : 'off',
schedule: document.getElementById('reportSchedule')?.value || '',
endpoint: document.getElementById('reportEndpoint')?.value || ''
}
},
// IPs autorisées
allowedIps: Array.from(document.querySelectorAll('input[name="allowedIps[]"]'))
.map(input => input.value.trim())
.filter(value => value !== '')
};
// Ajout des champs LDAP si activé
if (formObject.ldap.enabled === 'on') {
formObject.ldap.url = document.getElementById('ldapUrl').value;
formObject.ldap.baseDN = document.getElementById('ldapBaseDN').value;
formObject.ldap.username = document.getElementById('ldapUsername').value;
formObject.ldap.password = document.getElementById('ldapPassword').value;
}
// Ajout des champs Discord si activé
if (formObject.discord.enabled === 'on') {
formObject.discord.clientID = document.getElementById('discordClientID').value;
formObject.discord.clientSecret = document.getElementById('discordClientSecret').value;
formObject.discord.authorizedIDs = document.getElementById('discordAuthorizedIDs').value;
}
// Gestion des logs
formObject.logs = {
enabled: document.getElementById('logsEnabled')?.checked ? 'on' : 'off',
levels: [],
excludePaths: [],
includeOnly: []
};
// Si les logs sont activés, ajout des configurations supplémentaires
if (formObject.logs.enabled === 'on') {
// Récupération des niveaux de logs sélectionnés
formObject.logs.levels = Array.from(document.querySelectorAll('input[name="logs[levels][]"]:checked'))
.map(input => input.value);
// Récupération des chemins exclus
formObject.logs.excludePaths = Array.from(document.querySelectorAll('input[name="logs[excludePaths][]"]'))
.map(input => input.value.trim())
.filter(value => value !== '');
// Récupération des chemins inclus
formObject.logs.includeOnly = Array.from(document.querySelectorAll('input[name="logs[includeOnly][]"]'))
.map(input => input.value.trim())
.filter(value => value !== '');
}
console.log('Données à envoyer:', formObject);
const response = await fetch('/api/dpanel/dashboard/admin/update-setup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formObject)
});
const result = await response.json();
if (result.success) {
Swal.fire({
icon: 'success',
title: 'Configuration mise à jour',
text: result.message || 'Configuration sauvegardée avec succès'
}).then(() => {
window.location.reload();
});
} else {
throw new Error(result.message || 'Erreur lors de la mise à jour');
}
} catch (error) {
console.error('Erreur:', error);
Swal.fire({
icon: 'error',
title: 'Erreur',
text: error.message || 'Une erreur est survenue lors de la mise à jour'
});
}
});
}
});
// Fonctions de validation
function validateCron(cron) {
const cronRegex = /^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])) (\*|([0-6]))$/;
return cronRegex.test(cron.trim());
}
function validateUrl(url) {
try {
new URL(url);
return true;
} catch {
return false;
}
}
// Gestion des onglets
document.addEventListener('DOMContentLoaded', function() {
// Init des onglets
const tabs = document.querySelectorAll('.tab');
tabs.forEach(tab => {
tab.addEventListener('click', () => switchTab(tab));
});
// Init du thème
initTheme();
// Init du formulaire
initForm();
});
// Gestion du thème
function initTheme() {
const themeSwitcher = document.getElementById('themeSwitcher');
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.classList.toggle('dark', savedTheme === 'dark');
updateThemeIcon(savedTheme);
themeSwitcher.addEventListener('click', toggleTheme);
}
function toggleTheme() {
const isDark = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
updateThemeIcon(isDark ? 'dark' : 'light');
}
function updateThemeIcon(theme) {
const icon = document.querySelector('#themeSwitcher i');
icon.className = theme === 'dark' ? 'fas fa-moon' : 'fas fa-sun';
}
// Gestion des onglets
function switchTab(selectedTab) {
const tabs = document.querySelectorAll('.tab');
const contents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => tab.classList.remove('active'));
contents.forEach(content => content.classList.remove('active'));
selectedTab.classList.add('active');
const targetContent = document.querySelector(`[data-tab-content="${selectedTab.dataset.tab}"]`);
targetContent.classList.add('active');
}
// Gestion des sections toggle
function toggleSection(sectionId, checkbox) {
const section = document.getElementById(sectionId);
if (section) {
section.style.display = checkbox.checked ? 'block' : 'none';
if (checkbox.checked) {
section.classList.add('animate');
} else {
section.classList.add('fade-out');
setTimeout(() => {
section.classList.remove('fade-out');
section.style.display = 'none';
}, 300);
}
}
}
// Gestion des IPs
function addIp() {
const ipList = document.getElementById('ipList');
const newEntry = document.createElement('div');
newEntry.className = 'ip-entry flex items-center gap-2 animate';
newEntry.innerHTML = `
<input type="text" name="allowedIps[]" class="form-control flex-1" placeholder="IPv4/IPv6 ou CIDR">
<button type="button" class="btn btn-icon" onclick="removeIp(this)">
<i class="fas fa-trash"></i>
</button>
`;
ipList.appendChild(newEntry);
}
function removeIp(button) {
const entry = button.closest('.ip-entry');
entry.classList.add('fade-out');
setTimeout(() => entry.remove(), 300);
}
// Gestion des chemins
function addPath(type) {
const input = document.getElementById(`${type}PathInput`);
const path = input.value.trim();
if (!path) return;
const list = document.getElementById(`${type}PathsList`);
const newEntry = document.createElement('div');
newEntry.className = 'path-entry animate';
newEntry.innerHTML = `
<span>${path}</span>
<button type="button" onclick="removePath(this)" class="text-gray-400 hover:text-red-500 transition-colors">
<i class="fas fa-times"></i>
</button>
<input type="hidden" name="logs[${type}Paths][]" value="${path}">
`;
list.appendChild(newEntry);
input.value = '';
}
function removePath(button) {
const entry = button.closest('.path-entry');
entry.classList.add('fade-out');
setTimeout(() => entry.remove(), 300);
}
// Gestion des niveaux de log
function toggleLogLevel(button) {
button.classList.toggle('active');
const checkbox = button.querySelector('input[type="checkbox"]');
checkbox.checked = !checkbox.checked;
}
// Chemins communs
function showCommonPaths(type) {
const commonPaths = [
'/api',
'/auth',
'/public',
'/uploads',
'/static',
'/assets',
'/images',
'/temp'
];
Swal.fire({
title: 'Chemins communs',
html: `
<div class="modal-common-paths">
${commonPaths.map(path => `
<div class="path-option" onclick="selectCommonPath('${path}', '${type}')">
${path}
</div>
`).join('')}
</div>
`,
showConfirmButton: false,
customClass: {
popup: 'swal2-dark'
}
});
}
function selectCommonPath(path, type) {
const input = document.getElementById(`${type}PathInput`);
input.value = path;
Swal.close();
}