Fix issue with QR code login and caching. Update README
This commit is contained in:
57
README.md
57
README.md
@@ -9,7 +9,10 @@ A web-based gate access management and control system. Authorized users can remo
|
||||
- **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
|
||||
- **Access audit log** — every open attempt is logged with timestamp, keypass, gate, IP, and result; filterable and paginated
|
||||
- **Keypass QR codes** — generate a scannable QR code for each keypass; scanning opens the PWA and logs in automatically
|
||||
- **Keypass code options** — choose character set (alphanumeric, alpha, numeric, or a 4-word passphrase) and length when auto-generating codes
|
||||
- **Telegram notifications** — optional push notifications to a Telegram group whenever a gate is opened
|
||||
- **Progressive Web App** — installable on mobile devices with offline caching
|
||||
|
||||
## Tech Stack
|
||||
@@ -22,6 +25,8 @@ A web-based gate access management and control system. Authorized users can remo
|
||||
| Auth | JWT (HS256) + bcrypt |
|
||||
| Credential storage | Fernet symmetric encryption |
|
||||
| Gate integration | AVConnect HTTP API |
|
||||
| Notifications | Telegram Bot API |
|
||||
| QR generation | qrcode + Pillow |
|
||||
| Frontend | Vanilla JS PWA |
|
||||
|
||||
## Project Structure
|
||||
@@ -38,13 +43,15 @@ src/
|
||||
├── 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
|
||||
│ ├── keypasses.py # Admin keypass CRUD + QR code generation
|
||||
│ ├── admins.py # Admin user management
|
||||
│ ├── credentials.py # AVConnect credential management
|
||||
│ └── stats.py # Access log / statistics
|
||||
│ ├── stats.py # Access log / statistics (paginated, filtered)
|
||||
│ └── telegram.py # Telegram notification configuration
|
||||
├── services/
|
||||
│ ├── avconnect.py # AVConnect session management and macro execution
|
||||
│ └── gates.py # Gate open orchestration
|
||||
│ ├── gates.py # Gate open orchestration
|
||||
│ └── telegram.py # Telegram Bot API client
|
||||
└── static/ # Frontend PWA (index.html, admin.html, JS, CSS)
|
||||
data/
|
||||
└── gates.db # SQLite database (auto-created on first run)
|
||||
@@ -84,6 +91,7 @@ data/
|
||||
| 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 |
|
||||
| GET | `/api/admin/keypasses/{kp_id}/qr` | Download QR code PNG for a keypass |
|
||||
|
||||
### Admin — Users (admin only)
|
||||
|
||||
@@ -100,12 +108,24 @@ data/
|
||||
|---|---|---|
|
||||
| GET | `/api/admin/credentials` | View stored credentials |
|
||||
| PUT | `/api/admin/credentials` | Create or update credentials |
|
||||
| GET | `/api/admin/credentials/mock` | Get mock mode status |
|
||||
| PUT | `/api/admin/credentials/mock` | Enable or disable mock mode |
|
||||
|
||||
### Admin — Statistics (manager+)
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|---|---|---|
|
||||
| GET | `/api/admin/stats` | Retrieve the last 500 access log entries |
|
||||
| GET | `/api/admin/stats` | Paginated, filtered access log |
|
||||
|
||||
Query parameters: `gate_id`, `keypass_code` (partial match), `success` (bool), `date_from`, `date_to`, `page` (default 1), `page_size` (default 50, max 200).
|
||||
|
||||
### Admin — Telegram Notifications (admin only)
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|---|---|---|
|
||||
| GET | `/api/admin/telegram` | Get current Telegram configuration |
|
||||
| PUT | `/api/admin/telegram` | Save bot token and chat ID |
|
||||
| POST | `/api/admin/telegram/test` | Send a test message |
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -189,9 +209,32 @@ Gates are controlled through the AVConnect platform. Each gate is mapped to an A
|
||||
|
||||
Credentials (password) are stored encrypted in the database using Fernet symmetric encryption derived from `SECRET_KEY`.
|
||||
|
||||
**Mock mode** — when enabled via the admin dashboard, gate open requests always succeed without contacting AVConnect. Useful for testing.
|
||||
|
||||
## Keypass QR Codes
|
||||
|
||||
Each active keypass has a **QR** button in the admin panel. Clicking it generates a PNG QR code that encodes the URL:
|
||||
|
||||
```
|
||||
https://<your-domain>/?k=<KEYPASS_CODE>
|
||||
```
|
||||
|
||||
Scanning the code with a phone opens the web app and logs in automatically. If the keypass is expired or revoked, the user is shown an error on the login screen.
|
||||
|
||||
## Telegram Notifications
|
||||
|
||||
Configure a Telegram bot to receive a message in a group or chat every time a gate is opened:
|
||||
|
||||
1. Create a bot via [@BotFather](https://t.me/BotFather) and copy the token
|
||||
2. Add the bot to your group and obtain the chat ID (e.g. using [@userinfobot](https://t.me/userinfobot))
|
||||
3. Open **Admin → Notifications**, enter the token and chat ID, and click **Save**
|
||||
4. Use **Send test message** to verify the setup
|
||||
|
||||
Notifications are sent in a background thread and never block the gate open response. Failures are logged as warnings and do not affect gate operation.
|
||||
|
||||
## 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 |
|
||||
| `admin` | Full access — all endpoints including gate/user/credential/notification management |
|
||||
| `manager` | Gate open, keypass management, statistics — cannot manage admin users, AVConnect credentials, gate configuration, or Telegram settings |
|
||||
|
||||
@@ -215,15 +215,18 @@ document.getElementById("logout-btn").addEventListener("click", () => {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ code: k.toUpperCase() }),
|
||||
})
|
||||
.then(res => res.ok ? res.json() : Promise.reject())
|
||||
.then(res => res.ok ? res.json() : res.json().then(j => Promise.reject(j.detail || "Invalid keypass")))
|
||||
.then(data => {
|
||||
saveToken(data.token);
|
||||
showGatesView();
|
||||
loadGates();
|
||||
})
|
||||
.catch(() => {
|
||||
.catch(msg => {
|
||||
clearToken();
|
||||
showLogin();
|
||||
const errEl = document.getElementById("login-error");
|
||||
errEl.textContent = typeof msg === "string" ? msg : "QR code login failed";
|
||||
errEl.classList.remove("hidden");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Service worker - Lagomare Gates */
|
||||
const CACHE = "lagomare-gates-v1";
|
||||
const PRECACHE = ["/", "/static/style.css", "/static/app.js", "/static/logo.svg", "/static/mobile_icon.png", "/manifest.json"];
|
||||
const PRECACHE = ["/static/style.css", "/static/app.js", "/static/logo.svg", "/static/mobile_icon.png", "/manifest.json"];
|
||||
|
||||
self.addEventListener("install", event => {
|
||||
event.waitUntil(
|
||||
@@ -20,6 +20,10 @@ self.addEventListener("fetch", event => {
|
||||
// Let API calls always go to the network
|
||||
if (event.request.url.includes("/api/")) return;
|
||||
|
||||
// Navigation requests (page loads, QR code opens) must always hit the network
|
||||
// so query parameters like ?k=CODE are preserved for app.js
|
||||
if (event.request.mode === "navigate") return;
|
||||
|
||||
event.respondWith(
|
||||
caches.match(event.request).then(cached => cached || fetch(event.request))
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user