Won't store validation results in the controller.
Instead the form itself keeps track of the active async task. The validation state is returned from the task object itself.
This commit is contained in:
parent
888eb344a2
commit
f576c6fc85
|
@ -50,9 +50,5 @@ class IdentityController(SubiquityTuiController):
|
||||||
identity_data)
|
identity_data)
|
||||||
self.app.next_screen(self.endpoint.POST(identity_data))
|
self.app.next_screen(self.endpoint.POST(identity_data))
|
||||||
|
|
||||||
async def _validate_username(self, username):
|
async def validate_username(self, username):
|
||||||
self.username_validation = \
|
return await self.endpoint.validate_username.GET(username)
|
||||||
await self.endpoint.validate_username.GET(username)
|
|
||||||
|
|
||||||
def validate_username(self, _, value):
|
|
||||||
self.app.aio_loop.create_task(self._validate_username(value))
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import re
|
||||||
from urwid import (
|
from urwid import (
|
||||||
connect_signal,
|
connect_signal,
|
||||||
)
|
)
|
||||||
|
from subiquitycore.async_helpers import schedule_task
|
||||||
|
|
||||||
from subiquitycore.ui.interactive import (
|
from subiquitycore.ui.interactive import (
|
||||||
PasswordEditor,
|
PasswordEditor,
|
||||||
|
@ -85,9 +86,10 @@ class IdentityForm(Form):
|
||||||
|
|
||||||
def __init__(self, controller, initial):
|
def __init__(self, controller, initial):
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
self.validation_task = None
|
||||||
super().__init__(initial=initial)
|
super().__init__(initial=initial)
|
||||||
connect_signal(self.username.widget, 'change',
|
connect_signal(self.username.widget, 'change',
|
||||||
controller.validate_username)
|
self.on_username_change)
|
||||||
|
|
||||||
realname = RealnameField(_("Your name:"))
|
realname = RealnameField(_("Your name:"))
|
||||||
hostname = UsernameField(
|
hostname = UsernameField(
|
||||||
|
@ -97,6 +99,23 @@ class IdentityForm(Form):
|
||||||
password = PasswordField(_("Choose a password:"))
|
password = PasswordField(_("Choose a password:"))
|
||||||
confirm_password = PasswordField(_("Confirm your password:"))
|
confirm_password = PasswordField(_("Confirm your password:"))
|
||||||
|
|
||||||
|
def on_username_change(self, _, value):
|
||||||
|
if len(value) < 2:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.validation_task is not None:
|
||||||
|
self.validation_task.cancel()
|
||||||
|
|
||||||
|
self.validation_task = \
|
||||||
|
schedule_task(self.controller.validate_username(value))
|
||||||
|
|
||||||
|
def username_validation_state(self):
|
||||||
|
task = self.validation_task
|
||||||
|
if task is None or not task.done():
|
||||||
|
return UsernameValidation.OK
|
||||||
|
|
||||||
|
return task.result()
|
||||||
|
|
||||||
def validate_realname(self):
|
def validate_realname(self):
|
||||||
if len(self.realname.value) > REALNAME_MAXLEN:
|
if len(self.realname.value) > REALNAME_MAXLEN:
|
||||||
return _(
|
return _(
|
||||||
|
@ -118,7 +137,6 @@ class IdentityForm(Form):
|
||||||
|
|
||||||
def validate_username(self):
|
def validate_username(self):
|
||||||
username = self.username.value
|
username = self.username.value
|
||||||
state = self.controller.username_validation
|
|
||||||
if len(username) < 1:
|
if len(username) < 1:
|
||||||
return _("Username missing")
|
return _("Username missing")
|
||||||
|
|
||||||
|
@ -131,6 +149,7 @@ class IdentityForm(Form):
|
||||||
return _(
|
return _(
|
||||||
"Username must match USERNAME_REGEX: " + USERNAME_REGEX)
|
"Username must match USERNAME_REGEX: " + USERNAME_REGEX)
|
||||||
|
|
||||||
|
state = self.username_validation_state()
|
||||||
if state == UsernameValidation.SYSTEM_RESERVED:
|
if state == UsernameValidation.SYSTEM_RESERVED:
|
||||||
return _(
|
return _(
|
||||||
'The username "{username}" is reserved for use by the system.'
|
'The username "{username}" is reserved for use by the system.'
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import asyncio
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
@ -65,22 +66,24 @@ class IdentityViewTests(unittest.TestCase):
|
||||||
view_helpers.enter_data(view.form, valid_data)
|
view_helpers.enter_data(view.form, valid_data)
|
||||||
self.assertTrue(view.form.done_btn.enabled)
|
self.assertTrue(view.form.done_btn.enabled)
|
||||||
|
|
||||||
def test_username_validation_system_reserved(self):
|
async def test_username_validation_system_reserved(self):
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
view.controller.username_validation = \
|
view.controller.validate_username.return_value = \
|
||||||
UsernameValidation.SYSTEM_RESERVED
|
UsernameValidation.SYSTEM_RESERVED
|
||||||
view_helpers.enter_data(view.form, system_reserved)
|
view_helpers.enter_data(view.form, system_reserved)
|
||||||
|
await asyncio.wait(view.form.validation_task)
|
||||||
self.assertFalse(view.form.done_btn.enabled)
|
self.assertFalse(view.form.done_btn.enabled)
|
||||||
|
|
||||||
def test_username_validation_in_use(self):
|
async def test_username_validation_in_use(self):
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
view.controller.username_validation = UsernameValidation.ALREADY_IN_USE
|
view.controller.validate_username.return_value = \
|
||||||
|
UsernameValidation.ALREADY_IN_USE
|
||||||
view_helpers.enter_data(view.form, already_taken)
|
view_helpers.enter_data(view.form, already_taken)
|
||||||
|
await asyncio.wait(view.form.validation_task)
|
||||||
self.assertFalse(view.form.done_btn.enabled)
|
self.assertFalse(view.form.done_btn.enabled)
|
||||||
|
|
||||||
def test_username_validation_too_long(self):
|
def test_username_validation_too_long(self):
|
||||||
view = self.make_view()
|
view = self.make_view()
|
||||||
view.controller.username_validation = UsernameValidation.TOO_LONG
|
|
||||||
view_helpers.enter_data(view.form, too_long)
|
view_helpers.enter_data(view.form, too_long)
|
||||||
self.assertFalse(view.form.done_btn.enabled)
|
self.assertFalse(view.form.done_btn.enabled)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue