Starts in:
1 DAY
2 HRS
20 MIN
4 SEC
Starts in:
1 D
2 H
20 M
4 S

Activities of "alexander.nikonov"

currently app.component.ts is the bootstraped component https://angular.io/guide/bootstrapping so if you place any api call in there it will be called so you have to use conditional operator there to calling api when the state is not authenticated.

Sorry, but i didn't get it. I have a lot of different components like the one below - with a bunch of API calls triggered based on different conditions - button clicks, subscriptions, route parameter values, etc.:

    @Component({ ... })
    export class ComponentHHH extends BaseComponent {
    
        //Condition method can be invoked based on various conditions in unknown moment of time
        ConditionMethodAAA() {
            ....
            this.apiServiceXXX.apiMethodYYY(...).pipe(takeUntil(this.unsubscriber$))
                .subscribe((response) => { ... });
            ....
            this.apiServiceZZZ.apiMethodAAA(...).pipe(takeUntil(this.unsubscriber$))
                .subscribe((response) => { ... });
            ....
        }

        ConditionMethodBBB() {
            ....
            this.apiServiceDDD.apiMethodSSS(...).pipe(takeUntil(this.unsubscriber$))
                .subscribe((response) => { ... });
            ....
        }
    }

If I activate another component in the menu - this.unsubscriber$ (property in "BaseComponent" class) receives null and completes. Due to this and to using "takeUntil", no matter which API calls were active, they all will be removed. I've tried to subcribe to "logout" event in "BaseComponent" and do the same I do with this.unsubscriber$ in "ngOnDestroy". However this does not work - API calls keep being invoked. Even more now: logout works only from Home page (probably these two things are unrelated, but I am not sure). I have not found explanation to this.

So you suggest to summon "app.component.ts" to resolve the problem. But I cannot figure out, how it can help here: there is no connection between AppComponent and another components API calls.

Hi Anjali.

First of all, ngOnDestroy with the suggested code already present in the base class HomeComponent is inherited from. Nevertheless, I've added ngOnDestroy here for test, too.

Also I've replace this.oAuthService.events with your suggestion.

After pressing "Logout" button I'm getting "Logout event received" message. But API call is STILL invoked as always. There has to be explanation WHY it is called though.

P.S. Please hold on - I want to check something...

UPDATE: I made some experiments. Good news: In the given specific case the API call I mentioned before was also invoked by other service - this was the reason it "resurrected" all the time after logout; Bad news: In a common case, only using if (this.authService.isAuthenticated) check or similar like you suggested helps resolving the initial problem. However, it is not a good approach: we have hundreds of API calls from hundreds of components. It is not a way to go to add hundreds of "if". Instead, it is supposed that for both component destroying and user logout action unsubscriber$ needs to received proper null value and be completed:

this.apiService
  .apiCall(...)
  .pipe(
    finalize(() => (...)),
    takeUntil(this.unsubscriber$) //this has to be enough for all cases
  )
  .subscribe((...) => {
      ...
  });

The problem is that for some reason using logout event does not help to resolve this issue. I use this in Component base class (no matter, "tap" or "subscribe" actually) and this block DOES get triggered, however eventually API is still invoked for unknown for me reason:

  ngOnInit(): void {
    this.oAuthService.events
      .pipe
      (
        filter(event => event?.type === 'logout'),
        takeUntil(this.unsubscriber$),
        tap(() => {
          this.unsubscriber$.next(null);
          this.unsubscriber$.complete();
        })
      )
      .subscribe();
      

I've tried to make unsubscriber$ as ReplaySubject and create its new with buffer == 1, but it does not change the things.

I am confused even more now: it appeared that logging out works only for Home page: if I take any page - even the ABP page - after clicking "logout" button the user is eventually redirected to Home page again without landing at Identity Server Login page: and then - all the rest our services required for the page are loaded as usual... And this is workflow when I click "Logout" on Home page: Afterwards I'm redirected to Identity Server Login page as expected. All the relevant pages have canActivate: [AuthGuard] It's absolutely strange given that "Logout" functionality is the same for all pages, i.e. the same code has to be invoked. Do you have any clues? If required, I will create a new ticket for this issue...

I had additional experiment. Please have a look:

I've modified ngOnInit a bit:

this.oAuthService.events
  .pipe(
    filter(event => event?.type === 'logout'),
    tap(() => {
      this.unsubscriber$.next(null);
      this.unsubscriber$.complete();
      console.log('unsubscriber null!');
    }))
    .subscribe();

if (this.authService.isAuthenticated) {
  this.homeService.getNewsForHomePage()
    .pipe(tap(() => console.log('getNewsForHomePage still invoked')), takeUntil(this.unsubscriber$))
    .subscribe((newsResponse) => {
      this.newsForHomePage = newsResponse.items;
    });
  this.homeService.getUrlsForHomePage()
    .pipe(tap(() => console.log('getUrlsForHomePage still invoked')), takeUntil(this.unsubscriber$))
    .subscribe((newsUrlParameterResponse) => {
      this.urls = newsUrlParameterResponse.items;
      this.urlDigimedia = this.urls.filter(i => i.columnValue === 'DM')[0]?.stringValue;
      this.urlMasterData = this.urls.filter(i => i.columnValue === 'MD')[0]?.stringValue;
    });
}

I got 'unsubscriber null' message instantly after clicking "Logout" button. Despite this, shortly after, the method was still being invoked (getUrlsForHomePage matches '/api/ct/central-tool/parameters/values' API route). I cannot explain what's going on: The messages "getNewsForHomePage still invoked" and "getUrlsForHomePage still invoked" were never shown - obviosly because this.authService.isAuthenticated was false by the moment.

I thought it could have something to do with using guards. But even if I remove guard for Home page, the given API call is still invoked.

Hi

Now after logout i guess your api will also not get called, can you check please?

The API is still called though - after I click Logout, but before actual logging out is complete.

Hi,

you can directly redirect to login page by attaching you root page or home component a authguard.

Great! Thank you so much - this part is now resolved.

Thank you! Will be waiting. Also please suggest me how to logout directly to Identity Server Login box without visiting intermediate root page (Home page). I was trying to find the way (like editing SignOut URLs in Identity Server settings via admin UI page), but it did not bring me anywhere. I believe this used to work properly in some previous ABP version. Maybe we have unintentionally have changed some relevant setting.

Hi Anjali.

Don't want to upset you, but it's even worse now: the mentioned API call is still GET called after I press 'Logout'. But now after I'm doing this - I never gets logged out: after several chaning screens I'm eventually redirected to the root page, i.e. Home page...

Hi Anjali,

i've run debug again.

  1. when I click "Logout" on Home page - the onInit method IS get triggered with expected this.authService.isAuthenticated == false. But prior to that, I'm already getting 401 error request (sometimes - only this one request, sometimes - another one too): The "initiator" there is shown as "zone.js", later on it's getting cleared. So it's still looking confusing.

  2. our users complain about being redirected to landing page "Login" dialog, then - to Identity Server "Login" dialog (as shown on second screenshot). The request is to be redirected to the second "Login" dialog straight away... How to do that?

Hi Anjali.

I have to reopen this ticket, because without using this.routesService.refresh() it appeared, that sometimes just setting items to invisible is not enough: menu is still shown complete (suprisingly - sometimes it DOES work properly - when navigating to specific page menu is rebuilt according to invisibility of items). But using this.routesService.refresh() makes combineLatest trigger again. Could you please suggest the changed code - where the menu always refreshes properly, but there are no extra unnecessary invocations?

      init() {
        this.routesService.flat.filter(x => x.requiredPolicy && (x as any).data?.moduleId).forEach(x => x.invisible = true);
        this.routesService.refresh(); // HAVE TO USE IT to make invisibility to have effect
        combineLatest([this.configStateService.getDeep$('extraProperties.modulePermissionMap'), this.routesService.flat$.pipe(take(1))])
          .pipe
          (
            filter(([modulePermissionMap, route]) => Object.keys(modulePermissionMap).length > 0 && Object.keys(route).length > 0),
            takeUntil(this.destroy)
          )
          .subscribe(([modulePermissionMap, nonLazyLoadedRoute])  => {
            nonLazyLoadedRoute.filter(node => node.requiredPolicy).forEach((nonLazyRouteItem: ABP.Route) => {
              let moduleId = (nonLazyRouteItem as any).data?.moduleId;
              if (moduleId) {
                const moduleIdPolicyViolated = !modulePermissionMap[moduleId] || modulePermissionMap[moduleId] && !modulePermissionMap[moduleId].includes(nonLazyRouteItem.requiredPolicy as string);
                const ordinaryRolePolicyViolated = !modulePermissionMap['_ordinaryRole'] || modulePermissionMap['_ordinaryRole'] && !modulePermissionMap['_ordinaryRole'].includes(nonLazyRouteItem.requiredPolicy as string);
                if (!moduleIdPolicyViolated || !ordinaryRolePolicyViolated) {
                  nonLazyRouteItem.invisible = false;
                }
              }
            });
            this.routesService.refresh(); // HAVE TO USE IT to make invisibility to have effect, but combineLatest is called again... :(
        });
      }
      

UPDATE: this is a modified version - does it look ok?

      init() {
        this.routesService.flat.filter(x => x.requiredPolicy && (x as any).data?.moduleId).forEach(x => x.invisible = true);
        this.routesService.refresh();
        let routeStateBefore = JSON.stringify(this.routesService.flat, ['name', 'invisible']);
        combineLatest([this.configStateService.getDeep$('extraProperties.modulePermissionMap'), this.routesService.flat$.pipe(take(1))])
          .pipe
          (
            filter(([modulePermissionMap, route]) => Object.keys(modulePermissionMap).length > 0 && Object.keys(route).length > 0),
            takeUntil(this.destroy)
          )
          .subscribe(([modulePermissionMap, nonLazyLoadedRoute])  => {
            nonLazyLoadedRoute.filter(node => node.requiredPolicy).forEach((nonLazyRouteItem: ABP.Route) => {
              let moduleId = (nonLazyRouteItem as any).data?.moduleId;
              if (moduleId) {
                const moduleIdPolicyViolated = !modulePermissionMap[moduleId] || modulePermissionMap[moduleId] && !modulePermissionMap[moduleId].includes(nonLazyRouteItem.requiredPolicy as string);
                const ordinaryRolePolicyViolated = !modulePermissionMap['_ordinaryRole'] || modulePermissionMap['_ordinaryRole'] && !modulePermissionMap['_ordinaryRole'].includes(nonLazyRouteItem.requiredPolicy as string);
                if (!moduleIdPolicyViolated || !ordinaryRolePolicyViolated) {
                  nonLazyRouteItem.invisible = false;
                }
              }
            });
            let routeStateNow = JSON.stringify(this.routesService.flat, ['name', 'invisible']);
            if (routeStateNow !== routeStateBefore) {
              routeStateBefore = routeStateNow;
              this.routesService.refresh();
            }
          });
      }

Hi Anjali,

unfortunately, it did not help - still getting 401 on logout in one of two methods. Suprisingly, this method has another problem - it is for some reason invoked twice, even though in debug I just got it triggered once.

I'm attaching the Home module code - probably you will figure out what is wrong. It is actually not my code, so I am not sure I would be able to reply you all the questions. But I'm ready to assist in any possible way.

Thank you. Home page

Actually one more thing confuses me: after I do log out - I'm redirected to this page ("Home"): instead of this: So I need to click "Login" again to be redirected to the second dialog. But the routing in the app is the same as in test ABP app...

Showing 111 to 120 of 333 entries
Made with ❤️ on ABP v9.1.0-preview. Updated on November 20, 2024, 13:06