简体   繁体   English

Angular 基于集合查询结果的Route Guard

[英]Angular Route Guard based on collection query result

I have a 'Teams' collection in Firestore.我在 Firestore 中有一个“团队”系列。 A team document will include a team_users map field where userID: true if they are a part of that team.团队文档将包含一个team_users map 字段,其中userID: true如果他们是该团队的一部分。

I have a query in a service that returns and displays all team documents where the logged in user id matches an ID within the team_users field.我在服务中有一个查询,该查询返回并显示所有团队文档,其中登录的用户 ID 与team_users字段中的 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());
}

What I need to achieve is a route guard that performs the following:我需要实现的是执行以下操作的路由守卫:

  1. Prevents a user accessing a team they don't belong to / use to belong to.防止用户访问他们不属于/曾经属于的团队。 For example, if the user has a bookmark for a document whilst they were in Team A , but have since left, they should not be able to access this route and should instead be redirected back to the url of /teams例如,如果用户在Team A中时有一个文档书签,但后来离开了,他们应该无法访问此路由,而是应该重定向回/teams的 url
  2. If the user does not belong to any teams (the collection query doesn't produce any results), then no routes are accessible a part from the /teams listing url如果用户不属于任何团队(集合查询不产生任何结果),则无法访问/teams列表 url 中的一部分

Note: A user can be a part of multiple teams.注意:一个用户可以是多个团队的一部分。 If the user was a part of Team A, B and C and has bookmarks for pages in Team A, but has since left, the route guard should prevent them from accessing any pages that were a part of Team A, but still allow access to Team B and C pages.如果用户是团队 A、B 和 C 的成员,并且在团队 A 中有页面的书签,但后来离开了,则路由守卫应阻止他们访问属于团队 A 的任何页面,但仍允许访问B 组和 C 页面。

Does this mean that:这是否意味着:

  1. Every URL within my app will need this guard?我的应用程序中的每个 URL 都需要这个保护吗?
  2. That every URL within my app will need to contain the team ID?我的应用程序中的每个 URL 都需要包含团队 ID?

Any help would be greatly appreciated.任何帮助将不胜感激。

A user is on /teams page displaying teams (You don't need a guard on this route).用户在 /teams 页面上显示团队(您不需要在这条路线上看守)。 When a user clicks on one of the teams navigate to /teams/teamID (Now this route needs a guard to prevent a user that doesn't belong to teamID from accessing it. To set the guard do this:当用户点击其中一个团队时,导航到 /teams/teamID (现在这条路线需要一个守卫来防止不属于 teamID 的用户访问它。要设置守卫,请执行以下操作:

  1. Write a function that checks on firestore if a user is a member of a team.编写一个 function 来检查用户是否是团队成员。

 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. Call the function in your Guard (CanActivate implemented like this).在 Guard 中调用 function(CanActivate 像这样实现)。 Remember to inject a service/store containing your current user and retrieve teamId from Url.请记住注入包含当前用户的服务/存储并从 Url 检索 teamId。 The 2 are used to call the function on firestore 2用于在firestore上调用function

 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)); }

You can do it this way: 1. Make an Auth guard, let say it "AG".你可以这样做: 1. 做一个 Auth 守卫,假设它是“AG”。 2. In this "AG", make a REST call to your backend. 2. 在此“AG”中,对您的后端进行 REST 调用。 Sending the bookmark ID, USer ID, Current Team Id.发送书签 ID、用户 ID、当前团队 ID。 "AG" will get triggered on route change where-ever applied. “AG”将在任何应用的路线更改时触发。 3. This REST call will compare the current team Id and the Team Id saved with that Bookmark(Assumption: Bookmark table has the column of Team Id as foreign key). 3. 这个 REST 调用将比较当前团队 ID 和使用该书签保存的团队 ID(假设:书签表有团队 ID 列作为外键)。 4. So when the service return TRUE/FALSE, then "AG" will know that if it is authorized or not. 4.所以当服务返回TRUE/FALSE时,“AG”就会知道它是否被授权。 5. If it is FALSE, then route user to whatever url. 5. 如果为 FALSE,则将用户路由到 url。

Example of sample code:示例代码示例:

@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;
    }
}

Adding the route example:添加路由示例:

export const ROUTES: Routes = [
  { path: '', component: Home},
  { 
    path: 'team/{id}',
    component: TeamComponent,
    canActivate: [AuthGuard] 
  },
  { path: '**', redirectTo: '' }
];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM