Angular 9: деактивировать охрану и тайм-аут сеанса - PullRequest
0 голосов
/ 30 мая 2020
• 1000 на страницу выхода.

В некоторых компонентах у меня есть форма, и когда пользователь не сохранил изменения, есть canDeactive guard с модальным всплывающим окном, предупреждающим пользователя о несохраненных изменениях. Проблема в том, что теперь, когда сеанс недействителен, срабатывает охрана (поскольку приложение angular еще не знает о недопустимом сеансе), и я застрял во всплывающем окне. Моей целью было бы проверить, действителен ли сеанс, до того, как охранник будет уволен (или оценить в самом охраннике, если сеанс действителен). Моя идея заключалась в том, чтобы вызвать функцию isAuthenticated в бэкэнде, а в охраннике перейти к выходу из системы, на 401 и еще показать диалоговое окно, но поскольку вызов является асинхронным c, он не сработает, и я не понял, как сделай это.

component.ts

createChangeGuard() {
    setTimeout(() => {
      this.myObjectOrig$ = new BehaviorSubject(this.bookingForm.value).asObservable();
      this.isDirty$ = this.bookingForm.valueChanges.pipe(dirtyCheck(this.myObjectOrig$));
      this.myObjectOrig$.pipe(untilDestroyed(this)).subscribe(state => { this.bookingForm.patchValue(state, { emitEvent: false }); });
    }, 1000);
  }

компонент грязной проверки

export interface DirtyComponent {
  isDirty$: Observable<boolean>;
  // isPrinting: boolean;
  hasValidSession$: Observable<boolean>;
}

export function dirtyCheck<U>( source: Observable<U> ) {
  let subscription: Subscription;
  let isDirty = false;
  return function <T>( valueChanges: Observable<T> ): Observable<boolean> {

    const isDirty$ = combineLatest(
      [source,
      valueChanges]
    ).pipe(
      debounceTime(300),
      map(( [a, b] ) => { return isDirty = isEqual(a, b) === false;
      }),
      finalize(() => subscription.unsubscribe()),
      startWith(false),
      shareReplay({ bufferSize: 1, refCount: true }),
    );

    subscription = fromEvent(window, 'beforeunload').subscribe(event => {
        isDirty && (event.returnValue = false) && event.preventDefault();
    });
    return isDirty$;
  };
}

деактивировать Охранник

export class DirtyCheckGuard implements CanDeactivate<DirtyComponent> {
   ....

    constructor( private modalService: NzModalService,
                 .....
                  ) {
    }

    contentNormal = 'Die Änderungen wurden nicht gespeichert. Wollen Sie wirklich die Seite verlassen?';
    contentPrint = 'Die Änderungen wurden noch nicht gespeichert. Trotzdem drucken?';
    canDeactivate( component: DirtyComponent, currentRoute: ActivatedRouteSnapshot ): Observable<boolean> | boolean {
      let formIsDirty = false;
      ...some logic to set formIsDirty...
      return component.isDirty$.pipe(switchMap(dirty => {
        let navigate;
        if ( (dirty === false && !formIsDirty ) ) {
          // update status to status before the booking went into edit mode since no change was made
            this.checkPage(currentRoute.data.origin);
          return of(true);
        } else if (dirty === true || (dirty === false && formIsDirty)) {
        return this.modalService.create({
          nzTitle: 'Not saved',
          nzContent: content,
          nzFooter: [
            {
              label: 'Abbrechen',
              onClick: () => {navigate = false; this.modalService.closeAll(); }
            },
            {
              label: confirmText,
              type: 'primary',
              onClick: () => { navigate = true; this.checkPage(currentRoute.data.origin); this.modalService.closeAll(); }
            }
          ]
        }).afterClose.pipe(map(() => navigate ));

      }}), take(1));
    }
  }

перехватчик

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
     const requestRoute = this.router.url;
       return next.handle(request).pipe(retry(1), catchError((error: HttpErrorResponse) => {
         // this.errorCount = true;|| this.authenticationService.isLoggedIn() === false
         if (error.status === 401 ) {
             this.authenticationService.logout(requestRoute);
           }
         if (error.error instanceof ErrorEvent) {
               // A client-side or network error occurred. Handle it accordingly.
               console.error('An error occurred:', error.error.message);
             } else {
               console.error('An error occurred:', error);
               // The backend returned an unsuccessful response code.
               // The response body may contain clues as to what went wrong,
               if (error.error !== null){
                   this.showErrorNotification(error.status, error.error?.errorCode, error.error?.errorText);
                   console.error(`Backend returned code ${error.status}, body was: ${error.error?.errorText}}`);
                 }
             }
         return throwError(error.error);
       })
       );

служба аутентификации

async isAuthenticated(){
    const serverUrl = this.baseURL + 'isValidSession';
    const response = await this.http.get(serverUrl, httpOptions).toPromise();
    return response.toString();
 }

1 Ответ

0 голосов
/ 30 мая 2020

Если вам нужно проверять сеанс на каждом canActivate. Для этого у вас должен быть api.

допустим, что у вас есть этот api в AuthService

async isSessionValid() {
   var res = await this.http.get('url').toPromise();
   return res;
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...