"""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')