Add the ability to password protect pages
Useful for sharing drafts
This commit is contained in:
parent
9ee46721c9
commit
e7c4acce8b
7 changed files with 99 additions and 2 deletions
|
@ -104,3 +104,8 @@ section.hero {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#view-restriction-banner {
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
43
static/src/scss/_password_required.scss
Normal file
43
static/src/scss/_password_required.scss
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
body.page-password-required {
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
main {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
@include dark-mode {
|
||||||
|
background-color: color.adjust($dark, $alpha: -0.2);
|
||||||
|
color: $dark-mode-text;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(214 210 205 / 80%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorlist {
|
||||||
|
color: $danger;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
p {
|
||||||
|
@include dark-mode {
|
||||||
|
color: $dark-mode-text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
@import "spotify";
|
@import "spotify";
|
||||||
@import "404";
|
@import "404";
|
||||||
@import "contact";
|
@import "contact";
|
||||||
|
@import "password_required";
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
|
|
41
website/common/templates/password_required.html
Normal file
41
website/common/templates/password_required.html
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load static wagtailcore_tags wagtailimages_tags %}
|
||||||
|
|
||||||
|
{% block body_class %}page-password-required{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}Password required{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<h1 class="is-size-1 has-text-primary"><i class="fa-solid fa-lock"></i></h1>
|
||||||
|
<h1 class="is-size-3 has-text-weight-bold">Password required</h1>
|
||||||
|
<p>You need a password to access this page.</p>
|
||||||
|
|
||||||
|
<form action="{{ action_url }}" method="POST" class="mt-5">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{{ form.non_field_errors }}
|
||||||
|
{{ form.password.errors }}
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<input
|
||||||
|
class="input is-medium"
|
||||||
|
type="password"
|
||||||
|
name="{{ form.password.html_name }}"
|
||||||
|
required=""
|
||||||
|
id="{{ form.password.id_for_label }}"
|
||||||
|
placeholder="Password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% for field in form.hidden_fields %}
|
||||||
|
{{ field }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<input class="button is-primary" type="submit" value="Submit" />
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -15,6 +15,12 @@
|
||||||
<img class="hero" src="{{ page.hero_image_url }}" decoding="async" />
|
<img class="hero" src="{{ page.hero_image_url }}" decoding="async" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if page.get_view_restrictions.exists %}
|
||||||
|
<section class="notification is-danger" id="view-restriction-banner">
|
||||||
|
<strong>Note</strong>: This page has a view restriction. Please do not share its content until the page is public or this message is removed.
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<section class="hero">
|
<section class="hero">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
|
|
|
@ -35,7 +35,7 @@ class ContentPageTestCase(TestCase):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_queries(self) -> None:
|
def test_queries(self) -> None:
|
||||||
with self.assertNumQueries(26):
|
with self.assertNumQueries(28):
|
||||||
self.client.get(self.page.url)
|
self.client.get(self.page.url)
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class ListingPageTestCase(TestCase):
|
||||||
ContentPageFactory(parent=cls.page)
|
ContentPageFactory(parent=cls.page)
|
||||||
|
|
||||||
def test_accessible(self) -> None:
|
def test_accessible(self) -> None:
|
||||||
with self.assertNumQueries(31):
|
with self.assertNumQueries(33):
|
||||||
response = self.client.get(self.page.url)
|
response = self.client.get(self.page.url)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(len(response.context["listing_pages"]), 2)
|
self.assertEqual(len(response.context["listing_pages"]), 2)
|
||||||
|
|
|
@ -187,6 +187,7 @@ BASE_HOSTNAME = env("BASE_HOSTNAME")
|
||||||
WAGTAILADMIN_BASE_URL = f"https://{BASE_HOSTNAME}"
|
WAGTAILADMIN_BASE_URL = f"https://{BASE_HOSTNAME}"
|
||||||
|
|
||||||
WAGTAIL_FRONTEND_LOGIN_URL = "/admin/login/"
|
WAGTAIL_FRONTEND_LOGIN_URL = "/admin/login/"
|
||||||
|
PASSWORD_REQUIRED_TEMPLATE = "password_required.html"
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue