events: deepcopy event kwargs to prevent objects being removed, remove workaround
closes #4041 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		
							
								
								
									
										15
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@ -20,15 +20,20 @@
 | 
				
			|||||||
    "todo-tree.tree.showCountsInTree": true,
 | 
					    "todo-tree.tree.showCountsInTree": true,
 | 
				
			||||||
    "todo-tree.tree.showBadges": true,
 | 
					    "todo-tree.tree.showBadges": true,
 | 
				
			||||||
    "python.formatting.provider": "black",
 | 
					    "python.formatting.provider": "black",
 | 
				
			||||||
    "yaml.customTags": [
 | 
					    "yaml.customTags": ["!Find sequence", "!KeyOf scalar"],
 | 
				
			||||||
        "!Find sequence",
 | 
					 | 
				
			||||||
        "!KeyOf scalar"
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "typescript.preferences.importModuleSpecifier": "non-relative",
 | 
					    "typescript.preferences.importModuleSpecifier": "non-relative",
 | 
				
			||||||
    "typescript.preferences.importModuleSpecifierEnding": "index",
 | 
					    "typescript.preferences.importModuleSpecifierEnding": "index",
 | 
				
			||||||
    "typescript.tsdk": "./web/node_modules/typescript/lib",
 | 
					    "typescript.tsdk": "./web/node_modules/typescript/lib",
 | 
				
			||||||
    "typescript.enablePromptUseWorkspaceTsdk": true,
 | 
					    "typescript.enablePromptUseWorkspaceTsdk": true,
 | 
				
			||||||
    "yaml.schemas": {
 | 
					    "yaml.schemas": {
 | 
				
			||||||
        "./blueprints/schema.json": "blueprints/**/*.yaml"
 | 
					        "./blueprints/schema.json": "blueprints/**/*.yaml"
 | 
				
			||||||
    }
 | 
					    },
 | 
				
			||||||
 | 
					    "gitlens.autolinks": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "alphanumeric": true,
 | 
				
			||||||
 | 
					            "prefix": "#<num>",
 | 
				
			||||||
 | 
					            "url": "https://github.com/goauthentik/authentik/issues/<num>",
 | 
				
			||||||
 | 
					            "ignoreCase": false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
"""authentik events models"""
 | 
					"""authentik events models"""
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
from collections import Counter
 | 
					from collections import Counter
 | 
				
			||||||
 | 
					from copy import deepcopy
 | 
				
			||||||
from datetime import timedelta
 | 
					from datetime import timedelta
 | 
				
			||||||
from inspect import currentframe
 | 
					from inspect import currentframe
 | 
				
			||||||
from smtplib import SMTPException
 | 
					from smtplib import SMTPException
 | 
				
			||||||
@ -210,7 +211,7 @@ class Event(SerializerModel, ExpiringModel):
 | 
				
			|||||||
            current = currentframe()
 | 
					            current = currentframe()
 | 
				
			||||||
            parent = current.f_back
 | 
					            parent = current.f_back
 | 
				
			||||||
            app = parent.f_globals["__name__"]
 | 
					            app = parent.f_globals["__name__"]
 | 
				
			||||||
        cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs))
 | 
					        cleaned_kwargs = cleanse_dict(sanitize_dict(deepcopy(kwargs)))
 | 
				
			||||||
        event = Event(action=action, app=app, context=cleaned_kwargs)
 | 
					        event = Event(action=action, app=app, context=cleaned_kwargs)
 | 
				
			||||||
        return event
 | 
					        return event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,17 @@
 | 
				
			|||||||
"""evaluator tests"""
 | 
					"""evaluator tests"""
 | 
				
			||||||
from django.test import TestCase
 | 
					from django.test import RequestFactory, TestCase
 | 
				
			||||||
from guardian.shortcuts import get_anonymous_user
 | 
					from guardian.shortcuts import get_anonymous_user
 | 
				
			||||||
from rest_framework.serializers import ValidationError
 | 
					from rest_framework.serializers import ValidationError
 | 
				
			||||||
from rest_framework.test import APITestCase
 | 
					from rest_framework.test import APITestCase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from authentik.core.models import Application
 | 
				
			||||||
 | 
					from authentik.lib.generators import generate_id
 | 
				
			||||||
from authentik.policies.exceptions import PolicyException
 | 
					from authentik.policies.exceptions import PolicyException
 | 
				
			||||||
from authentik.policies.expression.api import ExpressionPolicySerializer
 | 
					from authentik.policies.expression.api import ExpressionPolicySerializer
 | 
				
			||||||
from authentik.policies.expression.evaluator import PolicyEvaluator
 | 
					from authentik.policies.expression.evaluator import PolicyEvaluator
 | 
				
			||||||
from authentik.policies.expression.models import ExpressionPolicy
 | 
					from authentik.policies.expression.models import ExpressionPolicy
 | 
				
			||||||
 | 
					from authentik.policies.models import PolicyBinding
 | 
				
			||||||
 | 
					from authentik.policies.process import PolicyProcess
 | 
				
			||||||
from authentik.policies.types import PolicyRequest
 | 
					from authentik.policies.types import PolicyRequest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -15,7 +19,15 @@ class TestEvaluator(TestCase):
 | 
				
			|||||||
    """Evaluator tests"""
 | 
					    """Evaluator tests"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        factory = RequestFactory()
 | 
				
			||||||
 | 
					        self.http_request = factory.get("/")
 | 
				
			||||||
 | 
					        self.obj = Application.objects.create(
 | 
				
			||||||
 | 
					            name=generate_id(),
 | 
				
			||||||
 | 
					            slug=generate_id(),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
        self.request = PolicyRequest(user=get_anonymous_user())
 | 
					        self.request = PolicyRequest(user=get_anonymous_user())
 | 
				
			||||||
 | 
					        self.request.obj = self.obj
 | 
				
			||||||
 | 
					        self.request.http_request = self.http_request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_full(self):
 | 
					    def test_full(self):
 | 
				
			||||||
        """Test full with Policy instance"""
 | 
					        """Test full with Policy instance"""
 | 
				
			||||||
@ -63,6 +75,41 @@ class TestEvaluator(TestCase):
 | 
				
			|||||||
        with self.assertRaises(ValidationError):
 | 
					        with self.assertRaises(ValidationError):
 | 
				
			||||||
            evaluator.validate(template)
 | 
					            evaluator.validate(template)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_execution_logging(self):
 | 
				
			||||||
 | 
					        """test execution_logging"""
 | 
				
			||||||
 | 
					        expr = ExpressionPolicy.objects.create(
 | 
				
			||||||
 | 
					            name=generate_id(),
 | 
				
			||||||
 | 
					            execution_logging=True,
 | 
				
			||||||
 | 
					            expression="ak_message(request.http_request.path)\nreturn True",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        evaluator = PolicyEvaluator("test")
 | 
				
			||||||
 | 
					        evaluator.set_policy_request(self.request)
 | 
				
			||||||
 | 
					        proc = PolicyProcess(PolicyBinding(policy=expr), request=self.request, connection=None)
 | 
				
			||||||
 | 
					        res = proc.profiling_wrapper()
 | 
				
			||||||
 | 
					        self.assertEqual(res.messages, ("/",))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_call_policy(self):
 | 
				
			||||||
 | 
					        """test ak_call_policy"""
 | 
				
			||||||
 | 
					        expr = ExpressionPolicy.objects.create(
 | 
				
			||||||
 | 
					            name=generate_id(),
 | 
				
			||||||
 | 
					            execution_logging=True,
 | 
				
			||||||
 | 
					            expression="ak_message(request.http_request.path)\nreturn True",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        tmpl = (
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					        ak_message(request.http_request.path)
 | 
				
			||||||
 | 
					        res = ak_call_policy('%s')
 | 
				
			||||||
 | 
					        ak_message(request.http_request.path)
 | 
				
			||||||
 | 
					        for msg in res.messages:
 | 
				
			||||||
 | 
					            ak_message(msg)
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					            % expr.name
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        evaluator = PolicyEvaluator("test")
 | 
				
			||||||
 | 
					        evaluator.set_policy_request(self.request)
 | 
				
			||||||
 | 
					        res = evaluator.evaluate(tmpl)
 | 
				
			||||||
 | 
					        self.assertEqual(res.messages, ("/", "/", "/"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestExpressionPolicyAPI(APITestCase):
 | 
					class TestExpressionPolicyAPI(APITestCase):
 | 
				
			||||||
    """Test expression policy's API"""
 | 
					    """Test expression policy's API"""
 | 
				
			||||||
 | 
				
			|||||||
@ -56,8 +56,6 @@ class PolicyProcess(PROCESS_CLASS):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def create_event(self, action: str, message: str, **kwargs):
 | 
					    def create_event(self, action: str, message: str, **kwargs):
 | 
				
			||||||
        """Create event with common values from `self.request` and `self.binding`."""
 | 
					        """Create event with common values from `self.request` and `self.binding`."""
 | 
				
			||||||
        # Keep a reference to http_request even if its None, because cleanse_dict will remove it
 | 
					 | 
				
			||||||
        http_request = self.request.http_request
 | 
					 | 
				
			||||||
        event = Event.new(
 | 
					        event = Event.new(
 | 
				
			||||||
            action=action,
 | 
					            action=action,
 | 
				
			||||||
            message=message,
 | 
					            message=message,
 | 
				
			||||||
@ -67,8 +65,8 @@ class PolicyProcess(PROCESS_CLASS):
 | 
				
			|||||||
            **kwargs,
 | 
					            **kwargs,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        event.set_user(self.request.user)
 | 
					        event.set_user(self.request.user)
 | 
				
			||||||
        if http_request:
 | 
					        if self.request.http_request:
 | 
				
			||||||
            event.from_http(http_request)
 | 
					            event.from_http(self.request.http_request)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            event.save()
 | 
					            event.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user