77 lines
2.7 KiB
Python
77 lines
2.7 KiB
Python
"""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()
|
|
|
|
class FieldMatcherPolicy(Policy):
|
|
"""Policy which checks if a field of the User model matches/doesn't match a
|
|
certain pattern"""
|
|
|
|
MATCH_STARTSWITH = 'startswith'
|
|
MATCH_ENDSWITH = 'endswith'
|
|
MATCH_CONTAINS = 'contains'
|
|
MATCH_REGEXP = 'regexp'
|
|
MATCH_EXACT = 'exact'
|
|
|
|
MATCHES = (
|
|
(MATCH_STARTSWITH, _('Starts with')),
|
|
(MATCH_ENDSWITH, _('Ends with')),
|
|
(MATCH_CONTAINS, _('Contains')),
|
|
(MATCH_REGEXP, _('Regexp')),
|
|
(MATCH_EXACT, _('Exact')),
|
|
)
|
|
|
|
USER_FIELDS = (
|
|
('username', _('Username'),),
|
|
('name', _('Name'),),
|
|
('email', _('E-Mail'),),
|
|
('is_staff', _('Is staff'),),
|
|
('is_active', _('Is active'),),
|
|
('data_joined', _('Date joined'),),
|
|
)
|
|
|
|
user_field = models.TextField(choices=USER_FIELDS)
|
|
match_action = models.CharField(max_length=50, choices=MATCHES)
|
|
value = models.TextField()
|
|
|
|
form = 'passbook.policies.matcher.forms.FieldMatcherPolicyForm'
|
|
|
|
def __str__(self):
|
|
description = f"{self.name}, user.{self.user_field} {self.match_action} '{self.value}'"
|
|
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)
|
|
LOGGER.debug("Checking field", value=user_field_value,
|
|
action=self.match_action, should_be=self.value)
|
|
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:
|
|
|
|
verbose_name = _('Field matcher Policy')
|
|
verbose_name_plural = _('Field matcher Policies')
|