Files
lagomareGates/README.md
2026-05-09 17:52:59 +02:00

198 lines
7.2 KiB
Markdown

![](./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
├── 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 (centralised in `src/core/config.py`).
### Security
| Variable | Default | Description |
|---|---|---|
| `SECRET_KEY` | *(required)* | JWT signing key and Fernet encryption key. The application will refuse to start if this is not set. Use a long random string (`openssl rand -hex 32`). |
### Admin seed account
| Variable | Default | Description |
|---|---|---|
| `ADMIN_USERNAME` | `admin` | Username for the initial admin account created on first run. |
| `ADMIN_PASSWORD` | *(none)* | Password for the initial admin account. If unset, no seed account is created. Minimum 12 characters. |
### Server
| Variable | Default | Description |
|---|---|---|
| `APP_PORT` | `8000` | HTTP port the server listens on. |
### Database
| Variable | Default | Description |
|---|---|---|
| `DATABASE_URL` | `sqlite:///data/gates.db` | SQLAlchemy database URL. |
### Network / reverse proxy
| Variable | Default | Description |
|---|---|---|
| `CORS_ORIGINS` | *(empty — no cross-origin requests)* | Comma-separated list of allowed CORS origins, e.g. `https://gates.example.com`. |
| `TRUSTED_PROXY_IPS` | `127.0.0.1` | Comma-separated list of reverse-proxy IPs whose `X-Forwarded-For` header is trusted for client IP resolution. |
### Logging
| Variable | Default | Description |
|---|---|---|
| `LOG_LEVEL` | `INFO` | Logging verbosity. One of `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`. |
| `LOG_FILE` | `/var/log/lagomaregates.log` | Path to the rotating log file (10 MB, 5 backups). Set to an empty string to disable file logging. |
## 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`. Set a strong `SECRET_KEY` and, optionally, `ADMIN_USERNAME` / `ADMIN_PASSWORD` 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="$(openssl rand -hex 32)"
export ADMIN_USERNAME="admin"
export ADMIN_PASSWORD="changeme-at-least-12"
uvicorn src.main:app --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 |