v0.84.0: catalog-driven initial_credentials — read an app's auto-generated first-login from a file and show it on the app page
This commit is contained in:
@@ -477,6 +477,17 @@ func (s *Server) appDetailHandler(w http.ResponseWriter, r *http.Request, slug s
|
||||
data["HasAppInfo"] = found.Meta.HasAppInfo()
|
||||
data["EffectiveSubdomain"] = effectiveSubdomain
|
||||
|
||||
// Initial auto-generated login (e.g. Crafty writes a random admin password to a file at first
|
||||
// boot). Read it live from the container so the customer doesn't have to dig through logs. Only
|
||||
// for deployed apps that declare an initial_credentials spec; hidden when unreadable.
|
||||
if found.Deployed && found.Meta.InitialCreds != nil {
|
||||
if creds, err := s.stackMgr.ReadInitialCredentials(found.Name); err != nil {
|
||||
s.logger.Printf("[WARN] [web] initial-creds for %s: %v", found.Name, err)
|
||||
} else if creds != nil && creds.Available {
|
||||
data["InitialCreds"] = creds
|
||||
}
|
||||
}
|
||||
|
||||
// Per-app migration (B1): offer to move this app's data to another connected drive (≠ current).
|
||||
if found.Deployed {
|
||||
current := ""
|
||||
|
||||
@@ -140,6 +140,31 @@ function appMigrate(app,label){
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .InitialCreds}}
|
||||
<div class="app-info-card">
|
||||
<h3>Kezdeti belépési adatok</h3>
|
||||
<table class="initcred-table">
|
||||
{{if .InitialCreds.Username}}
|
||||
<tr>
|
||||
<td class="initcred-label" style="padding:.25rem .75rem .25rem 0;color:var(--text-muted);white-space:nowrap">Felhasználónév</td>
|
||||
<td><code class="initcred-user" style="user-select:all">{{.InitialCreds.Username}}</code></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
<tr>
|
||||
<td class="initcred-label" style="padding:.25rem .75rem .25rem 0;color:var(--text-muted);white-space:nowrap;vertical-align:middle">Jelszó</td>
|
||||
<td style="display:flex;align-items:center;gap:.5rem;flex-wrap:wrap">
|
||||
<code id="initcred-pw">••••••••••••</code>
|
||||
<span id="initcred-pw-val" hidden>{{.InitialCreds.Password}}</span>
|
||||
<button type="button" class="btn btn-sm btn-outline" onclick="icRevealPw(this)">Megjelenítés</button>
|
||||
<button type="button" class="btn btn-sm btn-outline" onclick="icCopyPw(this)">Másolás</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{if .InitialCreds.Note}}<p class="app-info-creds-warn">{{.InitialCreds.Note}}</p>{{end}}
|
||||
<p class="app-info-creds-warn">Az első bejelentkezés után azonnal változtasd meg! Ez a kezdeti, automatikusan generált jelszó — ha már megváltoztattad, hagyd figyelmen kívül.</p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .AppInfo.DefaultCreds}}
|
||||
<div class="app-info-card">
|
||||
<h3>Alapértelmezett belépés</h3>
|
||||
@@ -157,5 +182,38 @@ function appMigrate(app,label){
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .InitialCreds}}
|
||||
<script>
|
||||
// Initial-credential password reveal/copy. The value lives in a hidden element (HTML-escaped by the
|
||||
// template) so it's never inlined into a JS string literal.
|
||||
function icPwVal() {
|
||||
var el = document.getElementById('initcred-pw-val');
|
||||
return el ? el.textContent : '';
|
||||
}
|
||||
function icRevealPw(btn) {
|
||||
var code = document.getElementById('initcred-pw');
|
||||
if (!code) return;
|
||||
if (code.dataset.shown === '1') {
|
||||
code.textContent = '••••••••••••';
|
||||
code.dataset.shown = '0';
|
||||
btn.textContent = 'Megjelenítés';
|
||||
} else {
|
||||
code.textContent = icPwVal();
|
||||
code.dataset.shown = '1';
|
||||
btn.textContent = 'Elrejtés';
|
||||
}
|
||||
}
|
||||
function icCopyPw(btn) {
|
||||
var val = icPwVal();
|
||||
if (!val) return;
|
||||
navigator.clipboard.writeText(val).then(function () {
|
||||
var orig = btn.textContent;
|
||||
btn.textContent = 'Másolva ✓';
|
||||
setTimeout(function () { btn.textContent = orig; }, 1500);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{template "layout_end" .}}
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user