From b86ebed604e4baa53a04be57591bec463a573c5c Mon Sep 17 00:00:00 2001 From: Jorge Rojas Date: Mon, 9 Feb 2026 22:57:55 -0600 Subject: [PATCH 01/13] Fix end-user agreement checkbox reset and navigation hang --- .../end-user-agreement-current-user.guard.spec.ts | 4 ++-- .../end-user-agreement-current-user.guard.ts | 11 +++++++++-- .../end-user-agreement/end-user-agreement.service.ts | 10 +++++++++- .../end-user-agreement.component.ts | 4 +++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index 01835a62ef7..a291c86e3b0 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -22,7 +22,7 @@ describe('endUserAgreementGuard', () => { beforeEach(() => { endUserAgreementService = jasmine.createSpyObj('endUserAgreementService', { - hasCurrentUserAcceptedAgreement: of(true), + hasCurrentUserOrCookieAcceptedAgreement: of(true), }); router = jasmine.createSpyObj('router', { @@ -61,7 +61,7 @@ describe('endUserAgreementGuard', () => { describe('when the user hasn\'t accepted the agreement', () => { beforeEach(() => { - (endUserAgreementService.hasCurrentUserAcceptedAgreement as jasmine.Spy).and.returnValue(of(false)); + (endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement as jasmine.Spy).and.returnValue(of(false)); }); it('should return a UrlTree', (done) => { diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index e99ab32f27c..7595d564a9e 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -1,7 +1,10 @@ import { inject } from '@angular/core'; import { CanActivateFn } from '@angular/router'; import { APP_CONFIG } from '@dspace/config/app-config.interface'; -import { of } from 'rxjs'; +import { + of, +} from 'rxjs'; +import { take } from 'rxjs/operators'; import { endUserAgreementGuard } from './end-user-agreement.guard'; import { EndUserAgreementService } from './end-user-agreement.service'; @@ -20,6 +23,10 @@ export const endUserAgreementCurrentUserGuard: CanActivateFn = return of(true); } - return endUserAgreementService.hasCurrentUserAcceptedAgreement(true); + // Use hasCurrentUserOrCookieAcceptedAgreement to leverage synchronous cookie check + // This prevents guard hangs after PATCH operations when store cache may be stale + return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(true).pipe( + take(1), + ); }, ); diff --git a/src/app/core/end-user-agreement/end-user-agreement.service.ts b/src/app/core/end-user-agreement/end-user-agreement.service.ts index a7f92b244f8..573d3c1481c 100644 --- a/src/app/core/end-user-agreement/end-user-agreement.service.ts +++ b/src/app/core/end-user-agreement/end-user-agreement.service.ts @@ -52,6 +52,7 @@ export class EndUserAgreementService { switchMap((authenticated) => { if (authenticated) { return this.authService.getAuthenticatedUserFromStore().pipe( + take(1), map((user) => hasValue(user) && user.hasMetadata(END_USER_AGREEMENT_METADATA_FIELD) && user.firstMetadata(END_USER_AGREEMENT_METADATA_FIELD).value === 'true'), ); } else { @@ -84,7 +85,14 @@ export class EndUserAgreementService { return this.ePersonService.patch(user, [operation]); }), getFirstCompletedRemoteData(), - map((response) => response.hasSucceeded), + map((response) => { + const success = response.hasSucceeded; + // Set cookie as synchronous fallback to prevent guard hangs after PATCH + if (success) { + this.setCookieAccepted(accepted); + } + return success; + }), ); } else { this.setCookieAccepted(accepted); diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.ts b/src/app/info/end-user-agreement/end-user-agreement.component.ts index 3e6585a8667..06ac15aca4e 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.ts @@ -69,7 +69,9 @@ export class EndUserAgreementComponent implements OnInit { * Initialize the "accepted" property of this component by checking if the current user has accepted it before */ initAccepted() { - this.endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false).subscribe((accepted) => { + this.endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false).pipe( + take(1), + ).subscribe((accepted) => { this.accepted = accepted; }); } From 191bb3a05e4cc98ef9ceeb6a913f23fd21ac948c Mon Sep 17 00:00:00 2001 From: Jorge Rojas Date: Mon, 9 Feb 2026 23:17:18 -0600 Subject: [PATCH 02/13] Fix end-user agreement checkbox reset and navigation hang test --- .../end-user-agreement-current-user.guard.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index 7595d564a9e..fffe9a5baf3 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -1,9 +1,7 @@ import { inject } from '@angular/core'; import { CanActivateFn } from '@angular/router'; import { APP_CONFIG } from '@dspace/config/app-config.interface'; -import { - of, -} from 'rxjs'; +import { of } from 'rxjs'; import { take } from 'rxjs/operators'; import { endUserAgreementGuard } from './end-user-agreement.guard'; From ccec64ff4cd0920318846d68b593772f8b2bffdb Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 12:21:36 -0600 Subject: [PATCH 03/13] Fix 5085: prevent cookie bypass and refresh authenticated user after acceptance --- ...-user-agreement-current-user.guard.spec.ts | 6 ++-- .../end-user-agreement-current-user.guard.ts | 11 ++++++- .../end-user-agreement.service.ts | 29 ++++++++++++------- .../end-user-agreement.component.ts | 3 ++ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index a291c86e3b0..9bf8e6dd43d 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -14,6 +14,7 @@ import { import { EndUserAgreementService } from './end-user-agreement.service'; import { endUserAgreementCurrentUserGuard } from './end-user-agreement-current-user.guard'; +import { AuthService } from '../auth/auth.service'; describe('endUserAgreementGuard', () => { let endUserAgreementService: EndUserAgreementService; @@ -22,7 +23,7 @@ describe('endUserAgreementGuard', () => { beforeEach(() => { endUserAgreementService = jasmine.createSpyObj('endUserAgreementService', { - hasCurrentUserOrCookieAcceptedAgreement: of(true), + hasCurrentUserAcceptedAgreement: of(true), }); router = jasmine.createSpyObj('router', { @@ -40,6 +41,7 @@ describe('endUserAgreementGuard', () => { { provide: Router, useValue: router }, { provide: EndUserAgreementService, useValue: endUserAgreementService }, { provide: APP_CONFIG, useValue: environment }, + { provide: AuthService, useValue: jasmine.createSpyObj('AuthService', { isAuthenticated: of(true) }) }, ], }); @@ -61,7 +63,7 @@ describe('endUserAgreementGuard', () => { describe('when the user hasn\'t accepted the agreement', () => { beforeEach(() => { - (endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement as jasmine.Spy).and.returnValue(of(false)); + (endUserAgreementService.hasCurrentUserAcceptedAgreement as jasmine.Spy).and.returnValue(of(false)); }); it('should return a UrlTree', (done) => { diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index fffe9a5baf3..7d2c1c0bb0e 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -3,6 +3,8 @@ import { CanActivateFn } from '@angular/router'; import { APP_CONFIG } from '@dspace/config/app-config.interface'; import { of } from 'rxjs'; import { take } from 'rxjs/operators'; +import { switchMap } from 'rxjs/operators'; +import { AuthService } from '../auth/auth.service'; import { endUserAgreementGuard } from './end-user-agreement.guard'; import { EndUserAgreementService } from './end-user-agreement.service'; @@ -23,7 +25,14 @@ export const endUserAgreementCurrentUserGuard: CanActivateFn = // Use hasCurrentUserOrCookieAcceptedAgreement to leverage synchronous cookie check // This prevents guard hangs after PATCH operations when store cache may be stale - return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(true).pipe( + return inject(AuthService).isAuthenticated().pipe( + switchMap((authenticated) => { + if (!authenticated) { + return of(true); + } + + return endUserAgreementService.hasCurrentUserAcceptedAgreement(false); + }), take(1), ); }, diff --git a/src/app/core/end-user-agreement/end-user-agreement.service.ts b/src/app/core/end-user-agreement/end-user-agreement.service.ts index 573d3c1481c..fdf274aa150 100644 --- a/src/app/core/end-user-agreement/end-user-agreement.service.ts +++ b/src/app/core/end-user-agreement/end-user-agreement.service.ts @@ -35,11 +35,16 @@ export class EndUserAgreementService { * currently not authenticated (anonymous) */ hasCurrentUserOrCookieAcceptedAgreement(acceptedWhenAnonymous: boolean): Observable { - if (this.isCookieAccepted()) { - return of(true); - } else { - return this.hasCurrentUserAcceptedAgreement(acceptedWhenAnonymous); - } + return this.authService.isAuthenticated().pipe( + switchMap((authenticated) => { + if (authenticated) { + return this.hasCurrentUserAcceptedAgreement(acceptedWhenAnonymous); + } else { + return of(this.isCookieAccepted()); + } + }), + take(1), + ); } /** @@ -53,12 +58,17 @@ export class EndUserAgreementService { if (authenticated) { return this.authService.getAuthenticatedUserFromStore().pipe( take(1), - map((user) => hasValue(user) && user.hasMetadata(END_USER_AGREEMENT_METADATA_FIELD) && user.firstMetadata(END_USER_AGREEMENT_METADATA_FIELD).value === 'true'), + map((user) => + hasValue(user) && + user.hasMetadata(END_USER_AGREEMENT_METADATA_FIELD) && + user.firstMetadata(END_USER_AGREEMENT_METADATA_FIELD).value === 'true' + ), ); } else { return of(acceptedWhenAnonymous); } }), + take(1), ); } @@ -87,10 +97,9 @@ export class EndUserAgreementService { getFirstCompletedRemoteData(), map((response) => { const success = response.hasSucceeded; - // Set cookie as synchronous fallback to prevent guard hangs after PATCH - if (success) { - this.setCookieAccepted(accepted); - } + if (success) { + this.setCookieAccepted(true); + } return success; }), ); diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.ts b/src/app/info/end-user-agreement/end-user-agreement.component.ts index 06ac15aca4e..cb6d2de6fe6 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.ts @@ -95,6 +95,8 @@ export class EndUserAgreementComponent implements OnInit { ).subscribe((redirectUrl) => { if (isNotEmpty(redirectUrl)) { this.router.navigateByUrl(decodeURIComponent(redirectUrl)); + } else { + this.router.navigate(['/home']); } }); } @@ -107,6 +109,7 @@ export class EndUserAgreementComponent implements OnInit { cancel() { this.authService.isAuthenticated().pipe(take(1)).subscribe((authenticated) => { if (authenticated) { + this.endUserAgreementService.removeCookieAccepted(); this.store.dispatch(new LogOutAction()); } else { this.router.navigate(['home']); From 3822b8db01c20dcd29df57f427b6a0cda72757fb Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 19:54:57 -0600 Subject: [PATCH 04/13] Fix 5085: prevent cookie bypass and refresh authenticated user after acceptance --- .../end-user-agreement-current-user.guard.spec.ts | 4 ++-- .../end-user-agreement-current-user.guard.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index 9bf8e6dd43d..566c7f8c525 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -12,9 +12,9 @@ import { of, } from 'rxjs'; -import { EndUserAgreementService } from './end-user-agreement.service'; -import { endUserAgreementCurrentUserGuard } from './end-user-agreement-current-user.guard'; import { AuthService } from '../auth/auth.service'; +import { endUserAgreementCurrentUserGuard } from './end-user-agreement-current-user.guard'; +import { EndUserAgreementService } from './end-user-agreement.service'; describe('endUserAgreementGuard', () => { let endUserAgreementService: EndUserAgreementService; diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index 7d2c1c0bb0e..2996ebb2aea 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -2,8 +2,7 @@ import { inject } from '@angular/core'; import { CanActivateFn } from '@angular/router'; import { APP_CONFIG } from '@dspace/config/app-config.interface'; import { of } from 'rxjs'; -import { take } from 'rxjs/operators'; -import { switchMap } from 'rxjs/operators'; +import { switchMap, take } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { endUserAgreementGuard } from './end-user-agreement.guard'; From bb877cbd84fa864c9aadd0207ef1280f993a1dae Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 20:25:27 -0600 Subject: [PATCH 05/13] Fix 5085: prevent cookie bypass --- .../end-user-agreement-current-user.guard.spec.ts | 2 +- .../end-user-agreement-current-user.guard.ts | 7 +++++-- .../core/end-user-agreement/end-user-agreement.service.ts | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index 566c7f8c525..799d4435a76 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -13,8 +13,8 @@ import { } from 'rxjs'; import { AuthService } from '../auth/auth.service'; -import { endUserAgreementCurrentUserGuard } from './end-user-agreement-current-user.guard'; import { EndUserAgreementService } from './end-user-agreement.service'; +import { endUserAgreementCurrentUserGuard } from './end-user-agreement-current-user.guard'; describe('endUserAgreementGuard', () => { let endUserAgreementService: EndUserAgreementService; diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index 2996ebb2aea..c7d2bcf5634 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -2,9 +2,12 @@ import { inject } from '@angular/core'; import { CanActivateFn } from '@angular/router'; import { APP_CONFIG } from '@dspace/config/app-config.interface'; import { of } from 'rxjs'; -import { switchMap, take } from 'rxjs/operators'; -import { AuthService } from '../auth/auth.service'; +import { + switchMap, + take, +} from 'rxjs/operators'; +import { AuthService } from '../auth/auth.service'; import { endUserAgreementGuard } from './end-user-agreement.guard'; import { EndUserAgreementService } from './end-user-agreement.service'; diff --git a/src/app/core/end-user-agreement/end-user-agreement.service.ts b/src/app/core/end-user-agreement/end-user-agreement.service.ts index fdf274aa150..9311212abfc 100644 --- a/src/app/core/end-user-agreement/end-user-agreement.service.ts +++ b/src/app/core/end-user-agreement/end-user-agreement.service.ts @@ -61,7 +61,7 @@ export class EndUserAgreementService { map((user) => hasValue(user) && user.hasMetadata(END_USER_AGREEMENT_METADATA_FIELD) && - user.firstMetadata(END_USER_AGREEMENT_METADATA_FIELD).value === 'true' + user.firstMetadata(END_USER_AGREEMENT_METADATA_FIELD).value === 'true', ), ); } else { @@ -97,9 +97,9 @@ export class EndUserAgreementService { getFirstCompletedRemoteData(), map((response) => { const success = response.hasSucceeded; - if (success) { - this.setCookieAccepted(true); - } + if (success) { + this.setCookieAccepted(true); + } return success; }), ); From 7830e46ba6eb79db255fa732c8cef0e6b4a18eda Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 20:55:47 -0600 Subject: [PATCH 06/13] Fix 5085: resolve the test error and the guard problem --- .../end-user-agreement/end-user-agreement-current-user.guard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index c7d2bcf5634..40e78419aec 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -33,7 +33,7 @@ export const endUserAgreementCurrentUserGuard: CanActivateFn = return of(true); } - return endUserAgreementService.hasCurrentUserAcceptedAgreement(false); + return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false); }), take(1), ); From 2c135822a191ff57073c3c03af7e60e3b0547272 Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 22:35:58 -0600 Subject: [PATCH 07/13] Fix 5085: resolve the test error and the guard problem --- ...nd-user-agreement-current-user.guard.spec.ts | 17 ++++++++++++++--- .../end-user-agreement.component.spec.ts | 10 ++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index 799d4435a76..ecc7605ed6a 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -22,9 +22,20 @@ describe('endUserAgreementGuard', () => { let environment: AppConfig; beforeEach(() => { - endUserAgreementService = jasmine.createSpyObj('endUserAgreementService', { - hasCurrentUserAcceptedAgreement: of(true), - }); + endUserAgreementService = jasmine.createSpyObj('EndUserAgreementService', [ + 'hasCurrentUserAcceptedAgreement', + 'hasCurrentUserOrCookieAcceptedAgreement', + 'removeCookieAccepted', + 'setUserAcceptedAgreement', + 'isCookieAccepted', + 'setCookieAccepted' + ]); + + (endUserAgreementService.hasCurrentUserAcceptedAgreement as jasmine.Spy).and.returnValue(of(true)); + (endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement as jasmine.Spy).and.returnValue(of(true)); + (endUserAgreementService.setUserAcceptedAgreement as jasmine.Spy).and.returnValue(of(true)); + (endUserAgreementService.removeCookieAccepted as jasmine.Spy).and.callFake(() => {}); + (endUserAgreementService.setCookieAccepted as jasmine.Spy).and.callFake(() => {}); router = jasmine.createSpyObj('router', { navigateByUrl: {}, diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts index 421789f1b1e..ab4da6c6334 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts @@ -41,12 +41,14 @@ describe('EndUserAgreementComponent', () => { endUserAgreementService = jasmine.createSpyObj('endUserAgreementService', { hasCurrentUserOrCookieAcceptedAgreement: of(false), setUserAcceptedAgreement: of(true), + removeCookieAccepted: jasmine.createSpy('removeCookieAccepted') }); notificationsService = jasmine.createSpyObj('notificationsService', ['success', 'error']); - authService = jasmine.createSpyObj('authService', { - isAuthenticated: of(true), - }); - store = jasmine.createSpyObj('store', ['dispatch']); + authService = jasmine.createSpyObj('AuthService', ['isAuthenticated']); + (authService.isAuthenticated as jasmine.Spy).and.returnValue(of(true)); + + store = jasmine.createSpyObj('Store', ['dispatch']); + (store.dispatch as jasmine.Spy).and.callFake(() => {}); router = jasmine.createSpyObj('router', ['navigate', 'navigateByUrl']); route = Object.assign(new ActivatedRouteStub(), { queryParams: of({ From d3fe1f42f0ddb56d3c4a67d7af2b87de43950766 Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 22:47:19 -0600 Subject: [PATCH 08/13] Fix 5085: resolve the test error and the guard problem --- .../end-user-agreement-current-user.guard.spec.ts | 2 +- .../end-user-agreement/end-user-agreement.component.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index ecc7605ed6a..c71c6669c76 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -28,7 +28,7 @@ describe('endUserAgreementGuard', () => { 'removeCookieAccepted', 'setUserAcceptedAgreement', 'isCookieAccepted', - 'setCookieAccepted' + 'setCookieAccepted', ]); (endUserAgreementService.hasCurrentUserAcceptedAgreement as jasmine.Spy).and.returnValue(of(true)); diff --git a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts index ab4da6c6334..0517a0ec509 100644 --- a/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts +++ b/src/app/info/end-user-agreement/end-user-agreement.component.spec.ts @@ -41,7 +41,7 @@ describe('EndUserAgreementComponent', () => { endUserAgreementService = jasmine.createSpyObj('endUserAgreementService', { hasCurrentUserOrCookieAcceptedAgreement: of(false), setUserAcceptedAgreement: of(true), - removeCookieAccepted: jasmine.createSpy('removeCookieAccepted') + removeCookieAccepted: jasmine.createSpy('removeCookieAccepted'), }); notificationsService = jasmine.createSpyObj('notificationsService', ['success', 'error']); authService = jasmine.createSpyObj('AuthService', ['isAuthenticated']); From 6ddfde3fec99eba398e9ab9c34ba2e60dc148b8b Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 23:19:53 -0600 Subject: [PATCH 09/13] Fix 5085: resolve the test error and the guard problem --- .../end-user-agreement-current-user.guard.ts | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index 40e78419aec..69e987149a2 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -1,41 +1,47 @@ import { inject } from '@angular/core'; -import { CanActivateFn } from '@angular/router'; +import { + CanActivateFn, + Router, + UrlTree, +} from '@angular/router'; import { APP_CONFIG } from '@dspace/config/app-config.interface'; import { of } from 'rxjs'; import { + map, switchMap, take, } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; -import { endUserAgreementGuard } from './end-user-agreement.guard'; import { EndUserAgreementService } from './end-user-agreement.service'; +export const endUserAgreementCurrentUserGuard: CanActivateFn = (route, state) => { + const endUserAgreementService = inject(EndUserAgreementService); + const router = inject(Router); + const config = inject(APP_CONFIG); -/** - * Guard for preventing unauthorized access to certain pages - * requiring the end user agreement to have been accepted by the current user + if (!config.info.enableEndUserAgreement) { + return of(true); + } - */ -export const endUserAgreementCurrentUserGuard: CanActivateFn = - endUserAgreementGuard( - () => { - const endUserAgreementService = inject(EndUserAgreementService); - if (!inject(APP_CONFIG).info.enableEndUserAgreement) { + return inject(AuthService).isAuthenticated().pipe( + switchMap(authenticated => { + if (!authenticated) { return of(true); } - // Use hasCurrentUserOrCookieAcceptedAgreement to leverage synchronous cookie check - // This prevents guard hangs after PATCH operations when store cache may be stale - return inject(AuthService).isAuthenticated().pipe( - switchMap((authenticated) => { - if (!authenticated) { - return of(true); + return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false).pipe( + map(accepted => { + if (accepted) { + return true; } - return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false); + return router.createUrlTree(['/end-user-agreement'], { + queryParams: { redirect: state.url }, + }) as UrlTree; }), - take(1), ); - }, + }), + take(1), ); +}; From 4838acbf9b57a5b7aa7ff49dab52461a0dda4e62 Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Tue, 24 Mar 2026 23:43:28 -0600 Subject: [PATCH 10/13] Fix 5085: resolve the test error and the guard problem in spec --- .../end-user-agreement-current-user.guard.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index c71c6669c76..9f152b71280 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -74,7 +74,7 @@ describe('endUserAgreementGuard', () => { describe('when the user hasn\'t accepted the agreement', () => { beforeEach(() => { - (endUserAgreementService.hasCurrentUserAcceptedAgreement as jasmine.Spy).and.returnValue(of(false)); + (endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement as jasmine.Spy).and.returnValue(of(false)); }); it('should return a UrlTree', (done) => { From d085064d178606541e8a5ccae4a38643c32432c5 Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Fri, 27 Mar 2026 18:30:30 -0600 Subject: [PATCH 11/13] chore: rerun CI From f183103e8240d095c53b8de179bf323cb8ac2f1e Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Fri, 27 Mar 2026 23:17:29 -0600 Subject: [PATCH 12/13] fix 5085 : resolve the test error and the guard problem in ts --- .../end-user-agreement-current-user.guard.ts | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index 69e987149a2..8dd994ae21f 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -8,11 +8,9 @@ import { APP_CONFIG } from '@dspace/config/app-config.interface'; import { of } from 'rxjs'; import { map, - switchMap, take, } from 'rxjs/operators'; -import { AuthService } from '../auth/auth.service'; import { EndUserAgreementService } from './end-user-agreement.service'; export const endUserAgreementCurrentUserGuard: CanActivateFn = (route, state) => { @@ -24,23 +22,14 @@ export const endUserAgreementCurrentUserGuard: CanActivateFn = (route, state) => return of(true); } - return inject(AuthService).isAuthenticated().pipe( - switchMap(authenticated => { - if (!authenticated) { - return of(true); + return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false).pipe( + map(accepted => { + if (accepted) { + return true; } - - return endUserAgreementService.hasCurrentUserOrCookieAcceptedAgreement(false).pipe( - map(accepted => { - if (accepted) { - return true; - } - - return router.createUrlTree(['/end-user-agreement'], { - queryParams: { redirect: state.url }, - }) as UrlTree; - }), - ); + return router.createUrlTree(['/end-user-agreement'], { + queryParams: { redirect: state.url }, + }) as UrlTree; }), take(1), ); From 603b50f714a5379987dfdf5205dc6c7f0c57378d Mon Sep 17 00:00:00 2001 From: guillermo2519 Date: Fri, 27 Mar 2026 23:40:05 -0600 Subject: [PATCH 13/13] chore: rerun CI