19715: Add preserve url location flag to logout action - set to true for autologout
authorStephen Smith <stephen@curii.com>
Thu, 12 Jan 2023 20:44:45 +0000 (15:44 -0500)
committerStephen Smith <stephen@curii.com>
Thu, 12 Jan 2023 20:44:45 +0000 (15:44 -0500)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

src/services/auth-service/auth-service.ts
src/store/auth/auth-action.ts
src/store/auth/auth-middleware.test.ts
src/store/auth/auth-middleware.ts
src/views-components/auto-logout/auto-logout.tsx
src/views-components/main-app-bar/account-menu.tsx

index 52bfa29ecae21bb2a86967d0dbd63cd9b072f9fd..b530e4cd3e8d4933cf3e445fe6f306f8994b6d4c 100644 (file)
@@ -120,9 +120,13 @@ export class AuthService {
         window.location.assign(`https://${homeClusterHost}/login?${(uuidPrefix !== homeCluster && homeCluster !== loginCluster) ? "remote=" + uuidPrefix + "&" : ""}return_to=${currentUrl}`);
     }
 
-    public logout(expireToken: string) {
-        const currentUrl = `${window.location.protocol}//${window.location.host}`;
-        window.location.assign(`${this.baseUrl || ""}/logout?api_token=${expireToken}&return_to=${currentUrl}`);
+    public logout(expireToken: string, preservePath: boolean) {
+        const fullUrl = new URL(window.location.href);
+        const wbBase = `${fullUrl.protocol}//${fullUrl.host}`;
+        const wbPath = fullUrl.pathname + fullUrl.search;
+        const returnTo = `${wbBase}${preservePath ? wbPath : ''}`
+
+        window.location.assign(`${this.baseUrl || ""}/logout?api_token=${expireToken}&return_to=${returnTo}`);
     }
 
     public getUserDetails = (showErrors?: boolean): Promise<User> => {
index 6eb8356f5e403541547f1d91bddec9d1aad035ca..145a461c8fac717dcfb66c9f3a43779b765c83c6 100644 (file)
@@ -20,7 +20,7 @@ import { getTokenV2 } from 'models/api-client-authorization';
 
 export const authActions = unionize({
     LOGIN: {},
-    LOGOUT: ofType<{ deleteLinkData: boolean }>(),
+    LOGOUT: ofType<{ deleteLinkData: boolean, preservePath: boolean }>(),
     SET_CONFIG: ofType<{ config: Config }>(),
     SET_EXTRA_TOKEN: ofType<{ extraApiToken: string, extraApiTokenExpiration?: Date }>(),
     RESET_EXTRA_TOKEN: {},
@@ -113,7 +113,7 @@ export const saveApiToken = (token: string) => async (dispatch: Dispatch, getSta
         const tokenLocation = await svc.authService.getStorageType();
         dispatch(authActions.INIT_USER({ user, token, tokenExpiration, tokenLocation }));
     } catch (e) {
-        dispatch(authActions.LOGOUT({ deleteLinkData: false }));
+        dispatch(authActions.LOGOUT({ deleteLinkData: false, preservePath: false }));
     }
 };
 
@@ -163,8 +163,8 @@ export const login = (uuidPrefix: string, homeCluster: string, loginCluster: str
         dispatch(authActions.LOGIN());
     };
 
-export const logout = (deleteLinkData: boolean = false) =>
+export const logout = (deleteLinkData: boolean = false, preservePath: boolean = false) =>
     (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) =>
-        dispatch(authActions.LOGOUT({ deleteLinkData }));
+        dispatch(authActions.LOGOUT({ deleteLinkData, preservePath }))
 
 export type AuthAction = UnionOf<typeof authActions>;
index 9ded9e674ec02ddb8a0202e64d84276e4a6980da..5a0364ebf9000162ef7544dccd0607420ba2b290 100644 (file)
@@ -36,10 +36,10 @@ describe("AuthMiddleware", () => {
         window.location.assign = jest.fn();
         const next = jest.fn();
         const middleware = authMiddleware(services)(store)(next);
-        middleware(authActions.LOGOUT({deleteLinkData: false}));
+        middleware(authActions.LOGOUT({deleteLinkData: false, preservePath: false}));
         expect(window.location.assign).toBeCalledWith(
             `/logout?api_token=someToken&return_to=${location.protocol}//${location.host}`
         );
         expect(localStorage.getItem(API_TOKEN_KEY)).toBeFalsy();
     });
-});
\ No newline at end of file
+});
index 87a1253b8052840393a5abef4b3bcf66b668d0a7..eb1e42b5de74c475452647489482dc1892754740 100644 (file)
@@ -59,7 +59,7 @@ export const authMiddleware = (services: ServiceRepository): Middleware => store
             document.title = `Arvados Workbench (${config.uuidPrefix})`;
             next(action);
         },
-        LOGOUT: ({ deleteLinkData }) => {
+        LOGOUT: ({ deleteLinkData, preservePath }) => {
             next(action);
             if (deleteLinkData) {
                 services.linkAccountService.removeAccountToLink();
@@ -69,7 +69,7 @@ export const authMiddleware = (services: ServiceRepository): Middleware => store
             services.authService.removeSessions();
             services.authService.removeUser();
             removeAuthorizationHeader(services);
-            services.authService.logout(token || '');
+            services.authService.logout(token || '', preservePath);
         },
         default: () => next(action)
     });
index a2d71d08dc406bf2d1baf96d13ce2929f5291c28..b4bef2b5efdb51b40d73542f51aad87b86969a16 100644 (file)
@@ -30,7 +30,7 @@ const mapStateToProps = (state: RootState, ownProps: any): AutoLogoutDataProps =
 });
 
 const mapDispatchToProps = (dispatch: Dispatch): AutoLogoutActionProps => ({
-    doLogout: () => dispatch<any>(logout(true)),
+    doLogout: () => dispatch<any>(logout(true, true)),
     doWarn: (message: string, duration: number) =>
         dispatch(snackbarActions.OPEN_SNACKBAR({
             message, hideDuration: duration, kind: SnackbarKind.WARNING })),
index 7faf27c2eef507a68a776de5c692b50b8461ee34..4b62cea2c60f343739d92396ec6cc3dfbeb126fb 100644 (file)
@@ -95,7 +95,7 @@ export const AccountMenuComponent =
                 {user.isActive && accountMenuItems}
                 <Divider />
                 <MenuItem data-cy="logout-menuitem"
-                    onClick={() => dispatch(authActions.LOGOUT({ deleteLinkData: true }))}>
+                    onClick={() => dispatch(authActions.LOGOUT({ deleteLinkData: true, preservePath: false }))}>
                     Logout
                 </MenuItem>
             </DropdownMenu>