feat: add SMTP fields to MokoRestore config step
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 5s
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 4s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 6s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled

Since configuration.php is now sanitized in backups, MokoRestore
needs UI fields for the stripped SMTP credentials. Adds:

- SMTP Host, User, Password fields in Step 4 (Site Configuration)
- Clean card-based layout with General and Mail sections
- Only replaces SMTP values if provided (blank = leave existing)
- Pre-fills SMTP fields from extracted config (if not sanitized)
- Expanded info banner explaining secret key regeneration
This commit is contained in:
Jonathan Miller
2026-06-14 15:24:06 -05:00
parent a97db76caf
commit c96444fe80
@@ -272,6 +272,8 @@ function actionExtract(array $data): array
'user' => 'db_user',
'dbprefix' => 'db_prefix',
'sitename' => 'sitename',
'smtphost' => 'smtp_host',
'smtpuser' => 'smtp_user',
];
foreach ($fieldMap as $phpField => $configKey) {
@@ -388,6 +390,9 @@ function actionConfig(array $data): array
$prefix = $data['db_prefix'] ?? 'moko_';
$sitename = $data['sitename'] ?? 'Joomla Site';
$livesite = $data['live_site'] ?? '';
$smtpHost = $data['smtp_host'] ?? '';
$smtpUser = $data['smtp_user'] ?? '';
$smtpPass = $data['smtp_pass'] ?? '';
$tmpPath = RESTORE_DIR . '/tmp';
$logPath = RESTORE_DIR . '/administrator/logs';
@@ -413,6 +418,17 @@ function actionConfig(array $data): array
$replacements['/\$live_site\s*=\s*\'[^\']*\'/'] = "\$live_site = '{$livesite}'";
}
// Replace SMTP credentials (only if provided — leave existing values if blank)
if ($smtpHost !== '') {
$replacements['/\$smtphost\s*=\s*\'[^\']*\'/'] = "\$smtphost = '{$smtpHost}'";
}
if ($smtpUser !== '') {
$replacements['/\$smtpuser\s*=\s*\'[^\']*\'/'] = "\$smtpuser = '" . addcslashes($smtpUser, "'\\") . "'";
}
if ($smtpPass !== '') {
$replacements['/\$smtppass\s*=\s*\'[^\']*\'/'] = "\$smtppass = '" . addcslashes($smtpPass, "'\\") . "'";
}
foreach ($replacements as $pattern => $replacement) {
$config = preg_replace($pattern, $replacement, $config);
}
@@ -835,15 +851,33 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica N
<!-- Step 4: Site Configuration -->
<div class="mr-panel" id="panel4">
<h2>Site Configuration</h2>
<p class="mr-desc">Update or create configuration.php with the correct settings for this server.</p>
<div class="mr-field"><label>Site Name</label><input type="text" id="siteName" value="Joomla Site"></div>
<div class="mr-field">
<label>Live Site URL <span style="font-weight:normal;color:#94a3b8">(optional)</span></label>
<input type="text" id="liveSite" placeholder="https://example.com">
<div class="mr-hint">Leave blank to auto-detect. Set this if using a reverse proxy or custom domain.</div>
<p class="mr-desc">Configure your site settings. Credentials were removed from the backup for security &mdash; enter the correct values for this server.</p>
<div style="border:1px solid #e2e8f0;border-radius:8px;padding:1.25rem;margin-bottom:1.25rem;background:#f8fafc">
<div style="font-weight:600;font-size:0.9rem;color:#334155;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem">
<span style="font-size:1.1rem">&#127760;</span> General
</div>
<div class="mr-field"><label>Site Name</label><input type="text" id="siteName" value="Joomla Site"></div>
<div class="mr-field">
<label>Live Site URL <span style="font-weight:normal;color:#94a3b8">(optional)</span></label>
<input type="text" id="liveSite" placeholder="https://example.com">
<div class="mr-hint">Leave blank to auto-detect. Set this if using a reverse proxy or custom domain.</div>
</div>
</div>
<div style="border:1px solid #e2e8f0;border-radius:8px;padding:1.25rem;margin-bottom:1.25rem;background:#f8fafc">
<div style="font-weight:600;font-size:0.9rem;color:#334155;margin-bottom:1rem;display:flex;align-items:center;gap:0.5rem">
<span style="font-size:1.1rem">&#9993;</span> Mail / SMTP <span style="font-weight:normal;font-size:0.8rem;color:#94a3b8">&mdash; leave blank if using PHP mail()</span>
</div>
<div class="mr-field"><label>SMTP Host</label><input type="text" id="smtpHost" placeholder="smtp.example.com"></div>
<div class="mr-row">
<div class="mr-field"><label>SMTP User</label><input type="text" id="smtpUser" placeholder="user@example.com"></div>
<div class="mr-field"><label>SMTP Password</label><input type="password" id="smtpPass" placeholder=""></div>
</div>
</div>
<div class="mr-alert mr-alert-info">
A new Joomla secret will be generated automatically for security.
<span>&#128274;</span> A new Joomla secret key will be generated automatically. This invalidates active sessions (users will need to log in again) but does not affect passwords or user accounts.
</div>
<div class="mr-status" id="configStatus"></div>
<div class="mr-actions">
@@ -1055,13 +1089,16 @@ async function runExtract() {
setStatus('extractStatus', r.message, 'success');
log(r.message);
// Pre-fill DB config from extracted configuration.php
// Pre-fill config from extracted configuration.php
// (sanitized fields will be absent — those form fields stay empty)
if (r.config) {
if (r.config.db_host) document.getElementById('dbHost').value = r.config.db_host;
if (r.config.db_name) document.getElementById('dbName').value = r.config.db_name;
if (r.config.db_user) document.getElementById('dbUser').value = r.config.db_user;
if (r.config.db_prefix) document.getElementById('dbPrefix').value = r.config.db_prefix;
if (r.config.sitename) document.getElementById('siteName').value = r.config.sitename;
if (r.config.smtp_host) document.getElementById('smtpHost').value = r.config.smtp_host;
if (r.config.smtp_user) document.getElementById('smtpUser').value = r.config.smtp_user;
}
if (!r.has_db) {
@@ -1128,6 +1165,9 @@ async function runConfig() {
const params = Object.assign({}, dbConfig, {
sitename: document.getElementById('siteName').value,
live_site: document.getElementById('liveSite').value,
smtp_host: document.getElementById('smtpHost').value,
smtp_user: document.getElementById('smtpUser').value,
smtp_pass: document.getElementById('smtpPass').value,
});
const r = await post('config', params);