root: add common fixture loader (#4946)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-03-14 17:13:03 +01:00 committed by GitHub
parent 8b7a92068b
commit 73d7b5f110
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 113 additions and 103 deletions

View File

@ -7,8 +7,8 @@ charset = utf-8
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[html] [*.html]
indent_size = 2 indent_size = 2
[yaml] [*.{yaml,yml}]
indent_size = 2 indent_size = 2

View File

@ -1,6 +1,5 @@
"""Blueprint helpers""" """Blueprint helpers"""
from functools import wraps from functools import wraps
from pathlib import Path
from typing import Callable from typing import Callable
from django.apps import apps from django.apps import apps
@ -45,13 +44,3 @@ def reconcile_app(app_name: str):
return wrapper return wrapper
return wrapper_outer 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

View File

@ -3,12 +3,12 @@ from os import environ
from django.test import TransactionTestCase from django.test import TransactionTestCase
from authentik.blueprints.tests import load_yaml_fixture
from authentik.blueprints.v1.exporter import FlowExporter from authentik.blueprints.v1.exporter import FlowExporter
from authentik.blueprints.v1.importer import Importer, transaction_rollback from authentik.blueprints.v1.importer import Importer, transaction_rollback
from authentik.core.models import Group from authentik.core.models import Group
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.lib.generators import generate_id 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.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.models import OAuthSource
@ -113,14 +113,14 @@ class TestBlueprintsV1(TransactionTestCase):
"""Test export and import it twice""" """Test export and import it twice"""
count_initial = Prompt.objects.filter(field_key="username").count() 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.validate()[0])
self.assertTrue(importer.apply()) self.assertTrue(importer.apply())
count_before = Prompt.objects.filter(field_key="username").count() count_before = Prompt.objects.filter(field_key="username").count()
self.assertEqual(count_initial + 1, count_before) 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.assertTrue(importer.apply())
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before) 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() ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete()
Group.objects.filter(name="test").delete() Group.objects.filter(name="test").delete()
environ["foo"] = generate_id() 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.validate()[0])
self.assertTrue(importer.apply()) self.assertTrue(importer.apply())
policy = ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").first() policy = ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").first()

View File

@ -1,10 +1,10 @@
"""Test blueprints v1""" """Test blueprints v1"""
from django.test import TransactionTestCase from django.test import TransactionTestCase
from authentik.blueprints.tests import load_yaml_fixture
from authentik.blueprints.v1.importer import Importer from authentik.blueprints.v1.importer import Importer
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import load_fixture
class TestBlueprintsV1Conditions(TransactionTestCase): class TestBlueprintsV1Conditions(TransactionTestCase):
@ -14,7 +14,7 @@ class TestBlueprintsV1Conditions(TransactionTestCase):
"""Test conditions fulfilled""" """Test conditions fulfilled"""
flow_slug1 = generate_id() flow_slug1 = generate_id()
flow_slug2 = 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 "fixtures/conditions_fulfilled.yaml", id1=flow_slug1, id2=flow_slug2
) )
@ -31,7 +31,7 @@ class TestBlueprintsV1Conditions(TransactionTestCase):
"""Test conditions not fulfilled""" """Test conditions not fulfilled"""
flow_slug1 = generate_id() flow_slug1 = generate_id()
flow_slug2 = 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 "fixtures/conditions_not_fulfilled.yaml", id1=flow_slug1, id2=flow_slug2
) )

View File

@ -1,10 +1,10 @@
"""Test blueprints v1""" """Test blueprints v1"""
from django.test import TransactionTestCase from django.test import TransactionTestCase
from authentik.blueprints.tests import load_yaml_fixture
from authentik.blueprints.v1.importer import Importer from authentik.blueprints.v1.importer import Importer
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import load_fixture
class TestBlueprintsV1State(TransactionTestCase): class TestBlueprintsV1State(TransactionTestCase):
@ -13,7 +13,7 @@ class TestBlueprintsV1State(TransactionTestCase):
def test_state_present(self): def test_state_present(self):
"""Test state present""" """Test state present"""
flow_slug = generate_id() 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) importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0]) self.assertTrue(importer.validate()[0])
@ -39,7 +39,7 @@ class TestBlueprintsV1State(TransactionTestCase):
def test_state_created(self): def test_state_created(self):
"""Test state created""" """Test state created"""
flow_slug = generate_id() 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) importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0]) self.assertTrue(importer.validate()[0])
@ -65,7 +65,7 @@ class TestBlueprintsV1State(TransactionTestCase):
def test_state_absent(self): def test_state_absent(self):
"""Test state absent""" """Test state absent"""
flow_slug = generate_id() 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) importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0]) self.assertTrue(importer.validate()[0])
@ -74,7 +74,7 @@ class TestBlueprintsV1State(TransactionTestCase):
flow: Flow = Flow.objects.filter(slug=flow_slug).first() flow: Flow = Flow.objects.filter(slug=flow_slug).first()
self.assertEqual(flow.slug, flow_slug) 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) importer = Importer(import_yaml)
self.assertTrue(importer.validate()[0]) self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply()) self.assertTrue(importer.apply())

View File

@ -1,4 +1,7 @@
"""Test utils""" """Test utils"""
from inspect import currentframe
from pathlib import Path
from django.contrib.messages.middleware import MessageMiddleware from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sessions.middleware import SessionMiddleware from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpRequest from django.http import HttpRequest
@ -11,6 +14,21 @@ def dummy_get_response(request: HttpRequest): # pragma: no cover
return None 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): def get_request(*args, user=None, **kwargs):
"""Get a request with usable session""" """Get a request with usable session"""
request = RequestFactory().get(*args, **kwargs) request = RequestFactory().get(*args, **kwargs)

View File

@ -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: if OUTPOST_REMOTE_IP_HEADER not in request.META or OUTPOST_TOKEN_HEADER not in request.META:
return None return None
fake_ip = request.META[OUTPOST_REMOTE_IP_HEADER] fake_ip = request.META[OUTPOST_REMOTE_IP_HEADER]
tokens = Token.filter_not_expired( token = (
key=request.META.get(OUTPOST_TOKEN_HEADER), intent=TokenIntents.INTENT_API 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) LOGGER.warning("Attempted remote-ip override without token", fake_ip=fake_ip)
return None return None
user = tokens.first().user user = token.user
if not user.group_attributes(request).get(USER_ATTRIBUTE_CAN_OVERRIDE_IP, False): if not user.group_attributes(request).get(USER_ATTRIBUTE_CAN_OVERRIDE_IP, False):
LOGGER.warning( LOGGER.warning(
"Remote-IP override: user doesn't have permission", "Remote-IP override: user doesn't have permission",

View File

@ -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.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.flows.models import FlowDesignation from authentik.flows.models import FlowDesignation
from authentik.lib.generators import generate_id 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.models import SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.tests.test_metadata import load_fixture
class TestSAMLProviderAPI(APITestCase): class TestSAMLProviderAPI(APITestCase):

View File

@ -1,6 +1,4 @@
"""Test Service-Provider Metadata Parser""" """Test Service-Provider Metadata Parser"""
from pathlib import Path
import xmlsec import xmlsec
from defusedxml.lxml import fromstring from defusedxml.lxml import fromstring
from django.test import RequestFactory, TestCase from django.test import RequestFactory, TestCase
@ -9,6 +7,7 @@ from lxml import etree # nosec
from authentik.core.models import Application from authentik.core.models import Application
from authentik.core.tests.utils import create_test_cert, create_test_flow from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.lib.generators import generate_id 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.lib.xml import lxml_from_string
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.metadata import MetadataProcessor 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 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): class TestServiceProviderMetadataParser(TestCase):
"""Test ServiceProviderMetadataParser parsing and creation of SAML Provider""" """Test ServiceProviderMetadataParser parsing and creation of SAML Provider"""

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://127.0.0.1:9443/source/saml/google/acs/" ID="_ee7a8865ac457e7b22cb4f16b39ceca9" IssueInstant="2022-10-14T13:52:04.479Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://accounts.google.com/o/saml2?idpid=</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester">
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:RequestDenied"></saml2p:StatusCode>
</saml2p:StatusCode>
<saml2p:StatusMessage>Invalid request, ACS Url in request http://localhost:9000/source/saml/google/acs/ doesn't match configured ACS Url https://127.0.0.1:9443/source/saml/google/acs/.</saml2p:StatusMessage>
</saml2p:Status>
</saml2p:Response>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://127.0.0.1:9443/source/saml/google/acs/" ID="_1e17063957f10819a5a8e147971fec22" InResponseTo="_157fb504b59f4ae3919f74896a6b8565" IssueInstant="2022-10-14T14:11:49.590Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://accounts.google.com/o/saml2?idpid=</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></saml2p:StatusCode>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_346001c5708ffd118c40edbc0c72fc60" IssueInstant="2022-10-14T14:11:49.590Z" Version="2.0">
<saml2:Issuer>https://accounts.google.com/o/saml2?idpid=</saml2:Issuer>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jens@goauthentik.io</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="_157fb504b59f4ae3919f74896a6b8565" NotOnOrAfter="2022-10-14T14:16:49.590Z" Recipient="https://127.0.0.1:9443/source/saml/google/acs/"></saml2:SubjectConfirmationData>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2022-10-14T14:06:49.590Z" NotOnOrAfter="2022-10-14T14:16:49.590Z">
<saml2:AudienceRestriction>
<saml2:Audience>https://accounts.google.com/o/saml2?idpid=</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AttributeStatement>
<saml2:Attribute Name="name">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">foo</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="sn">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">bar</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="email">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">foo@bar.baz</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
<saml2:AuthnStatement AuthnInstant="2022-10-14T12:16:21.000Z" SessionIndex="_346001c5708ffd118c40edbc0c72fc60">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>

View File

@ -6,64 +6,10 @@ from django.test import RequestFactory, TestCase
from authentik.core.tests.utils import create_test_flow from authentik.core.tests.utils import create_test_flow
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response from authentik.lib.tests.utils import dummy_get_response, load_fixture
from authentik.sources.saml.models import SAMLSource from authentik.sources.saml.models import SAMLSource
from authentik.sources.saml.processors.response import ResponseProcessor from authentik.sources.saml.processors.response import ResponseProcessor
RESPONSE_ERROR = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://127.0.0.1:9443/source/saml/google/acs/" ID="_ee7a8865ac457e7b22cb4f16b39ceca9" IssueInstant="2022-10-14T13:52:04.479Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://accounts.google.com/o/saml2?idpid=</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester">
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:RequestDenied"></saml2p:StatusCode>
</saml2p:StatusCode>
<saml2p:StatusMessage>Invalid request, ACS Url in request http://localhost:9000/source/saml/google/acs/ doesn't match configured ACS Url https://127.0.0.1:9443/source/saml/google/acs/.</saml2p:StatusMessage>
</saml2p:Status>
</saml2p:Response>
"""
RESPONSE_SUCCESS = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://127.0.0.1:9443/source/saml/google/acs/" ID="_1e17063957f10819a5a8e147971fec22" InResponseTo="_157fb504b59f4ae3919f74896a6b8565" IssueInstant="2022-10-14T14:11:49.590Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://accounts.google.com/o/saml2?idpid=</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></saml2p:StatusCode>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_346001c5708ffd118c40edbc0c72fc60" IssueInstant="2022-10-14T14:11:49.590Z" Version="2.0">
<saml2:Issuer>https://accounts.google.com/o/saml2?idpid=</saml2:Issuer>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jens@goauthentik.io</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="_157fb504b59f4ae3919f74896a6b8565" NotOnOrAfter="2022-10-14T14:16:49.590Z" Recipient="https://127.0.0.1:9443/source/saml/google/acs/"></saml2:SubjectConfirmationData>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2022-10-14T14:06:49.590Z" NotOnOrAfter="2022-10-14T14:16:49.590Z">
<saml2:AudienceRestriction>
<saml2:Audience>https://accounts.google.com/o/saml2?idpid=</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AttributeStatement>
<saml2:Attribute Name="name">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">foo</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="sn">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">bar</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="email">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">foo@bar.baz</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
<saml2:AuthnStatement AuthnInstant="2022-10-14T12:16:21.000Z" SessionIndex="_346001c5708ffd118c40edbc0c72fc60">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>
"""
class TestResponseProcessor(TestCase): class TestResponseProcessor(TestCase):
"""Test ResponseProcessor""" """Test ResponseProcessor"""
@ -80,7 +26,12 @@ class TestResponseProcessor(TestCase):
def test_status_error(self): def test_status_error(self):
"""Test error status""" """Test error status"""
request = self.factory.post( request = self.factory.post(
"/", data={"SAMLResponse": b64encode(RESPONSE_ERROR.encode()).decode()} "/",
data={
"SAMLResponse": b64encode(
load_fixture("fixtures/response_error.xml").encode()
).decode()
},
) )
middleware = SessionMiddleware(dummy_get_response) middleware = SessionMiddleware(dummy_get_response)
@ -99,7 +50,12 @@ class TestResponseProcessor(TestCase):
def test_success(self): def test_success(self):
"""Test success""" """Test success"""
request = self.factory.post( request = self.factory.post(
"/", data={"SAMLResponse": b64encode(RESPONSE_SUCCESS.encode()).decode()} "/",
data={
"SAMLResponse": b64encode(
load_fixture("fixtures/response_success.xml").encode()
).decode()
},
) )
middleware = SessionMiddleware(dummy_get_response) middleware = SessionMiddleware(dummy_get_response)

View File

@ -68,14 +68,6 @@ export class UserForm extends ModelForm<User, number> {
${t`User's primary identifier. 150 characters or fewer.`} ${t`User's primary identifier. 150 characters or fewer.`}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Path`} ?required=${true} name="path">
<input
type="text"
value="${first(this.instance?.path, "users")}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Name`} name="name"> <ak-form-element-horizontal label=${t`Name`} name="name">
<input <input
type="text" type="text"
@ -110,6 +102,14 @@ export class UserForm extends ModelForm<User, number> {
${t`Designates whether this user should be treated as active. Unselect this instead of deleting accounts.`} ${t`Designates whether this user should be treated as active. Unselect this instead of deleting accounts.`}
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Path`} ?required=${true} name="path">
<input
type="text"
value="${first(this.instance?.path, "users")}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Attributes`} ?required=${true} name="attributes"> <ak-form-element-horizontal label=${t`Attributes`} ?required=${true} name="attributes">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"