Switch to HTTP Basic Auth
This commit is contained in:
parent
c49b7c47c4
commit
e03a98cda7
|
@ -82,7 +82,7 @@ class ThoughtForm(forms.ModelForm):
|
||||||
widgets = {
|
widgets = {
|
||||||
"text": forms.Textarea(attrs={"class": "thought", "rows": 1, "placeholder": "What are you thinking?"}),
|
"text": forms.Textarea(attrs={"class": "thought", "rows": 1, "placeholder": "What are you thinking?"}),
|
||||||
"extended_text": forms.Textarea(attrs={"class": "thought", "rows": 1, "placeholder": "Anything else?"}),
|
"extended_text": forms.Textarea(attrs={"class": "thought", "rows": 1, "placeholder": "Anything else?"}),
|
||||||
"timezone_offset": forms.HiddenInput,
|
"timezone_offset": forms.NumberInput,
|
||||||
"media_alt": forms.Textarea(attrs={"placeholder": "Media alternate text, please", "rows": 1})
|
"media_alt": forms.Textarea(attrs={"placeholder": "Media alternate text, please", "rows": 1})
|
||||||
}
|
}
|
||||||
field_classes = {
|
field_classes = {
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
{% extends "whispermaphone/page.html" %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %}Post{% endblock %}
|
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
<link href="{% static 'main/login.css' %}" rel="stylesheet">
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block navigation %}
|
|
||||||
<a class="text" href="/">Thoughts</a>
|
|
||||||
<a class="text" href="/about">About</a>
|
|
||||||
<h1 class="text" aria-current="page">Login</h1>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
<span class="text">
|
|
||||||
Please enter the password to access this page.
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<form id="password-form">
|
|
||||||
<input type="password" id="password">
|
|
||||||
<input type="submit" value="Login">
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block scripts %}
|
|
||||||
<script>
|
|
||||||
document.getElementById("password-form").addEventListener("submit", evt => {
|
|
||||||
document.cookie = `password=${document.getElementById("password").value}; max-age=15768000; samesite=strict`;
|
|
||||||
window.location.reload();
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
|
@ -62,7 +62,6 @@
|
||||||
textEl.value = value.substring(0, splitAt - 1); //Remove word and space from original
|
textEl.value = value.substring(0, splitAt - 1); //Remove word and space from original
|
||||||
|
|
||||||
// Only move down if we're at the end of the first box
|
// Only move down if we're at the end of the first box
|
||||||
console.log(startPos, endPos);
|
|
||||||
if (startPos === 141 && endPos === 141) {
|
if (startPos === 141 && endPos === 141) {
|
||||||
textExtEl.value = toMove + textExtEl.value;
|
textExtEl.value = toMove + textExtEl.value;
|
||||||
|
|
||||||
|
@ -122,6 +121,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const timezoneOffsetEl = document.getElementById("id_timezone_offset");
|
const timezoneOffsetEl = document.getElementById("id_timezone_offset");
|
||||||
timezoneOffsetEl.value = (new Date()).getTimezoneOffset();
|
timezoneOffsetEl.setAttribute("type", "hidden");
|
||||||
|
// The text box needs to be in hours, UTC offset (e.g. -8)
|
||||||
|
// .getTimezoneOffset() returns minutes behind UTC
|
||||||
|
timezoneOffsetEl.value = -(new Date()).getTimezoneOffset() / 60;
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import os.path
|
import os.path
|
||||||
import uuid
|
import uuid
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import base64
|
||||||
|
|
||||||
import magic
|
import magic
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.crypto import constant_time_compare
|
from django.utils.crypto import constant_time_compare
|
||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
from whispermaphone import settings
|
from whispermaphone import settings
|
||||||
from .models import Thought, ThoughtForm, ALLOWED_MEDIA_TYPES
|
from .models import Thought, ThoughtForm, ALLOWED_MEDIA_TYPES
|
||||||
|
@ -13,13 +15,15 @@ from .models import Thought, ThoughtForm, ALLOWED_MEDIA_TYPES
|
||||||
from .pagination import get_all_pages, get_page_slug
|
from .pagination import get_all_pages, get_page_slug
|
||||||
|
|
||||||
def check_authenticated(request):
|
def check_authenticated(request):
|
||||||
authenticated = False
|
|
||||||
try:
|
try:
|
||||||
if constant_time_compare(request.COOKIES["password"], settings.PASSWORD):
|
auth = request.headers["Authorization"].split()
|
||||||
authenticated = True
|
if auth[0].lower() == "basic":
|
||||||
except KeyError:
|
username, password = base64.b64decode(auth[1]).split(b":")
|
||||||
|
if password == bytes(settings.PASSWORD, "utf-8"):
|
||||||
|
return True
|
||||||
|
except (KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
return authenticated
|
return False
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
|
@ -64,10 +68,23 @@ def index(request):
|
||||||
|
|
||||||
def post(request):
|
def post(request):
|
||||||
if not check_authenticated(request):
|
if not check_authenticated(request):
|
||||||
return render(request, "whispermaphone/login.html", status=401)
|
res = HttpResponse(status=401)
|
||||||
|
res.headers["WWW-Authenticate"] = 'Basic realm="Poster"'
|
||||||
|
return res
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
thought_form = ThoughtForm(request.POST, request.FILES, instance=Thought())
|
# We post in hours, so we need to convert back to minutes for saving
|
||||||
|
# We can pass errors since form.is_valid catches most of them
|
||||||
|
# We just need to convert hours to minutes first, because otherwise it errors on non-integer values
|
||||||
|
if "timezone_offset" in request.POST:
|
||||||
|
values = request.POST.copy()
|
||||||
|
try:
|
||||||
|
values["timezone_offset"] = - float(values["timezone_offset"]) * 60
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
thought_form = ThoughtForm(values, request.FILES, instance=Thought())
|
||||||
|
|
||||||
if not thought_form.is_valid():
|
if not thought_form.is_valid():
|
||||||
errors = thought_form.errors.as_data()
|
errors = thought_form.errors.as_data()
|
||||||
# Media formatting errors
|
# Media formatting errors
|
||||||
|
@ -116,6 +133,6 @@ def post(request):
|
||||||
|
|
||||||
|
|
||||||
def about(request):
|
def about(request):
|
||||||
authenticated = check_authenticated(request)
|
return render(request, "whispermaphone/about.html", {
|
||||||
|
"authenticated": check_authenticated(request)
|
||||||
return render(request, "whispermaphone/about.html", {"authenticated": authenticated})
|
})
|
||||||
|
|
|
@ -65,7 +65,7 @@ MIDDLEWARE = [
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
CSRF_COOKIE_SECURE = True
|
CSRF_COOKIE_SECURE = False
|
||||||
|
|
||||||
ROOT_URLCONF = "whispermaphone.urls"
|
ROOT_URLCONF = "whispermaphone.urls"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue