diff --git a/apps/accounts/serializers/account/template.py b/apps/accounts/serializers/account/template.py index 635c221bf..f30821313 100644 --- a/apps/accounts/serializers/account/template.py +++ b/apps/accounts/serializers/account/template.py @@ -15,6 +15,7 @@ class PasswordRulesSerializer(serializers.Serializer): uppercase = serializers.BooleanField(default=True, label=_('Uppercase')) digit = serializers.BooleanField(default=True, label=_('Digit')) symbol = serializers.BooleanField(default=True, label=_('Special symbol')) + exclude_symbols = serializers.CharField(default='', max_length=16, label=_('Exclude symbol')) class AccountTemplateSerializer(BaseAccountSerializer): diff --git a/apps/accounts/utils.py b/apps/accounts/utils.py index 229cb0111..b8c9841f2 100644 --- a/apps/accounts/utils.py +++ b/apps/accounts/utils.py @@ -30,7 +30,8 @@ class SecretGenerator: 'lower': rules['lowercase'], 'upper': rules['uppercase'], 'digit': rules['digit'], - 'special_char': rules['symbol'] + 'special_char': rules['symbol'], + 'exclude_chars': rules['exclude_symbols'] } return random_string(**rules) diff --git a/apps/common/utils/random.py b/apps/common/utils/random.py index 505fbd041..7978267b9 100644 --- a/apps/common/utils/random.py +++ b/apps/common/utils/random.py @@ -32,7 +32,16 @@ def random_replace_char(s, chars, length): return ''.join(seq) -def random_string(length: int, lower=True, upper=True, digit=True, special_char=False, symbols=string_punctuation): +def remove_exclude_char(s, exclude_chars): + for i in exclude_chars: + s = s.replace(i, '') + return s + + +def random_string( + length: int, lower=True, upper=True, digit=True, + special_char=False, exclude_chars='', symbols=string_punctuation +): if not any([lower, upper, digit]): raise ValueError('At least one of `lower`, `upper`, `digit` must be `True`') if length < 4: @@ -44,11 +53,13 @@ def random_string(length: int, lower=True, upper=True, digit=True, special_char= (digit, string.digits), ) chars = ''.join([i[1] for i in chars_map if i[0]]) + chars = remove_exclude_char(chars, exclude_chars) texts = list(secrets.choice(chars) for __ in range(length)) texts = ''.join(texts) # 控制一下特殊字符的数量, 别随机出来太多 if special_char: + symbols = remove_exclude_char(symbols, exclude_chars) symbol_num = length // 16 + 1 texts = random_replace_char(texts, symbols, symbol_num) return texts