Add scouthub-home-fe
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
# scouthub-home-fe
|
||||
|
||||
Frontend Angular per la gestione organizzativa di Scouthub (creazione gruppi, inviti),
|
||||
affianca `scouthub-attivita-fe` nello stesso ecosistema. Parla con `scouthub-home-be`
|
||||
per le API e con Keycloak per l'autenticazione.
|
||||
|
||||
Generato con Angular CLI 22.0.7 (vedi output `ng version` più sotto), componenti
|
||||
standalone (nessun NgModule) e routing con lazy loading per feature.
|
||||
|
||||
## Stato del progetto
|
||||
|
||||
Implementati: modulo core di autenticazione (login OIDC via Keycloak, contesto
|
||||
organizzazione, guard di routing), feature `crea-gruppo` (form di creazione gruppo
|
||||
scout) e feature `inviti` (accettazione di un invito via link pubblico). Il tema
|
||||
Angular Material è configurato. Non c'è ancora una vera home/dashboard applicativa
|
||||
(il redirect post-successo va su `/`, che al momento non ha un componente associato).
|
||||
|
||||
## Struttura cartelle
|
||||
|
||||
```
|
||||
src/app/
|
||||
core/ servizi condivisi
|
||||
auth/
|
||||
keycloak.provider.ts provideKeycloakAngular() — login OIDC Authorization Code + PKCE
|
||||
auth.guard.ts authGuard — richiede login, poi organization (non usato in routing
|
||||
al momento: nessuna rotta protetta è ancora stata definita)
|
||||
organization-context.service.ts OrganizationContextService — legge il claim "organization" dal token
|
||||
crea-gruppo/ feature "crea gruppo scout" (/crea-gruppo, lazy-loaded, pubblica: è la
|
||||
destinazione di chi è autenticato ma senza organization)
|
||||
inviti/ feature "accetta invito" (/inviti/:token, lazy-loaded, pubblica: un invito
|
||||
deve essere visualizzabile anche da chi non ha ancora un account)
|
||||
src/environments/ environment.ts / environment.development.ts
|
||||
public/
|
||||
silent-check-sso.html richiesto dal flusso check-sso silenzioso di Keycloak
|
||||
```
|
||||
|
||||
### Modulo di autenticazione
|
||||
|
||||
- **Login**: `provideKeycloak` (in `keycloak.provider.ts`) usa il client pubblico
|
||||
`scouthub-frontend` con Authorization Code Flow + PKCE (comportamento di default di
|
||||
`keycloak-js` per i public client con `standardFlowEnabled: true`), `onLoad: 'check-sso'`
|
||||
e refresh automatico del token via `withAutoRefreshToken`.
|
||||
- **OrganizationContextService** (`core/organization-context.service.ts`): espone
|
||||
`hasOrganization` / `currentOrganizationId` / `currentOrganizationName` come `Observable`,
|
||||
derivati dal claim `organization` del token (client scope built-in di Keycloak
|
||||
Organizations). Se l'utente appartiene a più Organization, la scelta è già stata fatta
|
||||
da Keycloak durante il login: la SPA vede sempre una sola membership nel token.
|
||||
- **authGuard** (`core/auth/auth.guard.ts`): se non autenticato avvia `keycloak.login()`;
|
||||
se autenticato ma senza organization reindirizza a `/crea-gruppo`; altrimenti lascia
|
||||
proseguire. Non è ancora applicato a nessuna rotta (`crea-gruppo` e `inviti/:token`
|
||||
sono entrambe pubbliche per costruzione): va aggiunto quando saranno introdotte
|
||||
rotte riservate a chi ha già una organization.
|
||||
|
||||
### Feature `crea-gruppo` (`/crea-gruppo`)
|
||||
|
||||
Form a singolo campo ("Nome del gruppo scout", 3-100 caratteri) che chiama
|
||||
`POST {orgServiceApiBaseUrl}/gruppi`. Un 409 (nome già esistente) mostra il messaggio
|
||||
del backend e permette di correggere il nome senza reload. Al successo, forza un
|
||||
refresh del token (`keycloak.updateToken(-1)`, incondizionato: il token corrente non
|
||||
contiene ancora il nuovo claim `organization`) e poi naviga a `/`.
|
||||
|
||||
### Feature `inviti` (`/inviti/:token`)
|
||||
|
||||
Rotta pubblica (nessuna autenticazione richiesta per visualizzarla). Al caricamento
|
||||
chiama `GET {orgServiceApiBaseUrl}/inviti/:token` (endpoint pubblico) e mostra nome
|
||||
gruppo, ruolo offerto e validità. Se l'invito non è valido (scaduto o già accettato)
|
||||
non mostra alcuna azione. Se valido, il pulsante "Accetta invito":
|
||||
|
||||
- se l'utente non è autenticato, avvia `keycloak.login({ redirectUri: window.location.href })`
|
||||
— dopo login/registrazione l'utente torna sulla stessa pagina di invito;
|
||||
- se autenticato, chiama `POST {orgServiceApiBaseUrl}/inviti/:token/accetta`, forza il
|
||||
refresh del token e naviga a `/`. Errori (409 già accettato, 410 scaduto, 403 email
|
||||
non corrispondente) mostrano un messaggio dedicato senza reload.
|
||||
|
||||
## Prerequisiti
|
||||
|
||||
- Node.js 20+
|
||||
- I servizi dell'ecosistema Scouthub in esecuzione: Keycloak e `scouthub-home-be`
|
||||
(vedi `docker-compose.yml` e `scouthub-home-be/README.md` nella root del repo)
|
||||
|
||||
## Configurazione ambiente
|
||||
|
||||
`src/environments/environment.ts` (produzione) e `environment.development.ts` (dev,
|
||||
usato automaticamente da `ng serve`/`ng build --configuration development`)
|
||||
espongono:
|
||||
|
||||
- `keycloakBaseUrl` — URL base dell'istanza Keycloak (default `http://localhost:8081`,
|
||||
coerente con `KEYCLOAK_PORT` in `.env` alla root del repo)
|
||||
- `keycloakRealm` — realm Keycloak (`scouthub`)
|
||||
- `keycloakClientId` — client pubblico già definito in `keycloak/realm-export.json`
|
||||
(`scouthub-frontend`)
|
||||
- `orgServiceApiBaseUrl` — URL base di `scouthub-home-be` (default `http://localhost:8082`)
|
||||
|
||||
## Collegare Keycloak in locale
|
||||
|
||||
1. Avviare Keycloak (e Postgres) dalla root del repo:
|
||||
```bash
|
||||
docker compose up -d keycloak-db keycloak
|
||||
```
|
||||
Il realm `scouthub` viene importato automaticamente da `keycloak/realm-export.json`
|
||||
al primo avvio (`--import-realm`).
|
||||
2. Il client pubblico `scouthub-frontend` ha `redirectUris`/`webOrigins` che includono
|
||||
sia `http://localhost:4200` (usato da `scouthub-attivita-fe`) sia
|
||||
`http://localhost:4201` (porta di default di questo progetto, vedi sotto) — se si
|
||||
cambia porta, aggiornare `keycloak/realm-export.json` di conseguenza e reimportare
|
||||
il realm (o aggiornarlo da console admin Keycloak).
|
||||
3. `provideKeycloakAngular()` (`src/app/core/auth/keycloak.provider.ts`) inizializza
|
||||
il client con `onLoad: 'check-sso'`: all'avvio l'app verifica in un iframe nascosto
|
||||
se esiste già una sessione Keycloak, senza forzare un redirect immediato per le
|
||||
pagine pubbliche.
|
||||
|
||||
## Collegare scouthub-home-be in locale
|
||||
|
||||
1. Avviare `scouthub-home-be` seguendo il suo README (`npm run dev`, porta di default
|
||||
`8082`).
|
||||
2. Le richieste verso `orgServiceApiBaseUrl` ricevono automaticamente l'header
|
||||
`Authorization: Bearer <token>` tramite l'interceptor `includeBearerTokenInterceptor`
|
||||
di `keycloak-angular`, configurato in `app.config.ts`.
|
||||
|
||||
## Development server
|
||||
|
||||
Questo progetto usa la porta `4201` (per non collidere con `scouthub-attivita-fe`,
|
||||
che gira sulla `4200`):
|
||||
|
||||
```bash
|
||||
ng serve
|
||||
```
|
||||
|
||||
Apri il browser su `http://localhost:4201/`.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
ng build
|
||||
```
|
||||
|
||||
Artefatti di build in `dist/scouthub-home-fe`.
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
ng test
|
||||
```
|
||||
|
||||
Esegue gli unit test con Vitest.
|
||||
|
||||
## Versione Angular CLI usata per lo scaffold
|
||||
|
||||
```
|
||||
Angular CLI : 22.0.7
|
||||
Angular : 22.0.8
|
||||
Node.js : 24.16.0
|
||||
Package Manager : npm 11.12.0
|
||||
Operating System : win32 x64
|
||||
```
|
||||
Reference in New Issue
Block a user