Add LoginRequiredMiddleware to make (almost) every URL login required by default

This commit is contained in:
Neil Martinsen-Burrell 2023-06-01 16:03:31 -05:00
parent a54f804f4d
commit ae3ba84f1a
No known key found for this signature in database
GPG key ID: 6A3C818CC10D0184
8 changed files with 48 additions and 26 deletions

View file

@ -24,6 +24,7 @@ django-fsm = "*"
django-phonenumber-field = {extras = ["phonenumberslite"], version = "*"}
boto3 = "*"
typing-extensions ='*'
django-login-required-middleware = "*"
[dev-packages]
django-debug-toolbar = "*"

45
src/Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "6a6f3722d88e1f0059e38f23c104708d7922d41b42be1f17287cd4d84dcf9b05"
"sha256": "187278933085d8c5448015e2d28c23934c2098f4aadd82157379174629d8cf6b"
},
"pipfile-spec": 6,
"requires": {},
@ -24,19 +24,19 @@
},
"boto3": {
"hashes": [
"sha256:2eb9e688aa86bf1fadcec0b6995b42ec9788e7cd5f1a9c8ac1b66a2506aa209f",
"sha256:5b7e9f2674fe8aa99e2d168744023a3f66da12d9c51e0624489dd0db7aafe30d"
"sha256:30f8ab1cf89d5864a80ba2d5eb5316dbd2a63c9469877e0cffb522630438aa85",
"sha256:77e8fa7c257f9ed8bfe0c3ffc2ccc47b1cfa27058f99415b6003699d1202e0c0"
],
"index": "pypi",
"version": "==1.26.144"
"version": "==1.26.145"
},
"botocore": {
"hashes": [
"sha256:c60b9158cbc7447411abdec77b87a71d86d9404064702e92d317dca6a1ec9a5b",
"sha256:e2b970e68643cf4752cad4e45ba3319fc35707f1bff7f150f7ffcac1b1427b47"
"sha256:264a3f19ed280d80711b7e278be09acff7ed379a96432fdf179b4e6e3a687e6a",
"sha256:65e2a2b1cc70583225f87d6d63736215f93c6234721967bdab872270ba7a1f45"
],
"markers": "python_version >= '3.7'",
"version": "==1.29.144"
"version": "==1.29.145"
},
"cachetools": {
"hashes": [
@ -306,6 +306,13 @@
"index": "pypi",
"version": "==2.8.1"
},
"django-login-required-middleware": {
"hashes": [
"sha256:847ae9a69fd7a07618ed53192b3c06946af70a0caf6d0f4eb40a8f37593cd970"
],
"index": "pypi",
"version": "==0.9.0"
},
"django-phonenumber-field": {
"extras": [
"phonenumberslite"
@ -793,11 +800,11 @@
},
"boto3": {
"hashes": [
"sha256:2eb9e688aa86bf1fadcec0b6995b42ec9788e7cd5f1a9c8ac1b66a2506aa209f",
"sha256:5b7e9f2674fe8aa99e2d168744023a3f66da12d9c51e0624489dd0db7aafe30d"
"sha256:30f8ab1cf89d5864a80ba2d5eb5316dbd2a63c9469877e0cffb522630438aa85",
"sha256:77e8fa7c257f9ed8bfe0c3ffc2ccc47b1cfa27058f99415b6003699d1202e0c0"
],
"index": "pypi",
"version": "==1.26.144"
"version": "==1.26.145"
},
"boto3-mocking": {
"hashes": [
@ -809,27 +816,27 @@
},
"boto3-stubs": {
"hashes": [
"sha256:1062612f63f154f47a4f5b7b40c2cb15debe5f44774587110da76fd292f528f0",
"sha256:bc0cc5067f55b2da628db8a73119ecccd74b27cf424af83e56526cd90beaf9f8"
"sha256:9413cb395c803d5b85e9ec7b16fba855a613ecd78b2e0011e2f6b62cf0b4fc1e",
"sha256:be2007f92138781288c7a22eba30b7d60742466fc28edd04637b31fabee854a5"
],
"index": "pypi",
"version": "==1.26.144"
"version": "==1.26.145"
},
"botocore": {
"hashes": [
"sha256:c60b9158cbc7447411abdec77b87a71d86d9404064702e92d317dca6a1ec9a5b",
"sha256:e2b970e68643cf4752cad4e45ba3319fc35707f1bff7f150f7ffcac1b1427b47"
"sha256:264a3f19ed280d80711b7e278be09acff7ed379a96432fdf179b4e6e3a687e6a",
"sha256:65e2a2b1cc70583225f87d6d63736215f93c6234721967bdab872270ba7a1f45"
],
"markers": "python_version >= '3.7'",
"version": "==1.29.144"
"version": "==1.29.145"
},
"botocore-stubs": {
"hashes": [
"sha256:b9db32981b4deefb01784d9b196afeaca7df6f6f185d8ba7f96c02b1c3bc0d90",
"sha256:d456543af79fbdd23df76a2d7a7525cd672b4bb5b057d7e060bc117d9af71694"
"sha256:80ffab72ad428d20cb1cf538ee55fcd94f7d81315b77d84fec99e218c3974e8b",
"sha256:928c58a434dd83bef956e3b5bb1e96278fff5eee9f8b8ab08d916cef1e9a2014"
],
"markers": "python_version >= '3.7' and python_version < '4.0'",
"version": "==1.29.144"
"version": "==1.29.145"
},
"click": {
"hashes": [

View file

@ -104,6 +104,9 @@ class AvailableAPITest(TestCase):
def test_available_post(self):
"""Cannot post to the /available/ API endpoint."""
# have to log in to test the correct thing now that we require login
# for all URLs by default
self.client.force_login(self.user)
with less_console_noise():
response = self.client.post(API_BASE_PATH + "nonsense")
self.assertEqual(response.status_code, 405)

View file

@ -134,6 +134,8 @@ MIDDLEWARE = [
"django.middleware.csrf.CsrfViewMiddleware",
# add `user` (the currently-logged-in user) to incoming HttpRequest objects
"django.contrib.auth.middleware.AuthenticationMiddleware",
# Require login for every single request by default
"login_required.middleware.LoginRequiredMiddleware",
# provide framework for displaying messages to the user, see documentation
"django.contrib.messages.middleware.MessageMiddleware",
# provide clickjacking protection via the X-Frame-Options header
@ -461,6 +463,12 @@ AUTHENTICATION_BACKENDS = [
# the login_required() decorator, LoginRequiredMixin, or AccessMixin
LOGIN_URL = "/openid/login"
# We don't want the OIDC app to be login-required because then it can't handle
# the initial login requests without erroring.
LOGIN_REQUIRED_IGNORE_PATHS = [
r"/openid/(.+)$",
]
# where to go after logging out
LOGOUT_REDIRECT_URL = "home"

View file

@ -35,10 +35,9 @@ class TestViews(TestCase):
self.assertContains(response, "OK", status_code=200)
def test_home_page(self):
"""Home page should be available without a login."""
"""Home page should NOT be available without a login."""
response = self.client.get("/")
self.assertContains(response, "registrar", status_code=200)
self.assertContains(response, "Sign in")
self.assertEqual(response.status_code, 302)
def test_whoami_page_no_user(self):
"""Whoami page not accessible without a logged-in user."""

View file

@ -1,6 +1,5 @@
import logging
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, render
from django.urls import resolve, reverse
@ -44,7 +43,7 @@ class Step(StrEnum):
REVIEW = "review"
class ApplicationWizard(LoginRequiredMixin, TemplateView):
class ApplicationWizard(TemplateView):
"""
A common set of methods and configuration.

View file

@ -1,6 +1,10 @@
from django.http import HttpResponse
from login_required import login_not_required
# the health check endpoint needs to be globally available so that the
# PaaS orchestrator can make sure the app has come up properly
@login_not_required
def health(request):
return HttpResponse(
'<html lang="en"><head><title>OK - Get.gov</title></head><body>OK</body>'

View file

@ -1,7 +1,7 @@
-i https://pypi.python.org/simple
asgiref==3.7.2 ; python_version >= '3.7'
boto3==1.26.144
botocore==1.29.144 ; python_version >= '3.7'
boto3==1.26.145
botocore==1.29.145 ; python_version >= '3.7'
cachetools==5.3.1
certifi==2023.5.7 ; python_version >= '3.6'
cfenv==0.5.3
@ -17,6 +17,7 @@ django-auditlog==2.3.0
django-cache-url==3.4.4
django-csp==3.7
django-fsm==2.8.1
django-login-required-middleware==0.9.0
django-phonenumber-field[phonenumberslite]==7.1.0
django-widget-tweaks==1.4.12
environs[django]==9.5.0