Почему ReplaySubject в AuthGuard не работает должным образом, когда пользователь вошел в систему? Angular 10+ - PullRequest
0 голосов
/ 06 августа 2020

Я пытаюсь реализовать аутентификацию с помощью Observables в Angular 10 . Я использую ReplaySubject в AuthService для установки текущего пользователя, вошедшего в систему. Проблема в том, что AuthGuard никогда не перенаправляет на главную после входа пользователя. Я описываю проблему ниже на auth.guard.ts файл.

app.routing.ts

const routes: Routes = [
      {
        path: 'not-found',
        component: NotFoundComponent,
      },
      {
        path: '',
        component: MainLayoutComponent,
        children: [
          {
            path: '',
            canActivateChild: [AuthGuard],
            loadChildren: () =>
              import('./modules/landing/landing.module').then(
                (m) => m.LandingModule
              ),
          },
        ],
      },
      { path: '**', redirectTo: 'not-found', pathMatch: 'full' },
    ];

auth.service.ts

@Injectable({ providedIn: 'root' })
export class AuthService {
  baseUrl = environment.apiUrl;
  private currentUserSource = new ReplaySubject<LoggedIn>(1);
  currentUser$ = this.currentUserSource.asObservable();

  constructor(private http: HttpClient) {}

  signIn(user: SignInDto) {
    return this.http.post(this.baseUrl + 'auth/signin', user).pipe(
      map((user: LoggedInDto) => {
        if (user) {
          localStorage.setItem('token', user.token);
          this.currentUserSource.next(user);

          return user;
        }
      })
    );
  }

  getCurrentUser(token: string) {
    if (token === null) {
      this.currentUserSource.next(null);
      return of(null);
    }
    const headers = new HttpHeaders().set('Authorization', 'Bearer ' + token);

    return this.http.get(this.baseUrl + 'auth/me', { headers }).pipe(
      map((user: LoggedIn) => {
        if (user) {
          localStorage.setItem('token', user.token);
          this.currentUserSource.next(user);
        }
      })
    );
  }
}

app.component.ts

export class AppComponent implements OnInit {

  constructor(private readonly authService: AuthService) {}

  ngOnInit(): void {
    this.getCurrentUser();
  }

  getCurrentUser() {
    const token = localStorage.getItem('token');

    this.authService.getCurrentUser(token).subscribe(() => {
      console.log('user loaded');
    }, console.log);
  }
}
export class SignInComponent implements OnInit {
  returnUrl: string;

  constructor(
    private readonly authService: AuthService,
    private readonly router: Router,
    private readonly activatedRoute: ActivatedRoute
  ) {}

  ngOnInit(): void {
    this.returnUrl = this.activatedRoute.snapshot.queryParams.returnUrl || '';
  }

  onSubmit() {
    this.authService.signIn({username: 'xxx', password: 'xxx'}).subscribe(
      (response) => {
        this.router.navigateByUrl(this.returnUrl);
      },
      console.log
    );
  }
}

auth.guard.ts

Проблема здесь ... Когда пользователь подписывается в currentUser $ observable всегда равно null , все остальное работает нормально (токен сохраняется в локальном хранилище). Если я попытаюсь обновить sh страницу после входа в систему, охрана будет работать нормально, но если я вошел в систему без обновления страницы, ничего не произошло.

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivateChild {
  logged: boolean = false;
  constructor(private authService: AuthService, private router: Router) {}

  canActivateChild(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.authService.currentUser$.pipe(
      map((auth) => {
        // when you sign in, auth object is always null
        // so the guard never redirect. But, if I refresh the page
        // after the token was saved the guard works fine, the auth object comes with data
        // What's the problem? :(
        if (auth) {
          return true;
        }

        this.router.navigate(['/signin'], {
          queryParams: { returnUrl: state.url },
        });
      })
    );
  }
}

Итак, вопрос в том, что я делаю не так или игнорируя?

...