ssh: add identity table with ability to remove key

A new table shows all the SSH identities/keys that are currently
imported. The user can select one and delete it from the list if he
wants to.

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2023-03-04 00:12:23 +01:00
parent 446bf3814d
commit feaf0601d3
1 changed files with 80 additions and 1 deletions

View File

@ -21,12 +21,21 @@ from urwid import LineBox, Text, connect_signal
from subiquity.common.types import SSHData, SSHIdentity from subiquity.common.types import SSHData, SSHIdentity
from subiquity.ui.views.identity import UsernameField from subiquity.ui.views.identity import UsernameField
from subiquitycore.ui.actionmenu import Action, ActionMenu
from subiquitycore.ui.buttons import cancel_btn, menu_btn, ok_btn from subiquitycore.ui.buttons import cancel_btn, menu_btn, ok_btn
from subiquitycore.ui.container import ListBox, Pile, WidgetWrap from subiquitycore.ui.container import ListBox, Pile, WidgetWrap
from subiquitycore.ui.form import BooleanField, ChoiceField, Form, Toggleable from subiquitycore.ui.form import BooleanField, ChoiceField, Form, Toggleable
from subiquitycore.ui.spinner import Spinner from subiquitycore.ui.spinner import Spinner
from subiquitycore.ui.stretchy import Stretchy from subiquitycore.ui.stretchy import Stretchy
from subiquitycore.ui.utils import SomethingFailed, button_pile, screen from subiquitycore.ui.table import ColSpec, TablePile, TableRow
from subiquitycore.ui.utils import (
Color,
Padding,
SomethingFailed,
button_pile,
make_action_menu_row,
screen,
)
from subiquitycore.view import BaseView from subiquitycore.view import BaseView
log = logging.getLogger("subiquity.ui.views.ssh") log = logging.getLogger("subiquity.ui.views.ssh")
@ -222,6 +231,7 @@ class ConfirmSSHKeys(Stretchy):
def ok(self, sender): def ok(self, sender):
for identity in self.identities: for identity in self.identities:
self.parent.add_key_to_table(identity.to_authorized_key()) self.parent.add_key_to_table(identity.to_authorized_key())
self.parent.refresh_keys_table()
self.parent.remove_overlay() self.parent.remove_overlay()
@ -253,9 +263,22 @@ class SSHView(BaseView):
bp = button_pile([self._import_key_btn]) bp = button_pile([self._import_key_btn])
bp.align = "left" bp.align = "left"
colspecs = {
0: ColSpec(rpad=1),
1: ColSpec(can_shrink=True),
2: ColSpec(rpad=1),
3: ColSpec(rpad=1),
}
self.keys_table = TablePile([], colspecs=colspecs)
self.refresh_keys_table()
rows = self.form.as_rows() + [ rows = self.form.as_rows() + [
Text(""), Text(""),
bp, bp,
Text(""),
Text(_("AUTHORIZED KEYS")),
Text(""),
self.keys_table,
] ]
connect_signal(self.form, "submit", self.done) connect_signal(self.form, "submit", self.done)
@ -307,6 +330,62 @@ class SSHView(BaseView):
if self.form.install_server: if self.form.install_server:
self.form.pwauth.enabled = True self.form.pwauth.enabled = True
def remove_key_from_table(self, key: str) -> None:
"""Remove the specified key from the list of authorized keys. When
removing the last one, we also re-enable password authentication (and
disable the checkbox)."""
self.keys.remove(key)
if not self.keys:
self.form.pwauth.value = True
self.form.pwauth.enabled = False
def refresh_keys_table(self):
rows: List[TableRow] = []
if not self.keys:
rows = [
TableRow(
[
(
4,
Padding.push_2(
Color.info_minor(Text(_("No authorized key")))
),
)
]
)
]
for key in self.keys:
menu = ActionMenu(
[
Action(
label=_("Delete"),
enabled=True,
value=(None,),
opens_dialog=False,
),
]
)
rows.append(
make_action_menu_row(
[
Text("["),
Text(key, wrap="ellipsis"),
menu,
Text("]"),
],
menu,
)
)
connect_signal(menu, "action", self._action, key)
self.keys_table.set_contents(rows)
def _action(self, sender, value, key):
self.remove_key_from_table(key)
self.refresh_keys_table()
def _toggle_server(self, sender, installed: bool): def _toggle_server(self, sender, installed: bool):
self._import_key_btn.enabled = installed self._import_key_btn.enabled = installed