policy(minor): Move policy-related code to separate package

This commit is contained in:
Langhammer, Jens
2019-10-01 10:17:39 +02:00
parent 531ea1c039
commit b3aede5bba
25 changed files with 202 additions and 188 deletions

View File

@ -4,7 +4,7 @@ from datetime import timedelta
from logging import getLogger
from random import SystemRandom
from time import sleep
from typing import Tuple, Union
from typing import List
from uuid import uuid4
from django.contrib.auth.models import AbstractUser
@ -25,6 +25,20 @@ def default_nonce_duration():
"""Default duration a Nonce is valid"""
return now() + timedelta(hours=4)
class PolicyResult:
"""Small data-class to hold policy results"""
passing: bool = False
messages: List[str] = []
def __init__(self, passing: bool, *messages: str):
self.passing = passing
self.messages = messages
def __str__(self):
return f"<PolicyResult passing={self.passing}>"
class Group(UUIDModel):
"""Custom Group model which supports a basic hierarchy"""
@ -229,7 +243,7 @@ class Policy(UUIDModel, CreatedUpdatedModel):
return self.name
return "%s action %s" % (self.name, self.action)
def passes(self, user: User) -> Union[bool, Tuple[bool, str]]:
def passes(self, user: User) -> PolicyResult:
"""Check if user instance passes this policy"""
raise NotImplementedError()
@ -273,7 +287,7 @@ class FieldMatcherPolicy(Policy):
description = "%s: %s" % (self.name, description)
return description
def passes(self, user: User) -> Union[bool, Tuple[bool, str]]:
def passes(self, user: User) -> PolicyResult:
"""Check if user instance passes this role"""
if not hasattr(user, self.user_field):
raise ValueError("Field does not exist")
@ -294,7 +308,7 @@ class FieldMatcherPolicy(Policy):
passes = user_field_value == self.value
LOGGER.debug("User got '%r'", passes)
return passes
return PolicyResult(passes)
class Meta:
@ -313,10 +327,10 @@ class PasswordPolicy(Policy):
form = 'passbook.core.forms.policies.PasswordPolicyForm'
def passes(self, user: User) -> Union[bool, Tuple[bool, str]]:
def passes(self, user: User) -> PolicyResult:
# Only check if password is being set
if not hasattr(user, '__password__'):
return True
return PolicyResult(True)
password = getattr(user, '__password__')
filter_regex = r''
@ -329,8 +343,8 @@ class PasswordPolicy(Policy):
result = bool(re.compile(filter_regex).match(password))
LOGGER.debug("User got %r", result)
if not result:
return result, self.error_message
return result
return PolicyResult(result, self.error_message)
return PolicyResult(result)
class Meta:
@ -364,7 +378,7 @@ class WebhookPolicy(Policy):
form = 'passbook.core.forms.policies.WebhookPolicyForm'
def passes(self, user: User):
def passes(self, user: User) -> PolicyResult:
"""Call webhook asynchronously and report back"""
raise NotImplementedError()
@ -383,12 +397,12 @@ class DebugPolicy(Policy):
form = 'passbook.core.forms.policies.DebugPolicyForm'
def passes(self, user: User):
def passes(self, user: User) -> PolicyResult:
"""Wait random time then return result"""
wait = SystemRandom().randrange(self.wait_min, self.wait_max)
LOGGER.debug("Policy '%s' waiting for %ds", self.name, wait)
sleep(wait)
return self.result, 'Debugging'
return PolicyResult(self.result, 'Debugging')
class Meta:
@ -402,8 +416,8 @@ class GroupMembershipPolicy(Policy):
form = 'passbook.core.forms.policies.GroupMembershipPolicyForm'
def passes(self, user: User) -> Union[bool, Tuple[bool, str]]:
return self.group.user_set.filter(pk=user.pk).exists()
def passes(self, user: User) -> PolicyResult:
return PolicyResult(self.group.user_set.filter(pk=user.pk).exists())
class Meta:
@ -415,10 +429,10 @@ class SSOLoginPolicy(Policy):
form = 'passbook.core.forms.policies.SSOLoginPolicyForm'
def passes(self, user):
def passes(self, user) -> PolicyResult:
"""Check if user instance passes this policy"""
from passbook.core.auth.view import AuthenticationView
return user.session.get(AuthenticationView.SESSION_IS_SSO_LOGIN, False), ""
return PolicyResult(user.session.get(AuthenticationView.SESSION_IS_SSO_LOGIN, False))
class Meta: