Revert to working

* Remove HTTP Basic auth
* Keep changes to timezone input
* Re-add all views
This commit is contained in:
Matthias Portzel 2022-01-06 11:20:47 -08:00
parent c503bb6127
commit 0674bfee54
3 changed files with 170 additions and 6 deletions

View File

@ -0,0 +1,34 @@
{% 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 %}

View File

@ -1,4 +1,134 @@
from django.http import HttpRequest
import os.path
import uuid
import subprocess
import base64
import magic
from django.shortcuts import render
from django.utils.crypto import constant_time_compare
from django.http import HttpResponse
from whispermaphone import settings
from .models import Thought, ThoughtForm, ALLOWED_MEDIA_TYPES
from .pagination import get_all_pages, get_page_slug
def check_authenticated(request):
authenticated = False
try:
if constant_time_compare(request.COOKIES["password"], settings.PASSWORD):
authenticated = True
except KeyError:
pass
return authenticated
def index(request):
return HttpRequest("I'm done. The website's broken and I'm not smart enough to fix it. It's still available over Gemini I think.")
authenticated = check_authenticated(request)
try:
highlighted_uuid = uuid.UUID(request.GET.get("show", ""))
except ValueError:
highlighted_uuid = ""
# Figure out what page we're viewing
pages = get_all_pages()
# First item in pages should be listed first
requested_page = pages[0]
requested_slug = request.GET.get("page", default=requested_page.slug)
# show=uuid takes priority over page
if highlighted_uuid:
try:
highlighted_thought = Thought.objects.get(uuid=highlighted_uuid)
requested_slug = get_page_slug(highlighted_thought)
except Thought.DoesNotExist:
pass
if requested_page.slug != requested_slug:
for p in pages:
if p.slug == requested_slug:
requested_page = p
thoughts = requested_page.get_all_entries()
return render(request, "whispermaphone/index.html", {
"thoughts": thoughts,
"highlighted": highlighted_uuid,
"authenticated": authenticated,
"pages": pages,
"current_page": requested_slug,
"first_page": requested_page == pages[0] # if you're viewing the first page
})
def post(request):
if not check_authenticated(request):
return render(request, "whispermaphone/login.html", status=401)
if request.method == "POST":
# 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():
errors = thought_form.errors.as_data()
# Media formatting errors
try:
problem_field = list(errors.keys())[0]
message = list(errors.values())[0][0].messages[0]
# error_line = f"{problem_field[0].upper()}{problem_field[1:]}: {message}"
error_line = f"{message}"
except:
error_line = f"An unknown error occurred processing your request: {errors}"
return render(request, "whispermaphone/post.html", {
"form": thought_form,
"form_error": error_line
}, status=400)
# Create a thought object we can work with
# But don't save it the DB yet
thought = thought_form.save(commit=False)
# Do media processing (already validated)
if "media" in request.FILES:
chunk = next(thought.media.chunks(chunk_size=2048))
media_type = magic.from_buffer(chunk, mime="True")
thought.media.name = f"{thought.uuid}.{ALLOWED_MEDIA_TYPES[media_type]}"
if media_type == "audio/x-m4a":
# This is a hack-fix because I want to be able to upload audio
# In the future, this should be refactored to convert file types
# using ffmpeg.js on the client side (so there are 0 security concerns)
# and then the backend just has to check a 3 item whitelist
thought.save() # Save so that we have a file to work with
subprocess.run(["ffmpeg",
"-i", thought.media.path,
"-codec:a", "aac", "-vn",
os.path.join(settings.MEDIA_ROOT, f"{thought.uuid}.aac")
], check=True)
os.remove(os.path.join(settings.MEDIA_ROOT, f"{thought.uuid}.m4a")) # Remove the original file
thought.media.name = f"{thought.uuid}.aac" # Update the file in the DB
# Save for real
thought.save()
return render(request, "whispermaphone/post.html", {"form": ThoughtForm()})
def about(request):
return render(request, "whispermaphone/about.html", {
"authenticated": check_authenticated(request)
})

View File

@ -10,8 +10,8 @@ from haystack.forms import SearchForm
urlpatterns = [
path("", views.index, name="index"),
# path("about", views.about, name="about"),
# path("post", views.post, name="post"),
# path("feed", MainFeed()),
# path("search", SearchView(form_class=SearchForm), name="thoughts_search")
path("about", views.about, name="about"),
path("post", views.post, name="post"),
path("feed", MainFeed()),
path("search", SearchView(form_class=SearchForm), name="thoughts_search")
] + (static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG else [])