diff --git a/ceo/tui/controllers/Controller.py b/ceo/tui/controllers/Controller.py index f47f6ee..c9f389b 100644 --- a/ceo/tui/controllers/Controller.py +++ b/ceo/tui/controllers/Controller.py @@ -1,6 +1,7 @@ from abc import ABC import ceo.tui.utils as utils +from ...utils import validate_username # NOTE: one controller can control multiple views, @@ -52,8 +53,9 @@ class Controller(ABC): def get_username_from_view(self): username = self.view.username_edit.edit_text # TODO: share validation logic between CLI and TUI - if not username: - self.view.popup('Username must not be empty') + verification_res = validate_username(username) + if verification_res: + self.view.popup(verification_res) raise Controller.InvalidInput() return username diff --git a/ceo/utils.py b/ceo/utils.py index b053f7d..3106513 100644 --- a/ceo/utils.py +++ b/ceo/utils.py @@ -1,9 +1,10 @@ import functools import json import os -from typing import List, Dict, Tuple, Callable +from typing import List, Dict, Tuple, Callable, Union import requests +import re from zope import component from .StreamResponseHandler import StreamResponseHandler @@ -11,6 +12,8 @@ from ceo_common.interfaces import IHTTPClient, IConfig from ceo_common.model import Term from ceod.transactions.members import AddMemberTransaction +VALID_USERNAME_RE = re.compile(r"^[a-z0-9]+[a-z0-9-]+$") + def http_request(method: str, path: str, **kwargs) -> requests.Response: client = component.getUtility(IHTTPClient) @@ -266,3 +269,11 @@ From other CSC machines you can connect using return True except PermissionError: return False + + +def validate_username(username: str) -> Union[str, None]: + if not username: + return 'Username must not be empty' + if not VALID_USERNAME_RE.fullmatch(username): + return 'Username is invalid' + return None diff --git a/tests/ceo/utils.py b/tests/ceo/utils.py new file mode 100644 index 0000000..de503dd --- /dev/null +++ b/tests/ceo/utils.py @@ -0,0 +1,19 @@ +import ceo.utils as utils + + +def test_validate_username(): + assert utils.validate_username('') == 'Username must not be empty' + assert utils.validate_username('-failure') == 'Username is invalid' + assert utils.validate_username('35 - joe') == 'Username is invalid' + assert utils.validate_username('35 -joe') == 'Username is invalid' + assert utils.validate_username('35- joe') == 'Username is invalid' + assert utils.validate_username('35$joe') == 'Username is invalid' + assert utils.validate_username(' 35joe') == 'Username is invalid' + assert utils.validate_username('35 joe') == 'Username is invalid' + assert utils.validate_username('35joe ') == 'Username is invalid' + assert utils.validate_username('joe!') == 'Username is invalid' + assert utils.validate_username('e45jong') is None + assert utils.validate_username('joe-35') is None + assert utils.validate_username('joe35-') is None + assert utils.validate_username('35joe-') is None + assert utils.validate_username('35-joe') is None