mirror of
https://github.com/IT4Change/gradido.git
synced 2026-04-06 01:25:28 +00:00
step 1 automatic logout of session after 10 minutes, last 60 seconds warning modal
This commit is contained in:
parent
6fc3f71f99
commit
fae0685509
@ -25,7 +25,7 @@ const constants = {
|
|||||||
const server = {
|
const server = {
|
||||||
PORT: process.env.PORT || 4000,
|
PORT: process.env.PORT || 4000,
|
||||||
JWT_SECRET: process.env.JWT_SECRET || 'secret123',
|
JWT_SECRET: process.env.JWT_SECRET || 'secret123',
|
||||||
JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '30m',
|
JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '10m',
|
||||||
GRAPHIQL: process.env.GRAPHIQL === 'true' || false,
|
GRAPHIQL: process.env.GRAPHIQL === 'true' || false,
|
||||||
GDT_API_URL: process.env.GDT_API_URL || 'https://gdt.gradido.net',
|
GDT_API_URL: process.env.GDT_API_URL || 'https://gdt.gradido.net',
|
||||||
PRODUCTION: process.env.NODE_ENV === 'production' || false,
|
PRODUCTION: process.env.NODE_ENV === 'production' || false,
|
||||||
|
|||||||
@ -45,6 +45,7 @@
|
|||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-canvas-mock": "^2.3.1",
|
"jest-canvas-mock": "^2.3.1",
|
||||||
"jest-environment-jsdom-sixteen": "^2.0.0",
|
"jest-environment-jsdom-sixteen": "^2.0.0",
|
||||||
|
"jwt-decode": "^3.1.2",
|
||||||
"portal-vue": "^2.1.7",
|
"portal-vue": "^2.1.7",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"qrcanvas-vue": "2.1.1",
|
"qrcanvas-vue": "2.1.1",
|
||||||
@ -59,6 +60,7 @@
|
|||||||
"vue-loading-overlay": "^3.4.2",
|
"vue-loading-overlay": "^3.4.2",
|
||||||
"vue-moment": "^4.1.0",
|
"vue-moment": "^4.1.0",
|
||||||
"vue-router": "^3.0.6",
|
"vue-router": "^3.0.6",
|
||||||
|
"vue-timers": "^2.0.4",
|
||||||
"vue2-transitions": "^0.2.3",
|
"vue2-transitions": "^0.2.3",
|
||||||
"vuex": "^3.6.0",
|
"vuex": "^3.6.0",
|
||||||
"vuex-persistedstate": "^4.0.0-beta.3"
|
"vuex-persistedstate": "^4.0.0-beta.3"
|
||||||
|
|||||||
@ -32,6 +32,22 @@
|
|||||||
</fade-transition>
|
</fade-transition>
|
||||||
</div>
|
</div>
|
||||||
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
|
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
|
||||||
|
<b-modal id="modalSessionTimeOut">
|
||||||
|
<b-card header-tag="header" footer-tag="footer">
|
||||||
|
<b-card-text>
|
||||||
|
<div class="p-3">{{ $t('session.warningText') }}</div>
|
||||||
|
<div class="p-3 text-danger">
|
||||||
|
{{ $t('session.lightText') }}
|
||||||
|
<b>{{ closeTime }}</b>
|
||||||
|
{{ $t('time.seconds') }}
|
||||||
|
</div>
|
||||||
|
</b-card-text>
|
||||||
|
</b-card>
|
||||||
|
<template #modal-footer>
|
||||||
|
<b-button size="sm" variant="success" @click="handleOk">verlängern</b-button>
|
||||||
|
<b-button size="sm" variant="danger" @click="logout">Logout</b-button>
|
||||||
|
</template>
|
||||||
|
</b-modal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,6 +59,7 @@ import { logout, transactionsQuery } from '@/graphql/queries'
|
|||||||
import ContentFooter from '@/components/ContentFooter.vue'
|
import ContentFooter from '@/components/ContentFooter.vue'
|
||||||
import { FadeTransition } from 'vue2-transitions'
|
import { FadeTransition } from 'vue2-transitions'
|
||||||
import CONFIG from '@/config'
|
import CONFIG from '@/config'
|
||||||
|
import { verifyLogin } from '../graphql/queries'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DashboardLayout',
|
name: 'DashboardLayout',
|
||||||
@ -62,6 +79,10 @@ export default {
|
|||||||
pending: true,
|
pending: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
tunneledEmail: null,
|
tunneledEmail: null,
|
||||||
|
time: 0,
|
||||||
|
millisecondsShowModal: 75000,
|
||||||
|
millisecondsCheckTokenInterval: 15000,
|
||||||
|
closeTime: 60,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
@ -70,6 +91,41 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
timeout() {
|
||||||
|
if (this.closeTime > 0) {
|
||||||
|
this.closeTime = this.closeTime - 1
|
||||||
|
} else {
|
||||||
|
this.logout()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleOk(bvModalEvent) {
|
||||||
|
// Prevent modal from closing
|
||||||
|
bvModalEvent.preventDefault()
|
||||||
|
this.$apollo
|
||||||
|
.query({
|
||||||
|
query: verifyLogin,
|
||||||
|
fetchPolicy: 'network-only',
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
clearInterval(this.$options.interval2)
|
||||||
|
this.$bvModal.hide('modalSessionTimeOut')
|
||||||
|
this.closeTime = 60
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.logout()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async log() {
|
||||||
|
if (this.$route.meta.requiresAuth) {
|
||||||
|
const now = new Date().getTime()
|
||||||
|
const exp = new Date(this.$store.state.tokenTime * 1000).getTime()
|
||||||
|
const diff = exp - now
|
||||||
|
if (diff < this.millisecondsShowModal) {
|
||||||
|
this.$bvModal.show('modalSessionTimeOut')
|
||||||
|
this.$options.interval2 = setInterval(this.timeout, 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
async logout() {
|
async logout() {
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.query({
|
.query({
|
||||||
@ -139,6 +195,12 @@ export default {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.$options.interval = setInterval(this.log, this.millisecondsCheckTokenInterval)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
clearInterval(this.$options.interval)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@ -197,6 +197,10 @@
|
|||||||
"qrCode": "QR Code",
|
"qrCode": "QR Code",
|
||||||
"send_gdd": "GDD versenden",
|
"send_gdd": "GDD versenden",
|
||||||
"send_per_link": "GDD versenden per Link",
|
"send_per_link": "GDD versenden per Link",
|
||||||
|
"session": {
|
||||||
|
"warningText": "Die Session läuft gleich ab!",
|
||||||
|
"lightText": "Du wirst automatisch abgemeldet in"
|
||||||
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"language": {
|
"language": {
|
||||||
"changeLanguage": "Sprache ändern",
|
"changeLanguage": "Sprache ändern",
|
||||||
|
|||||||
@ -197,6 +197,10 @@
|
|||||||
"qrCode": "QR Code",
|
"qrCode": "QR Code",
|
||||||
"send_gdd": "GDD send",
|
"send_gdd": "GDD send",
|
||||||
"send_per_link": "GDD send via link",
|
"send_per_link": "GDD send via link",
|
||||||
|
"session": {
|
||||||
|
"warningText": "The session is about to expire!",
|
||||||
|
"lightText": "You will be automatically logged out in"
|
||||||
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"language": {
|
"language": {
|
||||||
"changeLanguage": "Change language",
|
"changeLanguage": "Change language",
|
||||||
|
|||||||
@ -18,6 +18,8 @@ import 'vue-loading-overlay/dist/vue-loading.css'
|
|||||||
|
|
||||||
import VueApollo from 'vue-apollo'
|
import VueApollo from 'vue-apollo'
|
||||||
|
|
||||||
|
import VueTimers from 'vue-timers'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(Vue) {
|
install(Vue) {
|
||||||
Vue.use(GlobalComponents)
|
Vue.use(GlobalComponents)
|
||||||
@ -29,5 +31,6 @@ export default {
|
|||||||
Vue.use(FlatPickr)
|
Vue.use(FlatPickr)
|
||||||
Vue.use(Loading)
|
Vue.use(Loading)
|
||||||
Vue.use(VueApollo)
|
Vue.use(VueApollo)
|
||||||
|
Vue.use(VueTimers)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import Vuex from 'vuex'
|
|||||||
import createPersistedState from 'vuex-persistedstate'
|
import createPersistedState from 'vuex-persistedstate'
|
||||||
import { localeChanged } from 'vee-validate'
|
import { localeChanged } from 'vee-validate'
|
||||||
import i18n from '@/i18n.js'
|
import i18n from '@/i18n.js'
|
||||||
|
import jwtDecode from 'jwt-decode'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
@ -26,6 +27,11 @@ export const mutations = {
|
|||||||
},
|
},
|
||||||
token: (state, token) => {
|
token: (state, token) => {
|
||||||
state.token = token
|
state.token = token
|
||||||
|
if (token) {
|
||||||
|
state.tokenTime = jwtDecode(token).exp
|
||||||
|
} else {
|
||||||
|
state.tokenTime = null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
newsletterState: (state, newsletterState) => {
|
newsletterState: (state, newsletterState) => {
|
||||||
state.newsletterState = newsletterState
|
state.newsletterState = newsletterState
|
||||||
@ -85,6 +91,7 @@ try {
|
|||||||
lastName: '',
|
lastName: '',
|
||||||
// username: '',
|
// username: '',
|
||||||
token: null,
|
token: null,
|
||||||
|
tokenTime: null,
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
newsletterState: null,
|
newsletterState: null,
|
||||||
hasElopage: false,
|
hasElopage: false,
|
||||||
|
|||||||
@ -9821,6 +9821,11 @@ jsprim@^1.2.2:
|
|||||||
json-schema "0.2.3"
|
json-schema "0.2.3"
|
||||||
verror "1.10.0"
|
verror "1.10.0"
|
||||||
|
|
||||||
|
jwt-decode@^3.1.2:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
|
||||||
|
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
|
||||||
|
|
||||||
killable@^1.0.1:
|
killable@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
|
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
|
||||||
@ -14472,6 +14477,11 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
||||||
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
||||||
|
|
||||||
|
vue-timers@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-timers/-/vue-timers-2.0.4.tgz#7e1c443abf2109db5eeab6e62b0f5a47e94cf70b"
|
||||||
|
integrity sha512-QOEVdO4V4o9WjFG6C0Kn9tfdTeeECjqvEQozcQlfL1Tn8v0qx4uUPhTYoc1+s6qoJnSbu8f68x8+nm1ZEir0kw==
|
||||||
|
|
||||||
vue2-transitions@^0.2.3:
|
vue2-transitions@^0.2.3:
|
||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/vue2-transitions/-/vue2-transitions-0.2.3.tgz#69c9d75b1db05f231b80980c03459d68490ba27d"
|
resolved "https://registry.yarnpkg.com/vue2-transitions/-/vue2-transitions-0.2.3.tgz#69c9d75b1db05f231b80980c03459d68490ba27d"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user