From fea3f63f494d81ab4b74286a528b767ddc308395 Mon Sep 17 00:00:00 2001 From: Daniel Chiquito Date: Fri, 4 Mar 2022 10:49:16 -0500 Subject: [PATCH 1/4] Replace idle-vue with idle-js We weren't really using any of the Vue features from idle-vue, so better to just use idle-js directly. --- client/package-lock.json | 76 ++++++++++++++++++++++++++++------------ client/package.json | 3 +- client/src/main.ts | 2 -- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 2db43dc5..d2952ad0 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,6 +11,7 @@ "@girder/oauth-client": "^0.7.7", "@mdi/font": "^6.5.95", "@sentry/vue": "^6.17.6", + "@types/idle-js": "^1.2.1", "@types/jest": "^27.0.1", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.0.0", @@ -21,7 +22,7 @@ "direct-vuex": "^0.12.1", "django-s3-file-field": "^0.3.0", "gl-matrix": "^3.4.3", - "idle-vue": "^2.0.5", + "idle-js": "^1.2.0", "itk": "14.0.0", "lodash": "^4.17.21", "mousetrap": "github:scottwittenburg/mousetrap#fix-listener-leak", @@ -1570,6 +1571,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/polyfill": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", + "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", + "deprecated": "🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.", + "dependencies": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/@babel/polyfill/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, "node_modules/@babel/preset-env": { "version": "7.16.11", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", @@ -2323,6 +2341,11 @@ "@types/node": "*" } }, + "node_modules/@types/idle-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/idle-js/-/idle-js-1.2.1.tgz", + "integrity": "sha512-lOB1BK2Z96LZQCVTUS8mNdUVsFevB1rhU6ZyA9xZlX0N406nvstHyV702AoZygFuEnTa+aN8ShF1nQ/NH5xlUg==" + }, "node_modules/@types/jest": { "version": "27.4.1", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", @@ -10513,20 +10536,11 @@ } }, "node_modules/idle-js": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/idle-js/-/idle-js-0.1.3.tgz", - "integrity": "sha512-Hvd+OLMUWfVJUv/HoX7wtBgPwx2OdcEd2TzXcBQJyuINXcf7Ig2SgxRMuq2wZNkarf/+DrzV7NxwjKcexIfWBg==" - }, - "node_modules/idle-vue": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/idle-vue/-/idle-vue-2.0.5.tgz", - "integrity": "sha1-MA48zZWBcMTX76fMmuzoYHi+9XY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/idle-js/-/idle-js-1.2.0.tgz", + "integrity": "sha512-ssRtcpcg8WMvXHOkNaq04NXftpuVR+npN0ke8d7EDSxoPyCxcpeZv1EkKft9KmB/v/Q1Q47z89d/9+5VKkvpxw==", "dependencies": { - "idle-js": "^0.1.3" - }, - "engines": { - "node": ">= 4.0.0", - "npm": ">= 3.0.0" + "@babel/polyfill": "^7.2.5" } }, "node_modules/ieee754": { @@ -20491,6 +20505,22 @@ "@babel/helper-plugin-utils": "^7.16.7" } }, + "@babel/polyfill": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", + "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", + "requires": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + } + } + }, "@babel/preset-env": { "version": "7.16.11", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", @@ -21125,6 +21155,11 @@ "@types/node": "*" } }, + "@types/idle-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/idle-js/-/idle-js-1.2.1.tgz", + "integrity": "sha512-lOB1BK2Z96LZQCVTUS8mNdUVsFevB1rhU6ZyA9xZlX0N406nvstHyV702AoZygFuEnTa+aN8ShF1nQ/NH5xlUg==" + }, "@types/jest": { "version": "27.4.1", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", @@ -27522,16 +27557,11 @@ } }, "idle-js": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/idle-js/-/idle-js-0.1.3.tgz", - "integrity": "sha512-Hvd+OLMUWfVJUv/HoX7wtBgPwx2OdcEd2TzXcBQJyuINXcf7Ig2SgxRMuq2wZNkarf/+DrzV7NxwjKcexIfWBg==" - }, - "idle-vue": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/idle-vue/-/idle-vue-2.0.5.tgz", - "integrity": "sha1-MA48zZWBcMTX76fMmuzoYHi+9XY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/idle-js/-/idle-js-1.2.0.tgz", + "integrity": "sha512-ssRtcpcg8WMvXHOkNaq04NXftpuVR+npN0ke8d7EDSxoPyCxcpeZv1EkKft9KmB/v/Q1Q47z89d/9+5VKkvpxw==", "requires": { - "idle-js": "^0.1.3" + "@babel/polyfill": "^7.2.5" } }, "ieee754": { diff --git a/client/package.json b/client/package.json index 1bf93da3..e91b5fb5 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,7 @@ "@girder/oauth-client": "^0.7.7", "@mdi/font": "^6.5.95", "@sentry/vue": "^6.17.6", + "@types/idle-js": "^1.2.1", "@types/jest": "^27.0.1", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.0.0", @@ -21,7 +22,7 @@ "direct-vuex": "^0.12.1", "django-s3-file-field": "^0.3.0", "gl-matrix": "^3.4.3", - "idle-vue": "^2.0.5", + "idle-js": "^1.2.0", "itk": "14.0.0", "lodash": "^4.17.21", "mousetrap": "github:scottwittenburg/mousetrap#fix-listener-leak", diff --git a/client/src/main.ts b/client/src/main.ts index 8098954c..0a6e7bc6 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -4,7 +4,6 @@ import Vuetify from 'vuetify'; import AsyncComputed from 'vue-async-computed'; import config from 'itk/itkConfig'; -import IdleVue from 'idle-vue'; import * as Sentry from '@sentry/vue'; import App from './App.vue'; import router from './router'; @@ -29,7 +28,6 @@ Vue.use(Vuetify); Vue.use(VueCompositionAPI); Vue.use(AsyncComputed); Vue.use(vMousetrap); -Vue.use(IdleVue, { store: store.original, idleTime: 900000 }); // 15 minutes inactive timeout const vuetify = new Vuetify(); From d918065be9f6c34759d0dcf379fb92f85cc77f81 Mon Sep 17 00:00:00 2001 From: Daniel Chiquito Date: Fri, 4 Mar 2022 10:50:36 -0500 Subject: [PATCH 2/4] Store the last time an API request was made --- client/src/django.ts | 2 +- client/src/store/index.ts | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/client/src/django.ts b/client/src/django.ts index ccf7709a..3715e816 100644 --- a/client/src/django.ts +++ b/client/src/django.ts @@ -44,7 +44,7 @@ const djangoClient = { // mark user not-idle apiClient.interceptors.request.use(async (config) => { await oauthClient.maybeRestoreLogin(); - await store.dispatch.resetActionTimer(); + await store.commit.updateLastApiRequestTime(); return config; }, (error) => Promise.reject(error)); diff --git a/client/src/store/index.ts b/client/src/store/index.ts index 137fd304..6943fd54 100644 --- a/client/src/store/index.ts +++ b/client/src/store/index.ts @@ -33,8 +33,6 @@ const poolSize = Math.floor(navigator.hardwareConcurrency / 2) || 2; let taskRunId = -1; let savedWorker = null; -const actiontime = 28 * 60 * 1000; // 28 minute no action timeout + 2 minutes to take action - function shrinkProxyManager(proxyManager) { proxyManager.getViews().forEach((view) => { view.setContainer(null); @@ -320,8 +318,7 @@ const { state: { ...initState, workerPool: new WorkerPool(poolSize, poolFunction), - actionTimer: null, - actionTimeout: false, + lastApiRequestTime: Date.now(), }, getters: { wholeState(state) { @@ -479,8 +476,8 @@ const { removeScreenshot(state, screenshot) { state.screenshots.splice(state.screenshots.indexOf(screenshot), 1); }, - setActionTimeout(state, value) { - state.actionTimeout = value; + updateLastApiRequestTime(state) { + state.lastApiRequestTime = Date.now(); }, setLoadingFrame(state, value) { state.loadingFrame = value; @@ -836,15 +833,6 @@ const { ); } }, - startActionTimer({ state, commit }) { - state.actionTimer = setTimeout(() => { - commit('setActionTimeout', true); - }, actiontime); - }, - resetActionTimer({ state, dispatch }) { - clearTimeout(state.actionTimer); - dispatch('startActionTimer'); - }, }, }); From 93e212e23d774f80cd69318ac212ea1fd50df0ee Mon Sep 17 00:00:00 2001 From: Daniel Chiquito Date: Fri, 4 Mar 2022 10:51:06 -0500 Subject: [PATCH 3/4] Rewrite TimeoutDialog - Use the last time an API request was made to determine if the session token is about to expire. - Use a setTimeout loop to keep the countdown up to date, not to actually trigger the logout. - Use IdleJS to determine if the user has been inactive for 15 minutes. - Separate messages for client side inactivity and an expiring session token. --- client/src/components/TimeoutDialog.vue | 205 ++++++++++++------------ 1 file changed, 99 insertions(+), 106 deletions(-) diff --git a/client/src/components/TimeoutDialog.vue b/client/src/components/TimeoutDialog.vue index 3226727c..74e23877 100644 --- a/client/src/components/TimeoutDialog.vue +++ b/client/src/components/TimeoutDialog.vue @@ -1,104 +1,105 @@ -