7fa8768cfd
gates / gates (push) Successful in 25s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
70 lines
3.1 KiB
Go
70 lines
3.1 KiB
Go
package web
|
||
|
||
import (
|
||
"strings"
|
||
"time"
|
||
|
||
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
|
||
)
|
||
|
||
// ── Known default logins (v0.279.0, `09` §3 decision 45) ────────────────────────────────────────────
|
||
//
|
||
// "An app is never published with a login a stranger knows." Where the template's after_install replaces
|
||
// the default with a generated password, the default is gone once that command succeeded — the page must
|
||
// then NOT show it (it would send the household to a login that no longer works). Where it cannot (no
|
||
// after_install) or the command failed, the page and the install dialog say plainly what the default is and
|
||
// to change it at once. Pinned by internal/web/known_login_test.go.
|
||
|
||
// afterInstallWindow is how long after an install an ABSENT after_install record still means "not run yet":
|
||
// the deploy-done hook waits up to 10 minutes for the app, then tries 6 × 20 s (after_install.go).
|
||
const afterInstallWindow = 30 * time.Minute
|
||
|
||
// knownLoginNow is the page's clock (a test seam).
|
||
var knownLoginNow = time.Now
|
||
|
||
// defaultLoginInEffect: the template has a default login and nothing has replaced it on this install.
|
||
// installed=false is the install dialog, before the install: a declared after_install WILL replace it.
|
||
func defaultLoginInEffect(meta *stacks.Metadata, cfg *stacks.AppConfig, installed bool) bool {
|
||
if meta == nil || strings.TrimSpace(meta.AppInfo.DefaultCreds) == "" {
|
||
return false
|
||
}
|
||
// R-710: the household said it changed the login by hand (the app page's "I changed it").
|
||
if installed && cfg != nil && cfg.DefaultLogin != nil {
|
||
return false
|
||
}
|
||
if meta.AfterInstall == nil {
|
||
return true
|
||
}
|
||
if !installed {
|
||
return false
|
||
}
|
||
if cfg == nil {
|
||
return true // the app's record is unreadable: say what the template's default is
|
||
}
|
||
if cfg.AfterInstall != nil {
|
||
return !cfg.AfterInstall.OK
|
||
}
|
||
// R-710 (measured on demo-hp 2026-09-29): an ABSENT record means "not run yet" only inside the command's
|
||
// window after the install. An app installed before its template gained an after_install never runs it —
|
||
// read as "not run yet" for ever, its live default login went unannounced.
|
||
at, err := time.Parse(time.RFC3339, cfg.DeployedAt)
|
||
return err != nil || knownLoginNow().Sub(at) > afterInstallWindow
|
||
}
|
||
|
||
// defaultLoginReplaced: installed, and something replaced the default (after_install, or the household).
|
||
func defaultLoginReplaced(meta *stacks.Metadata, cfg *stacks.AppConfig, installed bool) bool {
|
||
if meta == nil || !installed || defaultLoginInEffect(meta, cfg, installed) {
|
||
return false
|
||
}
|
||
return meta.AfterInstall != nil || (cfg != nil && cfg.DefaultLogin != nil)
|
||
}
|
||
|
||
// knownLoginLine is the sentence, in lang, or "" when no default login is in effect.
|
||
func (s *Server) knownLoginLine(lang string, meta *stacks.Metadata, cfg *stacks.AppConfig, installed bool) string {
|
||
if !defaultLoginInEffect(meta, cfg, installed) {
|
||
return ""
|
||
}
|
||
creds := strings.ReplaceAll(meta.AppInfo.DefaultCreds, "DOMAIN", s.cfg.Customer.Domain)
|
||
return s.msgLang(lang, "app_info.known_login", creds)
|
||
}
|