mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-06-24 22:12:06 +02:00
Set up Kicker to log out user when inactivity is detected
This commit is contained in:
parent
abce4a0a7a
commit
bde05233c5
@ -1,14 +1,49 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
|
const route = useRoute()
|
||||||
|
const kickUserAfter = ref(null)
|
||||||
|
const isProtectedRoute = ref(null)
|
||||||
|
|
||||||
onMounted(async () => {
|
watch(
|
||||||
const { useUserStore } = await import('./stores/user.js');
|
() => route.name,
|
||||||
|
() => {
|
||||||
|
isProtectedRoute.value = protectedRoute(route)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const kickInactiveUser = computed(() => kickUserAfter.value > 0 && isProtectedRoute.value)
|
||||||
|
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
const { useUserStore } = await import('./stores/user.js')
|
||||||
const { language } = useNavigatorLanguage()
|
const { language } = useNavigatorLanguage()
|
||||||
|
const user = useUserStore()
|
||||||
|
|
||||||
|
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
||||||
|
isProtectedRoute.value = protectedRoute(route)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => user.preferences.kickUserAfter,
|
||||||
|
() => {
|
||||||
|
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
watch(language, () => {
|
watch(language, () => {
|
||||||
useUserStore().applyLanguage()
|
user.applyLanguage()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function protectedRoute(route) {
|
||||||
|
let bool = false
|
||||||
|
route.meta.middlewares?.forEach(func => {
|
||||||
|
if (func instanceof Function && func.name == 'auth') {
|
||||||
|
bool = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return bool
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -16,4 +51,5 @@
|
|||||||
<main class="main-section">
|
<main class="main-section">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</main>
|
</main>
|
||||||
|
<kicker v-if="kickInactiveUser" :kickAfter="kickUserAfter"></kicker>
|
||||||
</template>
|
</template>
|
3
resources/js_vue3/app.js
vendored
3
resources/js_vue3/app.js
vendored
@ -56,7 +56,7 @@ import FormSelect from '@/components/formElements/FormSelect.vue'
|
|||||||
import FormToggle from '@/components/formElements/FormToggle.vue'
|
import FormToggle from '@/components/formElements/FormToggle.vue'
|
||||||
import FormCheckbox from '@/components/formElements/FormCheckbox.vue'
|
import FormCheckbox from '@/components/formElements/FormCheckbox.vue'
|
||||||
import FormButtons from '@/components/formElements/FormButtons.vue'
|
import FormButtons from '@/components/formElements/FormButtons.vue'
|
||||||
// import Kicker from './Kicker'
|
import Kicker from '@/components/Kicker.vue'
|
||||||
// import SettingTabs from './SettingTabs'
|
// import SettingTabs from './SettingTabs'
|
||||||
|
|
||||||
app
|
app
|
||||||
@ -73,6 +73,7 @@ app
|
|||||||
.component('FormToggle', FormToggle)
|
.component('FormToggle', FormToggle)
|
||||||
.component('FormCheckbox', FormCheckbox)
|
.component('FormCheckbox', FormCheckbox)
|
||||||
.component('FormButtons', FormButtons)
|
.component('FormButtons', FormButtons)
|
||||||
|
.component('Kicker', Kicker)
|
||||||
|
|
||||||
// Global error handling
|
// Global error handling
|
||||||
import { useNotifyStore } from '@/stores/notify'
|
import { useNotifyStore } from '@/stores/notify'
|
||||||
|
60
resources/js_vue3/components/Kicker.vue
Normal file
60
resources/js_vue3/components/Kicker.vue
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<script setup>
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
|
const user = useUserStore()
|
||||||
|
const events = ref(['click', 'mousedown', 'scroll', 'keypress', 'load'])
|
||||||
|
const logoutTimer = ref(null)
|
||||||
|
// const elapsed = ref(0)
|
||||||
|
// const counter = ref(null)
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
kickAfter: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
events.value.forEach(function (event) {
|
||||||
|
window.addEventListener(event, resetTimer)
|
||||||
|
}, this)
|
||||||
|
|
||||||
|
setTimer()
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
events.value.forEach(function (event) {
|
||||||
|
window.removeEventListener(event, resetTimer)
|
||||||
|
}, this)
|
||||||
|
|
||||||
|
clearTimeout(logoutTimer.value)
|
||||||
|
// clearInterval(counter.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
function setTimer() {
|
||||||
|
// elapsed.value = 0
|
||||||
|
// clearInterval(counter.value)
|
||||||
|
|
||||||
|
logoutTimer.value = setTimeout(logoutUser, props.kickAfter * 60 * 1000)
|
||||||
|
// counter.value = setInterval(() => {
|
||||||
|
// elapsed.value += 1
|
||||||
|
// console.log(elapsed.value + '/' + props.kickAfter * 60)
|
||||||
|
// }, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function logoutUser() {
|
||||||
|
clearTimeout(logoutTimer.value)
|
||||||
|
console.log('inativity detected, user kicked out')
|
||||||
|
|
||||||
|
user.logout()
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTimer() {
|
||||||
|
clearTimeout(logoutTimer.value)
|
||||||
|
setTimer()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
@ -66,6 +66,15 @@ export const httpClientFactory = (endpoint = 'api') => {
|
|||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// api calls are stateless so when user inactivity is detected
|
||||||
|
// by the backend middleware, it cannot logout the user directly
|
||||||
|
// so it returns a 418 response.
|
||||||
|
// We catch the 418 response and push the user to the autolock view
|
||||||
|
if ( error.response.status === 418 ) {
|
||||||
|
const user = useUserStore()
|
||||||
|
user.logout()
|
||||||
|
}
|
||||||
|
|
||||||
useNotifyStore().error(error)
|
useNotifyStore().error(error)
|
||||||
return new Promise(() => {})
|
return new Promise(() => {})
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user