首页 > 解决方案 > 基于集合查询结果的Angular Route Guard

问题描述

我在 Firestore 中有一个“团队”系列。团队文档将包含一个team_users地图字段,userID: true如果他们是该团队的一部分。

team_users我在服务中有一个查询,该查询返回并显示所有团队文档,其中登录的用户 ID 与字段中的 ID 匹配。

getTeamsList(user_id: string) {
  this.teamsCollection = this.afs.collection<any>(`teams`, ref => ref.where(`team_users.${user_id}`, "==", true))
  this.teams = this.teamsCollection.snapshotChanges().pipe(
  map(actions => actions.map(a => {
    const data = a.payload.doc.data();
    const id = a.payload.doc.id;
    return { id, ...data };
  }))
 ).pipe(shareReplay());
}

我需要实现的是执行以下操作的路由守卫:

  1. 防止用户访问他们不属于/曾经属于的团队。例如,如果用户在 中时有一个文档的书签Team A,但后来离开了,他们应该无法访问此路由,而是应该重定向回/teams
  2. 如果用户不属于任何团队(集合查询不产生任何结果),则无法从/teams列表 url访问路径

注意:一个用户可以是多个团队的一部分。如果用户是 A、B 和 C 组的成员,并且在 A 组中拥有页面的书签,但后来离开了,则路由守卫应阻止他们访问属于 A 组的任何页面,但仍允许访问B 组和 C 组页面。

这是否意味着:

  1. 我的应用程序中的每个 URL 都需要这个保护吗?
  2. 我的应用程序中的每个 URL 都需要包含团队 ID?

任何帮助将不胜感激。

标签: angulargoogle-cloud-firestoreangular-route-guards

解决方案


用户在 /teams 页面上显示团队(您不需要在这条路线上看守)。当用户点击其中一个团队时,导航到 /teams/teamID (现在这条路线需要一个守卫来防止不属于 teamID 的用户访问它。要设置守卫,请执行以下操作:

  1. 编写一个函数来检查用户是否是团队成员。

isTeamMember(userId: string, teamId: string): Observable < Boolean > {
  return this.firestore.doc < any > (`teams/${teamId}`).snapshotChanges().pipe(
    map(value => value.payload.data().team_users[userId] === true));
}

  1. 调用 Guard 中的函数(CanActivate 像这样实现)。请记住注入包含当前用户的服务/存储并从 Url 检索 teamId。2用于调用firestore上的函数

canActivate(
  next: ActivatedRouteSnapshot,
  state: RouterStateSnapshot): Observable < boolean > | Promise < boolean > | boolean {
  return this.firestoreService.isTeamMember(userIdFromWhereYouStoreYourCurrentUser, teamIdFromTheCurrentUrl).pipe(map(isTeamMember => {
      if (isTeamMember) {
        return true;
      } else {
        //Add your not team member logic here, eg Stay in the current route, may be show an error message
        return false;
      }
    }),
    take(1));
}


推荐阅读