Skip to content

Commit

Permalink
bye bye
Browse files Browse the repository at this point in the history
  • Loading branch information
ncovercash committed Oct 10, 2024
1 parent 50c1291 commit 46b503f
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 36 deletions.
11 changes: 6 additions & 5 deletions src/components/Root/FFetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
*/

import ms from 'ms';
import { okapi as okapiConfig, config } from 'stripes-config';
import { okapi as okapiConfig } from 'stripes-config';
import {
setRtrTimeout,
setRtrFlsTimeout,
Expand Down Expand Up @@ -77,9 +77,10 @@ const OKAPI_FETCH_OPTIONS = {
};

export class FFetch {
constructor({ logger, store }) {
constructor({ logger, store, rtrConfig }) {
this.logger = logger;
this.store = store;
this.rtrConfig = rtrConfig;
}

/**
Expand Down Expand Up @@ -129,11 +130,11 @@ export class FFetch {
scheduleRotation = (rotationP) => {
rotationP.then((rotationInterval) => {
// AT refresh interval: a large fraction of the actual AT TTL
const atInterval = (rotationInterval.accessTokenExpiration - Date.now()) * config.rtr.rotationIntervalFraction;
const atInterval = (rotationInterval.accessTokenExpiration - Date.now()) * this.rtrConfig.rotationIntervalFraction;

// RT timeout interval (session will end) and warning interval (warning that session will end)
const rtTimeoutInterval = (rotationInterval.refreshTokenExpiration - Date.now());
const rtWarningInterval = (rotationInterval.refreshTokenExpiration - Date.now()) - ms(config.rtr.fixedLengthSessionWarningTTL);
const rtWarningInterval = (rotationInterval.refreshTokenExpiration - Date.now()) - ms(this.rtrConfig.fixedLengthSessionWarningTTL);

// schedule AT rotation IFF the AT will expire before the RT. this avoids
// refresh-thrashing near the end of the FLS with progressively shorter
Expand All @@ -149,7 +150,7 @@ export class FFetch {
}

// schedule FLS end-of-session warning
this.logger.log('rtr-fls', `end-of-session warning at ${new Date(rotationInterval.refreshTokenExpiration - ms(config.rtr.fixedLengthSessionWarningTTL))}`);
this.logger.log('rtr-fls', `end-of-session warning at ${new Date(rotationInterval.refreshTokenExpiration - ms(this.rtrConfig.fixedLengthSessionWarningTTL))}`);
this.store.dispatch(setRtrFlsWarningTimeout(setTimeout(() => {
this.logger.log('rtr-fls', 'emitting RTR_FLS_WARNING_EVENT');
window.dispatchEvent(new Event(RTR_FLS_WARNING_EVENT));
Expand Down
33 changes: 18 additions & 15 deletions src/components/Root/FFetch.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

import ms from 'ms';
import { waitFor } from '@testing-library/react';
import { okapi, config } from 'stripes-config';
import { okapi } from 'stripes-config';

import { getTokenExpiry } from '../../loginServices';
import { FFetch } from './FFetch';
import { RTRError, UnexpectedResourceError } from './Errors';
import {
RTR_AT_EXPIRY_IF_UNKNOWN,
RTR_AT_TTL_FRACTION,
RTR_FORCE_REFRESH_EVENT,
RTR_FLS_WARNING_TTL,
RTR_TIME_MARGIN_IN_MS,
Expand All @@ -28,12 +29,6 @@ jest.mock('stripes-config', () => ({
okapi: {
url: 'okapiUrl',
tenant: 'okapiTenant'
},
config: {
rtr: {
rotationIntervalFraction: 0.5,
fixedLengthSessionWarningTTL: '1m',
}
}
}),
{ virtual: true });
Expand Down Expand Up @@ -215,7 +210,9 @@ describe('FFetch class', () => {
store: {
dispatch: jest.fn(),
},

rtrConfig: {
fixedLengthSessionWarningTTL: '1m',
},
});
testFfetch.replaceFetch();
testFfetch.replaceXMLHttpRequest();
Expand All @@ -229,7 +226,7 @@ describe('FFetch class', () => {
await setTimeout(Promise.resolve(), 2000);

// AT rotation
expect(st).toHaveBeenCalledWith(expect.any(Function), (accessTokenExpiration - whatTimeIsItMrFox) * config.rtr.rotationIntervalFraction);
expect(st).toHaveBeenCalledWith(expect.any(Function), (accessTokenExpiration - whatTimeIsItMrFox) * RTR_AT_TTL_FRACTION);

// FLS warning
expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox) - ms(RTR_FLS_WARNING_TTL));
Expand Down Expand Up @@ -269,7 +266,9 @@ describe('FFetch class', () => {
store: {
dispatch: jest.fn(),
},

rtrConfig: {
fixedLengthSessionWarningTTL: '1m',
},
});
testFfetch.replaceFetch();
testFfetch.replaceXMLHttpRequest();
Expand All @@ -281,7 +280,7 @@ describe('FFetch class', () => {
// gross, but on the other, since we're deliberately pushing rotation
// into a separate thread, I'm note sure of a better way to handle this.
await setTimeout(Promise.resolve(), 2000);
expect(st).toHaveBeenCalledWith(expect.any(Function), (atExpires - whatTimeIsItMrFox) * config.rtr.rotationIntervalFraction);
expect(st).toHaveBeenCalledWith(expect.any(Function), (atExpires - whatTimeIsItMrFox) * RTR_AT_TTL_FRACTION);
});

it('handles missing RTR data', async () => {
Expand All @@ -305,7 +304,9 @@ describe('FFetch class', () => {
store: {
dispatch: jest.fn(),
},

rtrConfig: {
fixedLengthSessionWarningTTL: '1m',
},
});
testFfetch.replaceFetch();
testFfetch.replaceXMLHttpRequest();
Expand All @@ -318,7 +319,7 @@ describe('FFetch class', () => {
// into a separate thread, I'm not sure of a better way to handle this.
await setTimeout(Promise.resolve(), 2000);

expect(st).toHaveBeenCalledWith(expect.any(Function), ms(RTR_AT_EXPIRY_IF_UNKNOWN) * config.rtr.rotationIntervalFraction);
expect(st).toHaveBeenCalledWith(expect.any(Function), ms(RTR_AT_EXPIRY_IF_UNKNOWN) * RTR_AT_TTL_FRACTION);
});

it('handles unsuccessful responses', async () => {
Expand Down Expand Up @@ -382,7 +383,9 @@ describe('FFetch class', () => {
store: {
dispatch: jest.fn(),
},

rtrConfig: {
fixedLengthSessionWarningTTL: '1m',
},
});
testFfetch.replaceFetch();
testFfetch.replaceXMLHttpRequest();
Expand All @@ -396,7 +399,7 @@ describe('FFetch class', () => {
await setTimeout(Promise.resolve(), 2000);

// AT rotation
expect(st).not.toHaveBeenCalledWith(expect.any(Function), (accessTokenExpiration - whatTimeIsItMrFox) * config.rtr.rotationIntervalFraction);
expect(st).not.toHaveBeenCalledWith(expect.any(Function), (accessTokenExpiration - whatTimeIsItMrFox) * RTR_AT_TTL_FRACTION);

// FLS warning
expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox) - ms(RTR_FLS_WARNING_TTL));
Expand Down
24 changes: 12 additions & 12 deletions src/components/Root/Root.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,26 +63,17 @@ class Root extends Component {
this.apolloClient = createApolloClient(okapi);
this.reactQueryClient = createReactQueryClient();

// configure RTR with default props if needed
// gross: this overwrites whatever is currently stored at config.rtr
// gross: technically, the props could change and not get re-run through
// here. Realistically, that'll never happen since config values are read
// only once from a static file at build time, but still, props are props
// so technically it's possible.
// Also, ui-developer provides facilities to change some of this
this.props.config.rtr = configureRtr(this.props.config.rtr);

// enhanced security mode:
// * configure fetch and xhr interceptors to conduct RTR
// * see SessionEventContainer for RTR handling
if (this.props.config.useSecureTokens) {
// FFetch relies on some of these properties, so we must ensure
// they are filled before initialization
const rtrConfig = configureRtr(this.props.config.rtr);

this.ffetch = new FFetch({
logger: this.props.logger,
store,
rtrConfig,
});
this.ffetch.registerEventListener();
this.ffetch.replaceFetch();
this.ffetch.replaceXMLHttpRequest();
}
Expand Down Expand Up @@ -137,6 +128,15 @@ class Root extends Component {
return (<SystemSkeleton />);
}

// make sure RTR is configured
// gross: this overwrites whatever is currently stored at config.rtr
// gross: technically, this may be different than what is configured
// in the constructor since the constructor only runs once but
// render runs when props change. realistically, that'll never happen
// since config values are read only once from a static file at build
// time, but still, props are props so technically it's possible.
config.rtr = configureRtr(this.props.config.rtr);

const stripes = new Stripes({
logger,
store,
Expand Down
7 changes: 3 additions & 4 deletions src/components/SessionEventContainer/SessionEventContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,9 @@ const SessionEventContainer = ({ history }) => {

// no deps? It should be history and stripes!!! >:)
// We only want to configure the event listeners once, not every time
// there is a change to stripes or history. Hence, those are left out.
// we do include stripes.config.rtr, though, because these are configurable
// at runtime via ui-developer.
}, [stripes.config.rtr]); // eslint-disable-line react-hooks/exhaustive-deps
// there is a change to stripes or history. Hence, an empty dependency
// array.
}, []); // eslint-disable-line react-hooks/exhaustive-deps

const renderList = [];

Expand Down

0 comments on commit 46b503f

Please sign in to comment.