2019-10-07 14:33:48 +00: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.core.models import Policy
|
|
|
|
from passbook.policies.struct import PolicyRequest, PolicyResult
|
|
|
|
|
|
|
|
LOGGER = get_logger()
|
|
|
|
|
2019-12-31 11:51:16 +00:00
|
|
|
|
2019-10-07 14:33:48 +00:00
|
|
|
class FieldMatcherPolicy(Policy):
|
|
|
|
"""Policy which checks if a field of the User model matches/doesn't match a
|
|
|
|
certain pattern"""
|
|
|
|
|
2019-12-31 11:51:16 +00:00
|
|
|
MATCH_STARTSWITH = "startswith"
|
|
|
|
MATCH_ENDSWITH = "endswith"
|
|
|
|
MATCH_CONTAINS = "contains"
|
|
|
|
MATCH_REGEXP = "regexp"
|
|
|
|
MATCH_EXACT = "exact"
|
2019-10-07 14:33:48 +00:00
|
|
|
|
|
|
|
MATCHES = (
|
2019-12-31 11:51:16 +00:00
|
|
|
(MATCH_STARTSWITH, _("Starts with")),
|
|
|
|
(MATCH_ENDSWITH, _("Ends with")),
|
|
|
|
(MATCH_CONTAINS, _("Contains")),
|
|
|
|
(MATCH_REGEXP, _("Regexp")),
|
|
|
|
(MATCH_EXACT, _("Exact")),
|
2019-10-07 14:33:48 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
USER_FIELDS = (
|
2019-12-31 11:51:16 +00:00
|
|
|
("username", _("Username"),),
|
|
|
|
("name", _("Name"),),
|
|
|
|
("email", _("E-Mail"),),
|
|
|
|
("is_staff", _("Is staff"),),
|
|
|
|
("is_active", _("Is active"),),
|
|
|
|
("data_joined", _("Date joined"),),
|
2019-10-07 14:33:48 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
user_field = models.TextField(choices=USER_FIELDS)
|
|
|
|
match_action = models.CharField(max_length=50, choices=MATCHES)
|
|
|
|
value = models.TextField()
|
|
|
|
|
2019-12-31 11:51:16 +00:00
|
|
|
form = "passbook.policies.matcher.forms.FieldMatcherPolicyForm"
|
2019-10-07 14:33:48 +00:00
|
|
|
|
|
|
|
def __str__(self):
|
2019-12-31 11:51:16 +00:00
|
|
|
description = (
|
|
|
|
f"{self.name}, user.{self.user_field} {self.match_action} '{self.value}'"
|
|
|
|
)
|
2019-10-07 14:33:48 +00:00
|
|
|
if self.name:
|
|
|
|
description = f"{self.name}: {description}"
|
|
|
|
return description
|
|
|
|
|
|
|
|
def passes(self, request: PolicyRequest) -> PolicyResult:
|
|
|
|
"""Check if user instance passes this role"""
|
|
|
|
if not hasattr(request.user, self.user_field):
|
|
|
|
raise ValueError("Field does not exist")
|
|
|
|
user_field_value = getattr(request.user, self.user_field, None)
|
2019-12-31 11:51:16 +00:00
|
|
|
LOGGER.debug(
|
|
|
|
"Checking field",
|
|
|
|
value=user_field_value,
|
|
|
|
action=self.match_action,
|
|
|
|
should_be=self.value,
|
|
|
|
)
|
2019-10-07 14:33:48 +00:00
|
|
|
passes = False
|
|
|
|
if self.match_action == FieldMatcherPolicy.MATCH_STARTSWITH:
|
|
|
|
passes = user_field_value.startswith(self.value)
|
|
|
|
if self.match_action == FieldMatcherPolicy.MATCH_ENDSWITH:
|
|
|
|
passes = user_field_value.endswith(self.value)
|
|
|
|
if self.match_action == FieldMatcherPolicy.MATCH_CONTAINS:
|
|
|
|
passes = self.value in user_field_value
|
|
|
|
if self.match_action == FieldMatcherPolicy.MATCH_REGEXP:
|
|
|
|
pattern = re.compile(self.value)
|
|
|
|
passes = bool(pattern.match(user_field_value))
|
|
|
|
if self.match_action == FieldMatcherPolicy.MATCH_EXACT:
|
|
|
|
passes = user_field_value == self.value
|
|
|
|
return PolicyResult(passes)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
2019-12-31 11:51:16 +00:00
|
|
|
verbose_name = _("Field matcher Policy")
|
|
|
|
verbose_name_plural = _("Field matcher Policies")
|