From 4e7d07b204e086969a2340cb40637253119d2033 Mon Sep 17 00:00:00 2001 From: FrancescoMauto Date: Wed, 17 Jun 2026 15:18:42 +0200 Subject: [PATCH 1/4] [DURACOM-496] fix redirect for item page resolver Porting of [CST-24936] --- src/app/core/shared/authorized.operators.ts | 7 +++++-- src/app/core/shared/operators.spec.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/core/shared/authorized.operators.ts b/src/app/core/shared/authorized.operators.ts index 5ce081360f4..8f50b165ffb 100644 --- a/src/app/core/shared/authorized.operators.ts +++ b/src/app/core/shared/authorized.operators.ts @@ -46,8 +46,11 @@ export const redirectOn4xx = (router: Router, authService: AuthService) => router.navigateByUrl(getForbiddenRoute(), { skipLocationChange: true }); return false; } else { - authService.setRedirectUrl(router.url); - router.navigateByUrl('login'); + // During a resolver the navigation hasn't committed yet, so router.url still + // points to the previous URL (e.g. '/'). Use the in-flight navigation's URL + // when available, falling back to router.url for component-level calls. + const redirectUrl = router.getCurrentNavigation()?.extractedUrl?.toString() ?? router.url; + authService.setRedirectUrl(redirectUrl, 'login'); return false; } } diff --git a/src/app/core/shared/operators.spec.ts b/src/app/core/shared/operators.spec.ts index 8360b6e3d73..bd546baee9f 100644 --- a/src/app/core/shared/operators.spec.ts +++ b/src/app/core/shared/operators.spec.ts @@ -190,7 +190,7 @@ describe('Core Module - RxJS Operators', () => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); - router = jasmine.createSpyObj('router', ['navigateByUrl']); + router = jasmine.createSpyObj('router', ['navigateByUrl', 'getCurrentNavigation']); authService = jasmine.createSpyObj('authService', { isAuthenticated: of(true), setRedirectUrl: {}, From 518a9e8dbe9ab5ee3128001a17a9490becd8c27d Mon Sep 17 00:00:00 2001 From: FrancescoMauto Date: Fri, 19 Jun 2026 15:35:11 +0200 Subject: [PATCH 2/4] [DURACOM-496] edit: ported setRedirectUrl method and setRedirectUrlAndNaviogateAction from uon --- src/app/core/auth/auth.actions.ts | 18 ++++++++++++++++++ src/app/core/auth/auth.effects.ts | 8 ++++++++ src/app/core/auth/auth.reducer.ts | 6 ++++++ src/app/core/auth/auth.service.ts | 11 ++++++++--- src/app/core/shared/operators.spec.ts | 2 -- 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/app/core/auth/auth.actions.ts b/src/app/core/auth/auth.actions.ts index 4610d718374..74f4a1012cc 100644 --- a/src/app/core/auth/auth.actions.ts +++ b/src/app/core/auth/auth.actions.ts @@ -34,6 +34,7 @@ export const AuthActionTypes = { LOG_OUT_ERROR: type('dspace/auth/LOG_OUT_ERROR'), LOG_OUT_SUCCESS: type('dspace/auth/LOG_OUT_SUCCESS'), SET_REDIRECT_URL: type('dspace/auth/SET_REDIRECT_URL'), + SET_REDIRECT_URL_AND_NAVIGATE: type('dspace/auth/SET_REDIRECT_URL_AND_NAVIGATE'), RETRIEVE_AUTHENTICATED_EPERSON: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON'), RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS'), RETRIEVE_AUTHENTICATED_EPERSON_ERROR: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON_ERROR'), @@ -361,6 +362,23 @@ export class SetRedirectUrlAction implements Action { } } +/** + * Change the redirect url. + * @class SetRedirectUrlAction + * @implements {Action} + */ +export class SetRedirectUrlAndNavigateAction implements Action { + public type: string = AuthActionTypes.SET_REDIRECT_URL_AND_NAVIGATE; + payload: { + redirectUrl: string; + navigateUrl: string; + }; + + constructor(redirectUrl: string, navigateUrl: string) { + this.payload = { redirectUrl, navigateUrl }; + } +} + /** * Start loading for a hard redirect * @class StartHardRedirectLoadingAction diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index 7c2a494cff5..11d61203cdf 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -70,6 +70,7 @@ import { RetrieveAuthMethodsErrorAction, RetrieveAuthMethodsSuccessAction, RetrieveTokenAction, + SetRedirectUrlAndNavigateAction, SetUserAsIdleAction, } from './auth.actions'; // import services @@ -160,6 +161,13 @@ export class AuthEffects { }), ), { dispatch: false }); + public redirectAndNavigate$: Observable = createEffect(() => this.actions$ + .pipe(ofType(AuthActionTypes.SET_REDIRECT_URL_AND_NAVIGATE), + tap((action: SetRedirectUrlAndNavigateAction) => this.router.navigate([decodeURIComponent(action.payload.navigateUrl)])), + ), + { dispatch: false }, + ); + // It means "reacts to this action but don't send another" public authenticatedError$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.AUTHENTICATED_ERROR), diff --git a/src/app/core/auth/auth.reducer.ts b/src/app/core/auth/auth.reducer.ts index 25dda850326..73a2583ffab 100644 --- a/src/app/core/auth/auth.reducer.ts +++ b/src/app/core/auth/auth.reducer.ts @@ -14,6 +14,7 @@ import { RetrieveAuthMethodsSuccessAction, SetAuthCookieStatus, SetRedirectUrlAction, + SetRedirectUrlAndNavigateAction, } from './auth.actions'; import { AuthMethod } from './models/auth.method'; import { AuthMethodType } from './models/auth.method-type'; @@ -245,6 +246,11 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut redirectUrl: (action as SetRedirectUrlAction).payload, }); + case AuthActionTypes.SET_REDIRECT_URL_AND_NAVIGATE: + return Object.assign({}, state, { + redirectUrl: (action as SetRedirectUrlAndNavigateAction).payload.redirectUrl, + }); + case AuthActionTypes.REDIRECT_AFTER_LOGIN_SUCCESS: return Object.assign({}, state, { loading: true, diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index a762c857626..f45726ca597 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -69,6 +69,7 @@ import { ResetAuthenticationMessagesAction, SetAuthCookieStatus, SetRedirectUrlAction, + SetRedirectUrlAndNavigateAction, SetUserAsIdleAction, UnsetUserAsIdleAction, } from './auth.actions'; @@ -579,15 +580,19 @@ export class AuthService { /** * Set redirect url */ - setRedirectUrl(url: string) { + setRedirectUrl(redirectUrl: string, navigateUrl?: string) { // Add 1 hour to the current date const expireDate = Date.now() + (1000 * 60 * 60); // Set the cookie expire date const expires = new Date(expireDate); const options: Cookies.CookieAttributes = { expires: expires }; - this.storage.set(REDIRECT_COOKIE, url, options); - this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(url) ? url : '')); + this.storage.set(REDIRECT_COOKIE, redirectUrl, options); + if (hasValue(navigateUrl)) { + this.store.dispatch(new SetRedirectUrlAndNavigateAction(isNotUndefined(redirectUrl) ? redirectUrl : '', navigateUrl)); + } else { + this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(redirectUrl) ? redirectUrl : '')); + } } /** diff --git a/src/app/core/shared/operators.spec.ts b/src/app/core/shared/operators.spec.ts index bd546baee9f..4476ba98259 100644 --- a/src/app/core/shared/operators.spec.ts +++ b/src/app/core/shared/operators.spec.ts @@ -277,7 +277,6 @@ describe('Core Module - RxJS Operators', () => { expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values); flush(); expect(authService.setRedirectUrl).toHaveBeenCalled(); - expect(router.navigateByUrl).toHaveBeenCalledWith('login'); }); }); @@ -291,7 +290,6 @@ describe('Core Module - RxJS Operators', () => { expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values); flush(); expect(authService.setRedirectUrl).toHaveBeenCalled(); - expect(router.navigateByUrl).toHaveBeenCalledWith('login'); }); }); }); From cd3adf26e933f7bde92d9f2eeecafe546c59cd9c Mon Sep 17 00:00:00 2001 From: FrancescoMauto Date: Fri, 19 Jun 2026 15:48:26 +0200 Subject: [PATCH 3/4] [DURACOM-496] fix: linting --- src/app/core/auth/auth.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index f45726ca597..cefda5c085c 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -580,7 +580,7 @@ export class AuthService { /** * Set redirect url */ - setRedirectUrl(redirectUrl: string, navigateUrl?: string) { + setRedirectUrl(redirectUrl: string, navigateUrl?: string) { // Add 1 hour to the current date const expireDate = Date.now() + (1000 * 60 * 60); From eb6b38ae639210ef14efa318d1d32bca959526d3 Mon Sep 17 00:00:00 2001 From: FrancescoMauto Date: Fri, 19 Jun 2026 17:44:22 +0200 Subject: [PATCH 4/4] [DURACOM-496] fix: missing import and constructor init --- src/app/core/auth/auth.effects.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index 11d61203cdf..ec14f2996ff 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -4,6 +4,7 @@ import { NgZone, Type, } from '@angular/core'; +import { Router } from '@angular/router'; import { APP_CONFIG, AppConfig, @@ -340,6 +341,7 @@ export class AuthEffects { private zone: NgZone, private authorizationsService: AuthorizationDataService, private authService: AuthService, - private store: Store) { + private store: Store, + private router: Router) { } }