diff --git a/authentik/lib/expression/evaluator.py b/authentik/lib/expression/evaluator.py index 7681ef6c0..452eb4a85 100644 --- a/authentik/lib/expression/evaluator.py +++ b/authentik/lib/expression/evaluator.py @@ -3,6 +3,7 @@ import re from textwrap import indent from typing import Any, Iterable, Optional +from django.core.exceptions import FieldError from requests import Session from rest_framework.serializers import ValidationError from sentry_sdk.hub import Hub @@ -29,10 +30,10 @@ class BaseEvaluator: # update website/docs/expressions/_objects.md # update website/docs/expressions/_functions.md self._globals = { - "regex_match": BaseEvaluator.expr_filter_regex_match, - "regex_replace": BaseEvaluator.expr_filter_regex_replace, - "ak_is_group_member": BaseEvaluator.expr_func_is_group_member, - "ak_user_by": BaseEvaluator.expr_func_user_by, + "regex_match": BaseEvaluator.expr_regex_match, + "regex_replace": BaseEvaluator.expr_regex_replace, + "ak_is_group_member": BaseEvaluator.expr_is_group_member, + "ak_user_by": BaseEvaluator.expr_user_by, "ak_logger": get_logger(), "requests": Session(), } @@ -40,25 +41,28 @@ class BaseEvaluator: self._filename = "BaseEvalautor" @staticmethod - def expr_filter_regex_match(value: Any, regex: str) -> bool: + def expr_regex_match(value: Any, regex: str) -> bool: """Expression Filter to run re.search""" - return re.search(regex, value) is None + return re.search(regex, value) is not None @staticmethod - def expr_filter_regex_replace(value: Any, regex: str, repl: str) -> str: + def expr_regex_replace(value: Any, regex: str, repl: str) -> str: """Expression Filter to run re.sub""" return re.sub(regex, repl, value) @staticmethod - def expr_func_user_by(**filters) -> Optional[User]: + def expr_user_by(**filters) -> Optional[User]: """Get user by filters""" - users = User.objects.filter(**filters) - if users: - return users.first() - return None + try: + users = User.objects.filter(**filters) + if users: + return users.first() + return None + except FieldError: + return None @staticmethod - def expr_func_is_group_member(user: User, **group_filters) -> bool: + def expr_is_group_member(user: User, **group_filters) -> bool: """Check if `user` is member of group with name `group_name`""" return user.ak_groups.filter(**group_filters).exists() diff --git a/authentik/lib/tests/test_evaluator.py b/authentik/lib/tests/test_evaluator.py new file mode 100644 index 000000000..931224d46 --- /dev/null +++ b/authentik/lib/tests/test_evaluator.py @@ -0,0 +1,32 @@ +"""Test Evaluator base functions""" +from django.test import TestCase + +from authentik.core.models import User +from authentik.lib.expression.evaluator import BaseEvaluator + + +class TestEvaluator(TestCase): + """Test Evaluator base functions""" + + def test_regex_match(self): + """Test expr_regex_match""" + self.assertFalse(BaseEvaluator.expr_regex_match("foo", "bar")) + self.assertTrue(BaseEvaluator.expr_regex_match("foo", "foo")) + + def test_regex_replace(self): + """Test expr_regex_replace""" + self.assertEqual(BaseEvaluator.expr_regex_replace("foo", "o", "a"), "faa") + + def test_user_by(self): + """Test expr_user_by""" + self.assertIsNotNone(BaseEvaluator.expr_user_by(username="akadmin")) + self.assertIsNone(BaseEvaluator.expr_user_by(username="bar")) + self.assertIsNone(BaseEvaluator.expr_user_by(foo="bar")) + + def test_is_group_member(self): + """Test expr_is_group_member""" + self.assertFalse( + BaseEvaluator.expr_is_group_member( + User.objects.get(username="akadmin"), name="test" + ) + ) diff --git a/schema.yml b/schema.yml index b0dbb39cb..8e85f84f7 100644 --- a/schema.yml +++ b/schema.yml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: title: authentik - version: 2021.6.1 + version: 2021.6.2 description: Making authentication simple. contact: email: hello@beryju.org