stages/invitation: add unittests
This commit is contained in:
parent
f289025d8e
commit
43a583e2d2
|
@ -0,0 +1,39 @@
|
||||||
|
"""dummy policy tests"""
|
||||||
|
from django.test import TestCase
|
||||||
|
from guardian.shortcuts import get_anonymous_user
|
||||||
|
|
||||||
|
from passbook.policies.dummy.forms import DummyPolicyForm
|
||||||
|
from passbook.policies.dummy.models import DummyPolicy
|
||||||
|
from passbook.policies.engine import PolicyRequest
|
||||||
|
|
||||||
|
|
||||||
|
class TestDummyPolicy(TestCase):
|
||||||
|
"""Test dummy policy"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.request = PolicyRequest(user=get_anonymous_user())
|
||||||
|
|
||||||
|
def test_policy(self):
|
||||||
|
"""test policy .passes"""
|
||||||
|
policy: DummyPolicy = DummyPolicy.objects.create(
|
||||||
|
name="dummy", wait_min=1, wait_max=2
|
||||||
|
)
|
||||||
|
result = policy.passes(self.request)
|
||||||
|
self.assertFalse(result.passing)
|
||||||
|
self.assertEqual(result.messages, ("dummy",))
|
||||||
|
|
||||||
|
def test_form(self):
|
||||||
|
"""test form"""
|
||||||
|
form = DummyPolicyForm(
|
||||||
|
data={
|
||||||
|
"name": "dummy",
|
||||||
|
"negate": False,
|
||||||
|
"order": 0,
|
||||||
|
"timeout": 1,
|
||||||
|
"result": True,
|
||||||
|
"wait_min": 1,
|
||||||
|
"wait_max": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertTrue(form.is_valid())
|
|
@ -45,20 +45,15 @@ ALLOWED_HOSTS = ["*"]
|
||||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||||
|
|
||||||
LOGIN_URL = "passbook_flows:default-authentication"
|
LOGIN_URL = "passbook_flows:default-authentication"
|
||||||
# CSRF_FAILURE_VIEW = 'passbook.core.views.errors.CSRFErrorView.as_view'
|
|
||||||
|
|
||||||
# Custom user model
|
# Custom user model
|
||||||
AUTH_USER_MODEL = "passbook_core.User"
|
AUTH_USER_MODEL = "passbook_core.User"
|
||||||
|
|
||||||
if DEBUG:
|
_cookie_suffix = "_debug" if DEBUG else ""
|
||||||
CSRF_COOKIE_NAME = "passbook_csrf_debug"
|
CSRF_COOKIE_NAME = f"passbook_csrf{_cookie_suffix}"
|
||||||
LANGUAGE_COOKIE_NAME = "passbook_language_debug"
|
LANGUAGE_COOKIE_NAME = f"passbook_language{_cookie_suffix}"
|
||||||
SESSION_COOKIE_NAME = "passbook_session_debug"
|
SESSION_COOKIE_NAME = f"passbook_session{_cookie_suffix}"
|
||||||
SESSION_COOKIE_SAMESITE = None
|
|
||||||
else:
|
|
||||||
CSRF_COOKIE_NAME = "passbook_csrf"
|
|
||||||
LANGUAGE_COOKIE_NAME = "passbook_language"
|
|
||||||
SESSION_COOKIE_NAME = "passbook_session"
|
|
||||||
SESSION_COOKIE_DOMAIN = CONFIG.y("domain", None)
|
SESSION_COOKIE_DOMAIN = CONFIG.y("domain", None)
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS = [
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
@ -396,6 +391,7 @@ for _app in INSTALLED_APPS:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
|
SESSION_COOKIE_SAMESITE = None
|
||||||
INSTALLED_APPS.append("debug_toolbar")
|
INSTALLED_APPS.append("debug_toolbar")
|
||||||
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
|
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
"""root tests"""
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.shortcuts import reverse
|
||||||
|
from django.test import Client, TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestRoot(TestCase):
|
||||||
|
"""Test root application"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.client = Client()
|
||||||
|
|
||||||
|
def test_monitoring_error(self):
|
||||||
|
"""Test monitoring without any credentials"""
|
||||||
|
response = self.client.get(reverse("metrics"))
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
|
def test_monitoring_ok(self):
|
||||||
|
"""Test monitoring with credentials"""
|
||||||
|
creds = "Basic " + b64encode(f"monitor:{settings.SECRET_KEY}".encode()).decode(
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
auth_headers = {"HTTP_AUTHORIZATION": creds}
|
||||||
|
response = self.client.get(reverse("metrics"), **auth_headers)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
|
@ -1,14 +1,18 @@
|
||||||
"""login tests"""
|
"""invitation tests"""
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from django.shortcuts import reverse
|
from django.shortcuts import reverse
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
|
from guardian.shortcuts import get_anonymous_user
|
||||||
|
|
||||||
from passbook.core.models import User
|
from passbook.core.models import User
|
||||||
from passbook.flows.models import Flow, FlowDesignation, FlowStageBinding
|
from passbook.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||||
from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
||||||
from passbook.flows.views import SESSION_KEY_PLAN
|
from passbook.flows.views import SESSION_KEY_PLAN
|
||||||
|
from passbook.stages.invitation.forms import InvitationStageForm
|
||||||
|
from passbook.stages.invitation.models import Invitation, InvitationStage
|
||||||
|
from passbook.stages.invitation.stage import INVITATION_TOKEN_KEY, PLAN_CONTEXT_PROMPT
|
||||||
from passbook.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
from passbook.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
from passbook.stages.user_login.forms import UserLoginStageForm
|
|
||||||
from passbook.stages.user_login.models import UserLoginStage
|
|
||||||
|
|
||||||
|
|
||||||
class TestUserLoginStage(TestCase):
|
class TestUserLoginStage(TestCase):
|
||||||
|
@ -20,15 +24,41 @@ class TestUserLoginStage(TestCase):
|
||||||
self.client = Client()
|
self.client = Client()
|
||||||
|
|
||||||
self.flow = Flow.objects.create(
|
self.flow = Flow.objects.create(
|
||||||
name="test-login",
|
name="test-invitation",
|
||||||
slug="test-login",
|
slug="test-invitation",
|
||||||
designation=FlowDesignation.AUTHENTICATION,
|
designation=FlowDesignation.AUTHENTICATION,
|
||||||
)
|
)
|
||||||
self.stage = UserLoginStage.objects.create(name="login")
|
self.stage = InvitationStage.objects.create(name="invitation")
|
||||||
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
|
FlowStageBinding.objects.create(flow=self.flow, stage=self.stage, order=2)
|
||||||
|
|
||||||
def test_valid_password(self):
|
def test_form(self):
|
||||||
"""Test with a valid pending user and backend"""
|
"""Test Form"""
|
||||||
|
data = {"name": "test"}
|
||||||
|
self.assertEqual(InvitationStageForm(data).is_valid(), True)
|
||||||
|
|
||||||
|
def test_without_invitation_fail(self):
|
||||||
|
"""Test without any invitation, continue_flow_without_invitation not set."""
|
||||||
|
plan = FlowPlan(flow_pk=self.flow.pk.hex, stages=[self.stage])
|
||||||
|
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||||
|
plan.context[
|
||||||
|
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
|
] = "django.contrib.auth.backends.ModelBackend"
|
||||||
|
session = self.client.session
|
||||||
|
session[SESSION_KEY_PLAN] = plan
|
||||||
|
session.save()
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
reverse(
|
||||||
|
"passbook_flows:flow-executor", kwargs={"flow_slug": self.flow.slug}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertEqual(response.url, reverse("passbook_flows:denied"))
|
||||||
|
|
||||||
|
def test_without_invitation_continue(self):
|
||||||
|
"""Test without any invitation, continue_flow_without_invitation is set."""
|
||||||
|
self.stage.continue_flow_without_invitation = True
|
||||||
|
self.stage.save()
|
||||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, stages=[self.stage])
|
plan = FlowPlan(flow_pk=self.flow.pk.hex, stages=[self.stage])
|
||||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||||
plan.context[
|
plan.context[
|
||||||
|
@ -45,39 +75,36 @@ class TestUserLoginStage(TestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertEqual(response.url, reverse("passbook_core:overview"))
|
self.assertEqual(response.url, reverse("passbook_core:overview"))
|
||||||
|
self.stage.continue_flow_without_invitation = False
|
||||||
|
self.stage.save()
|
||||||
|
|
||||||
def test_without_user(self):
|
def test_with_invitation(self):
|
||||||
"""Test a plan without any pending user, resulting in a denied"""
|
"""Test with invitation, check data in session"""
|
||||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, stages=[self.stage])
|
|
||||||
session = self.client.session
|
|
||||||
session[SESSION_KEY_PLAN] = plan
|
|
||||||
session.save()
|
|
||||||
|
|
||||||
response = self.client.get(
|
|
||||||
reverse(
|
|
||||||
"passbook_flows:flow-executor", kwargs={"flow_slug": self.flow.slug}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.assertEqual(response.status_code, 302)
|
|
||||||
self.assertEqual(response.url, reverse("passbook_flows:denied"))
|
|
||||||
|
|
||||||
def test_without_backend(self):
|
|
||||||
"""Test a plan with pending user, without backend, resulting in a denied"""
|
|
||||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, stages=[self.stage])
|
plan = FlowPlan(flow_pk=self.flow.pk.hex, stages=[self.stage])
|
||||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||||
|
plan.context[
|
||||||
|
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
|
] = "django.contrib.auth.backends.ModelBackend"
|
||||||
session = self.client.session
|
session = self.client.session
|
||||||
session[SESSION_KEY_PLAN] = plan
|
session[SESSION_KEY_PLAN] = plan
|
||||||
session.save()
|
session.save()
|
||||||
|
|
||||||
response = self.client.get(
|
data = {"foo": "bar"}
|
||||||
reverse(
|
invite = Invitation.objects.create(
|
||||||
|
created_by=get_anonymous_user(), fixed_data=data
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("passbook.flows.views.FlowExecutorView.cancel", MagicMock()):
|
||||||
|
base_url = reverse(
|
||||||
"passbook_flows:flow-executor", kwargs={"flow_slug": self.flow.slug}
|
"passbook_flows:flow-executor", kwargs={"flow_slug": self.flow.slug}
|
||||||
)
|
)
|
||||||
|
response = self.client.get(
|
||||||
|
base_url + f"?{INVITATION_TOKEN_KEY}={invite.pk.hex}"
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 302)
|
|
||||||
self.assertEqual(response.url, reverse("passbook_flows:denied"))
|
|
||||||
|
|
||||||
def test_form(self):
|
session = self.client.session
|
||||||
"""Test Form"""
|
plan: FlowPlan = session[SESSION_KEY_PLAN]
|
||||||
data = {"name": "test"}
|
self.assertEqual(plan.context[PLAN_CONTEXT_PROMPT], data)
|
||||||
self.assertEqual(UserLoginStageForm(data).is_valid(), True)
|
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertEqual(response.url, reverse("passbook_core:overview"))
|
||||||
|
|
Reference in New Issue