Add SSL certificate provisioning button for superadmin
- New provision_ssl API endpoint runs certbot for new domains - SSL button appears next to domain textarea for superadmin - Shell script on server handles Apache config + Let's Encrypt - DNS check skips domains without resolution to avoid certbot errors Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
32
api.php
32
api.php
@@ -4256,6 +4256,38 @@ switch ($action) {
|
|||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'provision_ssl':
|
||||||
|
requireSuperAdmin();
|
||||||
|
if ($method !== 'POST') break;
|
||||||
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
$domains = $input['domains'] ?? [];
|
||||||
|
if (empty($domains)) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Domainit puuttuvat']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Validoi domainit
|
||||||
|
foreach ($domains as $d) {
|
||||||
|
if (!preg_match('/^[a-z0-9.-]+\.[a-z]{2,}$/', $d)) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => "Virheellinen domain: $d"]);
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Suorita provisiointi shell-skriptinä
|
||||||
|
$escapedDomains = array_map('escapeshellarg', $domains);
|
||||||
|
$domainList = implode(' ', $escapedDomains);
|
||||||
|
$output = [];
|
||||||
|
$exitCode = 0;
|
||||||
|
exec("sudo /usr/local/bin/provision-ssl.sh $domainList 2>&1", $output, $exitCode);
|
||||||
|
if ($exitCode !== 0) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['error' => 'SSL-provisiointi epäonnistui: ' . implode("\n", $output)]);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => true, 'message' => 'SSL-sertifikaatti päivitetty: ' . implode(', ', $domains)]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'company_switch':
|
case 'company_switch':
|
||||||
requireAuth();
|
requireAuth();
|
||||||
if ($method !== 'POST') break;
|
if ($method !== 'POST') break;
|
||||||
|
|||||||
@@ -1673,6 +1673,8 @@
|
|||||||
<div class="form-group full-width">
|
<div class="form-group full-width">
|
||||||
<label>Domainit (yksi per rivi)</label>
|
<label>Domainit (yksi per rivi)</label>
|
||||||
<textarea id="company-edit-domains" rows="3" placeholder="intra.yritys.fi intra.toinen.fi" style="font-family:monospace;font-size:0.85rem;"></textarea>
|
<textarea id="company-edit-domains" rows="3" placeholder="intra.yritys.fi intra.toinen.fi" style="font-family:monospace;font-size:0.85rem;"></textarea>
|
||||||
|
<button class="btn-secondary" id="btn-provision-ssl" style="display:none;margin-top:0.5rem;font-size:0.82rem;" title="Lisää domainit Apache-configiin ja päivitä Let's Encrypt -sertifikaatti">🔒 Päivitä SSL-sertifikaatti</button>
|
||||||
|
<small id="ssl-provision-status" style="display:none;margin-top:0.25rem;color:#888;"></small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Moduulit (vain superadmin) -->
|
<!-- Moduulit (vain superadmin) -->
|
||||||
|
|||||||
26
script.js
26
script.js
@@ -2908,6 +2908,8 @@ async function showCompanyDetail(id) {
|
|||||||
if (modulesSection) modulesSection.style.display = isSA ? '' : 'none';
|
if (modulesSection) modulesSection.style.display = isSA ? '' : 'none';
|
||||||
if (integrationsSection) integrationsSection.style.display = isSA ? '' : 'none';
|
if (integrationsSection) integrationsSection.style.display = isSA ? '' : 'none';
|
||||||
if (ipsSection) ipsSection.style.display = isSA ? '' : 'none';
|
if (ipsSection) ipsSection.style.display = isSA ? '' : 'none';
|
||||||
|
const sslBtn = document.getElementById('btn-provision-ssl');
|
||||||
|
if (sslBtn) sslBtn.style.display = isSA ? '' : 'none';
|
||||||
|
|
||||||
// Moduuli-checkboxit (yhteensopivuus: vanha 'devices' → 'tekniikka')
|
// Moduuli-checkboxit (yhteensopivuus: vanha 'devices' → 'tekniikka')
|
||||||
let enabledMods = comp?.enabled_modules || [];
|
let enabledMods = comp?.enabled_modules || [];
|
||||||
@@ -3203,6 +3205,30 @@ document.getElementById('btn-save-company-settings').addEventListener('click', a
|
|||||||
} catch (e) { alert(e.message); }
|
} catch (e) { alert(e.message); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// SSL-sertifikaatin provisiointi (superadmin)
|
||||||
|
document.getElementById('btn-provision-ssl')?.addEventListener('click', async () => {
|
||||||
|
const domains = document.getElementById('company-edit-domains').value.trim().split('\n').map(d => d.trim()).filter(Boolean);
|
||||||
|
if (!domains.length) { alert('Lisää ensin domainit!'); return; }
|
||||||
|
if (!confirm('Päivitetäänkö Apache-config ja Let\'s Encrypt -sertifikaatti seuraavilla domaineilla?\n\n' + domains.join('\n'))) return;
|
||||||
|
const btn = document.getElementById('btn-provision-ssl');
|
||||||
|
const status = document.getElementById('ssl-provision-status');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = '⏳ Provisioidaan...';
|
||||||
|
status.style.display = 'block';
|
||||||
|
status.textContent = 'Päivitetään Apache-config ja Let\'s Encrypt...';
|
||||||
|
try {
|
||||||
|
const result = await apiCall('provision_ssl', 'POST', { domains });
|
||||||
|
status.style.color = '#27ae60';
|
||||||
|
status.textContent = '✅ ' + (result.message || 'SSL-sertifikaatti päivitetty!');
|
||||||
|
} catch (e) {
|
||||||
|
status.style.color = '#e74c3c';
|
||||||
|
status.textContent = '❌ ' + e.message;
|
||||||
|
} finally {
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = '🔒 Päivitä SSL-sertifikaatti';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ==================== POSTILAATIKOT ====================
|
// ==================== POSTILAATIKOT ====================
|
||||||
|
|
||||||
let mailboxesData = [];
|
let mailboxesData = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user