feat: add min_len, max_len, forbidden_char for password option
This commit is contained in:
parent
c3bb590415
commit
a3228fbf30
9 changed files with 85 additions and 4 deletions
|
@ -293,6 +293,9 @@ Unix options
|
||||||
* - PasswordOption
|
* - PasswordOption
|
||||||
- Simple string with no other restriction:
|
- Simple string with no other restriction:
|
||||||
-
|
-
|
||||||
|
- min_len: minimum length autorise for a password
|
||||||
|
- max_len: maximum length autorise for a passwword
|
||||||
|
- forbidden_char: list of forbidden characters for a password
|
||||||
|
|
||||||
* - FilenameOption
|
* - FilenameOption
|
||||||
- For this option, only lowercase and uppercas ASCII character, "-", ".", "_", "~", and "/" are allowed.
|
- For this option, only lowercase and uppercas ASCII character, "-", ".", "_", "~", and "/" are allowed.
|
||||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Tiramisu\n"
|
"Project-Id-Version: Tiramisu\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-10-30 13:15+0100\n"
|
"POT-Creation-Date: 2024-11-05 08:49+0100\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
||||||
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
|
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
|
||||||
|
@ -762,6 +762,18 @@ msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1}
|
||||||
msgid "group_type: {0} not allowed"
|
msgid "group_type: {0} not allowed"
|
||||||
msgstr "group_type : {0} non autorisé"
|
msgstr "group_type : {0} non autorisé"
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:49
|
||||||
|
msgid "at least {0} characters are required"
|
||||||
|
msgstr "au moins {0} caractères sont requis"
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:52
|
||||||
|
msgid "maximum {0} characters required"
|
||||||
|
msgstr "un maximum de {0} caractères sont autorisés"
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:57
|
||||||
|
msgid "must not have the characters {0}"
|
||||||
|
msgstr "ne doit pas contenir les caractères {0}"
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:52
|
#: tiramisu/option/permissionsoption.py:52
|
||||||
msgid "only 3 or 4 octal digits are allowed"
|
msgid "only 3 or 4 octal digits are allowed"
|
||||||
msgstr "seulement 3 ou 4 chiffres octal sont autorisées"
|
msgstr "seulement 3 ou 4 chiffres octal sont autorisées"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"POT-Creation-Date: 2024-10-30 13:15+0100\n"
|
"POT-Creation-Date: 2024-11-05 08:52+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -668,6 +668,18 @@ msgstr ""
|
||||||
msgid "group_type: {0} not allowed"
|
msgid "group_type: {0} not allowed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:49
|
||||||
|
msgid "at least {0} characters are required"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:52
|
||||||
|
msgid "maximum {0} characters required"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:57
|
||||||
|
msgid "must not have the characters {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:52
|
#: tiramisu/option/permissionsoption.py:52
|
||||||
msgid "only 3 or 4 octal digits are allowed"
|
msgid "only 3 or 4 octal digits are allowed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -9,6 +9,7 @@ authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
description = "an options controller tool"
|
description = "an options controller tool"
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
|
license = {file = "LICENSE"}
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||||
"Programming Language :: Python",
|
"Programming Language :: Python",
|
||||||
|
|
|
@ -158,13 +158,38 @@ def test_with_many_subgroups(config_type):
|
||||||
|
|
||||||
def test_password_option(config_type):
|
def test_password_option(config_type):
|
||||||
o = PasswordOption('o', '')
|
o = PasswordOption('o', '')
|
||||||
od1 = OptionDescription('d', '', [o])
|
o1 = PasswordOption('o1', '', min_len=4)
|
||||||
|
o2 = PasswordOption('o2', '', max_len=4)
|
||||||
|
o3 = PasswordOption('o3', '', forbidden_char=['p'])
|
||||||
|
od1 = OptionDescription('d', '', [o, o1, o2, o3])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
|
|
||||||
cfg.option('o').value.set('a_valid_password')
|
cfg.option('o').value.set('a_valid_password')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('o').value.set(1)
|
cfg.option('o').value.set(1)
|
||||||
|
#
|
||||||
|
assert cfg.option('o1').value.get() is None
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('o1').value.set("1")
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('o1').value.set("12")
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('o1').value.set("123")
|
||||||
|
cfg.option('o1').value.set("1234")
|
||||||
|
cfg.option('o1').value.set("12345")
|
||||||
|
#
|
||||||
|
assert cfg.option('o2').value.get() is None
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('o2').value.set("12345")
|
||||||
|
cfg.option('o2').value.set("1")
|
||||||
|
cfg.option('o2').value.set("12")
|
||||||
|
cfg.option('o2').value.set("123")
|
||||||
|
cfg.option('o2').value.set("1234")
|
||||||
|
#
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('o3').value.set("password")
|
||||||
|
cfg.option('o3').value.set("assword")
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,6 @@
|
||||||
from gettext import translation
|
from gettext import translation
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
t = translation('tiramisu', str(Path(__file__).parent / 'locale'), fallback=True)
|
t = translation("tiramisu", str(Path(__file__).parent / "locale"), fallback=True)
|
||||||
|
|
||||||
_ = t.gettext
|
_ = t.gettext
|
||||||
|
|
Binary file not shown.
|
@ -22,6 +22,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
|
from ..error import display_list
|
||||||
from .stroption import StrOption
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,3 +31,30 @@ class PasswordOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "password"
|
_type = "password"
|
||||||
|
|
||||||
|
def __init__(self, *args, min_len=None, max_len=None, forbidden_char=[], **kwargs):
|
||||||
|
extra = {}
|
||||||
|
if min_len is not None:
|
||||||
|
extra["min_len"] = min_len
|
||||||
|
if max_len is not None:
|
||||||
|
extra["max_len"] = max_len
|
||||||
|
if forbidden_char:
|
||||||
|
extra["forbidden_char"] = set(forbidden_char)
|
||||||
|
super().__init__(*args, extra=extra, **kwargs)
|
||||||
|
|
||||||
|
def validate(self, value: str) -> None:
|
||||||
|
super().validate(value)
|
||||||
|
min_len = self.impl_get_extra("min_len")
|
||||||
|
if min_len and len(value) < min_len:
|
||||||
|
raise ValueError(_("at least {0} characters are required").format(min_len))
|
||||||
|
max_len = self.impl_get_extra("max_len")
|
||||||
|
if max_len and len(value) > max_len:
|
||||||
|
raise ValueError(_("maximum {0} characters required").format(max_len))
|
||||||
|
if self.impl_get_extra("forbidden_char"):
|
||||||
|
forbidden_char = set(value) & self.impl_get_extra("forbidden_char")
|
||||||
|
if forbidden_char:
|
||||||
|
raise ValueError(
|
||||||
|
_("must not have the characters {0}").format(
|
||||||
|
display_list(list(forbidden_char), add_quote=True)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue