Remove maxAllowedOffsetMs from TimeSyncService

This commit is contained in:
copilot-swe-agent[bot]
2026-07-03 20:25:58 +00:00
committed by GitHub
parent 41c0bdc346
commit 264fc90e67
2 changed files with 4 additions and 67 deletions
@@ -102,42 +102,6 @@ describe('TimeSyncService', () => {
await promise;
expect(service.clockOffsetMs).toBe(5000);
});
it('should not update offset when it exceeds maxAllowedOffsetMs', async () => {
const timeBeforeRequest = 1728911579000;
const timeResponseReceived = 1728911580000;
spyOn(Date, 'now').and.returnValues(timeBeforeRequest, timeResponseReceived);
service.clockOffsetMs = 1000;
const promise = firstValueFrom(service.syncClockOffset(60000));
const req = httpMock.expectOne(() => true);
// Server is 600 seconds ahead — exceeds cap of 60 seconds
req.flush(null, { headers: { date: 'Mon, 14 Oct 2024 13:22:59 GMT' } });
await promise;
expect(service.clockOffsetMs).toBe(1000);
});
it('should update offset when it is within maxAllowedOffsetMs', async () => {
const timeBeforeRequest = 1728911579000;
const timeResponseReceived = 1728911580000;
spyOn(Date, 'now').and.returnValues(timeBeforeRequest, timeResponseReceived);
// Server is 30 seconds ahead (within cap of 60 seconds)
// serverTime = 1728911610000, roundTrip = 1000ms
// adjustedServerTime = 1728911610500, offset = 30500ms
const promise = firstValueFrom(service.syncClockOffset(60000));
const req = httpMock.expectOne(() => true);
req.flush(null, { headers: { date: 'Mon, 14 Oct 2024 13:13:30 GMT' } });
await promise;
expect(service.clockOffsetMs).toBe(30500);
});
});
describe('checkTimeSync', () => {
@@ -233,25 +197,6 @@ describe('TimeSyncService', () => {
expect(service.clockOffsetMs).toBe(30500);
});
it('should apply maxAllowedOffsetMs cap during visibility re-sync', () => {
const timeBeforeRequest = 1728911579000;
const timeResponseReceived = 1728911580000;
spyOn(Date, 'now').and.returnValues(timeBeforeRequest, timeResponseReceived);
service.clockOffsetMs = 1000;
service.startPeriodicSync(60000, 60000);
Object.defineProperty(document, 'visibilityState', { value: 'visible', writable: true, configurable: true });
document.dispatchEvent(new Event('visibilitychange'));
const req = httpMock.expectOne(() => true);
// Server is 600 seconds ahead — exceeds cap
req.flush(null, { headers: { date: 'Mon, 14 Oct 2024 13:22:59 GMT' } });
expect(service.clockOffsetMs).toBe(1000);
});
});
describe('stopPeriodicSync', () => {
@@ -72,12 +72,9 @@ export class TimeSyncService {
* The HEAD request is lightweight (no response body) and targets the same origin,
* so there are no CORS issues. Nginx always includes a `Date` header in its responses.
*
* @param maxAllowedOffsetMs Optional safety cap. If the computed offset exceeds this value,
* it is ignored to prevent a compromised proxy from
* tricking the client into accepting expired tokens.
* @returns Observable that completes after the offset has been stored (or silently on error)
*/
syncClockOffset(maxAllowedOffsetMs?: number): Observable<void> {
syncClockOffset(): Observable<void> {
const appRootUrl = this.getAppRootUrl();
try {
@@ -101,10 +98,6 @@ export class TimeSyncService {
const adjustedServerTimeInMs = serverTimeInMs + roundTripTimeInMs / 2;
const newOffset = adjustedServerTimeInMs - endTime;
if (maxAllowedOffsetMs != null && Math.abs(newOffset) > maxAllowedOffsetMs) {
return;
}
this.clockOffsetMs = newOffset;
}),
catchError(() => of(void 0))
@@ -153,19 +146,18 @@ export class TimeSyncService {
* - When the document becomes visible again (e.g., Citrix session resumes after idle)
*
* @param intervalMs How often to re-sync in milliseconds (default: 5 minutes)
* @param maxAllowedOffsetMs Safety cap for the offset. If exceeded, the new offset is ignored.
*/
startPeriodicSync(intervalMs: number = DEFAULT_PERIODIC_SYNC_INTERVAL_MS, maxAllowedOffsetMs?: number): void {
startPeriodicSync(intervalMs: number = DEFAULT_PERIODIC_SYNC_INTERVAL_MS): void {
this.stopPeriodicSync();
this._ngZone.runOutsideAngular(() => {
this._periodicSyncSubscription = interval(intervalMs)
.pipe(switchMap(() => this.syncClockOffset(maxAllowedOffsetMs)))
.pipe(switchMap(() => this.syncClockOffset()))
.subscribe();
this._visibilityChangeHandler = () => {
if (typeof document !== 'undefined' && document.visibilityState === 'visible') {
this.syncClockOffset(maxAllowedOffsetMs).subscribe();
this.syncClockOffset().subscribe();
}
};