# Authentication & Authorization ## Overview Trackpull uses session-based authentication backed by a SQLite database. There are two roles: **admin** and **user**. Passwords are hashed using werkzeug's PBKDF2-based scheme — no plaintext is ever stored. --- ## Login Flow 1. User submits credentials via `POST /login`. 2. `get_user_by_username()` looks up the record in the `users` table. 3. `check_password_hash()` verifies the submitted password against the stored hash. 4. On success, Flask session is populated with `user_id`, `username`, and `role`. 5. User is redirected to the main app. On failure, the login page re-renders with an error. Logout is a simple `GET /logout` that clears the session and redirects to `/login`. --- ## Authorization Enforcement A `@app.before_request` hook runs before every request. If the session lacks a `user_id`, the request is redirected to `/login`. Public (unauthenticated) routes are whitelisted: - `/login` - `/logout` - `/static/*` - `/offline` - `/sw.js` Admin-only routes check `session["role"] == "admin"` via a `require_admin()` helper. Unauthorized admin access returns `403`. --- ## Role Permissions | Action | User | Admin | |--------|------|-------| | Download (Votify/Monochrome/Unified) | Yes | Yes | | View own jobs & files | Yes | Yes | | Cancel/delete own jobs | Yes | Yes | | Change own password | Yes | Yes | | View any user's jobs/files | No | Yes | | Manage users (create/delete/reset) | No | Yes | | Upload cookies.txt / device.wvd | No | Yes | | Change global settings | No | Yes | --- ## Admin Seeding On first run, if no users exist in the database, an admin account is created automatically from `ADMIN_USERNAME` and `ADMIN_PASSWORD` environment variables (see [docker-deployment.md](docker-deployment.md)). --- ## Session Security - Sessions are encrypted using Flask's `SECRET_KEY` env var (should be a 32-byte random hex string). - Sessions survive application restarts because the key is stable. - There is no token-based auth or "remember me" — sessions expire when the browser closes by default. --- ## Password Management - `update_user_password()` in `db.py` re-hashes and saves a new password. - Users change their own password at `POST /api/account/password`. - Admins reset any user's password at `POST /api/admin/users//password`. --- ## Key Files | File | Relevance | |------|-----------| | [app.py](../app.py) | Route definitions, `before_request` hook, `require_admin()` | | [db.py](../db.py) | `create_user`, `get_user_by_username`, `verify_password`, `update_user_password` |