fix: password field value, masked post-deploy creds, initial pw note
- Fix password fields showing empty after deployment: now reads value from DeployedFieldValues (app.yaml env) instead of only .Default - Post-deploy card: passwords are masked with reveal + copy buttons instead of showing plaintext - Settings page: deployed password fields show "initial password" hint explaining the value won't update if changed in the app - Hide Generate button on settings page for already-deployed apps - Added EMAIL to username-detection heuristic for credential display Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -309,7 +309,7 @@
|
||||
{{else if eq .Type "password"}}
|
||||
<div class="input-with-button">
|
||||
<input type="password" id="field-{{.EnvVar}}" name="{{.EnvVar}}"
|
||||
class="form-control" value="{{.Default}}"
|
||||
class="form-control" value="{{if and $.AlreadyDeployed $.DeployedFieldValues}}{{index $.DeployedFieldValues .EnvVar}}{{else}}{{.Default}}{{end}}"
|
||||
placeholder="{{.Placeholder}}"
|
||||
data-field-type="password"
|
||||
required
|
||||
@@ -317,10 +317,14 @@
|
||||
<button type="button" class="btn btn-sm btn-outline pw-toggle-btn"
|
||||
onclick="togglePasswordField('field-{{.EnvVar}}', 'field-confirm-{{.EnvVar}}', this)"
|
||||
title="Megjelenítés">👁</button>
|
||||
{{if not $.AlreadyDeployed}}
|
||||
<button type="button" class="btn btn-sm btn-outline"
|
||||
onclick="generatePassword('field-{{.EnvVar}}', 'field-confirm-{{.EnvVar}}')">Generálás</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if not $.AlreadyDeployed}}
|
||||
{{if $.AlreadyDeployed}}
|
||||
<span class="form-hint">Telepítéskor beállított kezdeti jelszó — ha az alkalmazásban megváltoztattad, az itt nem frissül.</span>
|
||||
{{else}}
|
||||
<div class="input-with-button" style="margin-top:.25rem">
|
||||
<input type="password" id="field-confirm-{{.EnvVar}}"
|
||||
class="form-control" placeholder="Jelszó megerősítése"
|
||||
@@ -428,7 +432,7 @@ function buildPostDeployCard(stackName) {
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// First steps
|
||||
// First steps — with dynamic credential hint
|
||||
if (postDeployInfo.firstSteps && postDeployInfo.firstSteps.length > 0) {
|
||||
html += '<div class="app-info-card" style="margin-top:1rem"><h4>Első lépések</h4><ol class="app-info-list">';
|
||||
for (var i = 0; i < postDeployInfo.firstSteps.length; i++) {
|
||||
@@ -440,25 +444,38 @@ function buildPostDeployCard(stackName) {
|
||||
|
||||
// Credentials from deploy fields (show actual values from form)
|
||||
var credRows = '';
|
||||
var hasUserCredFields = false;
|
||||
if (postDeployInfo.deployFields) {
|
||||
for (var i = 0; i < postDeployInfo.deployFields.length; i++) {
|
||||
var f = postDeployInfo.deployFields[i];
|
||||
// Show secrets, passwords, and username-like text fields
|
||||
var isCredential = f.type === 'secret' || f.type === 'password';
|
||||
if (!isCredential && f.type === 'text') {
|
||||
var isPassword = f.type === 'secret' || f.type === 'password';
|
||||
var isUsername = false;
|
||||
if (!isPassword && f.type === 'text') {
|
||||
var ev = f.env_var.toUpperCase();
|
||||
isCredential = ev.indexOf('USER') >= 0 || ev.indexOf('ADMIN') >= 0 || ev.indexOf('LOGIN') >= 0;
|
||||
isUsername = ev.indexOf('USER') >= 0 || ev.indexOf('ADMIN') >= 0 || ev.indexOf('LOGIN') >= 0 || ev.indexOf('EMAIL') >= 0;
|
||||
}
|
||||
if (!isCredential) continue;
|
||||
if (!isPassword && !isUsername) continue;
|
||||
// Skip internal DB credentials
|
||||
var evUp = f.env_var.toUpperCase();
|
||||
if (evUp.indexOf('DB_PASSWORD') >= 0 || evUp.indexOf('MYSQL_ROOT') >= 0 || evUp.indexOf('SECRET_KEY') >= 0) continue;
|
||||
if (isPassword || isUsername) hasUserCredFields = true;
|
||||
// Read value from DOM
|
||||
var el = document.getElementById('auto-field-' + f.env_var) || document.getElementById('field-' + f.env_var);
|
||||
var val = el ? el.value : '';
|
||||
if (!val) continue;
|
||||
credRows += '<tr><td style="padding:.25rem .75rem .25rem 0;color:var(--text-muted);white-space:nowrap">' + f.label + '</td>' +
|
||||
'<td style="padding:.25rem 0;font-family:var(--font-mono);user-select:all">' + val + '</td></tr>';
|
||||
if (isPassword) {
|
||||
var credId = 'postdeploy-cred-' + i;
|
||||
credRows += '<tr><td style="padding:.25rem .75rem .25rem 0;color:var(--text-muted);white-space:nowrap">' + f.label + '</td>' +
|
||||
'<td style="padding:.25rem 0;display:flex;align-items:center;gap:.5rem">' +
|
||||
'<code id="' + credId + '" style="font-family:var(--font-mono);letter-spacing:1px">••••••••••••</code>' +
|
||||
'<button type="button" class="btn btn-sm btn-outline" onclick="togglePostDeployCred(this,\'' + credId + '\',\'' + val.replace(/'/g, "\\'") + '\')" style="padding:.15rem .4rem;font-size:.75rem">Megjelenítés</button>' +
|
||||
'<button type="button" class="btn btn-sm btn-outline" onclick="copyPostDeployCred(this,\'' + val.replace(/'/g, "\\'") + '\')" style="padding:.15rem .4rem;font-size:.75rem">Másolás</button>' +
|
||||
'</td></tr>';
|
||||
} else {
|
||||
credRows += '<tr><td style="padding:.25rem .75rem .25rem 0;color:var(--text-muted);white-space:nowrap">' + f.label + '</td>' +
|
||||
'<td style="padding:.25rem 0;font-family:var(--font-mono);user-select:all">' + val + '</td></tr>';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (credRows) {
|
||||
@@ -583,6 +600,27 @@ function togglePasswordField(fieldId, confirmFieldId, btn) {
|
||||
btn.title = newType === 'password' ? 'Megjelenítés' : 'Elrejtés';
|
||||
}
|
||||
|
||||
function togglePostDeployCred(btn, credId, val) {
|
||||
var el = document.getElementById(credId);
|
||||
if (!el) return;
|
||||
if (el.textContent === val) {
|
||||
el.textContent = '••••••••••••';
|
||||
btn.textContent = 'Megjelenítés';
|
||||
} else {
|
||||
el.textContent = val;
|
||||
btn.textContent = 'Elrejtés';
|
||||
}
|
||||
}
|
||||
function copyPostDeployCred(btn, val) {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(val).then(function() {
|
||||
var orig = btn.textContent;
|
||||
btn.textContent = 'Másolva!';
|
||||
setTimeout(function() { btn.textContent = orig; }, 1500);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function deleteStaleData(stackName, stalePath, btn) {
|
||||
if (!confirm('Biztosan törölni szeretnéd a korábbi adatokat?\n\nTárhely: ' + stalePath + '\n\n⚠️ Ez a művelet visszavonhatatlan!\nElőtte győződj meg róla, hogy az alkalmazás az új tárolóról megfelelően működik.')) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user