From 52c5d80a896e568fca9c05721977b4798ac72af4 Mon Sep 17 00:00:00 2001
From: Jack Reed <phillipjreed@gmail.com>
Date: Wed, 15 Apr 2020 13:38:27 -0600
Subject: [PATCH] Wipeaway the infoResponses for a given token that is reset

---
 __tests__/src/reducers/infoResponse.test.js | 27 +++++++++++++++++++++
 src/state/actions/infoResponse.js           | 21 +++++++++-------
 src/state/reducers/infoResponses.js         |  9 +++++++
 3 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/__tests__/src/reducers/infoResponse.test.js b/__tests__/src/reducers/infoResponse.test.js
index c67ceb531..c340e7259 100644
--- a/__tests__/src/reducers/infoResponse.test.js
+++ b/__tests__/src/reducers/infoResponse.test.js
@@ -28,6 +28,7 @@ describe('info response reducer', () => {
           content: 'lots of canvases and metadata and such',
           id: 'abc123',
         },
+        tokenServiceId: 'efg456',
         type: ActionTypes.RECEIVE_INFO_RESPONSE,
       },
     )).toMatchObject({
@@ -35,6 +36,7 @@ describe('info response reducer', () => {
         id: 'abc123',
         isFetching: false,
         json: {},
+        tokenServiceId: 'efg456',
       },
     });
   });
@@ -49,6 +51,7 @@ describe('info response reducer', () => {
       {
         error: "This institution didn't enable CORS.",
         infoId: 'abc123',
+        tokenServiceId: 'efg456',
         type: ActionTypes.RECEIVE_INFO_RESPONSE_FAILURE,
       },
     )).toEqual({
@@ -56,6 +59,7 @@ describe('info response reducer', () => {
         error: "This institution didn't enable CORS.",
         id: 'abc123',
         isFetching: false,
+        tokenServiceId: 'efg456',
       },
     });
   });
@@ -88,4 +92,27 @@ describe('info response reducer', () => {
       type: ActionTypes.IMPORT_MIRADOR_STATE,
     })).toEqual({});
   });
+  it('should handle RESET_AUTHENTICATION_STATE', () => {
+    expect(infoResponsesReducer(
+      {
+        abc123: {
+          stuff: 'foo',
+          tokenServiceId: 'abc123',
+        },
+        def456: {
+          stuff: 'foo',
+          tokenServiceId: 'def456',
+        },
+      },
+      {
+        tokenServiceId: 'abc123',
+        type: ActionTypes.RESET_AUTHENTICATION_STATE,
+      },
+    )).toEqual({
+      def456: {
+        stuff: 'foo',
+        tokenServiceId: 'def456',
+      },
+    });
+  });
 });
diff --git a/src/state/actions/infoResponse.js b/src/state/actions/infoResponse.js
index a0a869bdd..19a77edc3 100644
--- a/src/state/actions/infoResponse.js
+++ b/src/state/actions/infoResponse.js
@@ -22,11 +22,12 @@ export function requestInfoResponse(infoId) {
  * @param  {Object} manifestJson
  * @memberof ActionCreators
  */
-export function receiveInfoResponse(infoId, infoJson, ok) {
+export function receiveInfoResponse(infoId, infoJson, ok, tokenServiceId) {
   return {
     infoId,
     infoJson,
     ok,
+    tokenServiceId,
     type: ActionTypes.RECEIVE_INFO_RESPONSE,
   };
 }
@@ -38,15 +39,16 @@ export function receiveInfoResponse(infoId, infoJson, ok) {
  * @param  {String} error
  * @memberof ActionCreators
  */
-export function receiveInfoResponseFailure(infoId, error) {
+export function receiveInfoResponseFailure(infoId, error, tokenServiceId) {
   return {
     error,
     infoId,
+    tokenServiceId,
     type: ActionTypes.RECEIVE_INFO_RESPONSE_FAILURE,
   };
 }
 /** @private */
-function getAccessToken({ accessTokens }, iiifService) {
+function getAccessTokenService({ accessTokens }, iiifService) {
   if (!iiifService) return undefined;
 
   const services = Utils.getServices(iiifService).filter(s => s.getProfile().match(/http:\/\/iiif.io\/api\/auth\/1\//));
@@ -55,7 +57,7 @@ function getAccessToken({ accessTokens }, iiifService) {
     const authService = services[i];
     const accessTokenService = Utils.getService(authService, 'http://iiif.io/api/auth/1/token');
     const token = accessTokens[accessTokenService.id];
-    if (token && token.json) return token.json.accessToken;
+    if (token && token.json) return token;
   }
 
   return undefined;
@@ -79,21 +81,22 @@ export function fetchInfoResponse({ imageId, imageResource }) {
       && !state.infoResponses[infoId].isFetching
       && state.infoResponses[infoId].json;
 
-    const token = getAccessToken(
+    const tokenService = getAccessTokenService(
       getState(),
       infoResponse || (imageResource && imageResource.getServices()[0]),
     );
 
-    if (token) {
-      headers.Authorization = `Bearer ${token}`;
+    if (tokenService) {
+      headers.Authorization = `Bearer ${tokenService.json.accessToken}`;
     }
 
     dispatch(requestInfoResponse(infoId));
 
+    const tokenServiceId = tokenService && tokenService.id;
     return fetch(`${infoId.replace(/\/$/, '')}/info.json`, { headers })
       .then(response => response.json().then(json => ({ json, ok: response.ok })))
-      .then(({ json, ok }) => dispatch(receiveInfoResponse(infoId, json, ok)))
-      .catch(error => dispatch(receiveInfoResponseFailure(infoId, error)));
+      .then(({ json, ok }) => dispatch(receiveInfoResponse(infoId, json, ok, tokenServiceId)))
+      .catch(error => dispatch(receiveInfoResponseFailure(infoId, error, tokenServiceId)));
   });
 }
 
diff --git a/src/state/reducers/infoResponses.js b/src/state/reducers/infoResponses.js
index 558a2dd12..a20657db0 100644
--- a/src/state/reducers/infoResponses.js
+++ b/src/state/reducers/infoResponses.js
@@ -22,6 +22,7 @@ export const infoResponsesReducer = (state = {}, action) => {
           id: action.infoId,
           isFetching: false,
           json: action.infoJson,
+          tokenServiceId: action.tokenServiceId,
         },
       };
     case ActionTypes.RECEIVE_INFO_RESPONSE_FAILURE:
@@ -31,6 +32,7 @@ export const infoResponsesReducer = (state = {}, action) => {
           error: action.error,
           id: action.infoId,
           isFetching: false,
+          tokenServiceId: action.tokenServiceId,
         },
       };
     case ActionTypes.REMOVE_INFO_RESPONSE:
@@ -42,6 +44,13 @@ export const infoResponsesReducer = (state = {}, action) => {
       }, {});
     case ActionTypes.IMPORT_MIRADOR_STATE:
       return {};
+    case ActionTypes.RESET_AUTHENTICATION_STATE:
+      return Object.keys(state).reduce((object, key) => {
+        if (state[key].tokenServiceId !== action.tokenServiceId) {
+          object[key] = state[key]; // eslint-disable-line no-param-reassign
+        }
+        return object;
+      }, {});
     default: return state;
   }
 };
-- 
GitLab