authentik/passbook/policies/password/models.py

48 lines
1.7 KiB
Python
Raw Normal View History

2019-10-07 15:33:48 +01:00
"""user field matcher models"""
import re
from django.db import models
from django.utils.translation import gettext as _
from structlog import get_logger
from passbook.policies.models import Policy
from passbook.policies.types import PolicyRequest, PolicyResult
2019-10-07 15:33:48 +01:00
LOGGER = get_logger()
class PasswordPolicy(Policy):
"""Policy to make sure passwords have certain properties"""
amount_uppercase = models.IntegerField(default=0)
amount_lowercase = models.IntegerField(default=0)
amount_symbols = models.IntegerField(default=0)
length_min = models.IntegerField(default=0)
symbol_charset = models.TextField(default=r"!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ")
error_message = models.TextField()
2019-12-31 11:51:16 +00:00
form = "passbook.policies.password.forms.PasswordPolicyForm"
2019-10-07 15:33:48 +01:00
def passes(self, request: PolicyRequest) -> PolicyResult:
# Only check if password is being set
2019-12-31 11:51:16 +00:00
if not hasattr(request.user, "__password__"):
2019-10-07 15:33:48 +01:00
return PolicyResult(True)
2019-12-31 11:51:16 +00:00
password = getattr(request.user, "__password__")
2019-10-07 15:33:48 +01:00
2019-12-31 11:51:16 +00:00
filter_regex = r""
2019-10-07 15:33:48 +01:00
if self.amount_lowercase > 0:
2019-12-31 11:51:16 +00:00
filter_regex += r"[a-z]{%d,}" % self.amount_lowercase
2019-10-07 15:33:48 +01:00
if self.amount_uppercase > 0:
2019-12-31 11:51:16 +00:00
filter_regex += r"[A-Z]{%d,}" % self.amount_uppercase
2019-10-07 15:33:48 +01:00
if self.amount_symbols > 0:
2019-12-31 11:51:16 +00:00
filter_regex += r"[%s]{%d,}" % (self.symbol_charset, self.amount_symbols)
2019-10-07 15:33:48 +01:00
result = bool(re.compile(filter_regex).match(password))
if not result:
return PolicyResult(result, self.error_message)
return PolicyResult(result)
class Meta:
2019-12-31 11:51:16 +00:00
verbose_name = _("Password Policy")
verbose_name_plural = _("Password Policies")