From b86ebed604e4baa53a04be57591bec463a573c5c Mon Sep 17 00:00:00 2001 From: Jorge Rojas Date: Mon, 9 Feb 2026 22:57:55 -0600 Subject: [PATCH 1/2] 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 2/2] 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';