sign in to manage uploads and slugs.
+no-frills static site hosting "hackfoo"
From ebfd27170bdb4426af2a284a85d195a3cbe9611b Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Fri, 3 Apr 2026 01:27:11 -0400 Subject: refactor: usability and styling simplicity --- auth_backend.py | 7 +- noir-overrides.css | 80 ++++++++++++++ shim_app.py | 305 +++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 321 insertions(+), 71 deletions(-) create mode 100644 noir-overrides.css diff --git a/auth_backend.py b/auth_backend.py index e1ac01c..7219931 100644 --- a/auth_backend.py +++ b/auth_backend.py @@ -5,6 +5,7 @@ import re import sqlite3 import subprocess import sys +import uuid from pathlib import Path from typing import Callable, Optional, Protocol @@ -69,10 +70,10 @@ class LocalMojicryptAuthBackend: with self.connect_db() as conn: conn.execute( """ - INSERT INTO users (username, role, encrypted_challenge, created_at) - VALUES (?, ?, ?, CURRENT_TIMESTAMP) + INSERT INTO users (user_uuid, username, role, encrypted_challenge, created_at) + VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP) """, - (username, role, encrypted), + (str(uuid.uuid4()), username, role, encrypted), ) return True, "user created" except sqlite3.IntegrityError: diff --git a/noir-overrides.css b/noir-overrides.css new file mode 100644 index 0000000..2a1b977 --- /dev/null +++ b/noir-overrides.css @@ -0,0 +1,80 @@ +body { + max-width: 1200px; +} + + +main { + max-width: 1120px; + margin: 0 auto; +} + +.topbar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.75rem; + justify-content: space-between; +} + +.topbar nav { + display: flex; + gap: 0.75rem; + align-items: center; +} + +.inline { + display: inline; +} + +.quiet { + opacity: 0.8; +} + +.stack { + display: grid; + gap: 1rem; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); + gap: 1rem; +} + +.flash { + padding: 0.75rem 1rem; + border-left: 0.35rem solid; +} + +.flash.error { + border-color: #b91c1c; +} + +.flash.success { + border-color: #0f766e; +} + +table { + width: 100%; +} + +td form { + margin: 0; +} + +input[type="text"], +input[type="password"], +input[type="file"], +select { + width: 100%; +} + +@media (max-width: 760px) { + .topbar { + align-items: flex-start; + } + + .topbar nav { + flex-wrap: wrap; + } +} \ No newline at end of file diff --git a/shim_app.py b/shim_app.py index 7e6891a..56799a8 100644 --- a/shim_app.py +++ b/shim_app.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import mimetypes +import json import os import re import secrets @@ -10,6 +11,7 @@ import stat import tarfile import tempfile import time +import uuid import zipfile from dataclasses import dataclass from pathlib import Path @@ -43,14 +45,14 @@ SESSION_COOKIE = "shim_session" ACTIVE_SITE_COOKIE = "shim_active_site" SLUG_RE = re.compile(r"^[a-z0-9](?:[a-z0-9-]{0,126}[a-z0-9])?$") ARCHIVE_SUFFIXES = ( - ".tar.gz", - ".tgz", + ".zip", + ".tar", ".tar.bz2", - ".tbz2", + ".tar.gz", ".tar.xz", + ".tbz2", + ".tgz", ".txz", - ".tar", - ".zip", ) ROOT_ATTR_RE = re.compile(r"(?i)\b(href|src|action|poster)=([\"'])/([^\"']*)\2") CSS_URL_RE = re.compile(r"(?i)url\(\s*([\"']?)/([^\)'\"\s]+)\1\s*\)") @@ -66,26 +68,61 @@ SHELL_TEMPLATE = """ -
sign in to manage uploads and slugs.
+no-frills static site hosting "hackfoo"