From e153d54917faf93c633185112b22270a7b676e67 Mon Sep 17 00:00:00 2001 From: Ettore <=> Date: Wed, 6 May 2026 23:50:40 +0200 Subject: [PATCH] Add readme --- README.md | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..46f9967 --- /dev/null +++ b/README.md @@ -0,0 +1,168 @@ +![](./src/static/logo.svg) + +# Lagomare Gates + +A web-based gate access management and control system. Authorized users can remotely open physical car and pedestrian gates via a mobile-friendly PWA. An admin dashboard provides full management of gates, access codes, and users. + +## Features + +- **Keypass authentication** — users authenticate with an access code; each keypass can have a per-gate allowlist and an optional expiration date +- **Remote gate control** — integrates with [AVConnect](https://www.avconnect.it) to trigger gate macros +- **Role-based admin panel** — two roles (`admin`, `manager`) with different permission levels +- **Access audit log** — every open attempt is logged with timestamp, keypass, gate, IP, and result +- **Progressive Web App** — installable on mobile devices with offline caching + +## Tech Stack + +| Layer | Technology | +|---|---| +| Backend | FastAPI + Uvicorn | +| ORM | SQLAlchemy | +| Database | SQLite | +| Auth | JWT (HS256) + bcrypt | +| Credential storage | Fernet symmetric encryption | +| Gate integration | AVConnect HTTP API | +| Frontend | Vanilla JS PWA | + +## Project Structure + +``` +src/ +├── main.py # App entry point, startup, static file serving +├── core/ +│ ├── auth.py # JWT creation/verification, password hashing +│ ├── config.py # Settings loaded from environment variables +│ ├── database.py # SQLAlchemy models and DB initialization +│ ├── dependencies.py # FastAPI dependency injection (auth guards) +│ └── schemas.py # Pydantic request/response schemas +├── models/ # Thin wrappers re-exporting DB models +├── routers/ +│ ├── auth.py # POST /api/auth/admin, POST /api/auth/keypass +│ ├── gates.py # User-facing gate list and open endpoints +│ ├── keypasses.py # Admin keypass CRUD +│ ├── admins.py # Admin user management +│ ├── credentials.py # AVConnect credential management +│ └── stats.py # Access log / statistics +├── services/ +│ ├── avconnect.py # AVConnect session management and macro execution +│ └── gates.py # Gate open orchestration +└── static/ # Frontend PWA (index.html, admin.html, JS, CSS) +data/ +└── gates.db # SQLite database (auto-created on first run) +``` + +## API Endpoints + +### Authentication + +| Method | Endpoint | Description | +|---|---|---| +| POST | `/api/auth/admin` | Admin login — returns JWT | +| POST | `/api/auth/keypass` | Keypass login — returns JWT | + +### User (keypass token required) + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/api/gates` | List gates accessible to the authenticated keypass | +| POST | `/api/gates/{gate_id}/open` | Open a gate | + +### Admin — Gates (manager+) + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/api/admin/gates` | List all gates | +| POST | `/api/admin/gates` | Create a gate *(admin only)* | +| PUT | `/api/admin/gates/{gate_id}` | Update a gate *(admin only)* | +| DELETE | `/api/admin/gates/{gate_id}` | Delete a gate *(admin only)* | +| POST | `/api/admin/gates/{gate_id}/open` | Manually open a gate | + +### Admin — Keypasses (manager+) + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/api/admin/keypasses` | List all keypasses | +| POST | `/api/admin/keypasses` | Create a keypass | +| PATCH | `/api/admin/keypasses/{kp_id}` | Update a keypass | +| DELETE | `/api/admin/keypasses/{kp_id}` | Revoke a keypass | + +### Admin — Users (admin only) + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/api/admin/admins` | List admin users | +| POST | `/api/admin/admins` | Create an admin user | +| DELETE | `/api/admin/admins/{username}` | Delete an admin user | +| PATCH | `/api/admin/admins/{username}/password` | Change password | + +### Admin — AVConnect Credentials (admin only) + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/api/admin/credentials` | View stored credentials | +| PUT | `/api/admin/credentials` | Create or update credentials | + +### Admin — Statistics (manager+) + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/api/admin/stats` | Retrieve the last 500 access log entries | + +## Configuration + +All settings are read from environment variables. + +| Variable | Default | Description | +|---|---|---| +| `SECRET_KEY` | Random 32 bytes | JWT signing key and Fernet encryption key. **Set this explicitly in production.** | +| `ADMIN_USERNAME` | `admin` | Username for the initial admin account | +| `ADMIN_PASSWORD` | *(none)* | Password for the initial admin account. If unset, no seed account is created. | +| `APP_PORT` | `8000` | HTTP port the server listens on | +| `DATABASE_URL` | `sqlite:///data/gates.db` | SQLAlchemy database URL | +| `MOCK_AVCONNECT` | `false` | Set to `true` to skip real AVConnect calls (always returns success — useful for development) | + +## Running with Docker Compose + +```bash +# Copy and edit the compose file to set your SECRET_KEY +docker compose up -d +``` + +The default `docker-compose.yml` starts the service on port `8000` with the initial admin credentials `admin` / `changeme`. Change `ADMIN_PASSWORD` and set a strong `SECRET_KEY` before deploying. + +The `./data` directory is mounted into the container so the SQLite database persists across restarts. + +## Running Locally + +```bash +python -m venv venv +source venv/bin/activate +pip install -r requirements.txt + +export SECRET_KEY="change-me" +export ADMIN_USERNAME="admin" +export ADMIN_PASSWORD="changeme" + +uvicorn src.main:app --reload --port 8000 +``` + +The application is then available at: + +- **User interface** — `http://localhost:8000/` +- **Admin dashboard** — `http://localhost:8000/admin` + +## AVConnect Integration + +Gates are controlled through the AVConnect platform. Each gate is mapped to an AVConnect *macro ID*. When a gate open request is received, the service: + +1. Authenticates with AVConnect using the stored credentials (session is cached in the database) +2. Executes the configured macro for the gate + +Credentials (password) are stored encrypted in the database using Fernet symmetric encryption derived from `SECRET_KEY`. + +## Roles + +| Role | Permissions | +|---|---| +| `admin` | Full access — all endpoints including gate/user/credential management | +| `manager` | Gate open, keypass management, statistics — cannot manage admin users, AVConnect credentials, or create/delete gates |