You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
17 KiB
544 lines
17 KiB
// ============================================
|
|
// GIT PUSHER - MAIN JAVASCRIPT
|
|
// Version 2.0 avec système de licence par fichier
|
|
// ============================================
|
|
|
|
// Configuration
|
|
const GIT_PUSHER_CONFIG = {
|
|
serverUrl: window.location.protocol + '//' + window.location.hostname + ':9999',
|
|
credentialsKey: 'git_pusher_credentials',
|
|
version: '2.0.0'
|
|
};
|
|
|
|
// État global
|
|
let selectedApps = [];
|
|
let isProcessing = false;
|
|
|
|
// ============================================
|
|
// INITIALISATION
|
|
// ============================================
|
|
|
|
require([
|
|
'jquery',
|
|
'splunkjs/mvc',
|
|
'splunkjs/mvc/searchmanager',
|
|
'splunkjs/mvc/simplexml/ready!'
|
|
], function($, mvc, SearchManager) {
|
|
|
|
console.log("Git Pusher v2.0 initializing...");
|
|
|
|
// Initialiser le système de licence
|
|
if (typeof initializeLicense === 'function') {
|
|
initializeLicense();
|
|
} else {
|
|
console.warn("License system not loaded");
|
|
}
|
|
|
|
// Charger les credentials sauvegardés
|
|
loadSavedCredentials();
|
|
|
|
// Récupérer les résultats de recherche pour les apps
|
|
const searchManager = mvc.Components.get('dsearch');
|
|
|
|
if (searchManager) {
|
|
searchManager.on('search:done', function() {
|
|
const results = searchManager.data('results');
|
|
if (results) {
|
|
results.on('data', function() {
|
|
const rows = results.data().rows;
|
|
const fields = results.data().fields;
|
|
renderAppsList(rows, fields);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Exposer les fonctions globalement
|
|
window.pushDashboards = pushDashboards;
|
|
window.resetForm = resetForm;
|
|
window.toggleSelectAll = toggleSelectAll;
|
|
});
|
|
|
|
// Attacher l'événement au bouton après chargement du DOM
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
setTimeout(function() {
|
|
var pushBtn = document.getElementById('push-btn');
|
|
if (pushBtn) {
|
|
pushBtn.onclick = function() {
|
|
if (typeof pushDashboards === 'function') {
|
|
pushDashboards();
|
|
} else if (typeof window.pushDashboards === 'function') {
|
|
window.pushDashboards();
|
|
}
|
|
};
|
|
console.log("Push button event attached");
|
|
}
|
|
}, 2000); // Attendre 2 secondes que tout soit chargé
|
|
});
|
|
|
|
// ============================================
|
|
// RENDU DE LA LISTE DES APPLICATIONS
|
|
// ============================================
|
|
|
|
function renderAppsList(rows, fields) {
|
|
const container = document.getElementById('dashboard-list');
|
|
if (!container) return;
|
|
|
|
console.log("Fields:", fields);
|
|
console.log("First row:", rows[0]);
|
|
|
|
// Trouver les index des colonnes
|
|
const nameIdx = fields.indexOf('name');
|
|
const labelIdx = fields.indexOf('label');
|
|
const descIdx = fields.indexOf('description');
|
|
|
|
console.log("Index - name:", nameIdx, "label:", labelIdx);
|
|
|
|
// Générer le HTML
|
|
let html = `
|
|
<div class="app-header">
|
|
<div>
|
|
<input type="checkbox" id="select-all" onchange="toggleSelectAll(this.checked)" />
|
|
<label for="select-all" style="cursor: pointer; margin-left: 8px;">Select All</label>
|
|
</div>
|
|
<span class="app-count">${rows.length} apps</span>
|
|
</div>
|
|
`;
|
|
|
|
let validApps = 0;
|
|
|
|
rows.forEach((row, index) => {
|
|
// Récupérer le nom - essayer plusieurs méthodes
|
|
let name = '';
|
|
if (nameIdx >= 0 && row[nameIdx]) {
|
|
name = row[nameIdx];
|
|
} else if (labelIdx >= 0 && row[labelIdx]) {
|
|
// Si name est null, utiliser label comme fallback temporaire
|
|
// On va chercher le vrai nom via l'API
|
|
name = row[labelIdx];
|
|
} else if (row[0]) {
|
|
name = row[0];
|
|
} else if (row[1]) {
|
|
name = row[1]; // Deuxième élément si premier est null
|
|
}
|
|
|
|
const label = (labelIdx >= 0 && row[labelIdx]) ? row[labelIdx] : name;
|
|
|
|
console.log(`Row ${index}: name="${name}", label="${label}"`);
|
|
|
|
// Ignorer si pas de nom ou apps système
|
|
if (!name || name.startsWith('splunk_') || name === 'learned' || name === 'launcher') {
|
|
return;
|
|
}
|
|
|
|
validApps++;
|
|
|
|
html += `
|
|
<div class="app-item">
|
|
<input type="checkbox"
|
|
id="app-${index}"
|
|
data-app-id="${name}"
|
|
data-app-label="${label}"
|
|
onchange="updateSelectedApps()" />
|
|
<label for="app-${index}">
|
|
<span class="app-badge">${name}</span>
|
|
${label !== name ? ' - ' + label : ''}
|
|
</label>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
container.innerHTML = html;
|
|
|
|
console.log(`Rendered ${validApps} valid applications out of ${rows.length}`);
|
|
}
|
|
|
|
// ============================================
|
|
// GESTION DE LA SÉLECTION
|
|
// ============================================
|
|
|
|
function updateSelectedApps() {
|
|
const checkboxes = document.querySelectorAll('#dashboard-list input[type="checkbox"][data-app-id]');
|
|
selectedApps = [];
|
|
|
|
checkboxes.forEach(cb => {
|
|
if (cb.checked) {
|
|
selectedApps.push({
|
|
id: cb.getAttribute('data-app-id'),
|
|
label: cb.getAttribute('data-app-label')
|
|
});
|
|
}
|
|
});
|
|
|
|
// Mettre à jour le "Select All"
|
|
const selectAll = document.getElementById('select-all');
|
|
if (selectAll) {
|
|
const allChecked = Array.from(checkboxes).every(cb => cb.checked);
|
|
const someChecked = Array.from(checkboxes).some(cb => cb.checked);
|
|
selectAll.checked = allChecked;
|
|
selectAll.indeterminate = someChecked && !allChecked;
|
|
}
|
|
|
|
console.log(`Selected ${selectedApps.length} apps`);
|
|
}
|
|
|
|
function toggleSelectAll(checked) {
|
|
const checkboxes = document.querySelectorAll('#dashboard-list input[type="checkbox"][data-app-id]');
|
|
checkboxes.forEach(cb => {
|
|
cb.checked = checked;
|
|
});
|
|
updateSelectedApps();
|
|
}
|
|
|
|
// ============================================
|
|
// PUSH VERS GIT
|
|
// ============================================
|
|
|
|
async function pushDashboards() {
|
|
console.log("Starting push process...");
|
|
|
|
// Vérifier si déjà en cours
|
|
if (isProcessing) {
|
|
console.log("Push already in progress");
|
|
return;
|
|
}
|
|
|
|
// Récupérer les apps sélectionnées directement depuis le DOM
|
|
var apps = [];
|
|
var checkboxes = document.querySelectorAll('#dashboard-list input[type="checkbox"][data-app-id]:checked');
|
|
checkboxes.forEach(function(cb) {
|
|
apps.push({
|
|
id: cb.getAttribute('data-app-id'),
|
|
label: cb.getAttribute('data-app-label') || cb.getAttribute('data-app-id')
|
|
});
|
|
});
|
|
|
|
console.log("Apps selected from DOM:", apps);
|
|
|
|
// Mettre à jour selectedApps
|
|
selectedApps = apps;
|
|
|
|
// Vérifier si déjà en cours
|
|
if (isProcessing) {
|
|
console.log("Push already in progress");
|
|
return;
|
|
}
|
|
|
|
// Vérifier la licence AVANT tout
|
|
if (typeof checkLicenseBeforePush === 'function') {
|
|
const licenseOk = await checkLicenseBeforePush();
|
|
if (!licenseOk) {
|
|
console.log("License check failed");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Récupérer les valeurs du formulaire
|
|
const gitUrl = document.getElementById('git-url')?.value?.trim();
|
|
const gitBranch = document.getElementById('git-branch')?.value?.trim() || 'main';
|
|
const gitToken = document.getElementById('git-token')?.value?.trim();
|
|
const commitMessage = document.getElementById('commit-message')?.value?.trim();
|
|
const saveCredentials = document.getElementById('save-credentials')?.checked;
|
|
|
|
// Mettre à jour la liste des apps sélectionnées
|
|
updateSelectedApps();
|
|
|
|
// Validation
|
|
if (!gitUrl) {
|
|
showMessage('error', 'Please enter a Git repository URL');
|
|
return;
|
|
}
|
|
|
|
if (!gitToken) {
|
|
showMessage('error', 'Please enter a Git token or password');
|
|
return;
|
|
}
|
|
|
|
if (!commitMessage) {
|
|
showMessage('error', 'Please enter a commit message');
|
|
return;
|
|
}
|
|
|
|
if (selectedApps.length === 0) {
|
|
showMessage('error', 'Please select at least one application to deploy');
|
|
return;
|
|
}
|
|
|
|
// Sauvegarder les credentials si demandé
|
|
if (saveCredentials) {
|
|
saveCredentialsToStorage(gitUrl, gitBranch, gitToken);
|
|
}
|
|
|
|
// Démarrer le push
|
|
isProcessing = true;
|
|
showLoading(true);
|
|
hideMessages();
|
|
|
|
try {
|
|
// Récupérer l'utilisateur courant
|
|
const currentUser = await getCurrentUser();
|
|
|
|
// Construire les paramètres
|
|
const params = new URLSearchParams({
|
|
git_url: gitUrl,
|
|
git_branch: gitBranch,
|
|
git_token: gitToken,
|
|
commit_message: commitMessage,
|
|
apps: JSON.stringify(selectedApps),
|
|
user: currentUser
|
|
});
|
|
|
|
console.log(`Pushing ${selectedApps.length} apps to ${gitUrl}`);
|
|
|
|
// Appeler le serveur
|
|
const response = await fetch(`${GIT_PUSHER_CONFIG.serverUrl}/push?${params.toString()}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
|
|
const result = await response.json();
|
|
console.log("Push result:", result);
|
|
|
|
if (result.status === 'success') {
|
|
showMessage('success', `✅ Successfully deployed ${result.apps_pushed || selectedApps.length} application(s) to Git!`);
|
|
|
|
// Reset la sélection après succès
|
|
setTimeout(() => {
|
|
toggleSelectAll(false);
|
|
}, 2000);
|
|
} else if (result.error_code === 'LICENSE_ERROR') {
|
|
showMessage('error', `🔐 ${result.message}`);
|
|
|
|
// Afficher le modal de licence
|
|
if (typeof showLicenseModal === 'function') {
|
|
showLicenseModal(result.message, result.error_code);
|
|
}
|
|
} else if (result.error_code === 'APP_LIMIT') {
|
|
showMessage('error', `📦 ${result.message}`);
|
|
} else {
|
|
showMessage('error', result.message || 'Unknown error occurred');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error("Push error:", error);
|
|
showMessage('error', `Connection error: ${error.message}. Is the Git Pusher server running?`);
|
|
} finally {
|
|
isProcessing = false;
|
|
showLoading(false);
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// UTILITAIRES UI
|
|
// ============================================
|
|
|
|
function showLoading(show) {
|
|
const loading = document.getElementById('loading');
|
|
const pushBtn = document.getElementById('push-btn');
|
|
|
|
if (loading) {
|
|
loading.classList.toggle('active', show);
|
|
}
|
|
|
|
if (pushBtn) {
|
|
pushBtn.disabled = show;
|
|
pushBtn.textContent = show ? '⏳ Deploying...' : '✈️ Deploy to Git';
|
|
}
|
|
}
|
|
|
|
function showMessage(type, text) {
|
|
hideMessages();
|
|
|
|
const successMsg = document.getElementById('success-msg');
|
|
const errorMsg = document.getElementById('error-msg');
|
|
const successText = document.getElementById('success-text');
|
|
const errorText = document.getElementById('error-text');
|
|
|
|
if (type === 'success' && successMsg && successText) {
|
|
successText.textContent = text;
|
|
successMsg.classList.add('active');
|
|
|
|
// Auto-hide après 5 secondes
|
|
setTimeout(() => {
|
|
successMsg.classList.remove('active');
|
|
}, 5000);
|
|
} else if (type === 'error' && errorMsg && errorText) {
|
|
errorText.textContent = text;
|
|
errorMsg.classList.add('active');
|
|
}
|
|
}
|
|
|
|
function hideMessages() {
|
|
const successMsg = document.getElementById('success-msg');
|
|
const errorMsg = document.getElementById('error-msg');
|
|
|
|
if (successMsg) successMsg.classList.remove('active');
|
|
if (errorMsg) errorMsg.classList.remove('active');
|
|
}
|
|
|
|
function resetForm(clearCredentials = false) {
|
|
// Reset les champs
|
|
const commitMessage = document.getElementById('commit-message');
|
|
if (commitMessage) commitMessage.value = '';
|
|
|
|
if (clearCredentials) {
|
|
const gitUrl = document.getElementById('git-url');
|
|
const gitToken = document.getElementById('git-token');
|
|
const saveCredentials = document.getElementById('save-credentials');
|
|
|
|
if (gitUrl) gitUrl.value = '';
|
|
if (gitToken) gitToken.value = '';
|
|
if (saveCredentials) saveCredentials.checked = false;
|
|
|
|
// Supprimer les credentials sauvegardés
|
|
localStorage.removeItem(GIT_PUSHER_CONFIG.credentialsKey);
|
|
}
|
|
|
|
// Reset la sélection
|
|
toggleSelectAll(false);
|
|
|
|
// Cacher les messages
|
|
hideMessages();
|
|
|
|
console.log("Form reset" + (clearCredentials ? " (with credentials)" : ""));
|
|
}
|
|
|
|
// ============================================
|
|
// GESTION DES CREDENTIALS
|
|
// ============================================
|
|
|
|
function saveCredentialsToStorage(gitUrl, gitBranch, gitToken) {
|
|
try {
|
|
const credentials = {
|
|
gitUrl: gitUrl,
|
|
gitBranch: gitBranch,
|
|
// Note: En production, envisager une solution plus sécurisée
|
|
gitToken: btoa(gitToken), // Encodage basique (pas sécurisé, juste pour l'obfuscation)
|
|
savedAt: new Date().toISOString()
|
|
};
|
|
|
|
localStorage.setItem(GIT_PUSHER_CONFIG.credentialsKey, JSON.stringify(credentials));
|
|
console.log("Credentials saved");
|
|
} catch (error) {
|
|
console.error("Error saving credentials:", error);
|
|
}
|
|
}
|
|
|
|
function loadSavedCredentials() {
|
|
try {
|
|
const saved = localStorage.getItem(GIT_PUSHER_CONFIG.credentialsKey);
|
|
if (!saved) return;
|
|
|
|
const credentials = JSON.parse(saved);
|
|
|
|
const gitUrl = document.getElementById('git-url');
|
|
const gitBranch = document.getElementById('git-branch');
|
|
const gitToken = document.getElementById('git-token');
|
|
const saveCredentials = document.getElementById('save-credentials');
|
|
|
|
if (gitUrl && credentials.gitUrl) {
|
|
gitUrl.value = credentials.gitUrl;
|
|
}
|
|
|
|
if (gitBranch && credentials.gitBranch) {
|
|
gitBranch.value = credentials.gitBranch;
|
|
}
|
|
|
|
if (gitToken && credentials.gitToken) {
|
|
gitToken.value = atob(credentials.gitToken);
|
|
}
|
|
|
|
if (saveCredentials) {
|
|
saveCredentials.checked = true;
|
|
}
|
|
|
|
console.log("Credentials loaded from storage");
|
|
} catch (error) {
|
|
console.error("Error loading credentials:", error);
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// RÉCUPÉRATION DE L'UTILISATEUR SPLUNK
|
|
// ============================================
|
|
|
|
async function getCurrentUser() {
|
|
try {
|
|
const response = await fetch('/en-US/splunkd/__raw/services/authentication/current-context?output_mode=json');
|
|
const data = await response.json();
|
|
return data.entry?.[0]?.content?.username || 'unknown';
|
|
} catch (error) {
|
|
console.error("Error getting current user:", error);
|
|
return 'unknown';
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// VÉRIFICATION DU SERVEUR
|
|
// ============================================
|
|
|
|
async function checkServerHealth() {
|
|
try {
|
|
const response = await fetch(`${GIT_PUSHER_CONFIG.serverUrl}/health`, {
|
|
method: 'GET',
|
|
timeout: 5000
|
|
});
|
|
const data = await response.json();
|
|
return data.status === 'ok';
|
|
} catch (error) {
|
|
console.error("Server health check failed:", error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Vérifier la santé du serveur au démarrage
|
|
setTimeout(async () => {
|
|
const healthy = await checkServerHealth();
|
|
if (!healthy) {
|
|
console.warn("Git Pusher server may not be running");
|
|
} else {
|
|
console.log("Git Pusher server is healthy");
|
|
}
|
|
}, 1000);
|
|
|
|
// ============================================
|
|
// EXPORT POUR DEBUG
|
|
// ============================================
|
|
|
|
window.GitPusher = {
|
|
config: GIT_PUSHER_CONFIG,
|
|
getSelectedApps: () => selectedApps,
|
|
checkServer: checkServerHealth,
|
|
version: GIT_PUSHER_CONFIG.version
|
|
};
|
|
|
|
// ============================================
|
|
// FIX: Attacher les événements aux boutons
|
|
// ============================================
|
|
(function attachButtonEvents() {
|
|
function tryAttach() {
|
|
var pushBtn = document.getElementById('push-btn');
|
|
if (pushBtn) {
|
|
pushBtn.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
console.log("Push button clicked");
|
|
pushDashboards();
|
|
});
|
|
console.log("✓ Push button event attached");
|
|
} else {
|
|
// Réessayer dans 500ms
|
|
setTimeout(tryAttach, 500);
|
|
}
|
|
}
|
|
|
|
// Démarrer après un délai
|
|
if (document.readyState === 'complete') {
|
|
setTimeout(tryAttach, 1000);
|
|
} else {
|
|
window.addEventListener('load', function() {
|
|
setTimeout(tryAttach, 1000);
|
|
});
|
|
}
|
|
})(); |