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:
1 parent
c59e76244c
commit
aa3c718522
3 files changed
+36
-5
No files matched your search
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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 & 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;
|
||||
|
||||
Reference in new issue
Block a user