[ARVADOS-WORKBENCH2] updated: 1.4.1-427-g0cb01f7d

Git user git at public.arvados.org
Fri Sep 4 22:54:34 UTC 2020


Summary of changes:
 cypress/integration/login.spec.js                | 19 +++++++
 docker/Dockerfile                                |  2 +-
 package.json                                     |  2 +
 src/common/config.ts                             |  2 +
 src/index.tsx                                    |  6 +-
 src/services/common-service/common-service.ts    |  2 +
 src/views-components/auto-logout/auto-logout.tsx | 72 ++++++++++++++++++++++++
 src/views/main-panel/main-panel-root.tsx         |  5 +-
 src/views/main-panel/main-panel.tsx              |  4 +-
 src/views/workbench/workbench.tsx                |  3 +
 yarn.lock                                        | 10 ++++
 11 files changed, 121 insertions(+), 6 deletions(-)
 create mode 100644 src/views-components/auto-logout/auto-logout.tsx

       via  0cb01f7da9fcb4fc3bb49cc5039f6b712466bf74 (commit)
       via  2f9cad5098e4261d61e5a72e24232f3a637b0d73 (commit)
       via  f17af4bfbdd3b0054d3494cdc6c5f75c2e872d9f (commit)
       via  68139213ebfa9eea7b38fa8236362d8acb7f1c5c (commit)
       via  9da811232b47b26dff20cdd076a5aa9812f3dbf0 (commit)
       via  202a49e579c8ba643f6bc7f2bcb55fcf57d12eb8 (commit)
      from  847f19027dbe050bdceb835f4c8c67d386159a72 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 0cb01f7da9fcb4fc3bb49cc5039f6b712466bf74
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Fri Sep 4 19:48:44 2020 -0300

    16679: Adds AutoLogout component that closes the session if configured.
    
    When Workbench.IdleTimeout is set to a non-zero value, it is used to
    check for user inactivity; 1 minute before closing the session, a warning
    snackbar is displayed until the session is auto-closed or user activity is
    detected.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>

diff --git a/package.json b/package.json
index 57c6e311..346d4910 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
     "lodash.mergewith": "4.6.2",
     "lodash.template": "4.5.0",
     "mem": "4.0.0",
+    "parse-duration": "0.4.4",
     "prop-types": "15.7.2",
     "query-string": "6.9.0",
     "react": "16.8.6",
@@ -47,6 +48,7 @@
     "react-dom": "16.8.6",
     "react-dropzone": "5.1.1",
     "react-highlight-words": "0.14.0",
+    "react-idle-timer": "4.3.6",
     "react-redux": "5.0.7",
     "react-router": "4.3.1",
     "react-router-dom": "4.3.1",
diff --git a/src/common/config.ts b/src/common/config.ts
index dd812c65..0f935602 100644
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@ -58,6 +58,7 @@ export interface ClusterConfigJSON {
         SSHHelpPageHTML: string;
         SSHHelpHostSuffix: string;
         SiteName: string;
+        IdleTimeout: string;
     };
     Login: {
         LoginCluster: string;
@@ -216,6 +217,7 @@ export const mockClusterConfigJSON = (config: Partial<ClusterConfigJSON>): Clust
         SSHHelpPageHTML: "",
         SSHHelpHostSuffix: "",
         SiteName: "",
+        IdleTimeout: "0s",
     },
     Login: {
         LoginCluster: "",
diff --git a/src/views-components/auto-logout/auto-logout.tsx b/src/views-components/auto-logout/auto-logout.tsx
new file mode 100644
index 00000000..52a1950a
--- /dev/null
+++ b/src/views-components/auto-logout/auto-logout.tsx
@@ -0,0 +1,72 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { connect } from "react-redux";
+import { useIdleTimer } from "react-idle-timer";
+import { Dispatch } from "redux";
+
+import { RootState } from "~/store/store";
+import { SnackbarKind, snackbarActions } from "~/store/snackbar/snackbar-actions";
+import { logout } from "~/store/auth/auth-action";
+import parse from "parse-duration";
+import * as React from "react";
+import { min } from "lodash";
+
+interface AutoLogoutDataProps {
+    sessionIdleTimeout: number;
+    lastWarningDuration: number;
+}
+
+interface AutoLogoutActionProps {
+    doLogout: () => void;
+    doWarn: (message: string, duration: number) => void;
+    doCloseWarn: () => void;
+}
+
+const mapStateToProps = (state: RootState, ownProps: any): AutoLogoutDataProps => {
+    return {
+        sessionIdleTimeout: parse(state.auth.config.clusterConfig.Workbench.IdleTimeout, 's') || 0,
+        lastWarningDuration: ownProps.lastWarningDuration || 60,
+    };
+};
+
+const mapDispatchToProps = (dispatch: Dispatch): AutoLogoutActionProps => ({
+    doLogout: () => dispatch<any>(logout(true)),
+    doWarn: (message: string, duration: number) =>
+        dispatch(snackbarActions.OPEN_SNACKBAR({
+            message, hideDuration: duration, kind: SnackbarKind.WARNING })),
+    doCloseWarn: () => dispatch(snackbarActions.CLOSE_SNACKBAR()),
+});
+
+type AutoLogoutProps = AutoLogoutDataProps & AutoLogoutActionProps;
+
+export const AutoLogout = connect(mapStateToProps, mapDispatchToProps)(
+    (props: AutoLogoutProps) => {
+        let logoutTimer: NodeJS.Timer;
+        const lastWarningDuration = min([props.lastWarningDuration, props.sessionIdleTimeout])! * 1000 ;
+
+        const handleOnIdle = () => {
+            logoutTimer = setTimeout(
+                () => props.doLogout(), lastWarningDuration);
+            props.doWarn(
+                "Your session is about to be closed due to inactivity",
+                lastWarningDuration);
+        };
+
+        const handleOnActive = () => {
+            clearTimeout(logoutTimer);
+            props.doCloseWarn();
+        };
+
+        useIdleTimer({
+            timeout: (props.lastWarningDuration < props.sessionIdleTimeout)
+                ? 1000 * (props.sessionIdleTimeout - props.lastWarningDuration)
+                : 1,
+            onIdle: handleOnIdle,
+            onActive: handleOnActive,
+            debounce: 500
+        });
+
+        return <span />;
+    });
diff --git a/src/views/main-panel/main-panel-root.tsx b/src/views/main-panel/main-panel-root.tsx
index 5806f5b8..acaa43ad 100644
--- a/src/views/main-panel/main-panel-root.tsx
+++ b/src/views/main-panel/main-panel-root.tsx
@@ -31,13 +31,14 @@ export interface MainPanelRootDataProps {
     isNotLinking: boolean;
     isLinkingPath: boolean;
     siteBanner: string;
+    sessionIdleTimeout: number;
 }
 
 type MainPanelRootProps = MainPanelRootDataProps & WithStyles<CssRules>;
 
 export const MainPanelRoot = withStyles(styles)(
     ({ classes, loading, working, user, buildInfo, uuidPrefix,
-        isNotLinking, isLinkingPath, siteBanner }: MainPanelRootProps) =>
+        isNotLinking, isLinkingPath, siteBanner, sessionIdleTimeout }: MainPanelRootProps) =>
         loading
             ? <WorkbenchLoadingScreen />
             : <>
@@ -53,7 +54,7 @@ export const MainPanelRoot = withStyles(styles)(
                 <Grid container direction="column" className={classes.root}>
                     {user
                         ? (user.isActive || (!user.isActive && isLinkingPath)
-                            ? <WorkbenchPanel isNotLinking={isNotLinking} isUserActive={user.isActive} />
+                            ? <WorkbenchPanel isNotLinking={isNotLinking} isUserActive={user.isActive} sessionIdleTimeout={sessionIdleTimeout} />
                             : <InactivePanel />)
                         : <LoginPanel />}
                 </Grid>
diff --git a/src/views/main-panel/main-panel.tsx b/src/views/main-panel/main-panel.tsx
index 5828c6db..edbf5cc4 100644
--- a/src/views/main-panel/main-panel.tsx
+++ b/src/views/main-panel/main-panel.tsx
@@ -4,6 +4,7 @@
 
 import { RootState } from '~/store/store';
 import { connect } from 'react-redux';
+import parse from 'parse-duration';
 import { MainPanelRoot, MainPanelRootDataProps } from '~/views/main-panel/main-panel-root';
 import { isSystemWorking } from '~/store/progress-indicator/progress-indicator-reducer';
 import { isWorkbenchLoading } from '~/store/workbench/workbench-actions';
@@ -19,7 +20,8 @@ const mapStateToProps = (state: RootState): MainPanelRootDataProps => {
         uuidPrefix: state.auth.localCluster,
         isNotLinking: state.linkAccountPanel.status === LinkAccountPanelStatus.NONE || state.linkAccountPanel.status === LinkAccountPanelStatus.INITIAL,
         isLinkingPath: state.router.location ? matchLinkAccountRoute(state.router.location.pathname) !== null : false,
-        siteBanner: state.auth.config.clusterConfig.Workbench.SiteName
+        siteBanner: state.auth.config.clusterConfig.Workbench.SiteName,
+        sessionIdleTimeout: parse(state.auth.config.clusterConfig.Workbench.IdleTimeout, 's') || 0
     };
 };
 
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 906c649c..b0f90894 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -98,6 +98,7 @@ import { FedLogin } from './fed-login';
 import { CollectionsContentAddressPanel } from '~/views/collection-content-address-panel/collection-content-address-panel';
 import { AllProcessesPanel } from '../all-processes-panel/all-processes-panel';
 import { NotFoundPanel } from '../not-found-panel/not-found-panel';
+import { AutoLogout } from '~/views-components/auto-logout/auto-logout';
 
 type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';
 
@@ -132,6 +133,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 interface WorkbenchDataProps {
     isUserActive: boolean;
     isNotLinking: boolean;
+    sessionIdleTimeout: number;
 }
 
 type WorkbenchPanelProps = WithStyles<CssRules> & WorkbenchDataProps;
@@ -148,6 +150,7 @@ const saveSplitterSize = (size: number) => localStorage.setItem('splitterSize',
 export const WorkbenchPanel =
     withStyles(styles)((props: WorkbenchPanelProps) =>
         <Grid container item xs className={props.classes.root}>
+            { props.sessionIdleTimeout > 0 && <AutoLogout />}
             <Grid container item xs className={props.classes.container}>
                 <SplitterLayout customClassName={props.classes.splitter} percentage={true}
                     primaryIndex={0} primaryMinSize={10}
diff --git a/yarn.lock b/yarn.lock
index 742db465..842d6cf8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8010,6 +8010,11 @@ parse-asn1@^5.0.0:
     pbkdf2 "^3.0.3"
     safe-buffer "^5.1.1"
 
+parse-duration at 0.4.4:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/parse-duration/-/parse-duration-0.4.4.tgz#11c0f51a689e97d06c57bd772f7fda7dc013243c"
+  integrity sha512-KbAJuYGUhZkB9gotDiKLnZ7Z3VTacK3fgwmDdB6ZVDtJbMBT6MfLga0WJaYpPDu0mzqT0NgHtHDt5PY4l0nidg==
+
 parse-glob@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
@@ -8948,6 +8953,11 @@ react-highlight-words at 0.14.0:
     memoize-one "^4.0.0"
     prop-types "^15.5.8"
 
+react-idle-timer at 4.3.6:
+  version "4.3.6"
+  resolved "https://registry.yarnpkg.com/react-idle-timer/-/react-idle-timer-4.3.6.tgz#bdf56cee6ccc8c144ece18d152b3e304e13f3fa2"
+  integrity sha512-sJS4w123E4HkuM/l3j8FTVl0St6ghGA22Ich/Nz/luJSM4MEA6PvSwEBaAXLx3uCLB1fK7CACjvB4ozW3uWuCA==
+
 react-is@^16.4.2, react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0:
   version "16.11.0"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa"

commit 2f9cad5098e4261d61e5a72e24232f3a637b0d73
Merge: 847f1902 f17af4bf
Author: Lucas Di Pentima <lucas at di-pentima.com.ar>
Date:   Wed Sep 2 11:25:04 2020 -0300

    16679: Merge branch 'master' into 16679-token-security-enhancements
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas at di-pentima.com.ar>


-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list