Защита маршрута AngularFire2 по ролям пользователей

У меня есть приложение angular 2, настроенное с защитой маршрута, которая в настоящее время проверяет, вошел ли пользователь в систему или нет. Это работает нормально, но теперь я пытаюсь настроить другую защиту маршрута, которая не только проверяет, вошел ли пользователь в систему, но и является ли он администратором.

Вот что у меня есть на данный момент:

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { AngularFire } from 'angularfire2';
import { AuthService } from './auth.service';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
import 'rxjs/add/operator/take';

@Injectable()
export class AdminGuard implements CanActivate {

  constructor(
    private af: AngularFire,
    private authService: AuthService,
    private router: Router
  ) {

  }

  canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean> {

    let redirectURL:string = state.url;

    return this.af.auth.map((auth) =>  {
      if (auth == null) {
        this.authService.redirectURL = redirectURL;
        this.router.navigate(['/login']);
        return false;
      } else {

        return this.af.database.object('roles/admins/'+auth.uid, { preserveSnapshot: true })
          .take(1)
          .subscribe(res => {
            if (res.val()) {
              console.log('is admin, return true');
              return true;
            } else {
              console.log('access denied');
              this.router.navigate(['/']);
              return false;
            }
          });

      }
    }).first();

  }

}

В тот момент, когда я пытаюсь перейти на маршрут, защищенный этим сторожем, я получаю вывод console.log 'is admin, return true', но дальше ничего не происходит. Новый маршрут не отображается, и приложение просто остается на текущей странице.

Может ли кто-нибудь сказать мне, где я ошибаюсь, пожалуйста? Спасибо за любую помощь.


person Daniel Hutton    schedule 14.10.2016    source источник
comment
Попробуйте без first(). У вас также есть вложенные подписки, возможно, вы могли бы реорганизовать код...   -  person Sasxa    schedule 14.10.2016
comment
Удаление first() не помогло. Как бы вы подошли к рефакторингу кода?   -  person Daniel Hutton    schedule 14.10.2016


Ответы (1)


Получил работу с этим в конце:

let redirectURL:string = state.url;

return this.af.auth
  .flatMap(auth => {
    if (auth == null) {
      return new Promise(resolve => { resolve({}) });
    } else {
      return this.af.database.object(`roles/admins/${auth.uid}`);
    }
  })
  .map(data => {
    if (data.$value) {
      return data.$value;
    } else {
      // User doesn't have permission
      this.authService.redirectURL = redirectURL;
      this.router.navigate(['/404']);
      return false;
    }
  })
  .first();

Все еще нуждается в тестировании, но я закончил его быстро, прежде чем покинуть офис. Кажется, теперь работает нормально :)

person Daniel Hutton    schedule 14.10.2016