add edit and all in one menu for hosts and services

This commit is contained in:
redlineo committed 2026-07-22 15:54:44 +03:00
1 parent 8c1b93c14e
commit e39ad275b5
15 files changed
+1136 -675

No files matched your search

+25 -41
View File
@@ -63,53 +63,37 @@ func (m Model) updateExportSelect(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
}
m.exportChosen = chosen
m.screen = scrExportConfirm
m.err = ""
// Issuing a brand new key is not destructive — nothing existing
// breaks — so it runs immediately. Re-exporting someone who
// already has a key rotates it and invalidates their current
// archive, which does need the typed-token confirmation.
st := m.loadState()
var rotating []string
for _, uname := range chosen {
if u := st.FindUser(uname); u != nil && u.PublicKey != "" {
rotating = append(rotating, uname)
}
}
if len(rotating) == 0 {
return m.runExport(chosen)
}
confirmMsg := "Будут перевыпущены ключи (старые архивы перестанут работать):\n\n"
for _, uname := range chosen {
if u := st.FindUser(uname); u != nil && u.PublicKey != "" {
confirmMsg += fmt.Sprintf(" %-20s ПЕРЕВЫПУСК\n", uname)
} else {
confirmMsg += fmt.Sprintf(" %-20s новый ключ\n", uname)
}
}
m = m.startConfirm(confirmExportRotate, "", confirmMsg, scrExportSelect)
return m, nil
}
}
return m, nil
}
// updateExportConfirm guards against the accidental case this screen exists
// for: selecting users who already have a key issued re-exports them, which
// generates a brand new keypair and immediately invalidates whatever archive
// they were already given (their old private key stops matching
// authorized_keys). Nothing is generated or written until this is confirmed.
func (m Model) updateExportConfirm(msg tea.Msg) (tea.Model, tea.Cmd) {
if key, ok := msg.(tea.KeyMsg); ok {
switch key.String() {
case "esc", "n":
m.screen = scrExportSelect
return m, nil
case "enter", "y":
return m.runExport(m.exportChosen)
}
}
return m, nil
}
func (m Model) viewExportConfirm() string {
st := m.loadState()
body := "Подтвердите экспорт\n\n"
anyRotate := false
for _, username := range m.exportChosen {
u := st.FindUser(username)
if u != nil && u.PublicKey != "" {
body += fmt.Sprintf(" %-20s %s\n", username, warnStyle.Render("ключ уже выдан — будет ПЕРЕВЫПУЩЕН, старый архив перестанет работать"))
anyRotate = true
} else {
body += fmt.Sprintf(" %-20s новый ключ\n", username)
}
}
if anyRotate {
body += "\n" + warnStyle.Render("Внимание: для отмеченных выше пользователей текущий ключ будет заменён.") + "\n"
body += warnStyle.Render("Все, у кого сейчас работает старый архив, потеряют доступ, пока им не выдадут новый.") + "\n"
}
body += "\n[enter/y] подтвердить и сгенерировать [esc/n] отмена, ничего не создано"
return borderStyle.Render(body)
}
// runExport performs the actual batch export: for each chosen user it
// (re)generates a keypair, rewrites authorized_keys with that user's
// currently-allowed hosts, builds the encrypted archive, and records the new
@@ -245,7 +229,7 @@ func (m Model) viewExportSelect() string {
}
body += fmt.Sprintf("%s%s %-20s %s\n", cursor, check, uname, status)
}
body += "\n[space] отметить [a] отметить всех [enter] далее (спросит подтверждение) [esc] назад"
body += "\n[space] отметить [a] отметить всех [enter] сгенерировать (перевыпуск попросит подтверждение) [esc] назад"
return borderStyle.Render(body)
}