From 3911dcafa5035b90ca28efd5cfab1adcc51c1833 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Sun, 14 Jun 2026 13:51:11 +0000 Subject: [PATCH] docs: add README and manual test instructions (35 protocols across 9 suites) --- README.md | 183 +++++++++++++++++++++ TEST_INSTRUCTIONS.md | 380 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 563 insertions(+) create mode 100644 README.md create mode 100644 TEST_INSTRUCTIONS.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4bf712 --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +# Next Workspace (NextWks) + +A self-hosted workspace platform — Google Workspace-like experience with integrated identity management, admin control plane, and a pluggable module system. + +## Features + +- **Workspace Launcher** — Dynamic app grid dashboard with PWA install support (desktop + mobile) +- **User Management** — SQLite-backed user CRUD with Authelia YAML synchronization +- **OIDC Authentication** — Delegated auth via Authelia (v4.38) with session cookies +- **Admin Panel** — Templ + HTMX admin UI with bearer token API +- **PWA Shell** — Manifest, service worker, offline support, install-to-desktop guide +- **Zero-CGO SQLite** — Single-binary deployment with no system dependencies +- **Pluggable Modules** — Architecture ready for drop-in apps (Office, Files, Calendar, etc.) + +## Architecture + +``` + ┌──────────────────┐ + │ Zoraxy Proxy │ + │ (TLS + routing) │ + └────┬─────────┬───┘ + │ │ + ┌────────────▼──┐ ┌──▼──────────────┐ + │ Authelia │ │ NextWks Core │ + │ :9091 (OIDC) │ │ :8080 (App) │ + │ │ │ │ + │ users_db.yml │◄─┤ core/admin/ │ + │ config.yml │ │ core/ui/ │ + └────────────────┘ │ core/auth/ │ + └──────────────────┘ +``` + +## Repository Structure + +``` +NextWks/ +├── src/ # Go source code (github.com/lexton-it/NextWks) +│ ├── main.go # Entry point (-config flag) +│ ├── cmd/setupcheck/ # Path verification tool +│ └── core/ +│ ├── config/ # YAML config parser +│ ├── db/ # SQLite driver + auto-migrations +│ ├── admin/ # User CRUD + Authelia sync + Templ UI +│ ├── auth/ # OIDC client + session store +│ ├── ui/ # Launcher, app grid, PWA templates +│ ├── api/ # gRPC proto definitions (future) +│ ├── modules/ # Drop-in app sources (future) +│ └── supervisor/ # Module process manager (future) +├── app/ # Dev distribution +│ ├── core # Compiled binary +│ ├── config.yaml # Dev configuration +│ ├── data/ # SQLite database (dev) +│ └── static/ # PWA assets (manifest, SW, icons) +├── scripts/ +│ └── install-authelia.sh # Authelia deployment script +├── install.sh # Production installer +└── testdata/ # Test fixtures +``` + +## Quick Start + +### Prerequisites + +- Go 1.22+ +- Authelia v4.38 (install with `bash scripts/install-authelia.sh`) + +### Development + +```bash +# Build +cd src && go build -o ../app/core . + +# Run (from app/ directory) +cd ../app && ./core + +# Run with custom config +./core -config /path/to/config.yaml +``` + +The server starts on `http://localhost:8080` with: +- **Workspace launcher**: `http://localhost:8080/` (OIDC-protected) +- **Admin panel**: `http://localhost:8080/admin` (bearer token) +- **Health API**: `http://localhost:8080/api/health` +- **Auth status**: `http://localhost:8080/auth/status` + +### Production Install + +```bash +# Full install (build → test → deploy → systemd → smoke test) +./install.sh + +# Check status +./install.sh --status + +# Uninstall +./install.sh --uninstall +``` + +More options: +```bash +./install.sh --build-only # Compile only +./install.sh --skip-build # Install existing binary +./install.sh --config-only # Generate config only +./install.sh --help # Show all options +``` + +### Run Tests + +```bash +cd src && go test ./... -v +``` + +46 tests covering config parsing, SQLite operations, user CRUD, auth middleware, and YAML synchronization. + +## Configuration + +```yaml +# config.yaml +server: + host: "0.0.0.0" + port: 8080 + +admin: + secret_token: "your-admin-token" # Protects /admin/* routes + +database: + type: "sqlite" + path: "./data/nextwks.db" + +authelia: + host: "http://127.0.0.1:9091" + config_path: "/opt/authelia/configuration.yml" + users_db_path: "/opt/authelia/users_database.yml" + +oidc: + client_id: "nextwks" + redirect_url: "https://wks.lohmar.co.uk/auth/callback" + domain: "wks.lohmar.co.uk" +``` + +## Admin API + +Protected by `Authorization: Bearer ` header. + +### List Users +```bash +curl -H "Authorization: Bearer $ADMIN_TOKEN" http://localhost:8080/admin/api/users +``` + +### Create User +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"users":[{"username":"jdoe","display_name":"John Doe","email":"john@example.com","groups":"users"}]}' +``` + +### Delete User +```bash +curl -X DELETE http://localhost:8080/admin/api/users/jdoe \ + -H "Authorization: Bearer $ADMIN_TOKEN" +``` + +### Health Check +```bash +curl -H "Authorization: Bearer $ADMIN_TOKEN" http://localhost:8080/admin/api/health +``` + +## Authelia Integration + +NextWks acts as a management layer for Authelia. When users are created or deleted: + +1. The user is stored in NextWks' SQLite database (source of truth) +2. The user is automatically synchronized to `/opt/authelia/users_database.yml` +3. Authelia detects the file change (watch mode) and reloads + +On first boot, NextWks bootstraps existing Authelia users into its database. + +**OIDC**: Authelia must be configured with the `nextwks` client. See the [Authelia configuration guide](https://www.authelia.com/configuration/identity-providers/openid-connect/clients/). + +## License + +MIT diff --git a/TEST_INSTRUCTIONS.md b/TEST_INSTRUCTIONS.md new file mode 100644 index 0000000..fa96a3b --- /dev/null +++ b/TEST_INSTRUCTIONS.md @@ -0,0 +1,380 @@ +# NextWks — Manual Test Instructions + +This document contains step-by-step test protocols you can run to verify the system end-to-end. + +## Pre-Test Setup + +```bash +# 1. Ensure services are running +systemctl status authelia # Should show: active (running) + +# 2. Build NextWks +cd /root/lexton-it/NextWks/src && go build -o ../app/core . + +# 3. Start NextWks in a separate terminal +cd /root/lexton-it/NextWks/app && ./core +``` + +Keep the server running for all tests below. Replace `` with your admin token from `app/config.yaml` (`admin.secret_token`). + +--- + +## Test Suite 1 — Core Health + +### T1.1 — Health Endpoint +```bash +curl http://localhost:8080/api/health +``` +**Expected:** `{"status":"ok"}` + +### T1.2 — Auth Status Endpoint +```bash +curl http://localhost:8080/auth/status +``` +**Expected:** `{"provider":"Authelia","issuer":"http://127.0.0.1:9091","status":"configured"}` + +### T1.3 — Authelia Health +```bash +curl http://127.0.0.1:9091/api/health +``` +**Expected:** `{"status":"OK"}` + +### T1.4 — Service Listening +```bash +ss -tlnp | grep -E '8080|9091' +``` +**Expected:** Both ports listed. 8080 = nextwks, 9091 = authelia. + +--- + +## Test Suite 2 — Admin API (Bearer Token) + +### T2.1 — Protected Access (No Token) +```bash +curl http://localhost:8080/admin/api/health +``` +**Expected:** `{"error":"unauthorized"}` (HTTP 401) + +### T2.2 — Protected Access (Wrong Token) +```bash +curl -H "Authorization: Bearer wrong-token" http://localhost:8080/admin/api/health +``` +**Expected:** `{"error":"unauthorized"}` (HTTP 401) + +### T2.3 — Admin Health (Correct Token) +```bash +TOKEN="dev-admin-secret-token" +curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/admin/api/health +``` +**Expected:** `{"status":"ok","user_count":...,"authelia_db":"/opt/authelia/users_database.yml"}` + +--- + +## Test Suite 3 — User Management + +### T3.1 — List Users (Empty/Fresh) +```bash +curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/admin/api/users +``` +**Expected:** JSON array (may include bootstrapped Authelia users: `admin`, `clohmar`) + +### T3.2 — Create Single User +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "users": [ + { + "username": "testuser1", + "display_name": "Test User", + "email": "test@example.com", + "groups": "users" + } + ] + }' | python3 -m json.tool +``` +**Expected:** +```json +{ + "results": [ + { + "username": "testuser1", + "generated_password": "<20-char-password>", + "error": "" + } + ] +} +``` +- ✅ Password is 20 characters +- ✅ No error +- ✅ Save the generated password for later + +### T3.3 — Create Duplicate User +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"users":[{"username":"testuser1"}]}' +``` +**Expected:** `{"results":[{"username":"testuser1","error":"user already exists"}]}` + +### T3.4 — Create Empty Username +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"users":[{"username":""}]}' +``` +**Expected:** `{"results":[{"username":"","error":"username is required"}]}` + +### T3.5 — Create Multiple Users +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "users": [ + {"username":"user-a","display_name":"User A"}, + {"username":"user-b","display_name":"User B"}, + {"username":"user-c","display_name":"User C"} + ] + }' | python3 -m json.tool +``` +**Expected:** 3 results, all with generated passwords, no errors. + +### T3.6 — List Users After Creation +```bash +curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/admin/api/users | python3 -m json.tool +``` +**Expected:** List includes `testuser1`, `user-a`, `user-b`, `user-c` plus bootstrapped users. + +### T3.7 — Delete User +```bash +curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:8080/admin/api/users/testuser1 +``` +**Expected:** `{"status":"deleted","username":"testuser1"}` + +### T3.8 — Delete Nonexistent User +```bash +curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:8080/admin/api/users/nonexistent +``` +**Expected:** `{"error":"user nonexistent not found"}` (HTTP 404) + +--- + +## Test Suite 4 — Authelia YAML Sync + +### T4.1 — Verify Sync After Creation +```bash +cat /opt/authelia/users_database.yml +``` +**Expected:** The file contains entries for `user-a`, `user-b`, `user-c` (the users created in T3.5). + +### T4.2 — Verify Sync After Deletion +```bash +cat /opt/authelia/users_database.yml | grep testuser1 || echo "testuser1 removed" +``` +**Expected:** `testuser1 removed` (not in the YAML anymore). + +### T4.3 — Verify Argon2 Hash Format +```bash +grep "password:" /opt/authelia/users_database.yml | head -1 +``` +**Expected:** `password: "$argon2id$v=19$m=65536,t=3,p=4$...$..."` + +--- + +## Test Suite 5 — Admin UI (Browser) + +### T5.1 — Admin Dashboard +Open in browser: +``` +http://localhost:8080/admin +``` +**Note:** You need the bearer token. Configure your browser to add header: +`Authorization: Bearer dev-admin-secret-token` (use browser extension or curl to verify). + +**Expected:** +- Dark-themed dashboard loads +- Shows "Admin Dashboard" with user count stat card +- Sidebar navigation visible (Dashboard, Users) + +### T5.2 — User Management Page +Navigate to `http://localhost:8080/admin/users` + +**Expected:** +- User table loads via HTMX (lazy-load) +- Shows created users with status badges +- "+ Add User" button visible +- Delete buttons with confirmation prompt + +### T5.3 — Create User (UI) +1. Click "+ Add User" button +2. Fill in: Username, Display Name, Email, Groups +3. Click "Create User" + +**Expected:** +- Success alert with generated password shown +- Auto-refreshes the user table after creation + +### T5.4 — Delete User (UI) +1. Click the red "Delete" button next to a test user +2. Confirm the dialog + +**Expected:** +- Row disappears from the table +- User removed from Authelia YAML + +--- + +## Test Suite 6 — OIDC Authentication Flow + +### Prerequisites +Authelia must have the `nextwks` OIDC client registered and running. Verify: +```bash +curl -s http://127.0.0.1:9091/.well-known/openid-configuration | grep authorization_endpoint +``` +**Expected:** `"authorization_endpoint":"http://127.0.0.1:9091/api/oidc/authorization"` + +### T6.1 — Login Redirect +Open in browser: +``` +http://localhost:8080/ +``` +**Expected:** Redirected to Authelia login page at `http://127.0.0.1:9091/` with OIDC parameters in URL. + +### T6.2 — Full Login Flow +1. Visit `http://localhost:8080/` → redirected to Authelia login +2. Login with credentials (e.g., `admin` / `ueM8tLARi5v3orIzvd56w6u6!`) +3. After successful login → redirected back to NextWks launcher + +**Expected:** +- See workspace launcher page +- Shows "Welcome" heading (with username if extracted) +- App grid visible with 6 tiles + +--- + +## Test Suite 7 — Launcher & PWA + +### T7.1 — Launcher Page +Visit `http://localhost:8080/` (after OIDC login or with session cookie) + +**Expected:** +- Dark-themed workspace layout +- Header bar with logo "NextWks" and install button +- App grid with 6 tiles: Admin Panel, Files, Calendar, Mail, Office, Settings +- Admin Panel tile shows "● Available" +- Other tiles show "● Coming Soon" and are greyed out + +### T7.2 — PWA Assets +```bash +curl http://localhost:8080/static/manifest.json | python3 -m json.tool +curl http://localhost:8080/static/sw.js | head -5 +curl -o /dev/null -w "%{http_code}" http://localhost:8080/static/icons/icon-192.svg +``` +**Expected:** +- `manifest.json` → valid JSON with `"name":"Next Workspace"` +- `sw.js` → JavaScript content +- `icon-192.svg` → HTTP 200 + +### T7.3 — PWA Install Modal +1. Click the install/download button in the header bar +2. If browser doesn't trigger native prompt → modal appears + +**Expected:** +- Modal shows "Install Next Workspace" with platform-specific instructions: + - Desktop Chrome/Edge steps + - iOS Safari steps (Share → Add to Home Screen) + - Android Chrome steps (Menu → Install app) +- "Got it" button closes the modal + +### T7.4 — Manifest Validity +```bash +curl -s http://localhost:8080/static/manifest.json | python3 -c " +import json, sys +m = json.load(sys.stdin) +assert m['name'] == 'Next Workspace', 'Wrong name' +assert m['display'] == 'standalone', 'Wrong display mode' +assert len(m['icons']) >= 2, 'Missing icons' +assert m['start_url'] == '/', 'Wrong start_url' +print('Manifest valid:', m['name']) +" +``` +**Expected:** `Manifest valid: Next Workspace` + +--- + +## Test Suite 8 — Installer + +### T8.1 — Installer Help +```bash +cd /root/lexton-it/NextWks && ./install.sh --help +``` +**Expected:** Usage text with all flags listed. + +### T8.2 — Status Check +```bash +./install.sh --status +``` +**Expected:** Shows binary, config, service status, Authelia status. + +### T8.3 — Build Only +```bash +./install.sh --build-only +``` +**Expected:** Compiles binary to `app/core`, runs tests, skips install. + +### T8.4 — Config Only +```bash +./install.sh --config-only 2>&1 | head -20 +``` +**Expected:** Generates config (or warns it exists), shows admin token. + +--- + +## Test Suite 9 — Error Cases + +### T9.1 — Invalid JSON Body +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d 'not-json' +``` +**Expected:** `{"error":"invalid JSON body"}` (HTTP 400) + +### T9.2 — Empty Users Array +```bash +curl -X POST http://localhost:8080/admin/api/users \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"users":[]}' +``` +**Expected:** `{"error":"no users provided"}` (HTTP 400) + +### T9.3 — 404 Page +```bash +curl http://localhost:8080/nonexistent-page +``` +**Expected:** 404 Not Found + +--- + +## Test Results Summary + +| Suite | Tests | Pass | Notes | +|-------|-------|------|-------| +| 1. Core Health | 4 | | | +| 2. Admin API Auth | 3 | | | +| 3. User Management | 8 | | | +| 4. Authelia Sync | 3 | | | +| 5. Admin UI | 4 | | | +| 6. OIDC Flow | 2 | | | +| 7. Launcher & PWA | 4 | | | +| 8. Installer | 4 | | | +| 9. Error Cases | 3 | | | +| **Total** | **35** | | | + +Fill in passes as you complete each test. Report any failures or unexpected behavior.