diff --git a/.editorconfig b/.editorconfig
index e12dc6e50..2a5b1f870 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -7,8 +7,8 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
-[html]
+[*.html]
indent_size = 2
-[yaml]
+[*.{yaml,yml}]
indent_size = 2
diff --git a/authentik/blueprints/tests/__init__.py b/authentik/blueprints/tests/__init__.py
index 4f62d668b..8b39ca6dd 100644
--- a/authentik/blueprints/tests/__init__.py
+++ b/authentik/blueprints/tests/__init__.py
@@ -1,6 +1,5 @@
"""Blueprint helpers"""
from functools import wraps
-from pathlib import Path
from typing import Callable
from django.apps import apps
@@ -45,13 +44,3 @@ def reconcile_app(app_name: str):
return wrapper
return wrapper_outer
-
-
-def load_yaml_fixture(path: str, **kwargs) -> str:
- """Load yaml fixture, optionally formatting it with kwargs"""
- with open(Path(__file__).resolve().parent / Path(path), "r", encoding="utf-8") as _fixture:
- fixture = _fixture.read()
- try:
- return fixture % kwargs
- except TypeError:
- return fixture
diff --git a/authentik/blueprints/tests/test_v1.py b/authentik/blueprints/tests/test_v1.py
index b5f6a252a..4679de909 100644
--- a/authentik/blueprints/tests/test_v1.py
+++ b/authentik/blueprints/tests/test_v1.py
@@ -3,12 +3,12 @@ from os import environ
from django.test import TransactionTestCase
-from authentik.blueprints.tests import load_yaml_fixture
from authentik.blueprints.v1.exporter import FlowExporter
from authentik.blueprints.v1.importer import Importer, transaction_rollback
from authentik.core.models import Group
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.lib.generators import generate_id
+from authentik.lib.tests.utils import load_fixture
from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding
from authentik.sources.oauth.models import OAuthSource
@@ -113,14 +113,14 @@ class TestBlueprintsV1(TransactionTestCase):
"""Test export and import it twice"""
count_initial = Prompt.objects.filter(field_key="username").count()
- importer = Importer(load_yaml_fixture("fixtures/static_prompt_export.yaml"))
+ importer = Importer(load_fixture("fixtures/static_prompt_export.yaml"))
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
count_before = Prompt.objects.filter(field_key="username").count()
self.assertEqual(count_initial + 1, count_before)
- importer = Importer(load_yaml_fixture("fixtures/static_prompt_export.yaml"))
+ importer = Importer(load_fixture("fixtures/static_prompt_export.yaml"))
self.assertTrue(importer.apply())
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before)
@@ -130,7 +130,7 @@ class TestBlueprintsV1(TransactionTestCase):
ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete()
Group.objects.filter(name="test").delete()
environ["foo"] = generate_id()
- importer = Importer(load_yaml_fixture("fixtures/tags.yaml"), {"bar": "baz"})
+ importer = Importer(load_fixture("fixtures/tags.yaml"), {"bar": "baz"})
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
policy = ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").first()
diff --git a/authentik/blueprints/tests/test_v1_conditions.py b/authentik/blueprints/tests/test_v1_conditions.py
index 02d657303..3914e19dd 100644
--- a/authentik/blueprints/tests/test_v1_conditions.py
+++ b/authentik/blueprints/tests/test_v1_conditions.py
@@ -1,10 +1,10 @@
"""Test blueprints v1"""
from django.test import TransactionTestCase
-from authentik.blueprints.tests import load_yaml_fixture
from authentik.blueprints.v1.importer import Importer
from authentik.flows.models import Flow
from authentik.lib.generators import generate_id
+from authentik.lib.tests.utils import load_fixture
class TestBlueprintsV1Conditions(TransactionTestCase):
@@ -14,7 +14,7 @@ class TestBlueprintsV1Conditions(TransactionTestCase):
"""Test conditions fulfilled"""
flow_slug1 = generate_id()
flow_slug2 = generate_id()
- import_yaml = load_yaml_fixture(
+ import_yaml = load_fixture(
"fixtures/conditions_fulfilled.yaml", id1=flow_slug1, id2=flow_slug2
)
@@ -31,7 +31,7 @@ class TestBlueprintsV1Conditions(TransactionTestCase):
"""Test conditions not fulfilled"""
flow_slug1 = generate_id()
flow_slug2 = generate_id()
- import_yaml = load_yaml_fixture(
+ import_yaml = load_fixture(
"fixtures/conditions_not_fulfilled.yaml", id1=flow_slug1, id2=flow_slug2
)
diff --git a/authentik/blueprints/tests/test_v1_state.py b/authentik/blueprints/tests/test_v1_state.py
index 02ddfcb50..e0bf4c13a 100644
--- a/authentik/blueprints/tests/test_v1_state.py
+++ b/authentik/blueprints/tests/test_v1_state.py
@@ -1,10 +1,10 @@
"""Test blueprints v1"""
from django.test import TransactionTestCase
-from authentik.blueprints.tests import load_yaml_fixture
from authentik.blueprints.v1.importer import Importer
from authentik.flows.models import Flow
from authentik.lib.generators import generate_id
+from authentik.lib.tests.utils import load_fixture
class TestBlueprintsV1State(TransactionTestCase):
@@ -13,7 +13,7 @@ class TestBlueprintsV1State(TransactionTestCase):
def test_state_present(self):
"""Test state present"""
flow_slug = generate_id()
- import_yaml = load_yaml_fixture("fixtures/state_present.yaml", id=flow_slug)
+ import_yaml = load_fixture("fixtures/state_present.yaml", id=flow_slug)
importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0])
@@ -39,7 +39,7 @@ class TestBlueprintsV1State(TransactionTestCase):
def test_state_created(self):
"""Test state created"""
flow_slug = generate_id()
- import_yaml = load_yaml_fixture("fixtures/state_created.yaml", id=flow_slug)
+ import_yaml = load_fixture("fixtures/state_created.yaml", id=flow_slug)
importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0])
@@ -65,7 +65,7 @@ class TestBlueprintsV1State(TransactionTestCase):
def test_state_absent(self):
"""Test state absent"""
flow_slug = generate_id()
- import_yaml = load_yaml_fixture("fixtures/state_created.yaml", id=flow_slug)
+ import_yaml = load_fixture("fixtures/state_created.yaml", id=flow_slug)
importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0])
@@ -74,7 +74,7 @@ class TestBlueprintsV1State(TransactionTestCase):
flow: Flow = Flow.objects.filter(slug=flow_slug).first()
self.assertEqual(flow.slug, flow_slug)
- import_yaml = load_yaml_fixture("fixtures/state_absent.yaml", id=flow_slug)
+ import_yaml = load_fixture("fixtures/state_absent.yaml", id=flow_slug)
importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
diff --git a/authentik/lib/tests/utils.py b/authentik/lib/tests/utils.py
index 35ec8391d..6e15fe61b 100644
--- a/authentik/lib/tests/utils.py
+++ b/authentik/lib/tests/utils.py
@@ -1,4 +1,7 @@
"""Test utils"""
+from inspect import currentframe
+from pathlib import Path
+
from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpRequest
@@ -11,6 +14,21 @@ def dummy_get_response(request: HttpRequest): # pragma: no cover
return None
+def load_fixture(path: str, **kwargs) -> str:
+ """Load fixture, optionally formatting it with kwargs"""
+ current = currentframe()
+ parent = current.f_back
+ calling_file_path = parent.f_globals["__file__"]
+ with open(
+ Path(calling_file_path).resolve().parent / Path(path), "r", encoding="utf-8"
+ ) as _fixture:
+ fixture = _fixture.read()
+ try:
+ return fixture % kwargs
+ except TypeError:
+ return fixture
+
+
def get_request(*args, user=None, **kwargs):
"""Get a request with usable session"""
request = RequestFactory().get(*args, **kwargs)
diff --git a/authentik/lib/utils/http.py b/authentik/lib/utils/http.py
index 94c01c9b7..d20ad29eb 100644
--- a/authentik/lib/utils/http.py
+++ b/authentik/lib/utils/http.py
@@ -38,13 +38,17 @@ def _get_outpost_override_ip(request: HttpRequest) -> Optional[str]:
if OUTPOST_REMOTE_IP_HEADER not in request.META or OUTPOST_TOKEN_HEADER not in request.META:
return None
fake_ip = request.META[OUTPOST_REMOTE_IP_HEADER]
- tokens = Token.filter_not_expired(
- key=request.META.get(OUTPOST_TOKEN_HEADER), intent=TokenIntents.INTENT_API
+ token = (
+ Token.filter_not_expired(
+ key=request.META.get(OUTPOST_TOKEN_HEADER), intent=TokenIntents.INTENT_API
+ )
+ .select_related("user")
+ .first()
)
- if not tokens.exists():
+ if not token:
LOGGER.warning("Attempted remote-ip override without token", fake_ip=fake_ip)
return None
- user = tokens.first().user
+ user = token.user
if not user.group_attributes(request).get(USER_ATTRIBUTE_CAN_OVERRIDE_IP, False):
LOGGER.warning(
"Remote-IP override: user doesn't have permission",
diff --git a/authentik/providers/saml/tests/test_api.py b/authentik/providers/saml/tests/test_api.py
index af103d8a3..f0c878e5a 100644
--- a/authentik/providers/saml/tests/test_api.py
+++ b/authentik/providers/saml/tests/test_api.py
@@ -10,8 +10,8 @@ from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.flows.models import FlowDesignation
from authentik.lib.generators import generate_id
+from authentik.lib.tests.utils import load_fixture
from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
-from authentik.providers.saml.tests.test_metadata import load_fixture
class TestSAMLProviderAPI(APITestCase):
diff --git a/authentik/providers/saml/tests/test_metadata.py b/authentik/providers/saml/tests/test_metadata.py
index 07fc6ad0e..ffe1b2a4a 100644
--- a/authentik/providers/saml/tests/test_metadata.py
+++ b/authentik/providers/saml/tests/test_metadata.py
@@ -1,6 +1,4 @@
"""Test Service-Provider Metadata Parser"""
-from pathlib import Path
-
import xmlsec
from defusedxml.lxml import fromstring
from django.test import RequestFactory, TestCase
@@ -9,6 +7,7 @@ from lxml import etree # nosec
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.lib.generators import generate_id
+from authentik.lib.tests.utils import load_fixture
from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.metadata import MetadataProcessor
@@ -16,12 +15,6 @@ from authentik.providers.saml.processors.metadata_parser import ServiceProviderM
from authentik.sources.saml.processors.constants import NS_MAP
-def load_fixture(path: str, **kwargs) -> str:
- """Load fixture"""
- with open(Path(__file__).resolve().parent / Path(path), "r", encoding="utf-8") as _fixture:
- return _fixture.read()
-
-
class TestServiceProviderMetadataParser(TestCase):
"""Test ServiceProviderMetadataParser parsing and creation of SAML Provider"""
diff --git a/authentik/sources/saml/tests/fixtures/response_error.xml b/authentik/sources/saml/tests/fixtures/response_error.xml
new file mode 100644
index 000000000..e0bf15cf2
--- /dev/null
+++ b/authentik/sources/saml/tests/fixtures/response_error.xml
@@ -0,0 +1,10 @@
+
+