0

我在 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?

任何帮助将不胜感激。

4

2 回答 2

2

用户在 /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));
}

于 2020-06-08T18:37:58.543 回答
0

你可以这样做: 1. 做一个 Auth 守卫,假设它是“AG”。2. 在此“AG”中,对您的后端进行 REST 调用。发送书签 ID、用户 ID、当前团队 ID。“AG”将在任何应用的路线更改时触发。3. 这个 REST 调用将比较当前的团队 ID 和使用该书签保存的团队 ID(假设:书签表有团队 ID 列作为外键)。4.所以当服务返回TRUE/FALSE时,“AG”就会知道它是否被授权。5. 如果为 FALSE,则将用户路由到任何 url。

示例代码示例:

@Injectable()
export class AuthGuardService implements CanActivate 
{ 
   constructor(public auth: AuthService, public router: Router) {}  

   canActivate(): boolean 
   {
    if (!this.auth.isAuthenticated()) {
      this.router.navigate(['team']);
      return false;
    }
    return true;
    }
}

添加路由示例:

export const ROUTES: Routes = [
  { path: '', component: Home},
  { 
    path: 'team/{id}',
    component: TeamComponent,
    canActivate: [AuthGuard] 
  },
  { path: '**', redirectTo: '' }
];
于 2020-06-08T14:44:48.237 回答