I have an Angular App with two authGuard Services:
export class AuthGuardService implements CanActivate {
constructor(public auth: AccountService, public router: Router) {}
canActivate(): Observable<boolean> {
return this.auth.identity().pipe(
map(account => {
if (account) {
return true;
}
this.router.navigate(['welcome']);
return false;
})
);
}
}
@Injectable()
export class StartupService implements CanActivate {
isAdmin: boolean;
constructor(public auth: AccountService, public router: Router, private sidebarService: SidebarService) {}
canActivate(): Observable<boolean> {
return this.auth.identity().pipe(
switchMap(account => {
this.isAdmin = account.isAdmin;
return this.sidebarService.getCompanies(account.id.toString());
}),
map(firms => {
if(this.isAdmin && Object.keys(firms).length === 0) {
this.router.navigate(['startup']);
return false;
}
return true;
}),
catchError(() => of(false))
);
}
}
In the AuthGuardService I call the identity service for checking if I'm logged or not, if not I need to redirect to the welcome page; in the StartupService I invoke the same service and I also check if I'm admin and I have some data available (companies). I also invoke the same service in the ngOnInit in the AppComponent and with ngrx I save the account state in the store. I invoke the same service for three times. Which is the best way to avoid this situation? Where can I use ngrx selector? I see in the debug that canActivate is invoked before the ngOnInit AppComponent. Any suggestions?
export class AuthGuardService implements CanActivate {
constructor(
public auth: AccountService
public router: Router
) {}
canActivate(): Observable<boolean> {
return this.auth.identity().pipe(
map(account => {
if (account) {
return true;
}
this.router.navigate(['welcome']);
return false;
})
);
}
}
@Injectable()
export class StartupService implements CanActivate {
constructor(
private auth: AccountService,
private router: Router,
private sidebarService: SidebarService
) {}
canActivate(): Observable<boolean> {
return this.auth.identity().pipe(
switchMap(account => this.sidebarService.getCompanies(account.id.toString())
.pipe(
map(firms => {
if(account.isAdmin && Object.keys(firms).length === 0) {
this.router.navigate(['startup']);
return false;
}
return true;
}),
catchError(() => of(false)) // you probably also want some redirection on error
)
),
);
}
}
In your setup more important is how you have implemented AccountService.identity
If it returns some observable that has current state of user identity something like this:
class AccountService {
identity$ = new ReplaySubject(1);
identity() {
return this.identity$;
}
authenticate() {
this.http.post('/authentication').subscribe((identity) => {
this.identity$.next(identity)
})
}
logout() {
this.identity$.next(null)
}
}
It will call HTTP only if you call authentication and your user identity will be stored in identity$
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.