ABP 7.0.1 / Angular
My home page shows some information to an authenticated user via API calls. If the user logs out - these methods need not to be invoked anymore.
Seems like I've tried all possible ways - and it still DOES call those methods with "Not authorized (401)" error from server after I click "Logout" button. I also have tried to call Subscription$.unsubscribe()
while logging out, but it still does not work.
Another question: I can logout from any page, not just Home page. There are plenty of API call subscriptions on each of them. How am I supposed to unsubscribe from all such calls with minimal code changes??
Here is the piece of the code of my Home page:
ngOnInit() {
this.oAuthService.events
.pipe(
filter(event => event?.type === 'logout'),
tap(() => {
this.logout$.next(null); //those are called, but API calls are still invoked
this.logout$.complete();
}))
.subscribe();
this.homeService.getNewsForHomePage()
.pipe(filter(() => this.configStateService.getDeep('currentUser.isAuthenticated')), takeUntil(this.destroy), takeUntil(this.logout$))
.subscribe((newsResponse) => {
...
});
this.homeService.getUrlsForHomePage()
.pipe(filter(() => this.configStateService.getDeep('currentUser.isAuthenticated')), takeUntil(this.destroy), takeUntil(this.logout$))
.subscribe((newsUrlParameterResponse) => {
...
});
}
ngOnDestroy(): void {
this.destroy.next(null);
this.destroy.complete();
}
Moreover - when I am already at this page (where this.configStateService.getDeep('currentUser.isAuthenticated')
is supposed to be false
, I guess):
the API calls are still invoked.
36 Answer(s)
-
0
Hi again,
If you want to unsubsribe or only subscribe when you logged in you can use isAuthenticated property in config state service for example
Component TS
import { Component, DestroyRef, inject } from '@angular/core'; import { filter, finalize, map, switchMap } from 'rxjs'; import { ConfigStateService } from '@abp/ng.core'; import { IdentityUserService } from '@volo/abp.ng.identity/proxy'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'], }) export class HomeComponent { protected readonly configStateService = inject(ConfigStateService); protected readonly identityUserService = inject(IdentityUserService); readonly #destryoRef = inject(DestroyRef); currentUser$ = this.configStateService.getOne$('currentUser'); users$ = this.identityUserService.getList({ maxResultCount: 10 }).pipe(map(res => res.items)); ngOnInit(): void { this.currentUser$ .pipe( filter(currentUser => !!currentUser?.isAuthenticated), switchMap(() => this.identityUserService.getList({ maxResultCount: 10 })), map(res => res.items), takeUntilDestroyed(this.#destryoRef), finalize(() => console.log('completed')) ) .subscribe(users => console.log(users)); } }
Component HTML
<div class="card" *ngIf="(currentUser$ | async).isAuthenticated"> <div class="card-header">{{ 'AbpIdentity::Users' | abpLocalization }}</div> <div class="card-body"> <pre>{{ users$ | async | json }}</pre> </div> </div>
Output
I'm logged in
I'm logged out
As you can see it's not sending any request if not authenticated. In template and in TS file I create a sample that you can use.
-
0
This approach works - I've already checked it before. But the problem is that I have hundreds of components, each of which has dozen of API calls. The components use base class which contains unsubscriber$ and it is used in
ngOnDestroy
to be nullified and complete. Thanks to that, when I go to another component, any API anywhere is properly unsubscribed (takeUntil(this.unsubscriber$)
).Making use of one more check means I need to add this
filter(...)
in all those API calls. And this is not a very good approach, IMHO.... I'd prefer to make changes in the base class unsubscriber$ only - to cover logout scenario... -
0
This approach works - I've already checked it before. But the problem is that I have hundreds of components, each of which has dozen of API calls. The components use base class which contains unsubscriber$ and it is used in
ngOnDestroy
to be nullified and complete. Thanks to that, when I go to another component, any API anywhere is properly unsubscribed (takeUntil(this.unsubscriber$)
).Making use of one more check means I need to add this
filter(...)
in all those API calls. And this is not a very good approach, IMHO.... I'd prefer to make changes in the base class unsubscriber$ only...There are 2 things here
Kill the stream after navigated
- which is solved with BaseComponent strategy. But I prefer the use takeUntilDestroyed() otherwise I'll add ngOnDestroy with no meaning 🙂
Don't request if not authenticated; for that I've just drop a simple solution you can use similar BaseComponent strategy or much better use async pipe and handle request process on template. Create a directive for authenticated condition etc.. This case seems like a specific case
-
0
If applying filter operator is resolves your problem, try to use interceptor and handle this filtering process at here. In that way you can decide to sending request or not in a one place. I hope these helps you
-
0
Saying honestly, I still hoped I would be able to use
unsubscriber$
in the component base class to control everything. It's a pity there's no some observable i can watch to change it... I would prefer not to scatter the changes around different classes (e.g.HttpInterceptor
, etc.) -
0
🙂
unsubscriber$
will trigger when component destroy which means it won't track authenticated status. I suggest interceptor for handle authenticated status and prevent request.unsubscriber$
just kill subscription on destroy stage. Please separate the concerns -
0
I think all in all you are right about that. But there's another problem. So I put the debug point in
intercept
call - I'm getting there ONCE or TWO TIMES (those are request to Identity Server) after I already pressed "Logout" button: So I release the debug point and receive this bunch of API requests with error 401... I have created another ticket (https://support.abp.io/QA/Questions/5781/Logout-does-not-actually-logs-out-in-Angular-app) - that I actually cannot logout from the page other than Home page. The guy there answers he cannot do anything, because the problem is not reproduced on his end. So I don't know whether these two problems are related and what to do. -
0
Not resolved. Reopening.
-
0
-
0
Not sure. Probably it's related. You might close this one. But if that ticket is resolved, however this problem does not go away - I will reopen this ticket.
-
0
ok