84 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.8 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")
 |