🔐 Flussi di accesso: AuthGuard & CompanyGuard
Questa pagina documenta i vincoli di navigazione della Dashboard:
- AuthGuard: blocca le rotte a utenti non autenticati → redirect al login.
- CompanyGuard: per utenti autenticati, richiede che sia selezionata/attiva una company → altrimenti redirect al company-connect.
🧱 AuthGuard (richiede autenticazione)
Comportamento:
- Attende che l’inizializzazione dello stato da storage sia completata.
- Se esiste un token → consente l’accesso.
- Se manca il token → redirect a
authentication/login.
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { Store } from "@ngrx/store";
import { Observable, combineLatest, filter, map } from "rxjs";
import { AUTHENTICATION_SELECTORS } from "../store/authentication.selectors";
@Injectable()
export class AuthGuard {
constructor(private _store: Store, private _router: Router) {}
canActivate(): Observable<boolean | void> {
return combineLatest([
this._store.select(AUTHENTICATION_SELECTORS.selectToken),
this._store.select(AUTHENTICATION_SELECTORS.selectInitFromStorageDone)
]).pipe(
// evita false negative finché lo stato non è idratato
filter(([_, initDone]) => initDone),
map(([token, _]) => {
return token ? true : this._router.navigate(['authentication/login']);
})
);
}
}
Risultato atteso:
- Rotte protette non sono raggiungibili senza login.
- L’utente viene reindirizzato alla pagina di login.
🧭 CompanyGuard (richiede company selezionata)
Comportamento:
- Valida che l’utente autenticato abbia una company attiva (selezionata nello store degli accessi).
- Se esiste una company attiva → consente l’accesso.
- Se non esiste → redirect a
company-connectper collegarsi/claimare una company.
import { Injectable } from "@angular/core";
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from "@angular/router";
import { Store } from "@ngrx/store";
import { Observable, combineLatest, map } from "rxjs";
import { USER_ACCES_SELECTORS } from "src/userAccessStore/userAccessStore.selectors";
@Injectable()
export class CompanyGuard {
constructor(private _store: Store, private _router: Router) {}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | void> {
return combineLatest([
this._store.select(USER_ACCES_SELECTORS.selectSelectedUserAccesses),
]).pipe(
map(([selectedCompanyAccess]) => {
return selectedCompanyAccess ? true : this._router.navigate(['company-connect']);
})
);
}
}
Risultato atteso:
- Le aree “operative” (elabel, wines, dispenser, ecc.) sono raggiungibili solo se l’utente ha una company attiva.
- In caso contrario l’utente viene guidato a connettersi a una company.
🗺️ Integrazione nel routing
Estratto rilevante da app.routing.ts:
- Il blocco Dashboard è protetto da AuthGuard e CompanyGuard.
- Alcune rotte extra (es.
profile,company-connect,company-create) richiedono solo AuthGuard.
export const ROUTES: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
// Flussi di autenticazione
{
path: 'authentication',
component: AuthenticationComponent,
children: [
{ path: 'login', loadChildren: () => import('../authentication/login/login.module').then(m => m.LoginModule) },
{ path: 'registration', loadChildren: () => import('../authentication/registration/registration.module').then(m => m.RegistrationModule) },
{ path: 'reset_password',loadChildren: () => import('../authentication/reset-password/reset-password.module').then(m => m.ResetPasswordModule) },
]
},
// Area operativa: richiede login + company selezionata
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard, CompanyGuard],
children: [
{ path: '', loadChildren: () => import('../dashboards/home-page/home-page.module').then(m => m.HomePageModule) },
{ path: 'elabel', loadChildren: () => import('../dashboards/elabel/elabel.module').then(m => m.ElabelComponentModule) },
{ path: 'wines', loadChildren: () => import('../dashboards/wine/wine.module').then(m => m.WineModule) },
{ path: 'company', loadChildren: () => import('../dashboards/company/company.module').then(m => m.CompanyModule) },
{ path: 'dispenser', loadChildren: () => import('../dashboards/dispenser/dispenser.module').then(m => m.DispenserModule) },
{ path: 'seller-panel',loadChildren: () => import('../dashboards/seller-panel/stock-listing/stock-listing.module').then(m => m.StockListingModule) },
{ path: 'cantina', loadChildren: () => import('../dashboards/cantina/cantina.module').then(m => m.CantinaModule) },
{ path: 'wine-list', loadChildren: () => import('../dashboards/wine-list/wine-list.module').then(m => m.WineListModule) },
]
},
// Rotte che richiedono solo autenticazione (nessuna company necessaria)
{ path: 'profile', canActivate: [AuthGuard], loadChildren: () => import('../profile/profile.module').then(m => m.ProfileModule) },
{ path: 'verify', loadChildren: () => import('../email-verification-page/email-verification-page.module').then(m => m.EmailVerificationPageModule) },
{ path: 'verify-invitation', canActivate: [AuthGuard], loadChildren: () => import('../company-invite-verification/company-invite-verification.module').then(m => m.CompanyInviteVerificationModule) },
{ path: 'company-pending-verification', canActivate: [AuthGuard], loadChildren: () => import('../company-pending-verification/company-pending-verification.module').then(m => m.CompanyPendingVerificationModule) },
{ path: 'company-connect', canActivate: [AuthGuard], loadChildren: () => import('../company-connect/company-connect.module').then(m => m.CompanyConnectModule) },
{ path: 'company-create', canActivate: [AuthGuard], loadChildren: () => import('../company-create/company-create.module').then(m => m.CompanyCreateModule) },
// Social callback, Not Found
{ path: 'callback', loadChildren: () => import('../social-callback/social-callback.module').then(m => m.SocialCallbackModule) },
{ path: 'not-found', component: NotFoundComponent, pathMatch: 'full' },
{ path: '', redirectTo: '/not-found', pathMatch: 'full' }
];
✅ Sintesi comportamento (corretto)
- AuthGuard
- ✅ Permette: utente autenticato (token presente).
- 🚫 Blocca → redirect
authentication/loginse non autenticato.
- CompanyGuard
- ✅ Permette: utente autenticato con company selezionata nello store (
selectSelectedUserAccesses). - 🚫 Blocca → redirect
company-connectse nessuna company attiva.
- ✅ Permette: utente autenticato con company selezionata nello store (
Insieme, garantiscono che l’utente sia loggato e nel contesto aziendale corretto prima di accedere alle sezioni operative della Dashboard.