diff --git a/apps/pusher_app_prem/appserver/static/appIcon.png b/apps/pusher_app_prem/appserver/static/appIcon.png
new file mode 100644
index 00000000..acc6b4b4
Binary files /dev/null and b/apps/pusher_app_prem/appserver/static/appIcon.png differ
diff --git a/apps/pusher_app_prem/appserver/static/appIcon_2x.png b/apps/pusher_app_prem/appserver/static/appIcon_2x.png
new file mode 100644
index 00000000..0c55cd3f
Binary files /dev/null and b/apps/pusher_app_prem/appserver/static/appIcon_2x.png differ
diff --git a/apps/pusher_app_prem/appserver/static/git_pusher.js b/apps/pusher_app_prem/appserver/static/git_pusher.js
old mode 100755
new mode 100644
index 74e7881c..79c23ee4
--- a/apps/pusher_app_prem/appserver/static/git_pusher.js
+++ b/apps/pusher_app_prem/appserver/static/git_pusher.js
@@ -48,23 +48,21 @@ function getServerUrl() {
return url;
}
- // Auto-détection basée sur le hostname
- // Si accès via le domaine Splunk principal, utiliser le domaine API
- if (hostname === 'myprivspldev.jp-engineering.fr') {
- return protocol + '//myprivspldev-api.jp-engineering.fr';
- }
-
- // Si déjà sur le domaine API
- if (hostname === 'myprivspldev-api.jp-engineering.fr') {
- return protocol + '//' + hostname;
- }
-
+ // Fallback : auto-détection basée sur le hostname
// Si c'est une IP ou localhost, ajouter le port 9999
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
return protocol + '//' + hostname + ':9999';
}
- // Par défaut, ajouter le port 9999
+ // Si c'est un domaine, essayer d'ajouter -api au sous-domaine
+ // Exemple: splunk.example.com → splunk-api.example.com
+ const parts = hostname.split('.');
+ if (parts.length >= 2) {
+ parts[0] = parts[0] + '-api';
+ return protocol + '//' + parts.join('.');
+ }
+
+ // Dernier fallback : même hostname avec port 9999
return protocol + '//' + hostname + ':9999';
}
@@ -79,7 +77,7 @@ const GIT_PUSHER_CONFIG = {
// Configuration SH Deployer (peut être modifiée via l'interface)
let SH_DEPLOYER_CONFIG = {
enabled: false,
- host: '10.10.40.14',
+ host: '',
port: 9998,
token: ''
};
@@ -1052,4 +1050,4 @@ window.GitPusher = {
checkServer: checkServerHealth,
checkDeployer: checkDeployerHealth,
version: GIT_PUSHER_CONFIG.version
-};
\ No newline at end of file
+};
diff --git a/apps/pusher_app_prem/appserver/static/git_pusher.js_old2 b/apps/pusher_app_prem/appserver/static/git_pusher.js_old2
new file mode 100755
index 00000000..74e7881c
--- /dev/null
+++ b/apps/pusher_app_prem/appserver/static/git_pusher.js_old2
@@ -0,0 +1,1055 @@
+// ============================================
+// GIT PUSHER - MAIN JAVASCRIPT
+// Version 2.1 avec déploiement vers SH Cluster
+// ============================================
+
+// Configuration par défaut
+const DEFAULT_CONFIG = {
+ api: {
+ url: '',
+ port: 9999,
+ useProxy: true
+ },
+ deployer: {
+ enabled: false,
+ host: '',
+ port: 9998,
+ token: '',
+ useSSL: true
+ }
+};
+
+// Charger la configuration
+function loadAppConfig() {
+ try {
+ const stored = localStorage.getItem('git_pusher_config');
+ if (stored) {
+ return JSON.parse(stored);
+ }
+ } catch (e) {
+ console.warn('Erreur chargement config localStorage:', e);
+ }
+ return DEFAULT_CONFIG;
+}
+
+// Déterminer l'URL du serveur API
+function getServerUrl() {
+ const config = loadAppConfig();
+ const hostname = window.location.hostname;
+ const protocol = window.location.protocol;
+
+ // Si une URL est configurée, l'utiliser
+ if (config.api && config.api.url) {
+ let url = config.api.url;
+ // Ajouter le port si pas de proxy
+ if (!config.api.useProxy && config.api.port) {
+ url = url.replace(/\/$/, '') + ':' + config.api.port;
+ }
+ return url;
+ }
+
+ // Auto-détection basée sur le hostname
+ // Si accès via le domaine Splunk principal, utiliser le domaine API
+ if (hostname === 'myprivspldev.jp-engineering.fr') {
+ return protocol + '//myprivspldev-api.jp-engineering.fr';
+ }
+
+ // Si déjà sur le domaine API
+ if (hostname === 'myprivspldev-api.jp-engineering.fr') {
+ return protocol + '//' + hostname;
+ }
+
+ // Si c'est une IP ou localhost, ajouter le port 9999
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
+ return protocol + '//' + hostname + ':9999';
+ }
+
+ // Par défaut, ajouter le port 9999
+ return protocol + '//' + hostname + ':9999';
+}
+
+// Configuration
+const GIT_PUSHER_CONFIG = {
+ serverUrl: getServerUrl(),
+ credentialsKey: 'git_pusher_credentials',
+ deployerConfigKey: 'git_pusher_deployer_config',
+ version: '2.1.0'
+};
+
+// Configuration SH Deployer (peut être modifiée via l'interface)
+let SH_DEPLOYER_CONFIG = {
+ enabled: false,
+ host: '10.10.40.14',
+ port: 9998,
+ token: ''
+};
+
+// État global
+let selectedApps = [];
+let selectedShClusterApps = []; // Apps sélectionnées pour le SH Cluster
+let isProcessing = false;
+let deployerAvailable = false;
+
+// ============================================
+// INITIALISATION
+// ============================================
+
+require([
+ 'jquery',
+ 'splunkjs/mvc',
+ 'splunkjs/mvc/searchmanager',
+ 'splunkjs/mvc/simplexml/ready!'
+], function($, mvc, SearchManager) {
+
+ console.log("Git Pusher v2.1 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();
+
+ // Charger la config du deployer
+ loadDeployerConfig();
+
+ // Vérifier la disponibilité du SH Deployer
+ checkDeployerHealth();
+
+ // 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;
+ window.toggleShClusterAllApps = toggleShClusterAllApps;
+ window.updateSelectedShClusterApps = updateSelectedShClusterApps;
+
+ // Attacher les événements pour la section SH Cluster
+ setTimeout(function() {
+ // Checkbox "Deploy to SH Cluster"
+ const deployCheckbox = document.getElementById('deploy-to-shcluster');
+ if (deployCheckbox) {
+ deployCheckbox.addEventListener('change', function() {
+ toggleDeployerOptions();
+ });
+ }
+
+ // Checkbox "All apps"
+ const allAppsCheckbox = document.getElementById('shcluster-all-apps');
+ if (allAppsCheckbox) {
+ allAppsCheckbox.addEventListener('change', function() {
+ toggleShClusterAllApps();
+ });
+ }
+
+ // Bouton configure
+ const configBtn = document.getElementById('deployer-config-btn');
+ if (configBtn) {
+ configBtn.addEventListener('click', function() {
+ showDeployerConfigModal();
+ });
+ }
+ }, 500);
+});
+
+// Afficher/masquer les options du deployer
+function toggleDeployerOptions() {
+ const checkbox = document.getElementById('deploy-to-shcluster');
+ const appsSection = document.getElementById('deployer-apps-section');
+ const authSection = document.getElementById('deployer-auth');
+
+ if (checkbox && checkbox.checked) {
+ if (appsSection) appsSection.classList.add('visible');
+ if (authSection) authSection.classList.add('visible');
+ } else {
+ if (appsSection) appsSection.classList.remove('visible');
+ if (authSection) authSection.classList.remove('visible');
+ }
+}
+
+// ============================================
+// RENDU DE LA LISTE DES APPLICATIONS
+// ============================================
+
+function renderAppsList(rows, fields) {
+ const container = document.getElementById('dashboard-list');
+ if (!container) return;
+
+ // Trouver les index des colonnes
+ const nameIdx = fields.indexOf('name');
+ const labelIdx = fields.indexOf('label');
+ const descIdx = fields.indexOf('description');
+
+ // Générer le HTML
+ let html = `
+
+ `;
+
+ rows.forEach((row, index) => {
+ const name = row[nameIdx] || '';
+ const label = row[labelIdx] || name;
+ const desc = row[descIdx] || '';
+
+ // Ignorer certaines apps système
+ if (name.startsWith('splunk_') || name === 'learned' || name === 'launcher') {
+ return;
+ }
+
+ html += `
+
+
+
+
+ `;
+ });
+
+ container.innerHTML = html;
+
+ console.log(`Rendered ${rows.length} applications`);
+}
+
+// ============================================
+// 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;
+ }
+
+ // Mettre à jour la liste des apps pour le SH Cluster
+ updateShClusterAppsList();
+
+ console.log(`Selected ${selectedApps.length} apps`);
+}
+
+function updateShClusterAppsList() {
+ const container = document.getElementById('shcluster-apps-container');
+ if (!container) return;
+
+ if (selectedApps.length === 0) {
+ container.innerHTML = 'Select apps from the left panel first
';
+ selectedShClusterApps = [];
+ return;
+ }
+
+ // Sauvegarder l'état actuel des checkboxes
+ const currentState = {};
+ const existingCheckboxes = container.querySelectorAll('input[type="checkbox"][data-app-id]');
+ existingCheckboxes.forEach(cb => {
+ currentState[cb.getAttribute('data-app-id')] = cb.checked;
+ });
+
+ // Vérifier si la liste a changé (nouvelles apps ajoutées ou apps retirées)
+ const currentAppIds = Array.from(existingCheckboxes).map(cb => cb.getAttribute('data-app-id'));
+ const newAppIds = selectedApps.map(app => app.id);
+ const listChanged = currentAppIds.length !== newAppIds.length ||
+ !currentAppIds.every(id => newAppIds.includes(id));
+
+ // Ne recréer le HTML que si la liste a changé
+ if (listChanged || existingCheckboxes.length === 0) {
+ let html = '';
+ selectedApps.forEach((app, index) => {
+ // Préserver l'état si l'app existait, sinon cocher par défaut
+ const isChecked = currentState.hasOwnProperty(app.id) ? currentState[app.id] : true;
+ html += `
+
+
+
+
+ `;
+ });
+
+ container.innerHTML = html;
+ }
+
+ // Mettre à jour la liste des apps SH Cluster sélectionnées (sans recréer le HTML)
+ updateSelectedShClusterApps();
+}
+
+function updateSelectedShClusterApps() {
+ const allAppsCheckbox = document.getElementById('shcluster-all-apps');
+
+ if (allAppsCheckbox && allAppsCheckbox.checked) {
+ // Toutes les apps sélectionnées pour Git
+ selectedShClusterApps = [...selectedApps];
+ } else {
+ // Seulement les apps cochées dans la liste SH Cluster
+ const checkboxes = document.querySelectorAll('#shcluster-apps-container input[type="checkbox"][data-app-id]');
+ selectedShClusterApps = [];
+
+ checkboxes.forEach(cb => {
+ if (cb.checked) {
+ selectedShClusterApps.push({
+ id: cb.getAttribute('data-app-id'),
+ label: cb.getAttribute('data-app-label')
+ });
+ }
+ });
+ }
+
+ console.log(`Selected ${selectedShClusterApps.length} apps for SH Cluster`);
+}
+
+function toggleShClusterAllApps() {
+ const allAppsCheckbox = document.getElementById('shcluster-all-apps');
+ const appsList = document.getElementById('shcluster-apps-list');
+
+ if (allAppsCheckbox && appsList) {
+ if (allAppsCheckbox.checked) {
+ // Masquer la liste et utiliser toutes les apps
+ appsList.style.display = 'none';
+ selectedShClusterApps = [...selectedApps];
+ console.log('SH Cluster: Using all selected apps');
+ } else {
+ // Afficher la liste pour permettre la sélection manuelle
+ appsList.style.display = 'block';
+ // Ne PAS appeler updateSelectedShClusterApps() ici
+ // L'utilisateur va faire sa sélection manuellement
+ // La liste garde son état actuel (tous cochés par défaut)
+ console.log('SH Cluster: Manual selection enabled');
+ }
+ }
+}
+
+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;
+ }
+
+ // 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;
+
+ // Ne PAS rappeler updateSelectedApps() ici car cela réinitialiserait la liste SH Cluster
+ // La liste selectedApps est déjà à jour grâce aux événements onchange
+
+ // 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);
+ }
+
+ // Vérifier si le déploiement vers SH Cluster est activé
+ const deployToSHCluster = document.getElementById('deploy-to-shcluster')?.checked || false;
+ const shAuthUser = document.getElementById('sh-auth-user')?.value?.trim() || '';
+ const shAuthPass = document.getElementById('sh-auth-pass')?.value?.trim() || '';
+
+ // La liste selectedShClusterApps est déjà à jour via les événements onchange
+ // Ne pas rappeler updateSelectedShClusterApps() pour éviter de réinitialiser la sélection
+
+ // Validation des apps SH Cluster si déploiement activé
+ if (deployToSHCluster && selectedShClusterApps.length === 0) {
+ showMessage('error', 'Please select at least one application to deploy to SH Cluster');
+ return;
+ }
+
+ // Démarrer le push
+ isProcessing = true;
+ showLoading(true, deployToSHCluster);
+ hideMessages();
+
+ try {
+ // Récupérer l'utilisateur courant
+ const currentUser = await getCurrentUser();
+
+ // Récupérer les infos de licence depuis le localStorage
+ const licenseInfo = getLicenseInfo ? getLicenseInfo() : null;
+ const licenseType = licenseInfo?.type_name || '';
+ const licenseId = licenseInfo?.license_id || '';
+
+ // Construire les paramètres
+ const params = new URLSearchParams({
+ git_url: gitUrl,
+ git_branch: gitBranch,
+ git_token: gitToken,
+ commit_message: commitMessage,
+ apps: JSON.stringify(selectedApps),
+ shcluster_apps: JSON.stringify(selectedShClusterApps), // Apps pour le SH Cluster
+ user: currentUser,
+ deploy_to_shcluster: deployToSHCluster.toString(),
+ deployer_host: SH_DEPLOYER_CONFIG.host,
+ deployer_token: SH_DEPLOYER_CONFIG.token,
+ license_type: licenseType,
+ license_id: licenseId
+ });
+
+ // Ajouter les credentials SH si fournis
+ if (shAuthUser) params.append('sh_auth_user', shAuthUser);
+ if (shAuthPass) params.append('sh_auth_pass', shAuthPass);
+
+ console.log(`Pushing ${selectedApps.length} apps to Git${deployToSHCluster ? `, ${selectedShClusterApps.length} apps to SH Cluster` : ''}`);
+
+ // 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') {
+ // Incrémenter le compteur d'utilisation côté client
+ console.log("=== INCREMENT USAGE ===");
+ console.log("typeof incrementUsage:", typeof incrementUsage);
+ console.log("typeof window.incrementUsage:", typeof window.incrementUsage);
+
+ try {
+ if (typeof window.incrementUsage === 'function') {
+ const stats = window.incrementUsage();
+ console.log("✓ Usage incremented successfully:", stats);
+ } else if (typeof incrementUsage === 'function') {
+ const stats = incrementUsage();
+ console.log("✓ Usage incremented (local):", stats);
+ } else {
+ console.warn("✗ incrementUsage function not available");
+ }
+ } catch (e) {
+ console.error("✗ Error incrementing usage:", e);
+ }
+
+ let message = `✅ Successfully deployed ${result.apps_pushed || selectedApps.length} application(s) to Git!`;
+
+ // Ajouter le statut du déploiement SH Cluster
+ if (deployToSHCluster && result.shcluster_deployment) {
+ if (result.shcluster_deployment.success) {
+ message += '\n🚀 SH Cluster deployment triggered successfully!';
+ } else {
+ message += `\n⚠️ SH Cluster deployment failed: ${result.shcluster_deployment.message}`;
+ }
+ }
+
+ showMessage('success', message);
+
+ // 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, deployToSHCluster = false) {
+ const loading = document.getElementById('loading');
+ const pushBtn = document.getElementById('push-btn');
+ const loadingText = document.querySelector('.loading-text');
+
+ if (loading) {
+ loading.classList.toggle('active', show);
+ }
+
+ if (loadingText && show) {
+ if (deployToSHCluster) {
+ loadingText.textContent = 'Deploying to Git and SH Cluster... Please wait';
+ } else {
+ loadingText.textContent = 'Deploying applications to Git... Please wait';
+ }
+ }
+
+ if (pushBtn) {
+ pushBtn.disabled = show;
+ if (show) {
+ pushBtn.textContent = deployToSHCluster ? '⏳ Deploying to Git + SH...' : '⏳ Deploying...';
+ } else {
+ pushBtn.textContent = '✈️ 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;
+ }
+}
+
+// ============================================
+// SH DEPLOYER FUNCTIONS
+// ============================================
+
+async function checkDeployerHealth() {
+ try {
+ const response = await fetch(`${GIT_PUSHER_CONFIG.serverUrl}/deployer/health`, {
+ method: 'GET',
+ timeout: 5000
+ });
+ const data = await response.json();
+
+ deployerAvailable = data.status === 'ok';
+
+ // Mettre à jour l'UI
+ updateDeployerUI();
+
+ console.log("SH Deployer status:", deployerAvailable ? "Available" : "Unavailable");
+ return deployerAvailable;
+ } catch (error) {
+ console.error("Deployer health check failed:", error);
+ deployerAvailable = false;
+ updateDeployerUI();
+ return false;
+ }
+}
+
+function updateDeployerUI() {
+ const deployerCheckbox = document.getElementById('deploy-to-shcluster');
+ const deployerStatus = document.getElementById('deployer-status');
+ const deployerSection = document.getElementById('deployer-section');
+
+ if (deployerCheckbox) {
+ deployerCheckbox.disabled = !deployerAvailable;
+ }
+
+ if (deployerStatus) {
+ if (deployerAvailable) {
+ deployerStatus.innerHTML = '● Connected';
+ } else {
+ deployerStatus.innerHTML = '● Disconnected';
+ }
+ }
+
+ if (deployerSection && !deployerAvailable) {
+ deployerSection.style.opacity = '0.6';
+ }
+}
+
+function loadDeployerConfig() {
+ try {
+ const saved = localStorage.getItem(GIT_PUSHER_CONFIG.deployerConfigKey);
+ if (saved) {
+ const config = JSON.parse(saved);
+ SH_DEPLOYER_CONFIG = { ...SH_DEPLOYER_CONFIG, ...config };
+ console.log("Deployer config loaded");
+ }
+ } catch (error) {
+ console.error("Error loading deployer config:", error);
+ }
+}
+
+function saveDeployerConfig() {
+ try {
+ localStorage.setItem(GIT_PUSHER_CONFIG.deployerConfigKey, JSON.stringify(SH_DEPLOYER_CONFIG));
+ console.log("Deployer config saved");
+ } catch (error) {
+ console.error("Error saving deployer config:", error);
+ }
+}
+
+function showDeployerConfigModal() {
+ const modal = document.createElement('div');
+ modal.id = 'deployer-config-modal';
+ modal.style.cssText = `
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.7);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 10000;
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+ `;
+
+ modal.innerHTML = `
+
+
⚙️ SH Deployer Configuration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ document.body.appendChild(modal);
+}
+
+function closeDeployerConfigModal() {
+ const modal = document.getElementById('deployer-config-modal');
+ if (modal) modal.remove();
+}
+
+async function saveDeployerConfigFromModal() {
+ const host = document.getElementById('deployer-config-host')?.value?.trim();
+ const port = parseInt(document.getElementById('deployer-config-port')?.value) || 9998;
+ const token = document.getElementById('deployer-config-token')?.value?.trim();
+ const msgEl = document.getElementById('deployer-config-message');
+
+ if (!host) {
+ if (msgEl) {
+ msgEl.style.display = 'block';
+ msgEl.style.background = '#ffebee';
+ msgEl.style.color = '#c62828';
+ msgEl.textContent = 'Please enter a host';
+ }
+ return;
+ }
+
+ // Mettre à jour la config
+ SH_DEPLOYER_CONFIG.host = host;
+ SH_DEPLOYER_CONFIG.port = port;
+ SH_DEPLOYER_CONFIG.token = token;
+
+ // Sauvegarder
+ saveDeployerConfig();
+
+ // Tester la connexion
+ if (msgEl) {
+ msgEl.style.display = 'block';
+ msgEl.style.background = '#e3f2fd';
+ msgEl.style.color = '#1565c0';
+ msgEl.textContent = 'Testing connection...';
+ }
+
+ const isHealthy = await checkDeployerHealth();
+
+ if (isHealthy) {
+ if (msgEl) {
+ msgEl.style.background = '#e8f5e9';
+ msgEl.style.color = '#2e7d32';
+ msgEl.textContent = '✓ Connected successfully!';
+ }
+ setTimeout(closeDeployerConfigModal, 1500);
+ } else {
+ if (msgEl) {
+ msgEl.style.background = '#ffebee';
+ msgEl.style.color = '#c62828';
+ msgEl.textContent = '✗ Connection failed. Check host and port.';
+ }
+ }
+}
+
+// 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 FONCTIONS GLOBALES
+// ============================================
+
+// Exposer les fonctions du deployer globalement pour les onclick du HTML
+window.showDeployerConfigModal = showDeployerConfigModal;
+window.closeDeployerConfigModal = closeDeployerConfigModal;
+window.saveDeployerConfigFromModal = saveDeployerConfigFromModal;
+
+// Exposer les fonctions principales
+window.pushDashboards = pushDashboards;
+window.resetForm = resetForm;
+window.toggleSelectAll = toggleSelectAll;
+window.updateSelectedApps = updateSelectedApps;
+
+// Fonction toggle pour le HTML
+window.toggleDeployerAuth = function() {
+ var checkbox = document.getElementById('deploy-to-shcluster');
+ var authSection = document.getElementById('deployer-auth');
+ if (checkbox && authSection) {
+ authSection.classList.toggle('visible', checkbox.checked);
+ }
+};
+
+// ============================================
+// ATTACHEMENT DES ÉVÉNEMENTS AUX BOUTONS
+// ============================================
+
+(function attachButtonEvents() {
+ function tryAttach() {
+ console.log("Trying to attach button events...");
+
+ // Bouton Deploy to Git
+ var pushBtn = document.getElementById('push-btn');
+ if (pushBtn) {
+ // Supprimer les anciens listeners
+ pushBtn.replaceWith(pushBtn.cloneNode(true));
+ pushBtn = document.getElementById('push-btn');
+
+ pushBtn.addEventListener('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ console.log("Deploy button clicked!");
+ pushDashboards();
+ });
+ console.log("✓ Deploy button event attached");
+ } else {
+ console.log("✗ Deploy button not found yet");
+ }
+
+ // Bouton Reset - chercher par classe ou contenu
+ var buttons = document.querySelectorAll('button.btn, button.btn-secondary');
+ buttons.forEach(function(btn) {
+ if (btn.textContent.includes('Reset') || btn.textContent.includes('🔄')) {
+ // Supprimer les anciens listeners
+ var newBtn = btn.cloneNode(true);
+ btn.parentNode.replaceChild(newBtn, btn);
+
+ newBtn.addEventListener('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ console.log("Reset button clicked!");
+ resetForm(true);
+ });
+ console.log("✓ Reset button event attached");
+ }
+ });
+
+ // Bouton Configure Deployer
+ var configBtn = document.querySelector('.deployer-config-btn');
+ if (configBtn) {
+ // Supprimer les anciens listeners
+ var newConfigBtn = configBtn.cloneNode(true);
+ configBtn.parentNode.replaceChild(newConfigBtn, configBtn);
+
+ newConfigBtn.addEventListener('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ console.log("Configure button clicked!");
+ showDeployerConfigModal();
+ });
+ console.log("✓ Configure button event attached");
+ }
+
+ // Checkbox deploy to shcluster
+ var deployCheckbox = document.getElementById('deploy-to-shcluster');
+ if (deployCheckbox) {
+ deployCheckbox.addEventListener('change', function() {
+ var authSection = document.getElementById('deployer-auth');
+ if (authSection) {
+ authSection.classList.toggle('visible', this.checked);
+ }
+ });
+ console.log("✓ Deploy checkbox event attached");
+ }
+
+ // Si le bouton principal n'est pas encore là, réessayer
+ if (!pushBtn) {
+ console.log("Retrying in 500ms...");
+ setTimeout(tryAttach, 500);
+ } else {
+ console.log("=== All button events attached successfully ===");
+ }
+ }
+
+ // Démarrer après un délai pour laisser le DOM se charger
+ if (document.readyState === 'complete') {
+ console.log("Document ready, attaching events in 1s...");
+ setTimeout(tryAttach, 1000);
+ } else {
+ window.addEventListener('load', function() {
+ console.log("Window loaded, attaching events in 1s...");
+ setTimeout(tryAttach, 1000);
+ });
+ }
+})();
+
+// ============================================
+// EXPORT POUR DEBUG
+// ============================================
+
+window.GitPusher = {
+ config: GIT_PUSHER_CONFIG,
+ deployerConfig: SH_DEPLOYER_CONFIG,
+ getSelectedApps: () => selectedApps,
+ checkServer: checkServerHealth,
+ checkDeployer: checkDeployerHealth,
+ version: GIT_PUSHER_CONFIG.version
+};
\ No newline at end of file
diff --git a/apps/pusher_app_prem/appserver/static/license_validation.js b/apps/pusher_app_prem/appserver/static/license_validation.js
old mode 100755
new mode 100644
index a3fe2f17..9a88ad40
--- a/apps/pusher_app_prem/appserver/static/license_validation.js
+++ b/apps/pusher_app_prem/appserver/static/license_validation.js
@@ -4,62 +4,62 @@
function _d(a,k){return a.map(function(c){return String.fromCharCode(c^k)}).join('')}
-var _MiUBIgGA='jF6eQXaxas4w3DbTBbjHZiQ9pKBGtnCQ';
-var _uKlfWBIg='4haWQeriLYkoyXjRgm6X6UHBz45iRbnH';
-var _vbjxOVJJ='NFf8EIHOXxItNBiBn1nSiOVI39nWY4Wo';
-var _NifpYSQF='jetKGSDo6z5wRmmho5pl4ShoEDLXkVTg';
-var _CSSdPwWe='s2M1c6dDT80YSEJOglkKzFWva728EKKd';
-var _VtTpaXDJ='djV609Ci8cH0QhX1OOHpP2HXFkbTwAPW';
-var _RgWpxUDG='GzNPrJtG62D1lXxQqQMqERzrIh6t6qVg';
-var _ZwgnBtAr='6XCIgzQVyOlGYGhIBEaGDoK54C5iw8mb';
-var _EcTaZDmf='zwJaPfiZyz4GZjG4yTqMhme6xYdJmiZY';
-var _QVrhuHpJ='HiWpaGdVoKTfYjVonGJv8QTbS6s2mvQd';
+var _uvQJmWQj='9AFwcZcRbBeXaJqKQLeqZcWcSEyEkGhu';
+var _rIioLjQm='tiWiFVaEItxAFuYv1tgMjnQ84wQKrKs3';
+var _jCFopnuP='0kIsCpE5TFRM4gQxNtJOe1ZAKklHltin';
+var _RPzUZFtx='U6pxCxKo055c5gnUwZpoI9GVyFme2Q2J';
+var _jqqIIADg='cayEoU4uUplCxipTjpvqwFvkxnPcOmsB';
+var _VqTudlrn='hNEfSUIXujr6nEyyJqw6bKYNfhrrop3r';
+var _UpWCTgAQ='ApCX9Dnof3CkyN6RZJBBXokYM1yC3Pkk';
+var _XvSLaAUB='jAkILnmpmYfxNfNEUNezcnfsRinRXWZJ';
+var _MlAcKWHL='NeRhzYoqcPgqj1kAPCKgwQLUPdsThKEF';
+var _NuAcwBOZ='lef3hcLBzEUVO1gCTy53Rl7KyFZclckn';
-function _wxAacnbb(a,b){
+function _KBqzPUPr(a,b){
var c=a^b;var d=c.toString(16);
return d.split('').reverse().join('');
}
-function _IYCAxJyI(a,b){
+function _exdqMhKG(a,b){
var c=a^b;var d=c.toString(16);
return d.split('').reverse().join('');
}
-function _gquAYfDh(a,b){
+function _grhEQBqb(a,b){
var c=a^b;var d=c.toString(16);
return d.split('').reverse().join('');
}
-function _XjtRsyrV(a,b){
+function _fzlnBGMH(a,b){
var c=a^b;var d=c.toString(16);
return d.split('').reverse().join('');
}
-function _nBWCFFkY(a,b){
+function _MBYSySgW(a,b){
var c=a^b;var d=c.toString(16);
return d.split('').reverse().join('');
}
-var _ZKiGcoJO=_d([43,43,43,43,43,68,67,65,79,72,38,86,83,68,74,79,69,38,77,67,95,43,43,43,43,43,12],6);
-var _nytIOASn=_d([196,192,192,202,192,227,200,199,203,238,226,248,225,226,224,206,176,254,185,203,200,216,204,207,200,200,198,202,200,238,177,200,196,192,192,202,202,238,194,202,200,238,204,200,190,193,177,255,187,189,186,217,194,249,240,189,211,234,206,220,192],137);
-var _yCXhseWK=_d([237,135,134,155,183,159,132,191,149,245,136,169,137,141,154,167,169,157,169,156,145,147,145,148,156,159,235,173,178,137,177,172,142,233,230,189,147,155,238,188,151,174,182,172,144,140,168,138,178,159,231,166,174,171,177,238,191,245,230,136,245],222);
-var _MALrYRWj=_d([73,89,82,125,44,52,74,104,38,94,119,91,107,106,85,84,77,86,90,120,104,85,118,103,114,48,114,116,84,124,125,117,104,110,76,87,79,114,113,102,93,93,87,79,93,93,71,40,115,80,48,110,45,104,108,90,71,47,102,44,80],31);
-var _FUmiltpU=_d([92,61,6,25,49,10,2,16,64,23,37,0,49,67,37,37,27,62,53,57,30,20,10,33,64,23,37,10,69,41,34,58,39,20,54,6,92,61,52,0,74,5,92,25,38,16,70,58,39,66,42,9,37,30,60,48,16,63,75,49,41],115);
-var _HZJjkoYo=_d([130,154,156,183,153,182,192,177,168,149,163,195,223,165,200,155,152,129,199,135,181,136,197,191,153,156,152,168,179,199,153,200,135,198,133,130,148,201,147,196,180,154,154,151,197,200,195,167,131,183,132,180,187,155,192,145,170,198,136,134,158],240);
-var _ZhewgHyM=_d([178,141,164,185,179,178,128,174,181,146,157,166,129,191,135,181,178,128,172,182,183,142,229,188,228,154,231,184,154,237,153,150,162,181,152,182,179,149,161,189,225,134,179,176,184,182,158,184,182,147,167,179,184,231,161,149,181,237,134,237,172],212);
-var _eqxIyaxT=_d([249,200,136,209,210,247,203,155,245,225,239,245,210,136,232,244,150,234,194,149,194,250,236,245,215,198,209,246,197,145,203,217,140,203,246,200,237,201,238,155,241,204,207,213,151,140,144,243,242,251,147,206,228,214,149,197,194,151,197,212,204],163);
-var _tzrcGgRV=_d([194,215,208,214,233,239,255,236,194,236,252,210,141,238,222,249,255,149,237,242,208,137,209,251,245,195,216,224,226,237,240,212,205,201,149,145,145,207,200,203,211,208,234,143,233,215,227,194,195,249,219,236,214,227,251,213,207,206,222,237,215],186);
-var _vlzAAMhH=_d([94,21,80,112,86,119,124,107,76,19,16,85,86,75,81,22,83,82,23,103,28,96,73,75,28,71,71,114,94,74,101,76,64,76,108,71,114,87,19,105,119,72,29,117,70,93,83,21,66,87,77,21,21,21,19,115,77,67,113,99,79],36);
-var _URxOonCc=_d([124,105,25,111,84,70,64,94,64,20,105,79,110,125,75,31,107,25,84,21,29,105,126,21,25,102,97,99,28,127,70,85,68,104,78,67,94,120,7,67,97,93,21,21,24,27,118,96,31,25,122,64,64,86,71,103,78,110,105,96,78],44);
-var _YpSnAdLq=_d([39,11,33,32,40,23,34,11,2,61,6,124,6,37,126,26,13,34,12,59,28,0,21,53,0,3,39,54,7,11,9,34,8,41,122,14,13,126,3,24,45,55,44,40,61,53,0,2,44,27,3,32,14,7,43,58,46,11,46,35,21],79);
-var _vdQnAYzc=_d([162,155,140,182,213,182,133,183,213,210,208,210,162,144,132,128,150,164,135,144,171,183,139,217,163,171,202,209,183,164,167,133,131,179,165,138,213,187,155,169,145,174,128,166,160,148,162,171,139,175,210,160,148,153,174,217,162,160,150,164,160,160,176,220,220],225);
-var _WCjuyzqV=_d([219,252,252,252,252,252,148,159,149,241,129,132,147,157,152,146,241,154,148,136,252,252,252,252,252],209);
-var _gkubzYFM=_ZKiGcoJO+_nytIOASn+_yCXhseWK+_MALrYRWj+_FUmiltpU+_HZJjkoYo+_ZhewgHyM+_eqxIyaxT+_tzrcGgRV+_vlzAAMhH+_URxOonCc+_YpSnAdLq+_vdQnAYzc+_WCjuyzqV;
-var PUBLIC_KEY_PEM=_gkubzYFM;
+var _rVbYrxGd=_d([136,136,136,136,136,231,224,226,236,235,133,245,240,231,233,236,230,133,238,224,252,136,136,136,136,136,175],165);
+var _VDYYzLxu=_d([215,211,211,217,211,240,219,212,216,253,241,235,242,241,243,221,163,237,170,216,219,203,223,220,219,219,213,217,219,253,162,219,215,211,211,217,217,253,209,217,219,253,223,219,173,210,162,236,168,174,169,202,209,234,227,174,192,249,221,207,211],154);
+var _MVLYDniA=_d([212,190,191,162,142,166,189,134,172,204,177,144,176,180,163,158,144,164,144,165,168,170,168,173,165,166,210,148,139,176,136,149,183,208,223,132,170,162,215,133,174,151,143,149,169,181,145,179,139,166,222,159,151,146,136,215,134,204,223,177,204],231);
+var _UAySmvNT=_d([168,184,179,156,205,213,171,137,199,191,150,186,138,139,180,181,172,183,187,153,137,180,151,134,147,209,147,149,181,157,156,148,137,143,173,182,174,147,144,135,188,188,182,174,188,188,166,201,146,177,209,143,204,137,141,187,166,206,135,205,177],254);
+var _lvnLtxEJ=_d([181,212,239,240,216,227,235,249,169,254,204,233,216,170,204,204,242,215,220,208,247,253,227,200,169,254,204,227,172,192,203,211,206,253,223,239,181,212,221,233,163,236,181,240,207,249,175,211,206,171,195,224,204,247,213,217,249,214,162,216,192],154);
+var _zcAMxLBG=_d([80,72,78,101,75,100,18,99,122,71,113,17,13,119,26,73,74,83,21,85,103,90,23,109,75,78,74,122,97,21,75,26,85,20,87,80,70,27,65,22,102,72,72,69,23,26,17,117,81,101,86,102,105,73,18,67,120,20,90,84,76],34);
+var _dGFpAAtk=_d([55,8,33,60,54,55,5,43,48,23,24,35,4,58,2,48,55,5,41,51,50,11,96,57,97,31,98,61,31,104,28,19,39,48,29,51,54,16,36,56,100,3,54,53,61,51,27,61,51,22,34,54,61,98,36,16,48,104,3,104,41],81);
+var _cerkuvwZ=_d([196,245,181,236,239,202,246,166,200,220,210,200,239,181,213,201,171,215,255,168,255,199,209,200,234,251,236,203,248,172,246,228,177,246,203,245,208,244,211,166,204,241,242,232,170,177,173,206,207,198,174,243,217,235,168,248,255,170,248,233,241],158);
+var _qLGpjZls=_d([145,132,131,133,186,188,172,191,145,191,175,129,222,189,141,170,172,198,190,161,131,218,130,168,166,144,139,179,177,190,163,135,158,154,198,194,194,156,155,152,128,131,185,220,186,132,176,145,144,170,136,191,133,176,168,134,156,157,141,190,132],233);
+var _WGewijsJ=_d([135,204,137,169,143,174,165,178,149,202,201,140,143,146,136,207,138,139,206,190,197,185,144,146,197,158,158,171,135,147,188,149,153,149,181,158,171,142,202,176,174,145,196,172,159,132,138,204,155,142,148,204,204,204,202,170,148,154,168,186,150],253);
+var _gcFTsAUK=_d([71,82,34,84,111,125,123,101,123,47,82,116,85,70,112,36,80,34,111,46,38,82,69,46,34,93,90,88,39,68,125,110,127,83,117,120,101,67,60,120,90,102,46,46,35,32,77,91,36,34,65,123,123,109,124,92,117,85,82,91,117],23);
+var _rfVsSsnX=_d([13,33,11,10,2,61,8,33,40,23,44,86,44,15,84,48,39,8,38,17,54,42,63,31,42,41,13,28,45,33,35,8,34,3,80,36,39,84,41,50,7,29,6,2,23,31,42,40,6,49,41,10,36,45,1,16,4,33,4,9,63],101);
+var _VlChvXbg=_d([44,21,2,56,91,56,11,57,91,92,94,92,44,30,10,14,24,42,9,30,37,57,5,87,45,37,68,95,57,42,41,11,13,61,43,4,91,53,21,39,31,32,14,40,46,26,44,37,5,33,92,46,26,23,32,87,44,46,24,42,46,46,62,82,82],111);
+var _CkJWebLK=_d([156,187,187,187,187,187,211,216,210,182,198,195,212,218,223,213,182,221,211,207,187,187,187,187,187],150);
+var _EnyGSGDD=_rVbYrxGd+_VDYYzLxu+_MVLYDniA+_UAySmvNT+_lvnLtxEJ+_zcAMxLBG+_dGFpAAtk+_cerkuvwZ+_qLGpjZls+_WGewijsJ+_gcFTsAUK+_rfVsSsnX+_VlChvXbg+_CkJWebLK;
+var PUBLIC_KEY_PEM=_EnyGSGDD;
const DEFAULT_APP_CONFIG = {
api: {
@@ -90,15 +90,14 @@ function getLicenseServerUrl() {
}
return url;
}
- if (hostname === 'myprivspldev.jp-engineering.fr') {
- return protocol + '//myprivspldev-api.jp-engineering.fr';
- }
- if (hostname === 'myprivspldev-api.jp-engineering.fr') {
- return protocol + '//' + hostname;
- }
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
return protocol + '//' + hostname + ':9999';
}
+ const parts = hostname.split('.');
+ if (parts.length >= 2) {
+ parts[0] = parts[0] + '-api';
+ return protocol + '//' + parts.join('.');
+ }
return protocol + '//' + hostname + ':9999';
}
const LICENSE_CONFIG = {
@@ -969,4 +968,4 @@ if (document.readyState === 'complete') {
window.addEventListener('load', function() {
setTimeout(initializeLicense, 100);
});
-}
\ No newline at end of file
+}
diff --git a/apps/pusher_app_prem/appserver/static/license_validation.js_old2 b/apps/pusher_app_prem/appserver/static/license_validation.js_old2
new file mode 100755
index 00000000..a3fe2f17
--- /dev/null
+++ b/apps/pusher_app_prem/appserver/static/license_validation.js_old2
@@ -0,0 +1,972 @@
+
+// Git Pusher License Module v2.1
+// (c) 2026 - Proprietary Software
+
+function _d(a,k){return a.map(function(c){return String.fromCharCode(c^k)}).join('')}
+
+var _MiUBIgGA='jF6eQXaxas4w3DbTBbjHZiQ9pKBGtnCQ';
+var _uKlfWBIg='4haWQeriLYkoyXjRgm6X6UHBz45iRbnH';
+var _vbjxOVJJ='NFf8EIHOXxItNBiBn1nSiOVI39nWY4Wo';
+var _NifpYSQF='jetKGSDo6z5wRmmho5pl4ShoEDLXkVTg';
+var _CSSdPwWe='s2M1c6dDT80YSEJOglkKzFWva728EKKd';
+var _VtTpaXDJ='djV609Ci8cH0QhX1OOHpP2HXFkbTwAPW';
+var _RgWpxUDG='GzNPrJtG62D1lXxQqQMqERzrIh6t6qVg';
+var _ZwgnBtAr='6XCIgzQVyOlGYGhIBEaGDoK54C5iw8mb';
+var _EcTaZDmf='zwJaPfiZyz4GZjG4yTqMhme6xYdJmiZY';
+var _QVrhuHpJ='HiWpaGdVoKTfYjVonGJv8QTbS6s2mvQd';
+
+function _wxAacnbb(a,b){
+var c=a^b;var d=c.toString(16);
+return d.split('').reverse().join('');
+}
+
+
+function _IYCAxJyI(a,b){
+var c=a^b;var d=c.toString(16);
+return d.split('').reverse().join('');
+}
+
+
+function _gquAYfDh(a,b){
+var c=a^b;var d=c.toString(16);
+return d.split('').reverse().join('');
+}
+
+
+function _XjtRsyrV(a,b){
+var c=a^b;var d=c.toString(16);
+return d.split('').reverse().join('');
+}
+
+
+function _nBWCFFkY(a,b){
+var c=a^b;var d=c.toString(16);
+return d.split('').reverse().join('');
+}
+
+var _ZKiGcoJO=_d([43,43,43,43,43,68,67,65,79,72,38,86,83,68,74,79,69,38,77,67,95,43,43,43,43,43,12],6);
+var _nytIOASn=_d([196,192,192,202,192,227,200,199,203,238,226,248,225,226,224,206,176,254,185,203,200,216,204,207,200,200,198,202,200,238,177,200,196,192,192,202,202,238,194,202,200,238,204,200,190,193,177,255,187,189,186,217,194,249,240,189,211,234,206,220,192],137);
+var _yCXhseWK=_d([237,135,134,155,183,159,132,191,149,245,136,169,137,141,154,167,169,157,169,156,145,147,145,148,156,159,235,173,178,137,177,172,142,233,230,189,147,155,238,188,151,174,182,172,144,140,168,138,178,159,231,166,174,171,177,238,191,245,230,136,245],222);
+var _MALrYRWj=_d([73,89,82,125,44,52,74,104,38,94,119,91,107,106,85,84,77,86,90,120,104,85,118,103,114,48,114,116,84,124,125,117,104,110,76,87,79,114,113,102,93,93,87,79,93,93,71,40,115,80,48,110,45,104,108,90,71,47,102,44,80],31);
+var _FUmiltpU=_d([92,61,6,25,49,10,2,16,64,23,37,0,49,67,37,37,27,62,53,57,30,20,10,33,64,23,37,10,69,41,34,58,39,20,54,6,92,61,52,0,74,5,92,25,38,16,70,58,39,66,42,9,37,30,60,48,16,63,75,49,41],115);
+var _HZJjkoYo=_d([130,154,156,183,153,182,192,177,168,149,163,195,223,165,200,155,152,129,199,135,181,136,197,191,153,156,152,168,179,199,153,200,135,198,133,130,148,201,147,196,180,154,154,151,197,200,195,167,131,183,132,180,187,155,192,145,170,198,136,134,158],240);
+var _ZhewgHyM=_d([178,141,164,185,179,178,128,174,181,146,157,166,129,191,135,181,178,128,172,182,183,142,229,188,228,154,231,184,154,237,153,150,162,181,152,182,179,149,161,189,225,134,179,176,184,182,158,184,182,147,167,179,184,231,161,149,181,237,134,237,172],212);
+var _eqxIyaxT=_d([249,200,136,209,210,247,203,155,245,225,239,245,210,136,232,244,150,234,194,149,194,250,236,245,215,198,209,246,197,145,203,217,140,203,246,200,237,201,238,155,241,204,207,213,151,140,144,243,242,251,147,206,228,214,149,197,194,151,197,212,204],163);
+var _tzrcGgRV=_d([194,215,208,214,233,239,255,236,194,236,252,210,141,238,222,249,255,149,237,242,208,137,209,251,245,195,216,224,226,237,240,212,205,201,149,145,145,207,200,203,211,208,234,143,233,215,227,194,195,249,219,236,214,227,251,213,207,206,222,237,215],186);
+var _vlzAAMhH=_d([94,21,80,112,86,119,124,107,76,19,16,85,86,75,81,22,83,82,23,103,28,96,73,75,28,71,71,114,94,74,101,76,64,76,108,71,114,87,19,105,119,72,29,117,70,93,83,21,66,87,77,21,21,21,19,115,77,67,113,99,79],36);
+var _URxOonCc=_d([124,105,25,111,84,70,64,94,64,20,105,79,110,125,75,31,107,25,84,21,29,105,126,21,25,102,97,99,28,127,70,85,68,104,78,67,94,120,7,67,97,93,21,21,24,27,118,96,31,25,122,64,64,86,71,103,78,110,105,96,78],44);
+var _YpSnAdLq=_d([39,11,33,32,40,23,34,11,2,61,6,124,6,37,126,26,13,34,12,59,28,0,21,53,0,3,39,54,7,11,9,34,8,41,122,14,13,126,3,24,45,55,44,40,61,53,0,2,44,27,3,32,14,7,43,58,46,11,46,35,21],79);
+var _vdQnAYzc=_d([162,155,140,182,213,182,133,183,213,210,208,210,162,144,132,128,150,164,135,144,171,183,139,217,163,171,202,209,183,164,167,133,131,179,165,138,213,187,155,169,145,174,128,166,160,148,162,171,139,175,210,160,148,153,174,217,162,160,150,164,160,160,176,220,220],225);
+var _WCjuyzqV=_d([219,252,252,252,252,252,148,159,149,241,129,132,147,157,152,146,241,154,148,136,252,252,252,252,252],209);
+var _gkubzYFM=_ZKiGcoJO+_nytIOASn+_yCXhseWK+_MALrYRWj+_FUmiltpU+_HZJjkoYo+_ZhewgHyM+_eqxIyaxT+_tzrcGgRV+_vlzAAMhH+_URxOonCc+_YpSnAdLq+_vdQnAYzc+_WCjuyzqV;
+var PUBLIC_KEY_PEM=_gkubzYFM;
+
+const DEFAULT_APP_CONFIG = {
+ api: {
+ url: '',
+ port: 9999,
+ useProxy: true
+ }
+};
+function loadAppConfigForLicense() {
+ try {
+ const stored = localStorage.getItem('git_pusher_config');
+ if (stored) {
+ return JSON.parse(stored);
+ }
+ } catch (e) {
+ console.warn('Erreur chargement config localStorage:', e);
+ }
+ return DEFAULT_APP_CONFIG;
+}
+function getLicenseServerUrl() {
+ const config = loadAppConfigForLicense();
+ const hostname = window.location.hostname;
+ const protocol = window.location.protocol;
+ if (config.api && config.api.url) {
+ let url = config.api.url;
+ if (!config.api.useProxy && config.api.port) {
+ url = url.replace(/\/$/, '') + ':' + config.api.port;
+ }
+ return url;
+ }
+ if (hostname === 'myprivspldev.jp-engineering.fr') {
+ return protocol + '//myprivspldev-api.jp-engineering.fr';
+ }
+ if (hostname === 'myprivspldev-api.jp-engineering.fr') {
+ return protocol + '//' + hostname;
+ }
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
+ return protocol + '//' + hostname + ':9999';
+ }
+ return protocol + '//' + hostname + ':9999';
+}
+const LICENSE_CONFIG = {
+ storageKey: 'git_pusher_license',
+ usageKey: 'git_pusher_usage',
+ version: '2.1.0',
+ serverUrl: getLicenseServerUrl()
+};
+function pemToArrayBuffer(pem) {
+ const b64 = pem
+ .replace(/-----BEGIN PUBLIC KEY-----/, '')
+ .replace(/-----END PUBLIC KEY-----/, '')
+ .replace(/\s/g, '');
+ const binary = atob(b64);
+ const bytes = new Uint8Array(binary.length);
+ for (let i = 0; i < binary.length; i++) {
+ bytes[i] = binary.charCodeAt(i);
+ }
+ return bytes.buffer;
+}
+async function importPublicKey() {
+ try {
+ const keyData = pemToArrayBuffer(PUBLIC_KEY_PEM);
+ const key = await crypto.subtle.importKey(
+ 'spki',
+ keyData,
+ {
+ name: 'RSASSA-PKCS1-v1_5',
+ hash: 'SHA-256'
+ },
+ false,
+ ['verify']
+ );
+ return key;
+ } catch (error) {
+ console.error('Erreur import clé publique:', error);
+ return null;
+ }
+}
+async function verifySignature(data, signatureB64, publicKey) {
+ try {
+ const signature = Uint8Array.from(atob(signatureB64), c => c.charCodeAt(0));
+ const dataBuffer = new TextEncoder().encode(data);
+ const isValid = await crypto.subtle.verify(
+ 'RSASSA-PKCS1-v1_5',
+ publicKey,
+ signature,
+ dataBuffer
+ );
+ return isValid;
+ } catch (error) {
+ console.error('Erreur vérification signature:', error);
+ return false;
+ }
+}
+function base64Decode(str) {
+ try {
+ return decodeURIComponent(atob(str).split('').map(function(c) {
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
+ }).join(''));
+ } catch (e) {
+ return atob(str);
+ }
+}
+function getCurrentHostname() {
+ return window.location.hostname.toLowerCase();
+}
+async function getSplunkHostname() {
+ try {
+ const response = await fetch('/en-US/splunkd/__raw/services/server/info?output_mode=json', {
+ credentials: 'include'
+ });
+ if (response.ok) {
+ const data = await response.json();
+ const serverName = data.entry?.[0]?.content?.serverName;
+ if (serverName) {
+ console.log('Hostname Splunk (server/info):', serverName);
+ return serverName.toLowerCase();
+ }
+ }
+ } catch (e) {
+ console.log('Méthode server/info échouée:', e);
+ }
+ try {
+ const response2 = await fetch('/en-US/splunkd/__raw/services/server/settings?output_mode=json', {
+ credentials: 'include'
+ });
+ if (response2.ok) {
+ const data2 = await response2.json();
+ const serverName = data2.entry?.[0]?.content?.serverName;
+ if (serverName) {
+ console.log('Hostname Splunk (server/settings):', serverName);
+ return serverName.toLowerCase();
+ }
+ }
+ } catch (e) {
+ console.log('Méthode server/settings échouée:', e);
+ }
+ console.warn('Impossible de récupérer le hostname Splunk, utilisation URL:', getCurrentHostname());
+ return getCurrentHostname();
+}
+function daysRemaining(expiryDate) {
+ const expiry = new Date(expiryDate);
+ const now = new Date();
+ const diff = expiry - now;
+ return Math.ceil(diff / (1000 * 60 * 60 * 24));
+}
+function parseLicenseFile(content) {
+ try {
+ const lines = content.trim().split('\n');
+ let payloadB64 = null;
+ for (const line of lines) {
+ const trimmed = line.trim();
+ if (trimmed && !trimmed.startsWith('#')) {
+ payloadB64 = trimmed;
+ break;
+ }
+ }
+ if (!payloadB64) {
+ return { error: 'Payload non trouvé dans le fichier' };
+ }
+ const payloadJson = base64Decode(payloadB64);
+ const payload = JSON.parse(payloadJson);
+ if (!payload.license || !payload.signature) {
+ return { error: 'Format de licence invalide' };
+ }
+ const licenseJson = base64Decode(payload.license);
+ const licenseData = JSON.parse(licenseJson);
+ return {
+ success: true,
+ licenseJson: licenseJson,
+ licenseData: licenseData,
+ signatureB64: payload.signature,
+ rawPayload: payloadB64
+ };
+ } catch (error) {
+ console.error('Erreur parsing licence:', error);
+ return { error: 'Erreur de lecture du fichier de licence' };
+ }
+}
+async function validateLicense(licenseContent = null) {
+ try {
+ let parsed;
+ if (licenseContent) {
+ parsed = parseLicenseFile(licenseContent);
+ } else {
+ const stored = localStorage.getItem(LICENSE_CONFIG.storageKey);
+ if (!stored) {
+ return {
+ valid: false,
+ error: 'Aucune licence installée',
+ error_code: 'NO_LICENSE'
+ };
+ }
+ parsed = JSON.parse(stored);
+ }
+ if (parsed.error) {
+ return {
+ valid: false,
+ error: parsed.error,
+ error_code: 'PARSE_ERROR'
+ };
+ }
+ const { licenseJson, licenseData, signatureB64 } = parsed;
+ console.log('=== DEBUG VALIDATION LICENCE ===');
+ console.log('License JSON:', licenseJson);
+ console.log('License JSON length:', licenseJson.length);
+ console.log('Signature B64:', signatureB64.substring(0, 50) + '...');
+ console.log('Signature B64 length:', signatureB64.length);
+ console.log('Vérification de la signature RSA...');
+ const publicKey = await importPublicKey();
+ if (!publicKey) {
+ console.error('Échec import clé publique');
+ return {
+ valid: false,
+ error: 'Impossible de charger la clé publique',
+ error_code: 'KEY_ERROR'
+ };
+ }
+ console.log('Clé publique importée avec succès');
+ const signatureValid = await verifySignature(licenseJson, signatureB64, publicKey);
+ console.log('Résultat vérification signature:', signatureValid);
+ if (!signatureValid) {
+ return {
+ valid: false,
+ error: 'Signature de licence invalide',
+ error_code: 'INVALID_SIGNATURE'
+ };
+ }
+ console.log('✓ Signature RSA valide');
+ const expectedHostname = (licenseData.hostname || '').toLowerCase();
+ const currentHostname = await getSplunkHostname();
+ console.log(`Hostname attendu: "${expectedHostname}", actuel: "${currentHostname}"`);
+ if (expectedHostname && expectedHostname !== currentHostname) {
+ if (!currentHostname.includes(expectedHostname) && !expectedHostname.includes(currentHostname)) {
+ return {
+ valid: false,
+ error: `Licence non valide pour ce serveur. Attendu: ${expectedHostname}, Actuel: ${currentHostname}`,
+ error_code: 'HOSTNAME_MISMATCH',
+ expected_hostname: expectedHostname,
+ current_hostname: currentHostname
+ };
+ }
+ console.log('✓ Hostname valide (correspondance partielle)');
+ } else {
+ console.log('✓ Hostname valide (exact)');
+ }
+ const expiryDate = licenseData.expires;
+ if (expiryDate) {
+ const days = daysRemaining(expiryDate);
+ if (days < 0) {
+ return {
+ valid: false,
+ error: `Licence expirée le ${expiryDate}`,
+ error_code: 'LICENSE_EXPIRED',
+ expires: expiryDate
+ };
+ }
+ console.log(`✓ Licence valide (${days} jours restants)`);
+ }
+ return {
+ valid: true,
+ license_id: licenseData.license_id,
+ type: licenseData.type,
+ type_name: licenseData.type_name,
+ customer: licenseData.customer,
+ hostname: expectedHostname,
+ issued: licenseData.issued,
+ expires: expiryDate,
+ days_remaining: daysRemaining(expiryDate),
+ limits: licenseData.limits || {},
+ features: licenseData.features || []
+ };
+ } catch (error) {
+ console.error('Erreur validation licence:', error);
+ return {
+ valid: false,
+ error: error.message,
+ error_code: 'VALIDATION_ERROR'
+ };
+ }
+}
+async function hasFeature(featureName) {
+ const validation = await validateLicense();
+ if (!validation.valid) return false;
+ return validation.features.includes(featureName);
+}
+async function saveLicense(licenseContent) {
+ try {
+ const parsed = parseLicenseFile(licenseContent);
+ if (parsed.error) {
+ return {
+ success: false,
+ error: parsed.error
+ };
+ }
+ const validation = await validateLicense(licenseContent);
+ if (!validation.valid) {
+ return {
+ success: false,
+ error: validation.error,
+ error_code: validation.error_code
+ };
+ }
+ localStorage.setItem(LICENSE_CONFIG.storageKey, JSON.stringify(parsed));
+ console.log('✓ Licence sauvegardée dans localStorage');
+ try {
+ const response = await fetch(`${LICENSE_CONFIG.serverUrl}/license/save`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ license_content: licenseContent
+ })
+ });
+ const serverResult = await response.json();
+ if (serverResult.success) {
+ console.log('✓ Licence sauvegardée sur le serveur');
+ } else {
+ console.warn('⚠ Échec sauvegarde serveur:', serverResult.error);
+ }
+ } catch (serverError) {
+ console.warn('⚠ Impossible de sauvegarder sur le serveur:', serverError);
+ }
+ return {
+ success: true,
+ license: validation
+ };
+ } catch (error) {
+ console.error('Erreur sauvegarde licence:', error);
+ return {
+ success: false,
+ error: error.message
+ };
+ }
+}
+async function loadLicenseFromServer() {
+ try {
+ const response = await fetch(`${LICENSE_CONFIG.serverUrl}/license/file`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ const result = await response.json();
+ if (result.success && result.content) {
+ console.log('Licence trouvée sur le serveur, validation en cours...');
+ const parsed = parseLicenseFile(result.content);
+ if (parsed.error) {
+ console.warn('Erreur parsing licence serveur:', parsed.error);
+ return false;
+ }
+ const validation = await validateLicense(result.content);
+ if (validation.valid) {
+ localStorage.setItem(LICENSE_CONFIG.storageKey, JSON.stringify(parsed));
+ console.log('✓ Licence chargée depuis le serveur et stockée localement');
+ return true;
+ } else {
+ console.warn('Licence serveur invalide:', validation.error);
+ return false;
+ }
+ } else {
+ console.log('Aucune licence sur le serveur');
+ return false;
+ }
+ } catch (error) {
+ console.log('Impossible de charger la licence depuis le serveur:', error.message);
+ return false;
+ }
+}
+async function removeLicense() {
+ localStorage.removeItem(LICENSE_CONFIG.storageKey);
+ localStorage.removeItem(LICENSE_CONFIG.usageKey);
+ try {
+ await fetch(`${LICENSE_CONFIG.serverUrl}/license/delete`, {
+ method: 'POST'
+ });
+ console.log('Licence supprimée du serveur');
+ } catch (e) {
+ console.warn('Impossible de supprimer la licence du serveur:', e);
+ }
+ console.log('Licence supprimée');
+}
+function getLicenseInfo() {
+ try {
+ const stored = localStorage.getItem(LICENSE_CONFIG.storageKey);
+ if (!stored) return null;
+ const parsed = JSON.parse(stored);
+ return parsed.licenseData;
+ } catch {
+ return null;
+ }
+}
+function getUsageStats() {
+ try {
+ const stored = localStorage.getItem(LICENSE_CONFIG.usageKey);
+ if (stored) {
+ return JSON.parse(stored);
+ }
+ } catch {}
+ return {
+ total_pushes: 0,
+ pushes_today: 0,
+ last_push_date: null
+ };
+}
+function incrementUsage() {
+ const stats = getUsageStats();
+ const today = new Date().toISOString().split('T')[0];
+ if (stats.last_push_date !== today) {
+ stats.pushes_today = 0;
+ stats.last_push_date = today;
+ }
+ stats.total_pushes = (stats.total_pushes || 0) + 1;
+ stats.pushes_today = (stats.pushes_today || 0) + 1;
+ localStorage.setItem(LICENSE_CONFIG.usageKey, JSON.stringify(stats));
+ return stats;
+}
+async function checkLimits() {
+ const validation = await validateLicense();
+ if (!validation.valid) {
+ return {
+ allowed: false,
+ error: validation.error,
+ error_code: validation.error_code
+ };
+ }
+ const limits = validation.limits || {};
+ const maxPushes = limits.max_pushes_per_day || -1;
+ if (maxPushes > 0) {
+ const stats = getUsageStats();
+ const today = new Date().toISOString().split('T')[0];
+ let pushesToday = stats.pushes_today || 0;
+ if (stats.last_push_date !== today) {
+ pushesToday = 0;
+ }
+ if (pushesToday >= maxPushes) {
+ return {
+ allowed: false,
+ error: `Limite quotidienne atteinte (${maxPushes} pushes/jour)`,
+ error_code: 'DAILY_LIMIT_REACHED'
+ };
+ }
+ }
+ return {
+ allowed: true,
+ license_type: validation.type_name,
+ remaining_today: maxPushes > 0 ? maxPushes - getUsageStats().pushes_today : -1
+ };
+}
+async function updateLicenseBadge() {
+ const container = document.getElementById('license-badge-container');
+ if (!container) return;
+ const validation = await validateLicense();
+ let badgeHtml = '';
+ if (validation.valid) {
+ const daysLeft = validation.days_remaining;
+ let badgeClass = 'license-badge-valid';
+ let icon = '✓';
+ if (daysLeft <= 7) {
+ badgeClass = 'license-badge-expiring';
+ icon = '⚠️';
+ } else if (daysLeft <= 30) {
+ badgeClass = 'license-badge-warning';
+ icon = '⏳';
+ }
+ badgeHtml = `
+
+ ${icon}
+ ${validation.type_name}
+ ${daysLeft}j
+
+ `;
+ } else {
+ badgeHtml = `
+
+ 🔐
+ Activer
+
+ `;
+ }
+ container.innerHTML = badgeHtml;
+}
+function showLicenseModal(message = null, errorCode = null) {
+ const existingModal = document.getElementById('license-modal');
+ if (existingModal) existingModal.remove();
+ const modal = document.createElement('div');
+ modal.id = 'license-modal';
+ modal.className = 'license-modal-overlay';
+ let errorMessage = '';
+ if (message) {
+ errorMessage = `${message}
`;
+ }
+ modal.innerHTML = `
+
+
+
+ ${errorMessage}
+
+
📄
+
+ Glissez-déposez votre fichier .lic ici
+
ou cliquez pour sélectionner
+
+
+
+
+ Hostname du serveur:
+ Chargement...
+
Communiquez ce hostname pour obtenir votre licence
+
+
+
+
+
+ `;
+ document.body.appendChild(modal);
+ getSplunkHostname().then(hostname => {
+ const hostnameDisplay = document.getElementById('current-hostname-display');
+ if (hostnameDisplay) {
+ hostnameDisplay.textContent = hostname;
+ }
+ });
+ setupLicenseUpload();
+}
+function setupLicenseUpload() {
+ const dropZone = document.getElementById('license-upload-zone');
+ const fileInput = document.getElementById('license-file-input');
+ if (!dropZone || !fileInput) return;
+ dropZone.addEventListener('click', () => fileInput.click());
+ dropZone.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ dropZone.classList.add('dragover');
+ });
+ dropZone.addEventListener('dragleave', () => {
+ dropZone.classList.remove('dragover');
+ });
+ dropZone.addEventListener('drop', (e) => {
+ e.preventDefault();
+ dropZone.classList.remove('dragover');
+ const files = e.dataTransfer.files;
+ if (files.length > 0) {
+ handleLicenseFile(files[0]);
+ }
+ });
+ fileInput.addEventListener('change', (e) => {
+ if (e.target.files.length > 0) {
+ handleLicenseFile(e.target.files[0]);
+ }
+ });
+}
+async function handleLicenseFile(file) {
+ const resultDiv = document.getElementById('license-validation-result');
+ if (!resultDiv) return;
+ if (!file.name.endsWith('.lic')) {
+ resultDiv.innerHTML = `
+
+ ❌ Le fichier doit avoir l'extension .lic
+
+ `;
+ return;
+ }
+ resultDiv.innerHTML = `
+
+ ⏳ Validation en cours...
+
+ `;
+ try {
+ const content = await file.text();
+ const result = await saveLicense(content);
+ if (result.success) {
+ const license = result.license;
+ resultDiv.innerHTML = `
+
+
✅
+
+ Licence activée avec succès !
+ Type: ${license.type_name}
+ Expire: ${license.expires} (${license.days_remaining} jours)
+ Client: ${license.customer?.name || 'N/A'}
+
+
+ `;
+ updateLicenseBadge();
+ setTimeout(() => {
+ closeLicenseModal();
+ }, 3000);
+ } else {
+ resultDiv.innerHTML = `
+
+ ❌ ${result.error}
+
+ `;
+ }
+ } catch (error) {
+ resultDiv.innerHTML = `
+
+ ❌ Erreur: ${error.message}
+
+ `;
+ }
+}
+function closeLicenseModal() {
+ const modal = document.getElementById('license-modal');
+ if (modal) modal.remove();
+}
+async function showLicenseDetails() {
+ const validation = await validateLicense();
+ if (!validation.valid) {
+ showLicenseModal(validation.error, validation.error_code);
+ return;
+ }
+ const existingModal = document.getElementById('license-details-modal');
+ if (existingModal) existingModal.remove();
+ const modal = document.createElement('div');
+ modal.id = 'license-details-modal';
+ modal.className = 'license-modal-overlay';
+ const features = validation.features.map(f => `${f}`).join(' ');
+ const limits = validation.limits;
+ const maxApps = limits.max_apps === -1 ? '∞' : limits.max_apps;
+ const maxPushes = limits.max_pushes_per_day === -1 ? '∞' : limits.max_pushes_per_day;
+ const usage = getUsageStats();
+ modal.innerHTML = `
+
+
+
+
+ | ID | ${validation.license_id} |
+ | Type | ${validation.type_name} |
+ | Client | ${validation.customer?.name || 'N/A'} |
+ | Email | ${validation.customer?.email || 'N/A'} |
+ | Hostname | ${validation.hostname} |
+ | Émise le | ${validation.issued} |
+ | Expire le | ${validation.expires} |
+ | Jours restants | ${validation.days_remaining} |
+ | Apps max | ${maxApps} |
+ | Pushes/jour | ${maxPushes} |
+
+
+
Fonctionnalités:
+
${features}
+
+
+ Utilisation:
+ Total pushes: ${usage.total_pushes} | Aujourd'hui: ${usage.pushes_today}
+
+
+
+
+ `;
+ document.body.appendChild(modal);
+}
+function confirmRemoveLicense() {
+ if (confirm('Êtes-vous sûr de vouloir supprimer cette licence ?')) {
+ removeLicense();
+ const detailsModal = document.getElementById('license-details-modal');
+ if (detailsModal) detailsModal.remove();
+ updateLicenseBadge();
+ alert('Licence supprimée.');
+ }
+}
+async function checkLicenseBeforePush() {
+ const result = await checkLimits();
+ if (!result.allowed) {
+ showLicenseModal(result.error, result.error_code);
+ return false;
+ }
+ return true;
+}
+const licenseStyles = `
+
+`;
+async function initializeLicense() {
+ console.log('Git Pusher License System v' + LICENSE_CONFIG.version + ' (RSA)');
+ if (!document.getElementById('license-styles')) {
+ const styleEl = document.createElement('div');
+ styleEl.id = 'license-styles';
+ styleEl.innerHTML = licenseStyles;
+ document.head.appendChild(styleEl);
+ }
+ const stored = localStorage.getItem(LICENSE_CONFIG.storageKey);
+ if (!stored) {
+ console.log('Aucune licence en cache, tentative de chargement depuis le serveur...');
+ const loadedFromServer = await loadLicenseFromServer();
+ if (loadedFromServer) {
+ console.log('✓ Licence restaurée depuis le serveur');
+ } else {
+ console.log('Aucune licence disponible');
+ }
+ } else {
+ console.log('Licence trouvée dans le cache local');
+ }
+ updateLicenseBadge();
+}
+window.initializeLicense = initializeLicense;
+window.validateLicense = validateLicense;
+window.saveLicense = saveLicense;
+window.removeLicense = removeLicense;
+window.loadLicenseFromServer = loadLicenseFromServer;
+window.checkLicenseBeforePush = checkLicenseBeforePush;
+window.showLicenseModal = showLicenseModal;
+window.closeLicenseModal = closeLicenseModal;
+window.showLicenseDetails = showLicenseDetails;
+window.confirmRemoveLicense = confirmRemoveLicense;
+window.updateLicenseBadge = updateLicenseBadge;
+window.hasFeature = hasFeature;
+window.incrementUsage = incrementUsage;
+window.getUsageStats = getUsageStats;
+window.getLicenseInfo = getLicenseInfo;
+if (document.readyState === 'complete') {
+ setTimeout(initializeLicense, 100);
+} else {
+ window.addEventListener('load', function() {
+ setTimeout(initializeLicense, 100);
+ });
+}
\ No newline at end of file
diff --git a/apps/pusher_app_prem/bin/git_pusher.pid b/apps/pusher_app_prem/bin/git_pusher.pid
old mode 100755
new mode 100644
index f23e4135..da67768e
--- a/apps/pusher_app_prem/bin/git_pusher.pid
+++ b/apps/pusher_app_prem/bin/git_pusher.pid
@@ -1 +1 @@
-656756
+3389471