stages/invitation: add unittests

This commit is contained in:
Jens Langhammer 2020-05-13 23:20:27 +02:00
parent f289025d8e
commit 43a583e2d2
4 changed files with 134 additions and 44 deletions

View file

@ -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())

View file

@ -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")

28
passbook/root/tests.py Normal file
View file

@ -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)

View file

@ -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"))