Primo commit
This commit is contained in:
332
README.md
332
README.md
@@ -1,172 +1,214 @@
|
||||
# Parking Manager
|
||||
# Org-Parking
|
||||
|
||||
A manager-centric parking spot management application with fair assignment algorithm.
|
||||
Un'applicazione leggera gestionale per i parcheggi aziendali, progettata per le organizzazioni. Offre un algoritmo di assegnazione equa, tracciamento delle presenze ed è ottimizzata per basse risorse.
|
||||
|
||||
## Features
|
||||
## Funzionalità
|
||||
|
||||
- **Manager-centric model**: Managers own parking spots, not offices
|
||||
- **Fair assignment algorithm**: Users with lowest parking/presence ratio get priority
|
||||
- **Presence tracking**: Calendar-based presence marking (present/remote/absent)
|
||||
- **Closing days**: Support for specific dates and weekly recurring closures
|
||||
- **Guarantees & exclusions**: Per-user parking rules
|
||||
- **Authelia/LLDAP integration**: SSO authentication with group-based roles
|
||||
- **Modello Centrato sull'Ufficio**: I posti auto appartengono agli Uffici, non ai Manager o agli Utenti.
|
||||
- **Algoritmo di Assegnazione Equa**: Gli utenti con il rapporto parcheggi/presenze più basso hanno la priorità.
|
||||
- **Tracciamento Presenze**: Marcatura delle presenze basata su calendario (presente/remoto/assente).
|
||||
- **Regole di Chiusura Flessibili**: Supporto per chiusure in date specifiche e chiusure settimanali ricorrenti per ufficio.
|
||||
- **Garanzie ed Esclusioni**: Regole di parcheggio per utente gestite dagli amministratori dell'ufficio.
|
||||
- **Accesso Basato sui Ruoli**:
|
||||
- **Admin**: Controllo completo del sistema, creazione uffici, gestione utenti.
|
||||
- **Manager**: Gestisce le impostazioni del proprio ufficio e il team.
|
||||
- **Impiegato**: Segna presenza, visualizza calendario, controlla stato parcheggio.
|
||||
- **Basso Consumo di Memoria**: Ottimizzato per piccoli server (<500MB RAM).
|
||||
- **Autenticazione**: Auth JWT integrata o integrazione SSO con Authelia.
|
||||
|
||||
## Architecture
|
||||
## Architettura
|
||||
|
||||
```
|
||||
├── app/
|
||||
│ ├── routes/ # API endpoints
|
||||
│ │ ├── auth.py # Authentication + holidays
|
||||
│ │ ├── users.py # User management
|
||||
│ │ ├── managers.py # Manager rules (closing days, guarantees)
|
||||
│ │ ├── presence.py # Presence marking
|
||||
│ │ └── parking.py # Parking assignments
|
||||
│ └── config.py # Application configuration
|
||||
├── database/
|
||||
│ ├── models.py # SQLAlchemy ORM models
|
||||
│ └── connection.py # Database setup
|
||||
├── services/
|
||||
│ ├── auth.py # JWT + password handling
|
||||
│ ├── parking.py # Fair assignment algorithm
|
||||
│ ├── holidays.py # Public holiday calculation
|
||||
│ └── notifications.py # Email notifications (TODO: scheduler)
|
||||
├── frontend/
|
||||
│ ├── pages/ # HTML pages
|
||||
│ ├── js/ # JavaScript modules
|
||||
│ └── css/ # Stylesheets
|
||||
└── main.py # FastAPI application entry
|
||||
app/
|
||||
├── routes/ # API endpoints
|
||||
│ ├── auth.py # Autenticazione
|
||||
│ ├── users.py # Gestione utenti
|
||||
│ ├── offices.py # Gestione uffici (quote, regole)
|
||||
│ ├── presence.py # Marcatura presenze
|
||||
│ └── parking.py # Logica di assegnazione
|
||||
└── config.py # Configurazione
|
||||
database/
|
||||
├── models.py # Modelli SQLAlchemy ORM
|
||||
└── connection.py # Setup Database
|
||||
frontend/ # Frontend Vanilla JS pulito
|
||||
├── pages/ # Viste HTML
|
||||
├── js/ # Moduli logici
|
||||
└── css/ # Stili
|
||||
```
|
||||
|
||||
## Quick Start (Development)
|
||||
## Guida Rapida
|
||||
|
||||
```bash
|
||||
# Create virtual environment
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
### Sviluppo Locale
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
1. **Setup Ambiente**:
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
# Run development server
|
||||
python main.py
|
||||
2. **Avvio Server**:
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
Accedi a `http://localhost:8000`
|
||||
|
||||
### Deployment Docker (Consigliato)
|
||||
|
||||
Questa applicazione è ottimizzata per ambienti con risorse limitate (es. Raspberry Pi, piccoli VPS).
|
||||
|
||||
1. **Build**:
|
||||
```bash
|
||||
docker compose build
|
||||
```
|
||||
|
||||
2. **Run**:
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**Nota sull'Uso della Memoria**:
|
||||
Il `Dockerfile` è configurato per eseguire `uvicorn` con `--workers 1` per minimizzare l'uso della memoria (~50MB in idle). Se in esecuzione su un server più grande, puoi rimuovere questo flag nel `Dockerfile`.
|
||||
|
||||
## Configurazione
|
||||
|
||||
Copia `.env.example` in `.env` e configura:
|
||||
|
||||
| Variabile | Descrizione | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `SECRET_KEY` | **Richiesto**. Chiave cripto per JWT. | `""` (Esce se mancante) |
|
||||
| `DATABASE_URL` | Vedi docs SQLAlchemy. | `sqlite:///data/parking.db` |
|
||||
| `AUTHELIA_ENABLED`| Abilita supporto header SSO. | `false` |
|
||||
| `SMTP_ENABLED` | Abilita notifiche email. | `false` |
|
||||
| `LOG_LEVEL` | Verbosità log. | `INFO` |
|
||||
|
||||
## Algoritmo di Equità
|
||||
|
||||
I posti auto vengono assegnati giornalmente basandosi su un rapporto di equità:
|
||||
```
|
||||
|
||||
Access at http://localhost:8000
|
||||
|
||||
## Docker Deployment
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker build -t parking-manager .
|
||||
|
||||
# Run with environment variables
|
||||
docker run -d \
|
||||
-p 8000:8000 \
|
||||
-v ./data:/app/data \
|
||||
-e SECRET_KEY=your-secret-key \
|
||||
-e AUTHELIA_ENABLED=true \
|
||||
parking-manager
|
||||
Rapporto = (Giorni Parcheggiati con successo) / (Giorni di Presenza in ufficio)
|
||||
```
|
||||
|
||||
Or use Docker Compose:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `SECRET_KEY` | JWT signing key | Random (dev only) |
|
||||
| `HOST` | Bind address | `0.0.0.0` |
|
||||
| `PORT` | Server port | `8000` |
|
||||
| `DATABASE_URL` | SQLite path | `sqlite:///data/parking.db` |
|
||||
| `AUTHELIA_ENABLED` | Enable Authelia SSO | `false` |
|
||||
| `ALLOWED_ORIGINS` | CORS origins | `*` |
|
||||
|
||||
### SMTP (Notifications - Optional)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `SMTP_HOST` | SMTP server hostname |
|
||||
| `SMTP_PORT` | SMTP port (default: 587) |
|
||||
| `SMTP_USER` | SMTP username |
|
||||
| `SMTP_PASSWORD` | SMTP password |
|
||||
| `SMTP_FROM` | From email address |
|
||||
|
||||
## Authentication
|
||||
|
||||
### Standalone Mode
|
||||
Built-in JWT authentication with bcrypt password hashing. Users register/login via `/login` and `/register`.
|
||||
|
||||
### Authelia Mode
|
||||
When `AUTHELIA_ENABLED=true`, the app trusts Authelia headers:
|
||||
- `Remote-User`: User email/username
|
||||
- `Remote-Name`: Display name
|
||||
- `Remote-Groups`: Comma-separated group list
|
||||
|
||||
Group mapping (follows lldap naming convention):
|
||||
- `parking_admins` → admin role
|
||||
- `managers` → manager role
|
||||
- Others → employee role
|
||||
|
||||
## User Roles
|
||||
|
||||
| Role | Permissions |
|
||||
|------|-------------|
|
||||
| **admin** | Full access, manage users and managers |
|
||||
| **manager** | Manage their team, set parking rules |
|
||||
| **employee** | Mark own presence, view calendar |
|
||||
- Gli utenti **Garantiti** vengono assegnati per primi.
|
||||
- I posti **Rimanenti** sono distribuiti agli utenti presenti iniziando da chi ha il rapporto più **basso**.
|
||||
- Gli utenti **Esclusi** non ricevono mai un posto.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Authentication
|
||||
- `POST /api/auth/login` - Login
|
||||
- `POST /api/auth/register` - Register (standalone mode)
|
||||
- `POST /api/auth/logout` - Logout
|
||||
- `GET /api/auth/me` - Current user info
|
||||
- `GET /api/auth/holidays/{year}` - Public holidays
|
||||
Di seguito la lista delle chiamate API disponibili suddivise per modulo.
|
||||
|
||||
### Users
|
||||
- `GET /api/users` - List users (admin)
|
||||
- `POST /api/users` - Create user (admin)
|
||||
- `PUT /api/users/{id}` - Update user (admin)
|
||||
- `DELETE /api/users/{id}` - Delete user (admin)
|
||||
- `GET /api/users/me/profile` - Own profile
|
||||
- `PUT /api/users/me/settings` - Own settings
|
||||
### Auth (`/api/auth`)
|
||||
Gestione autenticazione e sessione.
|
||||
|
||||
### Managers
|
||||
- `GET /api/managers` - List managers
|
||||
- `GET /api/managers/{id}` - Manager details
|
||||
- `PUT /api/managers/{id}/settings` - Update parking quota (admin)
|
||||
- `GET/POST/DELETE /api/managers/{id}/closing-days` - Specific closures
|
||||
- `GET/POST/DELETE /api/managers/{id}/weekly-closing-days` - Recurring closures
|
||||
- `GET/POST/DELETE /api/managers/{id}/guarantees` - Parking guarantees
|
||||
- `GET/POST/DELETE /api/managers/{id}/exclusions` - Parking exclusions
|
||||
- `POST /register`: Registrazione nuovo utente (Disabilitato se Authelia è attivo).
|
||||
- `POST /login`: Login con email e password (ritorna token JWT/cookie).
|
||||
- `POST /logout`: Logout e invalidazione sessione.
|
||||
- `GET /me`: Ritorna informazioni sull'utente corrente.
|
||||
- `GET /config`: Ritorna la configurazione pubblica di autenticazione.
|
||||
- `GET /holidays/{year}`: Ritorna i giorni festivi per l'anno specificato.
|
||||
|
||||
### Presence
|
||||
- `POST /api/presence/mark` - Mark presence
|
||||
- `POST /api/presence/mark-bulk` - Bulk mark
|
||||
- `GET /api/presence/my-presences` - Own presences
|
||||
- `GET /api/presence/team` - Team calendar (manager/admin)
|
||||
### Users (`/api/users`)
|
||||
Gestione utenti e profili.
|
||||
|
||||
### Parking
|
||||
- `GET /api/parking/assignments/{date}` - Day's assignments
|
||||
- `GET /api/parking/my-assignments` - Own assignments
|
||||
- `POST /api/parking/manual-assign` - Manual assignment
|
||||
- `POST /api/parking/reassign-spot` - Reassign spot
|
||||
- `GET /`: Lista di tutti gli utenti (Solo Admin).
|
||||
- `POST /`: Crea un nuovo utente (Solo Admin).
|
||||
- `GET /{user_id}`: Dettaglio di un utente specifico (Solo Admin).
|
||||
- `PUT /{user_id}`: Aggiorna dati di un utente (Solo Admin).
|
||||
- `DELETE /{user_id}`: Elimina un utente (Solo Admin).
|
||||
- `GET /me/profile`: Ottieni il proprio profilo.
|
||||
- `PUT /me/profile`: Aggiorna il proprio profilo.
|
||||
- `GET /me/settings`: Ottieni le proprie impostazioni.
|
||||
- `PUT /me/settings`: Aggiorna le proprie impostazioni.
|
||||
- `POST /me/change-password`: Modifica la propria password.
|
||||
|
||||
## Fairness Algorithm
|
||||
### Offices (`/api/offices`)
|
||||
Gestione uffici, regole di chiusura e quote.
|
||||
|
||||
Parking spots are assigned based on a fairness ratio:
|
||||
- `GET /`: Lista di tutti gli uffici.
|
||||
- `POST /`: Crea un nuovo ufficio (Solo Admin).
|
||||
- `GET /{office_id}`: Dettagli di un ufficio.
|
||||
- `PUT /{office_id}`: Aggiorna configurazione ufficio (Solo Admin).
|
||||
- `DELETE /{office_id}`: Elimina un ufficio (Solo Admin).
|
||||
- `GET /{office_id}/users`: Lista utenti assegnati all'ufficio.
|
||||
- `GET /{office_id}/closing-days`: Lista giorni di chiusura specifici.
|
||||
- `POST /{office_id}/closing-days`: Aggiungi giorno di chiusura.
|
||||
- `DELETE /{office_id}/closing-days/{id}`: Rimuovi giorno di chiusura.
|
||||
- `GET /{office_id}/weekly-closing-days`: Lista giorni di chiusura settimanali (es. Sabato/Domenica).
|
||||
- `POST /{office_id}/weekly-closing-days`: Aggiungi giorno di chiusura settimanale.
|
||||
- `DELETE /{office_id}/weekly-closing-days/{id}`: Rimuovi giorno di chiusura settimanale.
|
||||
- `GET /{office_id}/guarantees`: Lista utenti con posto garantito.
|
||||
- `POST /{office_id}/guarantees`: Aggiungi garanzia posto.
|
||||
- `DELETE /{office_id}/guarantees/{id}`: Rimuovi garanzia.
|
||||
- `GET /{office_id}/exclusions`: Lista utenti esclusi dal parcheggio.
|
||||
- `POST /{office_id}/exclusions`: Aggiungi esclusione.
|
||||
- `DELETE /{office_id}/exclusions/{id}`: Rimuovi esclusione.
|
||||
|
||||
```
|
||||
ratio = parking_days / presence_days
|
||||
```
|
||||
### Presence (`/api/presence`)
|
||||
Gestione presenze giornaliere.
|
||||
|
||||
Users with the lowest ratio get priority. Guaranteed users are always assigned first.
|
||||
- `POST /mark`: Segna la propria presenza per una data (Presente/Remoto/Assente).
|
||||
- `GET /my-presences`: Lista delle proprie presenze.
|
||||
- `DELETE /{date}`: Rimuovi la propria presenza per una data.
|
||||
- `POST /admin/mark`: Segna presenza per un altro utente (Manager/Admin).
|
||||
- `DELETE /admin/{user_id}/{date}`: Rimuovi presenza di un altro utente (Manager/Admin).
|
||||
- `GET /team`: Visualizza presenze e stato parcheggio del team.
|
||||
- `GET /admin/{user_id}`: Storico presenze di un utente.
|
||||
|
||||
## License
|
||||
### Parking (`/api/parking`)
|
||||
Gestione assegnazioni posti auto.
|
||||
|
||||
- `POST /init-office-pool`: Inizializza i posti disponibili per un giorno.
|
||||
- `GET /assignments/{date}`: Lista assegnazioni per una data.
|
||||
- `GET /my-assignments`: Le mie assegnazioni parcheggio.
|
||||
- `POST /run-allocation`: Esegui manualmente l'algoritmo di assegnazione per una data.
|
||||
- `POST /clear-assignments`: Cancella tutte le assegnazioni per una data.
|
||||
- `POST /manual-assign`: Assegna manualmente un posto a un utente.
|
||||
- `POST /reassign-spot`: Riassegna o libera un posto già assegnato.
|
||||
- `POST /release-my-spot/{id}`: Rilascia il proprio posto assegnato.
|
||||
- `GET /eligible-users/{id}`: Lista utenti idonei a ricevere un posto riassegnato.
|
||||
|
||||
## Utilizzo con AUTHELIA
|
||||
|
||||
Org-Parking supporta l'integrazione nativa con **Authelia** (o altri provider SSO compatibili con Forward Auth). Questo permette il Single Sign-On (SSO) e la gestione centralizzata degli utenti.
|
||||
|
||||
### Configurazione
|
||||
|
||||
1. **Abilita Authelia**:
|
||||
Nel file `.env`, imposta `AUTHELIA_ENABLED=true`.
|
||||
|
||||
2. **Configura gli Header del Proxy**:
|
||||
Assicurati che il tuo reverse proxy (es. Traefik, Nginx) passi i seguenti header all'applicazione dopo l'autenticazione:
|
||||
* `Remote-User`: Username dell'utente (spesso uguale all'email).
|
||||
* `Remote-Email`: Email dell'utente.
|
||||
* `Remote-Name`: Nome completo dell'utente (Opzionale).
|
||||
* `Remote-Groups`: Gruppi di appartenenza (separati da virgola).
|
||||
|
||||
3. **Gestione Admin**:
|
||||
L'applicazione assegna automaticamente il ruolo di **Admin** agli utenti che appartengono al gruppo specificato nella variabile `AUTHELIA_ADMIN_GROUP` (default: `parking_admins`).
|
||||
* Se un utente viene rimosso da questo gruppo su Authelia, perderà i privilegi di admin al login successivo.
|
||||
* Gli altri ruoli (Manager, Employee) e l'assegnazione agli uffici vengono gestiti manualmente all'interno di Org-Parking da un amministratore.
|
||||
|
||||
### Comportamento
|
||||
|
||||
* **Creazione Utenti**: Gli utenti vengono creati automaticamente nel database di Org-Parking al loro primo accesso riuscito tramite Authelia.
|
||||
* **Login/Logout**: Le pagine di login e registrazione interne vengono disabilitate o reindirizzano al portale SSO.
|
||||
* **Password**: Org-Parking non gestisce le password in questa modalità; l'autenticazione è interamente delegata al provider esterno.
|
||||
* **Sicurezza**: L'applicazione si fida degli header `Remote-*` solo se `AUTHELIA_ENABLED` è attivo. Assicurarsi che il container non sia esposto direttamente a internet senza passare per il proxy di autenticazione.
|
||||
|
||||
## Note di Deployment
|
||||
|
||||
- **Database**: SQLite è usato di default per semplicità e basso overhead. I dati persistono in `./data/parking.db`.
|
||||
- **Sicurezza**:
|
||||
- Rate limiting è attivo sugli endpoint sensibili (Login/Register).
|
||||
- Le password sono hashate con Bcrypt.
|
||||
- L'autenticazione via cookie è sicura di default.
|
||||
|
||||
### Risoluzione Problemi Comuni
|
||||
|
||||
**Errore: "Il reindirizzamento è stato determinato per essere non sicuro"**
|
||||
|
||||
Questo errore appare se si tenta di accedere all'applicazione tramite HTTP (es. `http://lvh.me:8000`) mentre Authelia è su HTTPS. Authelia blocca i reindirizzamenti verso protocolli non sicuri.
|
||||
**Soluzione**: Accedere all'applicazione tramite il Reverse Proxy (Caddy) usando HTTPS, ad esempio `https://parking.lvh.me`. Assicurarsi che Caddy sia configurato per gestire il dominio e l'autenticazione.
|
||||
|
||||
## Licenza
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user