Angular 9 и Ioni c Перенаправление на предыдущую страницу, когда auth Guard отправляет пользователя для входа или регистрации - PullRequest
0 голосов
/ 30 апреля 2020

Я работаю над приложением. У меня есть страница цилиндров, которая служит домашней страницей. Я прошел динамическую маршрутизацию c, когда пользователь нажимает на размер цилиндра, чтобы просмотреть его детали на другой странице. На этой странице с подробной информацией о цилиндре есть защита, которая позволяет пользователю войти или зарегистрироваться. После успешного входа в систему или входа в систему я хочу, чтобы пользователь go вернулся на страницу сведений о выбранном размере цилиндра, с которой он был перенаправлен изначально. Я попытался объединить ответы, которые я видел в стеке, но не работает. Я надеюсь, что смогу закончить с объяснением того, как это было решено тоже. Я приложу свои исходные коды.

auth.guard.ts

import { Injectable } from '@angular/core';
import { CanLoad, Route, UrlSegment, Router } from '@angular/router';
import { Observable, of } from 'rxjs';
import { take, tap, switchMap } from 'rxjs/operators';

import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanLoad {
  constructor(private authService: AuthService, private router: Router) {}

  canLoad(
    route: Route,
    segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
      return this.authService.userIsAuthenticated.pipe(
        take(1),
        switchMap(isAuthenticated => {
          if (!isAuthenticated) {
            return this.authService.autoLogin();
          } else {
            return of(isAuthenticated);
          }
        }),
        tap((isAuthenticated) => {
          if (!isAuthenticated) {
            this.router.navigateByUrl('/auth');
          }
        })
      ); // boolean
  }
}

auth.page.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { NgForm } from '@angular/forms';
import { Observable } from 'rxjs';

import { LoadingController, AlertController } from '@ionic/angular';
import { AuthService, AuthResponseData } from './auth.service';

@Component({
  selector: 'app-auth',
  templateUrl: './auth.page.html',
  styleUrls: ['./auth.page.scss'],
})
export class AuthPage implements OnInit {
  // property
  isLoading = false;
  isLogin = true;

  constructor(
    private authService: AuthService,
    private router: Router,
    private loadingCtrl: LoadingController,
    private alertCtrl: AlertController
  ) {}

  ngOnInit() {}

  authenticate(email: string, password: string) {
    this.isLoading = true;
    this.loadingCtrl
      .create({ keyboardClose: true, message: 'Logging you in...' })
      .then((loadingEl) => {
        loadingEl.present();
        let authObs: Observable<AuthResponseData>;
        if (this.isLogin) {
          authObs = this.authService.login(email, password);
        } else {
          // if we are not logged in but signing up
          authObs = this.authService.signUp(email, password);
        }
        authObs.subscribe(
          (resData) => {
            console.log(resData);
            this.isLoading = false;
            loadingEl.dismiss();
            this.router.navigateByUrl('/cylinders');
          },
          (errRes) => {
            console.log(errRes);
            loadingEl.dismiss();
            const code = errRes.error.error.message;
            let message = 'Could not sign you up, please try again';
            if (code === 'EMAIL_EXISTS') {
              message = 'This email address already exists!';
            } else if (code === 'EMAIL_NOT_FOUND') {
              message = 'E-Mail address could not be found.';
            } else if (code === 'INVALID_PASSWORD') {
              message = 'Your password is incorrect';
            }
            this.showAlert(message);
          }
        );
      });
  }

  onSwitchAuthMode() {
    this.isLogin = !this.isLogin;
  }

  // switch our authentication mode based on state. we invert. if its false its true if its true its false
  onSubmit(form: NgForm) {
    if (!form.valid) {
      return;
    }
    // IF YOU HAVE A VALID FORM THEN WE MAKE A POSITIVE IF CHECK AND PROCEED TO THE BELOW
    const email = form.value.email; // from the name given to our forms
    const password = form.value.password;

    // we check if authenticated and forward email and password
    this.authenticate(email, password);
    form.reset();
  }

  // SHOW ERROR MESSAGE TO USERS
  private showAlert(message: string) {
    this.alertCtrl
      .create({
        header: 'Authentication failed',
        // tslint:disable-next-line: object-literal-shorthand
        message: message,
        buttons: ['Okay'],
      })
      .then((alertEl) => {
        alertEl.present();
      });
  }
}

cylinders.page. html содержит мой список цилиндров, который приводит пользователя к странице с описанием цилиндров при нажатии для просмотра сведений о цилиндре, но это страница с описанием цилиндров имеет аутентификацию.

<ion-header>
  <ion-toolbar>
    <!-- HAMBURGER MENU BUTTON -->
    <ion-buttons slot="start" contentId="main">
      <ion-menu-button></ion-menu-button>
    </ion-buttons>

    <ion-title>Select Gas to Refill</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>

    <!-- SUCCESSFUL LOGIN OR SIGNUP SHOULD TAKE USER TO THE SPECIFIED ROUTE BELOW  -->

    <ion-item *ngFor="let cylinder of cylinders" [routerLink]="['./', cylinder.size]">
      <ion-avatar slot="start">
        <ion-img [src]="cylinder.imageUrl"></ion-img>
      </ion-avatar>

      <ion-label color="primary"> {{ cylinder.size }} </ion-label>
    </ion-item>
  </ion-list>
</ion-content>

app-routing.module.ts

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

import { AuthGuard } from './auth/auth.guard';

const routes: Routes = [
  { path: '', redirectTo: 'cylinders', pathMatch: 'full' },
  {
    path: 'cylinders',
    children: [
      {
        path: '',
        loadChildren: () =>
          import('./cylinders/cylinders.module').then(
            m => m.CylindersPageModule
          )
      },
      {
// BELOW IS THE DYNAMIC ROUTING WHEN USER SHOULD NAVIGATE AFTER AUTH
        path: ':cylinderSize',
        loadChildren: () =>
          import('./cylinders/cylinder-detail/cylinder-detail.module').then(
            m => m.CylinderDetailPageModule
          ),
        canLoad: [AuthGuard]
      }
    ]
  },
  {
    path: 'auth',
    loadChildren: () => import('./auth/auth.module').then(m => m.AuthPageModule)
  },
  {
    path: 'checkout',
    loadChildren: () => import('./checkout/checkout.module').then( m => m.CheckoutPageModule)
  }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

1 Ответ

0 голосов
/ 30 апреля 2020

Таким образом, для вашего варианта использования, когда вы хотите, чтобы ваш пользователь "возобновил" на первоначально запрошенной странице после успешной аутентификации, логика высокого уровня c реализации может быть достигнута следующим образом:

  • в вашей авторизации при перенаправлении пользователя на страницу авторизации вам нужно захватить его полный «обратный URL» и передать его так, чтобы страница входа / авторизации имела к нему доступ.

  • затем после успешной аутентификации вы используете этот returnURL и помогаете пользователю перемещаться туда

Если вы хотите придерживаться canLoad (что предотвращает не только доступ, но и загрузку модуля), есть способ сделать это:

1. Обновите ваш метод canLoad, чтобы передать обратный URL при переходе на страницу авторизации:

// **inside** canLoad guard obtain full path (returnURL) this way as suggested in this answer (segments is one of the arguments canLoad method receives): 

const returnUrl = segments.reduce((path, currentSegment) => {
  return `${path}/${currentSegment.path}`;
}, '');


// then instead of this.router.navigateByUrl('/auth'), do ~this:

this.router.navigate(['auth'], { queryParams: { returnUrl: this.router.routerState.snapshot.url }});

2. Теперь в вашей службе аутентификации, после успешной Если вы перенаправляете пользователя на ранее пробованную страницу:

// instead of this.router.navigateByUrl('/cylinders'), do ~this:
let returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/cylinders';
this.router.navigateByUrl(returnUrl)

Чтобы вышеперечисленное работало, вам нужно импортировать ActivatedRoute et c.

Надеюсь, вы можете взять его отсюда.

Также см. Симила r вопрос и ответ здесь: angular2: как получить полный путь к защите CanLoad при сохранении URL перенаправления

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