Вернуть логическое значение, наблюдаемое на угловой защите

Я хотел бы заблокировать доступ к URL-адресу от неавторизованных пользователей. В настоящее время я использую canActivate с route Guard из angular, чтобы заблокировать пользователям доступ к /my/specific_url_route.

Действительно, я хочу запретить некоторым пользователям (не указанным в списке в моей базе данных) доступ к ресурсу, введя соответствующий URL-адрес (например, mydomain/legalForm/123ytfdhs653HG). Для этого, во-первых, я уже блокирую доступ из моего пользовательского представления (ОК), но неавторизованные пользователи все еще могут получить доступ к ресурсу (странице), введя правильный URL-адрес напрямую (тема).

Мой код правильный (возвращает false и true, как и ожидалось в моем сервисе), но моя защита

можноактивировать()

выполняется и возвращает значение до завершения моей функции. Я знаю, что это проблема, связанная с обещанием/наблюдаемым. Мне нужно отредактировать две мои функции canActivate() и isAuthorizedToAccessForms0(), но я не знаю, как ожидать правильного поведения.

Я знаю, что pipe, map или then должны быть добавлены после моего вызова функции, чтобы дождаться результата в моей защите, здесь связаны тема 1 тема 2 тема 3

Мой сервис:

  public isAuthorizedToAccessForms0(id): boolean{ 
    var isFound = false;
    
    //query
    this.fire.collection('solutions').where(firebase.firestore.FieldPath.documentId(), '==', id).get().then(val => {
      val.forEach(v => {
        this.emailsAuthorizedVeolia = v.data().emailVeoliaAuthorized; //get each user
      })
    }).then(res => {
      //Check if a user is present in the list (whenever his position is in the list)
      for (let i = 0; i <= this.emailsAuthorizedVeolia.length-1 ; i++) {
        if (this.authService.currentUserEmail === this.emailsAuthorizedVeolia[i]) {
            isFound = true
          } else {
            //isFound = false by default
          }
      }
    }).then(final => {
      if (isFound === false) { //no occurrence finded
        console.info("DENIED!")
        isFound = false
        return false
      } else { //user finded
        console.info("GRANTED!")
        isFound = true
        return true
      }
    });
    
    return isFound;
  }

Моя охрана:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    const myId = route.paramMap.get('id')
    
    try{
        const authorized = this.formAllServ.isAuthorizedToAccessForms(myId) //HERE I need to add .pipe ? .then ? .map ?
        
        if (authorized === false) {
            console.info("FALSE")
            alert('You are not allowed to view this page');
            this.router.navigate(['/homeUser']);
            return false
        }
        else {
            console.info("TRUE")
            alert('Access granted !');
            return true
        }
    } catch(err) {
        return false;
    }  
    
}

Вам нужно изменить обе функции; isAuthorizedToAccessForms0 должен вернуть Observable<boolean>, потому что он не может вернуть boolean, как сейчас делает вид. Как только вы заработаете, вы можете вернуться this.formAllServ.isAuthorizedToAccessForms0(myId).pipe(map((‌​isAuthorized: boolean) => ... и делать то, что вам нужно. Предлагаю просмотреть документацию по Observables.

Heretic Monkey 03.04.2023 19:22

@HereticMonkey спасибо, на самом деле я возвращал простое логическое значение, поэтому я не мог получить свой результат настороже! Лучше вернуть Observable<boolean>. Большое спасибо

Dorian 04.04.2023 11:18
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
2
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема заключается в методе isAuthorizedToAccessForms0. Вы возвращаете переменную isFound, не дожидаясь окончания промиса. Соответственно результатом этой функции всегда будет false.

Вы можете обновить код isAuthorizedToAccessForms0 следующим образом:

 public isAuthorizedToAccessForms0(id): Observable<boolean> { 
    
    return new Observable<boolean>(observer => {
      this.fire.collection('solutions').where(firebase.firestore.FieldPath.documentId(), '==', id).get().then(val => {
        val.forEach(v => {
          this.emailsAuthorizedVeolia = v.data().emailVeoliaAuthorized; //get each user
        })
      }).then(res => {
        //Check if user is present in the list (whenever his position in the list)
        for (let i = 0; i <= this.emailsAuthorizedVeolia.length-1 ; i++) {
          if (this.authService.currentUserEmail === this.emailsAuthorizedVeolia[i]) {
              console.info('GRANTED!');
              observer.next(true);
              observer.complete();
              break;
            } else {
              observer.next(false);
              observer.complete();
              console.info('DENIED!');
              break;
              //isFound = false by default
            }
        }
      })
    })
  }

После этого следует обновить защиту

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    const myId = route.paramMap.get('id')
    
    try{
       return this.formAllServ.isAuthorizedToAccessForms(myId).pipe(
        tap((authorized) => {
 
          if (authorized === false) {
            console.info("FALSE")
            alert('You are not allowed to view this page');
            this.router.navigate(['/homeUser']);
        }
        else {
            console.info("TRUE")
            alert('Access granted !');
        }
        })
       )
       
    } catch(err) {
        return of(false);
    }  
    
}

Я надеюсь, это поможет вам

Большое спасибо, что работает, как ожидалось. Теперь я могу вернуть свой результат (true или flase) из моей функции (службы) и повлиять на изменения в моей защите. Лучше вернуть Observable<boolean>. Большое спасибо !

Dorian 04.04.2023 11:20

Другие вопросы по теме