feat: ADD password protection via URL query #34

This commit is contained in:
Caffeine Fueled 2026-09-02 17:27:29 +02:00
parent 8dbe149970
commit 5fb0af99e2
Signed by: cf7
GPG key ID: CA295D643074C68C
2 changed files with 15 additions and 0 deletions

View file

@ -23,6 +23,8 @@ The goal is to keep it simple! For feature-rich solutions please check out [hedg
**Editor:**
- real-time WebSocket collaboration with cursor preservation across remote edits
- per-pad password protection (PBKDF2-SHA256), with a built-in password generator in the UI
- `?pw=…` on a pad URL locks it with that password if it is not protected yet, and unlocks it if it is —
so `https://aukpad.com/{pad_id}/?pw=s3cret` is a one-step create-and-lock link
- line numbers; Tab inserts 4 spaces
- dark / light mode (auto-detects system preference, manual toggle)
- copy-to-clipboard and "new pad" buttons, live peer count in the header
@ -30,6 +32,7 @@ The goal is to keep it simple! For feature-rich solutions please check out [hedg
**Endpoints:**
- custom pad path `{pad_id}` (164 chars, `[a-zA-Z0-9_-]`); auto-generated IDs are 8-char `[a-z0-9]`
- `POST /` — create a pad from request body (curl-friendly, see *Usage*)
- `GET /{pad_id}/` — editor page (`?pw=…` sets the password on an unprotected pad, unlocks a protected one)
- `GET /{pad_id}/raw` — raw text (auth via `?pw=…` for protected pads)
- `GET /system/info` — instance configuration page
- `GET /health` — JSON health check (200 `ok` / 503 `degraded`)
@ -163,6 +166,11 @@ The following environment variables can be configured:
## Security
A password passed as `?pw=…` is convenient but not confidential: it stays in the address bar,
lands in browser history, and shows up in reverse-proxy access logs. Use the lock button in the
editor instead when that matters. Note also that pads have no owner — anyone who can open an
unprotected pad can set or change its password.
For security concerns or reports, please contact via `hello a t uphillsecurity d o t com` [gpg](https://uphillsecurity.com/gpg).
---

7
app.py
View file

@ -448,6 +448,13 @@ function connect(){
isAuthed = true;
hideOverlay();
ver = msg.ver; ta.value = msg.text; updateGutter();
// ?pw= on an unprotected pad sets the password instead of unlocking.
// Guard on !isProtected: the server re-sends init after a successful
// auth, and that init lands here too without the guard every unlock
// would re-hash the same password and re-broadcast protected_changed.
if (urlPw && !isProtected) {
ws.send(JSON.stringify({type: "set_password", password: urlPw}));
}
}
} else if (msg.type === "auth_ok") {
isAuthed = true;