docs: add README and manual test instructions (35 protocols across 9 suites)
This commit is contained in:
parent
5f9dec740c
commit
3911dcafa5
2 changed files with 563 additions and 0 deletions
183
README.md
Normal file
183
README.md
Normal file
|
|
@ -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 <admin.secret_token>` 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
|
||||
380
TEST_INSTRUCTIONS.md
Normal file
380
TEST_INSTRUCTIONS.md
Normal file
|
|
@ -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 `<TOKEN>` 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.
|
||||
Loading…
Reference in a new issue