Revert to working
* Remove HTTP Basic auth * Keep changes to timezone input * Re-add all views
This commit is contained in:
parent
c503bb6127
commit
0674bfee54
|
@ -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 %}
|
134
main/views.py
134
main/views.py
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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 [])
|
||||
|
|
Loading…
Reference in New Issue