Files
Cozy-Den/docs/guestbook.md
T

114 lines
3.4 KiB
Markdown

# Guestbook — Implementation Notes
## Architecture summary
The guestbook extends the Astro site with **hybrid SSR** mode using the `@astrojs/node` standalone adapter.
- Existing content pages remain static.
- Guestbook and admin pages are server-rendered (`export const prerender = false`).
- API routes handle submissions, moderation, and token-based admin login.
- SQLite (`better-sqlite3`) stores entries, sessions, rate-limit data, and audit logs.
## Relevant files
```
src/
lib/
db.ts — SQLite singleton + schema
guestbook.ts — Entry CRUD, pagination, moderation reads
auth.ts — Session management + cookie policy
spam.ts — Validation + heuristic spam scoring
pages/
guestbook.astro — Public guestbook page
admin/
index.astro — Moderation portal (session-gated)
login.astro — Token login form
pages/api/
guestbook/submit.ts — POST: public guestbook submission
admin/token-login.ts — POST: token authentication + session creation
admin/moderate.ts — POST: approve / reject / spam
admin/logout.ts — POST: end admin session
layouts/
AdminLayout.astro — Minimal admin UI layout
```
## Environment variables
Copy `.env.example` to `.env` and set:
| Variable | Required | Description |
|---|---|---|
| `SECRET_KEY` | **Yes** | Random secret for IP-hash salting and session-related values |
| `ADMIN_SECRET_TOKEN` | **Yes** | Shared secret token for `/admin/login` |
| `COOKIE_SECURE` | No | Force secure cookies (`true`/`false`). If unset, `NODE_ENV=production` => secure cookies |
| `DB_PATH` | No | SQLite path (default: `./data/guestbook.db`) |
| `PORT` | No | Server port (default: `3000`) |
| `HOST` | No | Bind host (default: `0.0.0.0`) |
Generate secrets:
```bash
openssl rand -hex 32 # SECRET_KEY
openssl rand -hex 32 # ADMIN_SECRET_TOKEN
```
## Admin setup
1. Set `ADMIN_SECRET_TOKEN` in your environment.
2. Open `/admin/login`.
3. Enter token.
4. After success, you are redirected to `/admin`.
If token is missing, `/admin/login` shows a configuration warning and login is disabled.
## Local development
```bash
npm install
cp .env.example .env
# set at minimum:
# SECRET_KEY=...
# ADMIN_SECRET_TOKEN=...
# DB_PATH=./data/guestbook.db
# COOKIE_SECURE=false # for local http
npm run dev
# guestbook: http://localhost:4321/guestbook
# admin: http://localhost:4321/admin/login
```
## Docker deployment
```bash
docker compose up -d --build
docker compose logs -f cozy-den
```
The `guestbook_data` Docker volume persists the SQLite database.
## Moderation flow
1. Visitor submits message at `/guestbook`.
2. Entry is saved as `pending`.
3. Admin logs in at `/admin/login` with token.
4. Admin approves/rejects/marks spam in `/admin`.
5. Approved entries are shown publicly.
## Privacy decisions
- IP addresses are never stored directly.
- A truncated salted hash is stored only for rate limiting.
- No tracking scripts or third-party analytics.
- Admin session cookie is `httpOnly` and `SameSite=Strict`.
- User content is stored as plain text (HTML stripped server-side).
## Database tables
| Table | Purpose |
|---|---|
| `guestbook_entries` | Submissions + moderation status |
| `admin_sessions` | Active admin sessions |
| `rate_limit` | Submission throttling by IP hash |
| `audit_log` | Moderation actions |