From 83b48e7f2d290b6397fb07dbda2a421538f3fd95 Mon Sep 17 00:00:00 2001 From: palajsamuel Date: Mon, 24 Aug 2026 10:54:47 +0200 Subject: [PATCH 1/3] [NAE-2473] Refresh roles on login - navigation loading bug fix --- .../lib/authentication/session/public-api.ts | 1 + .../services/session-clear.service.spec.ts | 16 ++++++++++++ .../session/services/session-clear.service.ts | 26 +++++++++++++++++++ .../session/services/session.service.ts | 6 ++++- .../double-drawer-navigation.service.ts | 15 ++++++++++- .../src/lib/navigation/service/uri.service.ts | 24 ++++++++++++++--- 6 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.spec.ts create mode 100644 projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.ts diff --git a/projects/netgrif-components-core/src/lib/authentication/session/public-api.ts b/projects/netgrif-components-core/src/lib/authentication/session/public-api.ts index f8a058d685..3e427dec3c 100644 --- a/projects/netgrif-components-core/src/lib/authentication/session/public-api.ts +++ b/projects/netgrif-components-core/src/lib/authentication/session/public-api.ts @@ -1,3 +1,4 @@ /* SERVICES */ export * from './services/session.service'; export * from './services/session-idle-timer.service' +export * from './services/session-clear.service' diff --git a/projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.spec.ts b/projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.spec.ts new file mode 100644 index 0000000000..caefdd89e4 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SessionClearService } from './session-clear.service'; + +describe('SessionClearService', () => { + let service: SessionClearService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SessionClearService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.ts b/projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.ts new file mode 100644 index 0000000000..6793a36c46 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/authentication/session/services/session-clear.service.ts @@ -0,0 +1,26 @@ +import {Injectable, OnDestroy} from '@angular/core'; +import {Observable, Subject} from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class SessionClearService implements OnDestroy { + + private readonly _sessionCleared$: Subject; + + constructor() { + this._sessionCleared$ = new Subject(); + } + + get sessionCleared(): Observable { + return this._sessionCleared$.asObservable(); + } + + clearSession() { + this._sessionCleared$.next(); + } + + ngOnDestroy(): void { + this._sessionCleared$.complete(); + } +} diff --git a/projects/netgrif-components-core/src/lib/authentication/session/services/session.service.ts b/projects/netgrif-components-core/src/lib/authentication/session/services/session.service.ts index f4728f8df4..f51d14b42a 100644 --- a/projects/netgrif-components-core/src/lib/authentication/session/services/session.service.ts +++ b/projects/netgrif-components-core/src/lib/authentication/session/services/session.service.ts @@ -8,6 +8,7 @@ import {catchError, map, take, tap} from 'rxjs/operators'; import {MessageResource} from '../../../resources/interface/message-resource'; import {LoadingEmitter} from '../../../utility/loading-emitter'; import {SessionIdleTimerService} from "./session-idle-timer.service"; +import {SessionClearService} from './session-clear.service'; @Injectable({ @@ -28,7 +29,9 @@ export class SessionService implements OnDestroy { constructor(private _config: ConfigurationService, private _log: LoggerService, private _http: HttpClient, - private idleTimerService: SessionIdleTimerService) { + private idleTimerService: SessionIdleTimerService, + private _sessionClearService: SessionClearService + ) { this._storage = this.resolveStorage(this._config.get().providers.auth['sessionStore']); this._sessionHeader = this._config.get().providers.auth.sessionBearer ? this._config.get().providers.auth.sessionBearer : SessionService.SESSION_BEARER_HEADER_DEFAULT; @@ -97,6 +100,7 @@ export class SessionService implements OnDestroy { this._verified = false; this.sessionToken = ''; this._storage.removeItem(SessionService.SESSION_TOKEN_STORAGE_KEY); + this._sessionClearService.clearSession(); } public verify(token?: string): Observable { diff --git a/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts b/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts index a8f5a6180d..3dd5330d9d 100644 --- a/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts +++ b/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts @@ -32,6 +32,7 @@ import { import { UriNodeResource } from '../../model/uri-resource'; import {MenuItemClickEvent, MenuItemLoadedEvent} from '../../model/navigation-menu-events'; import {GroupNavigationConstants} from "../../model/group-navigation-constants"; +import {SessionClearService} from '../../../authentication/session/services/session-clear.service'; import {UserService} from "../../../user/services/user.service"; /** @@ -81,6 +82,7 @@ export class DoubleDrawerNavigationService implements OnDestroy { protected hiddenCustomItemsInitialized: boolean; protected itemClicked: EventEmitter; protected itemLoaded: EventEmitter; + protected _sessionClearSubscription: Subscription; constructor(protected _uriService: UriService, protected _log: LoggerService, @@ -91,7 +93,8 @@ export class DoubleDrawerNavigationService implements OnDestroy { protected _accessService: AccessService, protected _translateService: TranslateService, protected _dynamicRoutingService: DynamicNavigationRouteProviderService, - protected _redirectService: RedirectService) { + protected _redirectService: RedirectService, + private _sessionClearService: SessionClearService) { this._leftItems$ = new BehaviorSubject([]); this._rightItems$ = new BehaviorSubject([]); this._moreItems$ = new BehaviorSubject([]); @@ -113,6 +116,16 @@ export class DoubleDrawerNavigationService implements OnDestroy { ).subscribe(node => { this.currentNode = node; }); + + this._sessionClearSubscription = this._sessionClearService.sessionCleared.subscribe({ + next: () => { + this._currentNavigationItem = null; + this._childCustomViews = {}; + this.customItemsInitialized = false; + this.hiddenCustomItemsInitialized = false; + this._currentNode = null; + } + }); } public ngOnDestroy(): void { diff --git a/projects/netgrif-components-core/src/lib/navigation/service/uri.service.ts b/projects/netgrif-components-core/src/lib/navigation/service/uri.service.ts index 60086823f9..7846f54446 100644 --- a/projects/netgrif-components-core/src/lib/navigation/service/uri.service.ts +++ b/projects/netgrif-components-core/src/lib/navigation/service/uri.service.ts @@ -1,7 +1,7 @@ import {HttpParams} from '@angular/common/http'; import {Inject, Injectable, OnDestroy, Optional} from '@angular/core'; -import {BehaviorSubject, Observable, of} from 'rxjs'; -import {map} from 'rxjs/operators'; +import {BehaviorSubject, Observable, of, Subscription} from 'rxjs'; +import {map, filter} from 'rxjs/operators'; import {CaseSearchRequestBody, PetriNetSearchRequest} from '../../filter/models/case-search-request-body'; import {SimpleFilter} from '../../filter/models/simple-filter'; import {ActiveGroupService} from '../../groups/services/active-group.service'; @@ -15,6 +15,8 @@ import {NAE_URI_NODE_CASES_PAGE_SIZE} from '../model/size-menu-injection-token'; import {UriNodeResource} from '../model/uri-resource'; import {UriResourceService} from './uri-resource.service'; import {GroupNavigationConstants} from "../model/group-navigation-constants"; +import {SessionClearService} from '../../authentication/session/services/session-clear.service'; +import {SessionService} from '../../authentication/session/services/session.service'; /** * Service for managing URIs @@ -29,11 +31,15 @@ export class UriService implements OnDestroy { private readonly _rootLoading$: LoadingEmitter; private readonly _parentLoading$: LoadingEmitter; private readonly _activeNode$: BehaviorSubject; + protected _sessionClearSubscription: Subscription; + protected _sessionSubscription: Subscription; constructor(protected _logger: LoggerService, protected _resourceService: UriResourceService, protected _caseResourceService: CaseResourceService, protected _activeGroupService: ActiveGroupService, + private _sessionClearService: SessionClearService, + private _sessionService: SessionService, @Optional() @Inject(NAE_URI_NODE_CASES_PAGE_SIZE) protected pageSize: string | number) { if (!pageSize) { this.pageSize = 20; @@ -44,13 +50,25 @@ export class UriService implements OnDestroy { this._rootLoading$ = new LoadingEmitter(); this._parentLoading$ = new LoadingEmitter(); this._activeNode$ = new BehaviorSubject(undefined); - this.loadRoot(); + this._sessionSubscription = this._sessionService.session$.pipe( + filter(token => token !== '' && this._sessionService.verified) + ).subscribe(() => { + this.loadRoot(); + }); + this._sessionClearSubscription = this._sessionClearService.sessionCleared.subscribe({ + next: () => { + this._rootNode = null; + this._activeNode$.next(undefined) + } + }); } public ngOnDestroy() { this._rootLoading$.complete(); this._parentLoading$.complete(); this._activeNode$.complete(); + this._sessionClearSubscription.unsubscribe(); + this._sessionSubscription.unsubscribe(); } public get root(): UriNodeResource { From 28f26d0ea7358a7bcac4ffcfce6ec0ea18155418 Mon Sep 17 00:00:00 2001 From: palajsamuel Date: Mon, 24 Aug 2026 12:31:56 +0200 Subject: [PATCH 2/3] [NAE-2473] Refresh roles on login - test fixes --- .../src/lib/navigation/service/uri.service.spec.ts | 4 ++++ .../import-net/abstract-import-net.component.spec.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/projects/netgrif-components-core/src/lib/navigation/service/uri.service.spec.ts b/projects/netgrif-components-core/src/lib/navigation/service/uri.service.spec.ts index 72ff8495d4..c68291eb23 100644 --- a/projects/netgrif-components-core/src/lib/navigation/service/uri.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/navigation/service/uri.service.spec.ts @@ -11,9 +11,11 @@ import {MockUriResourceService} from '../../utility/tests/mocks/mock-uri-resourc import {TestLoggingConfigurationService} from '../../utility/tests/test-logging-config'; import {UriResourceService} from './uri-resource.service'; import {UriService} from './uri.service'; +import {SessionService} from '../../authentication/session/services/session.service'; describe('UriService', () => { let service: UriService; + let sessionService: SessionService; beforeEach(() => { TestBed.configureTestingModule({ @@ -29,7 +31,9 @@ describe('UriService', () => { {provide: CaseResourceService, useClass: MockCaseResourceService}, ], }); + sessionService = TestBed.inject(SessionService); service = TestBed.inject(UriService); + sessionService.setVerifiedToken('sessionToken'); }); afterEach(() => { diff --git a/projects/netgrif-components-core/src/lib/side-menu/content-components/import-net/abstract-import-net.component.spec.ts b/projects/netgrif-components-core/src/lib/side-menu/content-components/import-net/abstract-import-net.component.spec.ts index 4656185afe..a582fb688f 100644 --- a/projects/netgrif-components-core/src/lib/side-menu/content-components/import-net/abstract-import-net.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/side-menu/content-components/import-net/abstract-import-net.component.spec.ts @@ -25,12 +25,14 @@ import {UriService} from "../../../navigation/service/uri.service"; import {AuthenticationModule} from "../../../authentication/authentication.module"; import {UriResourceService} from "../../../navigation/service/uri-resource.service"; import {MockUriResourceService} from "../../../utility/tests/mocks/mock-uri-resource.service"; +import {SessionService} from '../../../authentication/session/services/session.service'; describe('AbstractImportNetComponent', () => { let component: TestImportComponent; let fixture: ComponentFixture; let sideMenuCloseSpy: jasmine.Spy; let logSpy: jasmine.Spy; + let sessionService: SessionService; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -62,6 +64,8 @@ describe('AbstractImportNetComponent', () => { fixture.detectChanges(); sideMenuCloseSpy = spyOn(TestBed.inject(NAE_SIDE_MENU_CONTROL), 'close'); logSpy = spyOn(TestBed.inject(LoggerService), 'info'); + sessionService = TestBed.inject(SessionService); + sessionService.setVerifiedToken('sessionToken'); }); it('should create', () => { From 4ffeee95383ec2db773ad59d4ce6aeb6a40e4a62 Mon Sep 17 00:00:00 2001 From: palajsamuel Date: Fri, 28 Aug 2026 11:03:12 +0200 Subject: [PATCH 3/3] [NAE-2473] Refresh roles on login - sessionClearSubscription deletion on destroy added to double-drawer-navigation.service.ts --- .../service/double-drawer-navigation.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts b/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts index 3dd5330d9d..d5cf2926a7 100644 --- a/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts +++ b/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/service/double-drawer-navigation.service.ts @@ -130,6 +130,7 @@ export class DoubleDrawerNavigationService implements OnDestroy { public ngOnDestroy(): void { this._currentNodeSubscription?.unsubscribe(); + this._sessionClearSubscription?.unsubscribe(); this._leftLoading$.complete(); this._rightLoading$.complete(); this._nodeLoading$.complete();