diff --git a/docs/troubleshooting/access.md b/docs/troubleshooting/access.md new file mode 100644 index 000000000..46eaf3676 --- /dev/null +++ b/docs/troubleshooting/access.md @@ -0,0 +1,11 @@ +# Troubleshooting access problems + +## I get an access denied error when trying to access an application. + +If your user is a superuser, or has the attribute `passbook_user_debug` set to true: + +![](./passbook_user_debug.png) + +Afterwards, try to access the application again. You will now see a message explaining which policy denied you access: + +![](./access_denied_message.png) diff --git a/docs/troubleshooting/access_denied_message.png b/docs/troubleshooting/access_denied_message.png new file mode 100644 index 000000000..b6e1de3d8 Binary files /dev/null and b/docs/troubleshooting/access_denied_message.png differ diff --git a/docs/troubleshooting/passbook_user_debug.png b/docs/troubleshooting/passbook_user_debug.png new file mode 100644 index 000000000..4343d1950 Binary files /dev/null and b/docs/troubleshooting/passbook_user_debug.png differ diff --git a/mkdocs.yml b/mkdocs.yml index 50b205964..e0dc6689b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -55,6 +55,8 @@ nav: - Upgrading: - to 0.9: upgrading/to-0.9.md - to 0.10: upgrading/to-0.10.md + - Troubleshooting: + - Access problems: troubleshooting/access.md repo_name: "BeryJu/passbook" repo_url: https://github.com/BeryJu/passbook diff --git a/passbook/flows/tests/test_views.py b/passbook/flows/tests/test_views.py index f72f92e62..0dfe92c0e 100644 --- a/passbook/flows/tests/test_views.py +++ b/passbook/flows/tests/test_views.py @@ -1,4 +1,5 @@ """flow views tests""" +from json import loads from unittest.mock import MagicMock, PropertyMock, patch from django.shortcuts import reverse @@ -48,8 +49,8 @@ class TestFlowExecutor(TestCase): "passbook_flows:flow-executor", kwargs={"flow_slug": flow.slug} ), ) - self.assertEqual(response.status_code, 400) - self.assertEqual(cancel_mock.call_count, 1) + self.assertEqual(response.status_code, 200) + self.assertEqual(cancel_mock.call_count, 2) @patch( "passbook.policies.engine.PolicyEngine.result", POLICY_RETURN_FALSE, @@ -66,8 +67,11 @@ class TestFlowExecutor(TestCase): response = self.client.get( reverse("passbook_flows:flow-executor", kwargs={"flow_slug": flow.slug}), ) - self.assertEqual(response.status_code, 400) - self.assertInHTML(FlowNonApplicableException.__doc__, response.rendered_content) + self.assertEqual(response.status_code, 200) + self.assertJSONEqual( + force_str(response.content), + {"type": "redirect", "to": reverse("passbook_flows:denied")}, + ) def test_invalid_empty_flow(self): """Tests that an empty flow returns the correct error message""" @@ -81,8 +85,11 @@ class TestFlowExecutor(TestCase): response = self.client.get( reverse("passbook_flows:flow-executor", kwargs={"flow_slug": flow.slug}), ) - self.assertEqual(response.status_code, 400) - self.assertInHTML(EmptyFlowException.__doc__, response.rendered_content) + self.assertEqual(response.status_code, 200) + self.assertJSONEqual( + force_str(response.content), + {"type": "redirect", "to": reverse("passbook_flows:denied")}, + ) def test_invalid_flow_redirect(self): """Tests that an invalid flow still redirects""" diff --git a/passbook/flows/views.py b/passbook/flows/views.py index 08b878b79..91add4f79 100644 --- a/passbook/flows/views.py +++ b/passbook/flows/views.py @@ -56,7 +56,6 @@ class FlowExecutorView(View): LOGGER.debug("f(exec): Redirecting to next on fail") return redirect(self.request.GET.get(NEXT_ARG_NAME)) message = exc.__doc__ if exc.__doc__ else str(exc) - self.cancel() return to_stage_response( self.request, self.stage_invalid(error_message=message) ) diff --git a/passbook/policies/engine.py b/passbook/policies/engine.py index 7547e341c..cf48d706f 100644 --- a/passbook/policies/engine.py +++ b/passbook/policies/engine.py @@ -122,8 +122,10 @@ class PolicyEngine: if result.messages: final_result.messages.extend(result.messages) if not result.passing: + final_result.messages = tuple(final_result.messages) final_result.passing = False return final_result + final_result.messages = tuple(final_result.messages) final_result.passing = True return final_result diff --git a/passbook/policies/mixins.py b/passbook/policies/mixins.py index 712f00cee..ff513a7b3 100644 --- a/passbook/policies/mixins.py +++ b/passbook/policies/mixins.py @@ -12,7 +12,6 @@ from structlog import get_logger from passbook.core.models import Application, Provider, User from passbook.flows.views import ( SESSION_KEY_APPLICATION_PRE, - SESSION_KEY_DENIED_ERROR, SESSION_KEY_DENIED_POLICY_RESULT, ) from passbook.policies.engine import PolicyEngine diff --git a/passbook/policies/process.py b/passbook/policies/process.py index 137eb99b8..54b6e16b2 100644 --- a/passbook/policies/process.py +++ b/passbook/policies/process.py @@ -9,7 +9,7 @@ from sentry_sdk.tracing import Span from structlog import get_logger from passbook.policies.exceptions import PolicyException -from passbook.policies.models import Policy, PolicyBinding +from passbook.policies.models import PolicyBinding from passbook.policies.types import PolicyRequest, PolicyResult LOGGER = get_logger() diff --git a/passbook/policies/types.py b/passbook/policies/types.py index 1b759b802..0bbcadbbf 100644 --- a/passbook/policies/types.py +++ b/passbook/policies/types.py @@ -1,7 +1,6 @@ """policy structures""" from __future__ import annotations -from dataclasses import field from typing import TYPE_CHECKING, Dict, List, Optional, Tuple from django.db.models import Model