From: Michael Tremer Date: Sun, 9 May 2021 10:29:46 +0000 (+0000) Subject: Add a step for the root password X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4415ff5528355f7865a74e904fc1859dd7d28a5;p=people%2Fms%2Fbricklayer.git Add a step for the root password Signed-off-by: Michael Tremer --- diff --git a/src/python/__init__.py b/src/python/__init__.py index 58667bf..0e81c14 100644 --- a/src/python/__init__.py +++ b/src/python/__init__.py @@ -78,6 +78,7 @@ class Bricklayer(object): step.Welcome, disk.SelectDisk, disk.CalculatePartitionLayout, + step.RootPassword, # Go! disk.CreatePartitionLayout, diff --git a/src/python/errors.py b/src/python/errors.py index 1b94b00..df55c9a 100644 --- a/src/python/errors.py +++ b/src/python/errors.py @@ -30,3 +30,7 @@ class UserCanceledError(InstallError): Raised when the user wants to cancel the process """ pass + + +class TryAgainError(Exception): + pass diff --git a/src/python/step.py b/src/python/step.py index e58b903..3626e9f 100644 --- a/src/python/step.py +++ b/src/python/step.py @@ -132,3 +132,14 @@ class UnattendedWarning(Step): time.sleep(0.1) p.update(i + 1) + + +class RootPassword(InteractiveStep): + def run(self, tui): + password = tui.passwd( + _("Root Password"), + _("Please enter the password for the 'root' user"), + ) + + # Save the password for now + self.bricklayer.settings["root-password"] = password diff --git a/src/python/tui.py b/src/python/tui.py index b8b659a..19a646e 100644 --- a/src/python/tui.py +++ b/src/python/tui.py @@ -165,6 +165,11 @@ class Tui(object): return window.run() + def passwd(self, title, text, height=None, width=40, help=None): + window = PasswordWindow(self, title, text, height=height, width=width, help=help) + + return window.run() + class Window(object): def __init__(self, tui, title, text, height=None, width=None, help=None): @@ -192,13 +197,17 @@ class ButtonsWindow(Window): # Configure some default buttons if buttons is None: - buttons = [ - (_("Ok"), None), - (_("Cancel"), cancel), - ] + buttons = self.default_buttons self.buttons = snack.ButtonBar(self.tui.screen, buttons) + @property + def default_buttons(self): + return ( + (_("Ok"), None), + (_("Cancel"), cancel), + ) + def _make_window(self): # Create a grid grid = snack.GridFormHelp(self.tui.screen, self.title, self.help, 1, 2) @@ -215,18 +224,28 @@ class ButtonsWindow(Window): def run(self): window = self._make_window() - # Run the window - button = window.runOnce() + # Run the window in a loop. The callback must return a value, otherwise the lo + try: + while True: + button = window.run() + + # Which button was pressed? + callback = self.buttons.buttonPressed(button) - # Which button was pressed? - callback = self.buttons.buttonPressed(button) + try: + # If the button had a callback, we will call the callback + if callable(callback): + return callback() - # If the button had a callback, we will call the callback - if callable(callback): - return callback() + # Otherwise call the default action + return self.default_action() - # Otherwise call the default action - return self.default_action() + # If any of the callbacks raise TryAgain, we go back and let the user + # edit the form again + except TryAgainError: + continue + finally: + self.tui.screen.popWindow() def default_action(self): """ @@ -341,3 +360,68 @@ class ProgressWindow(Window): if self.max_value: self.scale.set(value) self.tui.refresh() + + +class PasswordWindow(ButtonsWindow): + @property + def default_buttons(self): + return ( + (_("Set Password"), self.set_password), + (_("Cancel"), cancel), + ) + + def _make_window(self): + # Create a grid + grid = snack.GridFormHelp(self.tui.screen, self.title, self.help, 1, 3) + + # Create the box that shows the text + textbox = snack.TextboxReflowed(self.width, self.text, maxHeight=self.max_height) + grid.add(textbox, 0, 0, padding=(0, 0, 0, 1)) + + # Create password fields + passwords = snack.Grid(2, 2) + + self.password1 = snack.Entry(24, password=True) + label = snack.Label(_("Password")) + + passwords.setField(label, 0, 0, padding=(0, 0, 1, 0), anchorLeft=True) + passwords.setField(self.password1, 1, 0, anchorLeft=True) + + self.password2 = snack.Entry(24, password=True) + label = snack.Label(_("Confirm")) + + passwords.setField(label, 0, 1, padding=(0, 0, 1, 0), anchorLeft=True) + passwords.setField(self.password2, 1, 1, anchorLeft=True) + + grid.add(passwords, 0, 1, padding=(0, 0, 0, 1)) + + # Create the button bar + grid.add(self.buttons, 0, 2, growx=True) + + return grid + + def set_password(self): + # Fetch the entered values + password1 = self.password1.value() + password2 = self.password2.value() + + # Has something been entered? + if not password1: + self.tui.message( + _("Error"), + _("You must enter a password"), + buttons=[_("OK")], + ) + raise TryAgainError + + # Do the passwords match? + if not password1 == password2: + self.tui.message( + _("Error"), + _("The entered passwords do not match"), + buttons=[_("OK")], + ) + raise TryAgainError + + # Return the password to the caller + return password1