Commit 45e43b91 authored by Andrew Fontaine's avatar Andrew Fontaine

Add Vuex State to Allow for Token Rotation

Actions, mutations, etc. all to allow for the retrieval of a rotated
instance ID for feature flag authorization.
parent 352fb274
...@@ -7,6 +7,11 @@ export const setFeatureFlagsEndpoint = ({ commit }, endpoint) => ...@@ -7,6 +7,11 @@ export const setFeatureFlagsEndpoint = ({ commit }, endpoint) =>
export const setFeatureFlagsOptions = ({ commit }, options) => export const setFeatureFlagsOptions = ({ commit }, options) =>
commit(types.SET_FEATURE_FLAGS_OPTIONS, options); commit(types.SET_FEATURE_FLAGS_OPTIONS, options);
export const setInstanceIdEndpoint = ({ commit }, endpoint) =>
commit(types.SET_INSTANCE_ID_ENDPOINT, endpoint);
export const setInstanceId = ({ commit }, instanceId) => commit(types.SET_INSTANCE_ID, instanceId);
export const fetchFeatureFlags = ({ state, dispatch }) => { export const fetchFeatureFlags = ({ state, dispatch }) => {
dispatch('requestFeatureFlags'); dispatch('requestFeatureFlags');
...@@ -28,5 +33,20 @@ export const receiveFeatureFlagsSuccess = ({ commit }, response) => ...@@ -28,5 +33,20 @@ export const receiveFeatureFlagsSuccess = ({ commit }, response) =>
commit(types.RECEIVE_FEATURE_FLAGS_SUCCESS, response); commit(types.RECEIVE_FEATURE_FLAGS_SUCCESS, response);
export const receiveFeatureFlagsError = ({ commit }) => commit(types.RECEIVE_FEATURE_FLAGS_ERROR); export const receiveFeatureFlagsError = ({ commit }) => commit(types.RECEIVE_FEATURE_FLAGS_ERROR);
export const rotateInstanceId = ({ state, dispatch }) => {
dispatch('requestRotateInstanceId');
axios
.get(state.rotateEndpoint)
.then(({ data = {}, headers }) => dispatch('receiveRotateInstanceIdSuccess', { data, headers }))
.catch(() => dispatch('receiveRotateInstanceIdError'));
};
export const requestRotateInstanceId = ({ commit }) => commit(types.REQUEST_ROTATE_INSTANCE_ID);
export const receiveRotateInstanceIdSuccess = ({ commit }, response) =>
commit(types.RECEIVE_ROTATE_INSTANCE_ID_SUCCESS, response);
export const receiveRotateInstanceIdError = ({ commit }) =>
commit(types.RECEIVE_ROTATE_INSTANCE_ID_ERROR);
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {}; export default () => {};
export const SET_FEATURE_FLAGS_ENDPOINT = 'SET_FEATURE_FLAGS_ENDPOINT'; export const SET_FEATURE_FLAGS_ENDPOINT = 'SET_FEATURE_FLAGS_ENDPOINT';
export const SET_FEATURE_FLAGS_OPTIONS = 'SET_FEATURE_FLAGS_OPTIONS'; export const SET_FEATURE_FLAGS_OPTIONS = 'SET_FEATURE_FLAGS_OPTIONS';
export const SET_INSTANCE_ID_ENDPOINT = 'SET_INSTANCE_ID_ENDPOINT';
export const SET_INSTANCE_ID = 'SET_INSTANCE_ID';
export const REQUEST_FEATURE_FLAGS = 'REQUEST_FEATURE_FLAGS'; export const REQUEST_FEATURE_FLAGS = 'REQUEST_FEATURE_FLAGS';
export const RECEIVE_FEATURE_FLAGS_SUCCESS = 'RECEIVE_FEATURE_FLAGS_SUCCESS'; export const RECEIVE_FEATURE_FLAGS_SUCCESS = 'RECEIVE_FEATURE_FLAGS_SUCCESS';
export const RECEIVE_FEATURE_FLAGS_ERROR = 'RECEIVE_FEATURE_FLAGS_ERROR'; export const RECEIVE_FEATURE_FLAGS_ERROR = 'RECEIVE_FEATURE_FLAGS_ERROR';
export const REQUEST_ROTATE_INSTANCE_ID = 'REQUEST_ROTATE_INSTANCE_ID';
export const RECEIVE_ROTATE_INSTANCE_ID_SUCCESS = 'RECEIVE_ROTATE_INSTANCE_ID_SUCCESS';
export const RECEIVE_ROTATE_INSTANCE_ID_ERROR = 'RECEIVE_ROTATE_INSTANCE_ID_ERROR';
...@@ -8,6 +8,9 @@ export default { ...@@ -8,6 +8,9 @@ export default {
[types.SET_FEATURE_FLAGS_OPTIONS](state, options = {}) { [types.SET_FEATURE_FLAGS_OPTIONS](state, options = {}) {
state.options = options; state.options = options;
}, },
[types.SET_INSTANCE_ID_ENDPOINT](state, endpoint) {
state.rotateEndpoint = endpoint;
},
[types.REQUEST_FEATURE_FLAGS](state) { [types.REQUEST_FEATURE_FLAGS](state) {
state.isLoading = true; state.isLoading = true;
}, },
...@@ -30,4 +33,22 @@ export default { ...@@ -30,4 +33,22 @@ export default {
state.isLoading = false; state.isLoading = false;
state.hasError = true; state.hasError = true;
}, },
[types.REQUEST_ROTATE_INSTANCE_ID](state) {
state.isRotating = true;
state.hasRotateError = false;
},
[types.RECEIVE_ROTATE_INSTANCE_ID_SUCCESS](
state,
{
data: { token },
},
) {
state.isRotating = false;
state.instanceId = token;
state.hasRotateError = false;
},
[types.RECEIVE_ROTATE_INSTANCE_ID_ERROR](state) {
state.isRotating = false;
state.hasRotateError = true;
},
}; };
...@@ -5,5 +5,9 @@ export default () => ({ ...@@ -5,5 +5,9 @@ export default () => ({
isLoading: true, isLoading: true,
hasError: false, hasError: false,
endpoint: null, endpoint: null,
rotateEndpoint: null,
instanceId: '',
isRotating: false,
hasRotateError: false,
options: {}, options: {},
}); });
...@@ -80,3 +80,5 @@ export const getRequestData = { ...@@ -80,3 +80,5 @@ export const getRequestData = {
enabled: 0, enabled: 0,
}, },
}; };
export const rotateData = { token: 'oP6sCNRqtRHmpy1gw2-F' };
...@@ -7,12 +7,18 @@ import { ...@@ -7,12 +7,18 @@ import {
fetchFeatureFlags, fetchFeatureFlags,
setFeatureFlagsEndpoint, setFeatureFlagsEndpoint,
setFeatureFlagsOptions, setFeatureFlagsOptions,
setInstanceIdEndpoint,
setInstanceId,
rotateInstanceId,
requestRotateInstanceId,
receiveRotateInstanceIdSuccess,
receiveRotateInstanceIdError,
} from 'ee/feature_flags/store/modules/index/actions'; } from 'ee/feature_flags/store/modules/index/actions';
import state from 'ee/feature_flags/store/modules/index/state'; import state from 'ee/feature_flags/store/modules/index/state';
import * as types from 'ee/feature_flags/store/modules/index/mutation_types'; import * as types from 'ee/feature_flags/store/modules/index/mutation_types';
import testAction from 'spec/helpers/vuex_action_helper'; import testAction from 'spec/helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import { getRequestData } from '../../mock_data'; import { getRequestData, rotateData } from '../../mock_data';
describe('Feature flags actions', () => { describe('Feature flags actions', () => {
let mockedState; let mockedState;
...@@ -47,6 +53,32 @@ describe('Feature flags actions', () => { ...@@ -47,6 +53,32 @@ describe('Feature flags actions', () => {
}); });
}); });
describe('setInstanceIdEndpoint', () => {
it('should commit SET_INSTANCE_ID_ENDPOINT mutation', done => {
testAction(
setInstanceIdEndpoint,
'instance_id.json',
mockedState,
[{ type: types.SET_INSTANCE_ID_ENDPOINT, payload: 'instance_id.json' }],
[],
done,
);
});
});
describe('setInstanceId', () => {
it('should commit SET_INSTANCE_ID mutation', done => {
testAction(
setInstanceId,
'test_instance_id',
mockedState,
[{ type: types.SET_INSTANCE_ID, payload: 'test_instance_id' }],
[],
done,
);
});
});
describe('fetchFeatureFlags', () => { describe('fetchFeatureFlags', () => {
let mock; let mock;
...@@ -148,4 +180,106 @@ describe('Feature flags actions', () => { ...@@ -148,4 +180,106 @@ describe('Feature flags actions', () => {
); );
}); });
}); });
describe('rotateInstanceId', () => {
let mock;
beforeEach(() => {
mockedState.rotateEndpoint = `${TEST_HOST}/endpoint.json`;
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
describe('success', () => {
it('dispatches requestRotateInstanceId and receiveRotateInstanceIdSuccess ', done => {
mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, rotateData, {});
testAction(
rotateInstanceId,
null,
mockedState,
[],
[
{
type: 'requestRotateInstanceId',
},
{
payload: { data: rotateData, headers: {} },
type: 'receiveRotateInstanceIdSuccess',
},
],
done,
);
});
});
describe('error', () => {
it('dispatches requestRotateInstanceId and receiveRotateInstanceIdError ', done => {
mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {});
testAction(
rotateInstanceId,
null,
mockedState,
[],
[
{
type: 'requestRotateInstanceId',
},
{
type: 'receiveRotateInstanceIdError',
},
],
done,
);
});
});
});
describe('requestRotateInstanceId', () => {
it('should commit REQUEST_ROTATE_INSTANCE_ID mutation', done => {
testAction(
requestRotateInstanceId,
null,
mockedState,
[{ type: types.REQUEST_ROTATE_INSTANCE_ID }],
[],
done,
);
});
});
describe('receiveRotateInstanceIdSuccess', () => {
it('should commit RECEIVE_ROTATE_INSTANCE_ID_SUCCESS mutation', done => {
testAction(
receiveRotateInstanceIdSuccess,
{ data: rotateData, headers: {} },
mockedState,
[
{
type: types.RECEIVE_ROTATE_INSTANCE_ID_SUCCESS,
payload: { data: rotateData, headers: {} },
},
],
[],
done,
);
});
});
describe('receiveRotateInstanceIdError', () => {
it('should commit RECEIVE_ROTATE_INSTANCE_ID_ERROR mutation', done => {
testAction(
receiveRotateInstanceIdError,
null,
mockedState,
[{ type: types.RECEIVE_ROTATE_INSTANCE_ID_ERROR }],
[],
done,
);
});
});
}); });
...@@ -2,7 +2,7 @@ import state from 'ee/feature_flags/store/modules/index/state'; ...@@ -2,7 +2,7 @@ import state from 'ee/feature_flags/store/modules/index/state';
import mutations from 'ee/feature_flags/store/modules/index/mutations'; import mutations from 'ee/feature_flags/store/modules/index/mutations';
import * as types from 'ee/feature_flags/store/modules/index/mutation_types'; import * as types from 'ee/feature_flags/store/modules/index/mutation_types';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils'; import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { getRequestData } from '../../mock_data'; import { getRequestData, rotateData } from '../../mock_data';
describe('Feature flags store Mutations', () => { describe('Feature flags store Mutations', () => {
let stateCopy; let stateCopy;
...@@ -83,4 +83,50 @@ describe('Feature flags store Mutations', () => { ...@@ -83,4 +83,50 @@ describe('Feature flags store Mutations', () => {
expect(stateCopy.hasError).toEqual(true); expect(stateCopy.hasError).toEqual(true);
}); });
}); });
describe('REQUEST_ROTATE_INSTANCE_ID', () => {
beforeEach(() => {
mutations[types.REQUEST_ROTATE_INSTANCE_ID](stateCopy);
});
it('should set isRotating to true', () => {
expect(stateCopy.isRotating).toBe(true);
});
it('should set hasRotateError to false', () => {
expect(stateCopy.hasRotateError).toBe(false);
});
});
describe('RECEIVE_ROTATE_INSTANCE_ID_SUCCESS', () => {
beforeEach(() => {
mutations[types.RECEIVE_ROTATE_INSTANCE_ID_SUCCESS](stateCopy, { data: rotateData });
});
it('should set the instance id to the received data', () => {
expect(stateCopy.instanceId).toBe(rotateData.token);
});
it('should set isRotating to false', () => {
expect(stateCopy.isRotating).toBe(false);
});
it('should set hasRotateError to false', () => {
expect(stateCopy.hasRotateError).toBe(false);
});
});
describe('RECEIVE_ROTATE_INSTANCE_ID_ERROR', () => {
beforeEach(() => {
mutations[types.RECEIVE_ROTATE_INSTANCE_ID_ERROR](stateCopy);
});
it('should set isRotating to false', () => {
expect(stateCopy.isRotating).toBe(false);
});
it('should set hasRotateError to true', () => {
expect(stateCopy.hasRotateError).toBe(true);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment