Skip to main content

🔐 Flussi di accesso: AuthGuard & CompanyGuard

Questa pagina documenta i vincoli di navigazione della Dashboard:

  1. AuthGuard: blocca le rotte a utenti non autenticati → redirect al login.
  2. 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-connect per 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/login se non autenticato.
  • CompanyGuard
    • ✅ Permette: utente autenticato con company selezionata nello store (selectSelectedUserAccesses).
    • 🚫 Blocca → redirect company-connect se nessuna company attiva.

Insieme, garantiscono che l’utente sia loggato e nel contesto aziendale corretto prima di accedere alle sezioni operative della Dashboard.