docs(e2e): add debugging notes and fix incorrect login example
Document lessons learned from debugging blocklist import tests: - RequestsLibrary vs Browser library auth isolation - CSRF header requirement - Robot variable type rules - network_mode: host implications - SSRF protection behavior - API response key discrepancies Also fix API login example: backend accepts plaintext passwords, not SHA256-hashed as previously documented. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -257,18 +257,71 @@ Backend: `http://127.0.0.1:8000` · Frontend (Vite proxy): `http://127.0.0.1:517
|
|||||||
|
|
||||||
### API login (dev)
|
### API login (dev)
|
||||||
|
|
||||||
The frontend SHA256-hashes the password before sending it to the API.
|
The backend accepts **plaintext** passwords (no frontend hashing).
|
||||||
The initial setup password must be at least 8 characters long and include one uppercase letter, one number, and one special character from `!@#$%^&*()`.
|
|
||||||
The session cookie is named `bangui_session`.
|
The session cookie is named `bangui_session`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Dev master password: Hallo123!
|
# Dev master password: Hallo123!
|
||||||
HASHED=$(echo -n "Hallo123!" | sha256sum | awk '{print $1}')
|
|
||||||
TOKEN=$(curl -s -X POST http://127.0.0.1:8000/api/v1/auth/login \
|
TOKEN=$(curl -s -X POST http://127.0.0.1:8000/api/v1/auth/login \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
-d "{\"password\":\"$HASHED\"}" \
|
-d '{"password":"Hallo123!"}' \
|
||||||
| python3 -c 'import sys,json; print(json.load(sys.stdin)["token"])')
|
| python3 -c 'import sys,json; print(json.load(sys.stdin)["expires_at"])')
|
||||||
|
# Login sets bangui_session cookie automatically.
|
||||||
# Use token in subsequent requests:
|
# Use the cookie in subsequent requests:
|
||||||
curl -H "Cookie: bangui_session=$TOKEN" http://127.0.0.1:8000/api/v1/dashboard/status
|
curl -b "bangui_session=$(cat ~/.bangui_session)" http://127.0.0.1:8000/api/v1/dashboard/status
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## E2E Testing Notes
|
||||||
|
|
||||||
|
Debugging failures: open `results/log.html` (not output.xml) for full request/response traces.
|
||||||
|
|
||||||
|
### Auth (RequestsLibrary vs Browser)
|
||||||
|
|
||||||
|
`Login As Admin` uses browser JavaScript (`Evaluate JavaScript`) — session cookie lives in the **browser context only**.
|
||||||
|
Any `RequestsLibrary` keyword (GET/POST to API) in the same test needs its own auth session.
|
||||||
|
Use `Login Via HTTP` from `auth.resource` to get a session cookie for RequestsLibrary calls.
|
||||||
|
RequestsLibrary and Browser library share no state.
|
||||||
|
|
||||||
|
### CSRF Protection
|
||||||
|
|
||||||
|
Backend enforces CSRF on all POST/PUT/DELETE via `X-BanGUI-Request: 1` header.
|
||||||
|
RequestsLibrary sessions must include this header on creation:
|
||||||
|
```
|
||||||
|
Create Session bangsess ${BACKEND_URL} headers=${headers} # headers = {X-BanGUI-Request: 1}
|
||||||
|
```
|
||||||
|
Then all requests on that session inherit it.
|
||||||
|
|
||||||
|
### Robot Variable Type Rules
|
||||||
|
|
||||||
|
Bare values in `Create Dictionary` are **strings**, not Python types:
|
||||||
|
- `enabled=true` → `"true"` (string) — backend Pydantic expects boolean → validation fails
|
||||||
|
- Fix: `enabled=${TRUE}` for booleans, `${60}` for integers
|
||||||
|
- `${NONE}` is Robot's null/None equivalent
|
||||||
|
- `${len(sources)}` is invalid — use `Get Length ${sources}` keyword instead
|
||||||
|
|
||||||
|
### Network Mode (podman-compose)
|
||||||
|
|
||||||
|
With `network_mode: host`, containers share the host network namespace.
|
||||||
|
- Backend can reach host's `127.0.0.1:PORT` — needed for mock HTTP servers
|
||||||
|
- Frontend must set `VITE_BACKEND_URL=http://localhost:8000` since `localhost` now resolves to host
|
||||||
|
- Vite proxy works when frontend also uses `network_mode: host` (same namespace)
|
||||||
|
|
||||||
|
### SSRF Protection
|
||||||
|
|
||||||
|
Blocklist source URLs are validated: hostname must resolve to a **public** IP.
|
||||||
|
- `127.0.0.1` and other loopback addresses are rejected
|
||||||
|
- In dev mode (`BANGUI_LOG_LEVEL=debug`), loopback is allowed for e2e testing
|
||||||
|
- For real e2e tests, use a public blocklist URL or ensure mock server is reachable
|
||||||
|
|
||||||
|
### API Response Keys
|
||||||
|
|
||||||
|
Always verify response shape in `results/log.html` — field names differ from expectations:
|
||||||
|
- Blocklist import log: `items` not `entries`
|
||||||
|
- Error responses: `{"code": "...", "detail": "..."}`
|
||||||
|
|
||||||
|
### Process Library Teardown
|
||||||
|
|
||||||
|
`Terminate Process` fails if the process alias doesn't exist (mock server not started).
|
||||||
|
Wrap in `Run Keyword And Return Status` to avoid teardown cascading failures.
|
||||||
|
|||||||
Reference in New Issue
Block a user