问题
THe problem is that I've implemented a Guard, meant to work with a specific directory . It should return true if the role of the current username equals 2 . If it doesn't then it shouldnt redirect.
THis is my app-routing-module.ts file , the problem is in the 'userlist' path, were we implement the [RoleGuard] canActivate
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule, Router } from '@angular/router';
import { PokemonListComponent } from '../../src/app/pokemon-list/pokemon-list.component';
import {LoginComponent} from '../../src/app/login/login.component'
import { AuthGuard } from './auth.guard';
import { RoleGuard} from './role.guard'
import {UserListComponent} from './pokemon-list/user-list/user-list.component'
const routes: Routes = [
{path: 'pokemonlist', component: PokemonListComponent , canActivate: [AuthGuard]},
{path: 'login', component: LoginComponent},
{path: '',redirectTo: '/login',pathMatch: 'full'},
{path: 'userlist', component: UserListComponent , canActivate : [ RoleGuard]} //this is the guard we are looking at
]
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
exports:[RouterModule]
})
export class AppRoutingModule { }
And this is my current role.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class RoleGuard implements CanActivate {
data2 //variable to store the role of the current user , (1 or 2) . If its 2 the canActivate should return true.
constructor(public db: AngularFirestore, private myRoute: Router) {
//role extraction
//We get the role by comparing the uid , and store it in the "data2" var
var docRef = this.db.collection('users').doc(localStorage.getItem('user'));
docRef.get().toPromise().then(doc => {
if (doc.exists) {
this.data2 = doc.data().role;
}
});
}
canActivate() {
//if data2 is 2, means that the redirection should work
if ( localStorage.getItem('user') && this.data2 == 2 ) {
return true;
} else {
return false;
}
}
}
My navbard component where the click occurs , onUsersClick function
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Router } from '@angular/router';
import {AuthService} from '../services/auth.service'
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
@Output() featureSelected = new EventEmitter<string>();
myName;
fullUser: any;
name: string;
constructor(public firebase: AngularFireAuth, public db: AngularFirestore, public router: Router, private _authS: AuthService) {
let userID = localStorage.getItem('user')
this.myName= localStorage.getItem('displayName');
//retrieve logged user data
let docRef = db.collection('users').doc(userID);
docRef.get().toPromise().then(doc => {
if (doc.exists) {
this.fullUser = doc.data();
} else {
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error getting document:", error);
});
}
ngOnInit() {
}
onUsersClick() {
this.router.navigate(['/userlist']);
}
onPokemonClick(feature: string) {
this.router.navigate(['/pokemonlist']);
}
onSignOut() {
localStorage.clear();
}
}
My navbar html
<!--navbar-->
<nav class="navbar navbar-expand-lg navbar-dark">
<a class="navbar-brand" href="#">Pokedex</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" (click)="onPokemonClick()">Pokemons <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" *ngIf="fullUser.role == 2" (click)="onUsersClick()">Users <span
class="sr-only">(current)</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" (click)="onSignOut()"href="#">Sign Out <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item active" *ngIf="myName != 'null'">
<a class="nav-link" [ngStyle]="{'color': 'yellow'}">Welcome {{ myName }} !! <span class="sr-only">(current)</span></a>
</li>
</ul>
</div>
</nav>
回答1:
Try with:
@Injectable({
providedIn: 'root'
})
export class RoleGuard implements CanActivate {
constructor(public db: AngularFirestore) {
}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
if (localStorage.getItem('user') ) {
const doc = await this.db.collection('users')
.doc(localStorage.getItem('user'))
.get()
.toPromise();
return doc.exists && doc.data().role === 2 ? true : false;
} else {
return false;
}
}
}
The issue might be related to the fact that you resolve a promise in your constructor and expect the result to be available at the moment that canActivate
is invoked.
来源:https://stackoverflow.com/questions/55627562/angular-7-guard-redirection-only-works-on-double-click