Skip to content

Commit

Permalink
fix: Handling expiring session for long running sync tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
steilerDev committed Aug 29, 2023
1 parent 0193b33 commit e044037
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 2 deletions.
3 changes: 3 additions & 0 deletions app/src/app/event/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export class CLIInterface {
})
.on(iCPSEventCloud.ACCOUNT_READY, () => {
this.print(chalk.white(`Sign in successful!`));
})
.on(iCPSEventCloud.SESSION_EXPIRED, () => {
this.print(chalk.yellowBright(`Session expired, re-authenticating...`));
});

Resources.events(this)
Expand Down
5 changes: 4 additions & 1 deletion app/src/app/event/error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,10 @@ export class ErrorHandler {
})
.on(iCPSEventCloud.ACCOUNT_READY, () => {
this.btClient.breadcrumbs.info(`ACCOUNT_READY`);
});
})
.on(iCPSEventCloud.SESSION_EXPIRED, async () => {
this.btClient.breadcrumbs.info(`SESSION_EXPIRED`)
})

Resources.events(this)
.on(iCPSEventMFA.STARTED, () => {
Expand Down
5 changes: 5 additions & 0 deletions app/src/app/event/metrics-exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const FIELDS = {
MFA_NOT_PROVIDED: `MFA_NOT_PROVIDED`,
DEVICE_TRUSTED: `DEVICE_TRUSTED`,
ACCOUNT_READY: `ACCOUNT_READY`,
SESSION_EXPIRED: `SESSION_EXPIRED`,
ICLOUD_READY: `ICLOUD_READY`,
SYNC_START: `SYNC_START`,
FETCH_N_LOAD_STARTED: `FETCH_N_LOAD_STARTED`,
Expand Down Expand Up @@ -371,6 +372,10 @@ export class MetricsExporter {
.on(iCPSEventCloud.ACCOUNT_READY, () => {
this.logDataPoint(new iCPSInfluxLineProtocolPoint()
.logStatus(FIELDS.STATUS.values.ACCOUNT_READY));
})
.on(iCPSEventCloud.SESSION_EXPIRED, () => {
this.logDataPoint(new iCPSInfluxLineProtocolPoint()
.logStatus(FIELDS.STATUS.values.SESSION_EXPIRED));
});

Resources.events(this)
Expand Down
11 changes: 10 additions & 1 deletion app/src/lib/icloud/icloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ export class iCloud {
})
.on(iCPSEventCloud.ACCOUNT_READY, async () => {
await this.getPhotosReady();
});
})
.on(iCPSEventCloud.SESSION_EXPIRED,async () => {
await this.authenticate()
})

this.ready = this.getReady();
}
Expand Down Expand Up @@ -261,6 +264,12 @@ export class iCloud {
Resources.logger(this).debug(`Account ready`);
Resources.emit(iCPSEventCloud.ACCOUNT_READY);
} catch (err) {
if ((err as any).isAxiosError && err.response.status === 421) {
Resources.logger(this).debug(`Session token expired, re-acquiring...`);
Resources.emit(iCPSEventCloud.SESSION_EXPIRED);
return;
}

Resources.emit(iCPSEventCloud.ERROR, new iCPSError(AUTH_ERR.ACCOUNT_SETUP).addCause(err));
}
}
Expand Down
4 changes: 4 additions & 0 deletions app/src/lib/resources/events-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export enum iCPSEventCloud {
* Emitted when the iCloud account information have been retrieved
*/
ACCOUNT_READY = `icloud-account_ready`,
/**
* Emitted if the session token expired
*/
SESSION_EXPIRED = `icloud-session_expired`,
/**
* Emitted when the iCloud connection has experienced an error - provides an iCPSError as argument
*/
Expand Down
28 changes: 28 additions & 0 deletions app/test/unit/icloud.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ describe(`Control structure`, () => {
expect(icloud.getPhotosReady).toHaveBeenCalled();
});

test(`SESSION_EXPIRED event triggered`, () => {
icloud.authenticate = jest.fn<typeof icloud.authenticate>()
.mockResolvedValue(true);

mockedEventManager.emit(iCPSEventCloud.SESSION_EXPIRED);

expect(icloud.authenticate).toHaveBeenCalled();
});

describe(`MFA_REQUIRED event triggered`, () => {
test(`Start MFA Server`, () => {
icloud.mfaServer.startServer = jest.fn<typeof icloud.mfaServer.startServer>();
Expand Down Expand Up @@ -636,6 +645,25 @@ describe.each([
expect(icloud.photos).toBeDefined();
});

test(`Session expired`, async () => {
mockedNetworkManager.sessionToken = Config.iCloudAuthSecrets.sessionSecret;

mockedValidator.validateSetupResponse = jest.fn<typeof mockedValidator.validateSetupResponse>(() => {
throw new iCPSError(VALIDATOR_ERR.SETUP_RESPONSE);
});

const sessionExpiredEvent = mockedEventManager.spyOnEvent(iCPSEventCloud.SESSION_EXPIRED);

mockedNetworkManager.mock
.onAny()
.reply(421);

await icloud.setupAccount();

expect(sessionExpiredEvent).toHaveBeenCalled()
expect(mockedValidator.validateSetupResponse).not.toHaveBeenCalled();
});

test(`Error - Invalid Response`, async () => {
mockedNetworkManager.sessionToken = Config.iCloudAuthSecrets.sessionSecret;

Expand Down

0 comments on commit e044037

Please sign in to comment.