Я хотел бы заблокировать доступ к 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;
}
}
@HereticMonkey спасибо, на самом деле я возвращал простое логическое значение, поэтому я не мог получить свой результат настороже! Лучше вернуть Observable<boolean>. Большое спасибо
Проблема заключается в методе 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>. Большое спасибо !
Вам нужно изменить обе функции;
isAuthorizedToAccessForms0
должен вернутьObservable<boolean>
, потому что он не может вернутьboolean
, как сейчас делает вид. Как только вы заработаете, вы можете вернутьсяthis.formAllServ.isAuthorizedToAccessForms0(myId).pipe(map((isAuthorized: boolean) => ...
и делать то, что вам нужно. Предлагаю просмотреть документацию по Observables.