feat(panel): expand admin-keys disclosure by default when a key is granted

- Default the 'admin public keys' list to expanded (button shows collapse)
  whenever the user has activated at least one admin key; otherwise keep it
  collapsed. JS derives the initial state from the DOM.
This commit is contained in:
bluebluesoda committed 2026-08-24 11:41:35 +00:00
1 parent c59e76244c
commit aa3c718522
3 files changed
+36 -5

No files matched your search

+6 -1
View File
@@ -160,6 +160,7 @@ type pageData struct {
SnapshotLimit int // configured per-container snapshot cap (for display)
SSHKeys []sshKeyRow
AdminSSHKeys []sshKeyRow // operator's own public keys, shown read-only
AdminKeysAnyActive bool // at least one admin key is granted: expand the disclosure by default
Impersonated bool // operator "log in as user": show a banner
AdminPrefix string // admin panel path, for the banner's return link
MaxNotesPlaintext int // sticky-notes plaintext byte cap (client-side check)
@@ -381,7 +382,11 @@ func (s *Server) buildData(u *db.User, msg, errMsg string) pageData {
}
}
for _, k := range akeys {
d.AdminSSHKeys = append(d.AdminSSHKeys, sshKeyRow{ID: k.ID, Name: k.Name, Key: k.Key, Active: granted[k.ID]})
granted := granted[k.ID]
d.AdminSSHKeys = append(d.AdminSSHKeys, sshKeyRow{ID: k.ID, Name: k.Name, Key: k.Key, Active: granted})
if granted {
d.AdminKeysAnyActive = true
}
}
}
return d
+25 -1
View File
@@ -1230,9 +1230,10 @@ func TestOverviewAdminKeysDisclosure(t *testing.T) {
{ID: 1, Name: "ops", Key: k1, Active: true}, // already granted
{ID: 2, Name: "ci", Key: k2, Active: false}, // not granted
},
AdminKeysAnyActive: true, // one key granted -> default expanded
})
for _, want := range []string{
`id="adminKeysToggle"`, "展开来自管理员的公钥",
`id="adminKeysToggle"`, "收起来自管理员的公钥",
"激活以下公钥则授权管理员登录你的机器",
`data-aid="1"`, `data-aid="2"`, `class="keyrow admin-keyrow"`,
} {
@@ -1240,6 +1241,13 @@ func TestOverviewAdminKeysDisclosure(t *testing.T) {
t.Errorf("overview missing %q", want)
}
}
// Granted keys default the disclosure to EXPANDED: no hidden attribute.
if !strings.Contains(html, `id="adminKeysList">`) {
t.Error("granted admin keys should render the list expanded (no hidden)")
}
if strings.Contains(html, `id="adminKeysList" hidden`) {
t.Error("granted admin keys must not render the list hidden")
}
// Exactly one granted (checked) row and one plain row.
if n := strings.Count(html, `class="kact" checked>`); n != 1 {
t.Errorf("checked admin rows = %d, want 1", n)
@@ -1248,6 +1256,22 @@ func TestOverviewAdminKeysDisclosure(t *testing.T) {
t.Errorf("unchecked admin rows = %d, want 1", n)
}
// No granted keys -> default COLLAPSED: list hidden, button shows expand.
collapsed := srv.renderToString(t, "overview.html", pageData{
User: &db.User{Name: "alice"},
Prefix: "/" + testSecret,
Lang: langZh,
AdminSSHKeys: []sshKeyRow{
{ID: 1, Name: "ops", Key: k1, Active: false},
},
})
if !strings.Contains(collapsed, `id="adminKeysList" hidden`) {
t.Error("no granted admin keys should default the list to hidden")
}
if !strings.Contains(collapsed, "展开来自管理员的公钥") {
t.Error("collapsed disclosure should show the expand label")
}
// Without operator keys the disclosure block is not rendered at all. The
// JS always references these ids, so assert on the rendered-only strings.
plain := srv.renderToString(t, "overview.html", pageData{
+5 -3
View File
@@ -345,8 +345,8 @@ footer a{color:var(--muted);text-decoration:underline}
<div class="btnrow"><button type="button" class="btn ok" id="sshKeyAdd">{{if eq .Lang "zh"}}添加公钥{{else}}Add key{{end}}</button></div>
{{if .AdminSSHKeys}}
<div class="adminkeys">
<button type="button" class="keylink" id="adminKeysToggle">{{if eq .Lang "zh"}}展开来自管理员的公钥{{else}}Show the administrator's public keys{{end}}</button>
<div id="adminKeysList" hidden>
<button type="button" class="keylink" id="adminKeysToggle">{{if .AdminKeysAnyActive}}{{if eq .Lang "zh"}}收起来自管理员的公钥{{else}}Hide the administrator's public keys{{end}}{{else}}{{if eq .Lang "zh"}}展开来自管理员的公钥{{else}}Show the administrator's public keys{{end}}{{end}}</button>
<div id="adminKeysList"{{if not .AdminKeysAnyActive}} hidden{{end}}>
<div class="err adminkeys-warn">{{if eq .Lang "zh"}}激活以下公钥则授权管理员登录你的机器{{else}}Activating the keys below authorizes the administrator to log in to your machine{{end}}</div>
<div class="muted adminkeys-hint">{{if eq .Lang "zh"}}勾选要授权的公钥后点击“保存并生效”:已激活的管理员公钥会写入你机器的授权列表(以 from-admin 标注);取消勾选后保存则会从机器上移除它。你自己手动添加的公钥不受影响。{{else}}Check the keys to grant, then Save &amp; apply: activated admin keys are written to your machine's authorized_keys (marked “from-admin”); unchecking one and saving removes it. Keys you added by hand are never touched.{{end}}</div>
{{range .AdminSSHKeys}}
@@ -646,7 +646,9 @@ apt-get update && apt-get install -y nginx{{end}}">{{.InitScript}}</textarea>
var adminToggle=document.getElementById('adminKeysToggle');
if(adminToggle){
var adminList=document.getElementById('adminKeysList');
var adminOpen=false;
// Default open when any admin key is already granted (the template
// omits the hidden attribute in that case).
var adminOpen=!adminList.hidden;
adminToggle.addEventListener('click',function(){
adminOpen=!adminOpen;
adminList.hidden=!adminOpen;