diff --git a/ceo/tui/ConfirmView.py b/ceo/tui/ConfirmView.py index 4dcfec0..be313f5 100644 --- a/ceo/tui/ConfirmView.py +++ b/ceo/tui/ConfirmView.py @@ -52,4 +52,5 @@ class ConfirmView(CeoFrame): self._model.resp = self._model.deferred_req() finally: self.clear_flash_message() - self.go_to_next_scene('Result') + next_scene = self._model.result_view_name or 'Result' + self.go_to_next_scene(next_scene) diff --git a/ceo/tui/Model.py b/ceo/tui/Model.py index b9b2a1b..8eac187 100644 --- a/ceo/tui/Model.py +++ b/ceo/tui/Model.py @@ -9,6 +9,7 @@ class Model: self.views = [] self.title = None self.scene_stack = [] + self.result_view_name = None self.error_message = None # view-specific data, to be used when e.g. resizing the window self._initial_viewdata = { @@ -32,6 +33,9 @@ class Model: 'GetUser': { 'uid': '', }, + 'ResetPassword': { + 'uid': '', + }, } self.viewdata = deepcopy(self._initial_viewdata) # data which is shared between multiple views @@ -51,6 +55,7 @@ class Model: self.title = None self.error_message = None self.scene_stack.clear() + self.result_view_name = None for view in self.views: if hasattr(view, '_ceoframe_on_reset'): view._ceoframe_on_reset() diff --git a/ceo/tui/members/GetUserView.py b/ceo/tui/members/GetUserView.py index 2b520dc..5884994 100644 --- a/ceo/tui/members/GetUserView.py +++ b/ceo/tui/members/GetUserView.py @@ -19,7 +19,7 @@ class GetUserView(CeoFrame): back_btn=True, next_scene='GetUserResult', on_next=self._next) self.fix() - + def _next(self): uid = self._username.value self.flash_message('Looking up user...', force_update=True) diff --git a/ceo/tui/members/ResetPasswordResultView.py b/ceo/tui/members/ResetPasswordResultView.py new file mode 100644 index 0000000..8cb1cbb --- /dev/null +++ b/ceo/tui/members/ResetPasswordResultView.py @@ -0,0 +1,12 @@ +from ..ResultView import ResultView + +import requests + + +class ResetPasswordResultView(ResultView): + def show_result(self, resp: requests.Response): + result = resp.json() + uid = self._model.viewdata['ResetPassword']['uid'] + self._add_text(f'The new password for {uid} is:', center=True) + self._add_text() + self._add_text(result['password'], center=True) diff --git a/ceo/tui/members/ResetPasswordView.py b/ceo/tui/members/ResetPasswordView.py new file mode 100644 index 0000000..c06d520 --- /dev/null +++ b/ceo/tui/members/ResetPasswordView.py @@ -0,0 +1,31 @@ +from asciimatics.widgets import Layout, Text, Label + +from ...utils import defer, http_post +from ..CeoFrame import CeoFrame + + +class ResetPasswordView(CeoFrame): + def __init__(self, screen, width, height, model): + super().__init__( + screen, height, width, model, 'ResetPassword', + save_data=True, + ) + layout = Layout([100], fill_frame=True) + self.add_layout(layout) + layout.add_widget(Label('Enter the username of the user whose password will be reset:')) + self._username = Text(None, "uid") + layout.add_widget(self._username) + + self.add_buttons( + back_btn=True, + next_scene='Confirm', on_next=self._next) + self.fix() + + def _next(self): + uid = self._username.value + self._model.viewdata['ResetPassword']['uid'] = uid + self._model.confirm_lines= [ + f"Are you sure you want to reset {uid}'s password?", + ] + self._model.deferred_req = defer(http_post, f'/api/members/{uid}/pwreset') + self._model.result_view_name = 'ResetPasswordResult' diff --git a/ceo/tui/start.py b/ceo/tui/start.py index 170342d..c5cd3a8 100644 --- a/ceo/tui/start.py +++ b/ceo/tui/start.py @@ -15,6 +15,8 @@ from .members.AddUserView import AddUserView from .members.GetUserView import GetUserView from .members.GetUserResultView import GetUserResultView from .members.RenewUserView import RenewUserView +from .members.ResetPasswordView import ResetPasswordView +from .members.ResetPasswordResultView import ResetPasswordResultView def unhandled(event): @@ -47,6 +49,8 @@ def screen_wrapper(screen, last_scene, model): ('RenewUser', RenewUserView(screen, width, height, model)), ('GetUser', GetUserView(screen, width, height, model)), ('GetUserResult', GetUserResultView(screen, width, height, model)), + ('ResetPassword', ResetPasswordView(screen, width, height, model)), + ('ResetPasswordResult', ResetPasswordResultView(screen, width, height, model)), ] scenes = [ Scene([view], -1, name=name) for name, view in views