mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-01-11 16:58:58 +01:00
Change the Kicker activation method to ensure minified code works as well
This commit is contained in:
parent
333b70e688
commit
3459a364a0
@ -1,17 +1,18 @@
|
||||
<script setup>
|
||||
import { RouterView } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const kickUser = ref(null)
|
||||
const kickUserAfter = ref(null)
|
||||
const isProtectedRoute = ref(null)
|
||||
const isProtectedRoute = ref(route.meta.watchedByKicker)
|
||||
|
||||
watch(
|
||||
() => route.name,
|
||||
() => {
|
||||
isProtectedRoute.value = protectedRoute(route)
|
||||
isProtectedRoute.value = route.meta.watchedByKicker
|
||||
}
|
||||
)
|
||||
|
||||
const kickInactiveUser = computed(() => kickUserAfter.value > 0 && isProtectedRoute.value)
|
||||
// const kickInactiveUser = computed(() => kickUser && kickUserAfter.value > 0 && isProtectedRoute.value)
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const { useUserStore } = await import('./stores/user.js')
|
||||
@ -19,7 +20,7 @@
|
||||
const user = useUserStore()
|
||||
|
||||
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
||||
isProtectedRoute.value = protectedRoute(route)
|
||||
kickUser.value = user.isAuthenticated
|
||||
|
||||
watch(
|
||||
() => user.preferences.kickUserAfter,
|
||||
@ -27,23 +28,17 @@
|
||||
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => user.isAuthenticated,
|
||||
() => {
|
||||
kickUser.value = user.isAuthenticated
|
||||
}
|
||||
)
|
||||
watch(language, () => {
|
||||
user.applyLanguage()
|
||||
})
|
||||
})
|
||||
|
||||
function protectedRoute(route) {
|
||||
let bool = false
|
||||
route.meta.middlewares?.forEach(func => {
|
||||
if (func instanceof Function && func.name == 'authGuard') {
|
||||
bool = true
|
||||
return
|
||||
}
|
||||
})
|
||||
return bool
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -59,5 +54,5 @@
|
||||
<main class="main-section">
|
||||
<RouterView />
|
||||
</main>
|
||||
<kicker v-if="kickInactiveUser" :kickAfter="kickUserAfter"></kicker>
|
||||
<kicker v-if="kickUser && kickUserAfter > 0 && isProtectedRoute" :kickAfter="kickUserAfter"></kicker>
|
||||
</template>
|
@ -2,7 +2,7 @@
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const user = useUserStore()
|
||||
const events = ref(['click', 'mousedown', 'scroll', 'keypress', 'load'])
|
||||
const events = ref(['mousedown', 'scroll', 'keypress'])
|
||||
const logoutTimer = ref(null)
|
||||
// const elapsed = ref(0)
|
||||
// const counter = ref(null)
|
||||
@ -14,45 +14,54 @@
|
||||
},
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.kickAfter,
|
||||
() => {
|
||||
restartTimer()
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
events.value.forEach(function (event) {
|
||||
window.addEventListener(event, resetTimer)
|
||||
window.addEventListener(event, restartTimer)
|
||||
}, this)
|
||||
|
||||
setTimer()
|
||||
startTimer()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
events.value.forEach(function (event) {
|
||||
window.removeEventListener(event, resetTimer)
|
||||
window.removeEventListener(event, restartTimer)
|
||||
}, this)
|
||||
|
||||
clearTimeout(logoutTimer.value)
|
||||
// clearInterval(counter.value)
|
||||
stopTimer()
|
||||
})
|
||||
|
||||
function setTimer() {
|
||||
// elapsed.value = 0
|
||||
// clearInterval(counter.value)
|
||||
|
||||
function startTimer() {
|
||||
logoutTimer.value = setTimeout(logoutUser, props.kickAfter * 60 * 1000)
|
||||
// counter.value = setInterval(() => {
|
||||
// elapsed.value += 1
|
||||
// console.log(elapsed.value + '/' + props.kickAfter * 60)
|
||||
// }, 1000);
|
||||
// }, 1000)
|
||||
}
|
||||
|
||||
// Triggers the user logout
|
||||
function logoutUser() {
|
||||
clearTimeout(logoutTimer.value)
|
||||
console.log('inativity detected, user kicked out')
|
||||
|
||||
user.logout({ kicked: true})
|
||||
}
|
||||
|
||||
function resetTimer() {
|
||||
// Restarts the timer
|
||||
function restartTimer() {
|
||||
stopTimer()
|
||||
startTimer()
|
||||
}
|
||||
|
||||
// Stops the timer
|
||||
function stopTimer() {
|
||||
clearTimeout(logoutTimer.value)
|
||||
setTimer()
|
||||
// elapsed.value = 0
|
||||
// clearInterval(counter.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
38
resources/js_vue3/router/index.js
vendored
38
resources/js_vue3/router/index.js
vendored
@ -14,24 +14,24 @@ import setReturnTo from './middlewares/setReturnTo'
|
||||
const router = createRouter({
|
||||
history: createWebHistory('/'),
|
||||
routes: [
|
||||
{ path: '/start', name: 'start', component: () => import('../views/Start.vue'), meta: { middlewares: [authGuard, setReturnTo] } },
|
||||
{ path: '/capture', name: 'capture', component: () => import('../views/twofaccounts/Capture.vue'), meta: { middlewares: [authGuard, setReturnTo] } },
|
||||
{ path: '/start', name: 'start', component: () => import('../views/Start.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true } },
|
||||
{ path: '/capture', name: 'capture', component: () => import('../views/twofaccounts/Capture.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true } },
|
||||
|
||||
{ path: '/accounts', name: 'accounts', component: () => import('../views/twofaccounts/Accounts.vue'), meta: { middlewares: [authGuard, starter, setReturnTo] }, alias: '/' },
|
||||
{ path: '/account/create', name: 'createAccount', component: () => import('../views/twofaccounts/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo] } },
|
||||
{ path: '/account/import', name: 'importAccounts', component: () => import('../views/twofaccounts/Import.vue'), meta: { middlewares: [authGuard, setReturnTo] } },
|
||||
{ path: '/account/:twofaccountId/edit', name: 'editAccount', component: () => import('../views/twofaccounts/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo] }, props: true },
|
||||
{ path: '/account/:twofaccountId/qrcode', name: 'showQRcode', component: () => import('../views/twofaccounts/QRcode.vue'), meta: { middlewares: [authGuard, setReturnTo] } },
|
||||
{ path: '/accounts', name: 'accounts', component: () => import('../views/twofaccounts/Accounts.vue'), meta: { middlewares: [authGuard, starter, setReturnTo], watchedByKicker: true }, alias: '/' },
|
||||
{ path: '/account/create', name: 'createAccount', component: () => import('../views/twofaccounts/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true } },
|
||||
{ path: '/account/import', name: 'importAccounts', component: () => import('../views/twofaccounts/Import.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true } },
|
||||
{ path: '/account/:twofaccountId/edit', name: 'editAccount', component: () => import('../views/twofaccounts/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true }, props: true },
|
||||
{ path: '/account/:twofaccountId/qrcode', name: 'showQRcode', component: () => import('../views/twofaccounts/QRcode.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true } },
|
||||
|
||||
{ path: '/groups', name: 'groups', component: () => import('../views/groups/Groups.vue'), meta: { middlewares: [authGuard, setReturnTo] }, props: true },
|
||||
{ path: '/group/create', name: 'createGroup', component: () => import('../views/groups/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo] } },
|
||||
{ path: '/group/:groupId/edit', name: 'editGroup', component: () => import('../views/groups/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo] }, props: true },
|
||||
{ path: '/groups', name: 'groups', component: () => import('../views/groups/Groups.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true }, props: true },
|
||||
{ path: '/group/create', name: 'createGroup', component: () => import('../views/groups/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true } },
|
||||
{ path: '/group/:groupId/edit', name: 'editGroup', component: () => import('../views/groups/CreateUpdate.vue'), meta: { middlewares: [authGuard, setReturnTo], watchedByKicker: true }, props: true },
|
||||
|
||||
{ path: '/settings/options', name: 'settings.options', component: () => import('../views/settings/Options.vue'), meta: { middlewares: [authGuard], showAbout: true } },
|
||||
{ path: '/settings/account', name: 'settings.account', component: () => import('../views/settings/Account.vue'), meta: { middlewares: [authGuard], showAbout: true } },
|
||||
{ path: '/settings/oauth', name: 'settings.oauth.tokens', component: () => import('../views/settings/OAuth.vue'), meta: { middlewares: [authGuard], showAbout: true, props: true } },
|
||||
{ path: '/settings/webauthn/:credentialId/edit', name: 'settings.webauthn.editCredential', component: () => import('../views/settings/Credentials/Edit.vue'), meta: { middlewares: [authGuard], showAbout: true }, props: true },
|
||||
{ path: '/settings/webauthn', name: 'settings.webauthn.devices', component: () => import('../views/settings/WebAuthn.vue'), meta: { middlewares: [authGuard], showAbout: true } },
|
||||
{ path: '/settings/options', name: 'settings.options', component: () => import('../views/settings/Options.vue'), meta: { middlewares: [authGuard], watchedByKicker: true, showAbout: true } },
|
||||
{ path: '/settings/account', name: 'settings.account', component: () => import('../views/settings/Account.vue'), meta: { middlewares: [authGuard], watchedByKicker: true, showAbout: true } },
|
||||
{ path: '/settings/oauth', name: 'settings.oauth.tokens', component: () => import('../views/settings/OAuth.vue'), meta: { middlewares: [authGuard], watchedByKicker: true, showAbout: true, props: true } },
|
||||
{ path: '/settings/webauthn/:credentialId/edit', name: 'settings.webauthn.editCredential', component: () => import('../views/settings/Credentials/Edit.vue'), meta: { middlewares: [authGuard], watchedByKicker: true, showAbout: true }, props: true },
|
||||
{ path: '/settings/webauthn', name: 'settings.webauthn.devices', component: () => import('../views/settings/WebAuthn.vue'), meta: { middlewares: [authGuard], watchedByKicker: true, showAbout: true } },
|
||||
|
||||
{ path: '/login', name: 'login', component: () => import('../views/auth/Login.vue'), meta: { middlewares: [setReturnTo], disabledWithAuthProxy: true, showAbout: true } },
|
||||
{ path: '/register', name: 'register', component: () => import('../views/auth/Register.vue'), meta: { middlewares: [noRegistration, setReturnTo], disabledWithAuthProxy: true, showAbout: true } },
|
||||
@ -40,10 +40,10 @@ const router = createRouter({
|
||||
{ path: '/webauthn/lost', name: 'webauthn.lost', component: () => import('../views/auth/RequestReset.vue'), meta: { middlewares: [setReturnTo], disabledWithAuthProxy: true, showAbout: true } },
|
||||
{ path: '/webauthn/recover', name: 'webauthn.recover', component: () => import('../views/auth/webauthn/Recover.vue'), meta: { middlewares: [setReturnTo], disabledWithAuthProxy: true, showAbout: true } },
|
||||
|
||||
{ path: '/about', name: 'about', component: () => import('../views/About.vue'), meta: { showAbout: true } },
|
||||
{ path: '/error', name: 'genericError', component: () => import('../views/Error.vue'), meta: { middlewares: [noEmptyError] } },
|
||||
{ path: '/404', name: '404', component: () => import('../views/Error.vue'), props: true },
|
||||
{ path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('../views/Error.vue'), props: true },
|
||||
{ path: '/about', name: 'about', component: () => import('../views/About.vue'), meta: { showAbout: true, watchedByKicker: true } },
|
||||
{ path: '/error', name: 'genericError', component: () => import('../views/Error.vue'), meta: { middlewares: [noEmptyError], watchedByKicker: true } },
|
||||
{ path: '/404', name: '404', component: () => import('../views/Error.vue'), meta: { watchedByKicker: true }, props: true },
|
||||
{ path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('../views/Error.vue'), meta: { watchedByKicker: true }, props: true },
|
||||
]
|
||||
})
|
||||
|
||||
|
4
resources/js_vue3/services/authService.js
vendored
4
resources/js_vue3/services/authService.js
vendored
@ -7,8 +7,8 @@ export default {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
logout() {
|
||||
return webClient.get('/user/logout')
|
||||
logout(config = {}) {
|
||||
return webClient.get('/user/logout', { ...config })
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -58,7 +58,7 @@ export const httpClientFactory = (endpoint = 'api') => {
|
||||
|
||||
if (error.response && [401].includes(error.response.status)) {
|
||||
const user = useUserStore()
|
||||
user.reset()
|
||||
user.tossOut()
|
||||
}
|
||||
|
||||
// Always return the form validation errors
|
||||
|
19
resources/js_vue3/stores/user.js
vendored
19
resources/js_vue3/stores/user.js
vendored
@ -58,6 +58,7 @@ export const useUserStore = defineStore({
|
||||
*/
|
||||
logout(options = {}) {
|
||||
const { kicked } = options
|
||||
const notify = useNotifyStore()
|
||||
|
||||
// async appLogout(evt) {
|
||||
if (this.$2fauth.config.proxyAuth) {
|
||||
@ -67,21 +68,29 @@ export const useUserStore = defineStore({
|
||||
else return false
|
||||
}
|
||||
else {
|
||||
return authService.logout().then(() => {
|
||||
this.reset()
|
||||
authService.logout({ returnError: true }).then(() => {
|
||||
if (kicked) {
|
||||
const notify = useNotifyStore()
|
||||
notify.clear()
|
||||
notify.warn({ text: trans('auth.autolock_triggered_punchline'), duration:-1 })
|
||||
}
|
||||
this.tossOut()
|
||||
})
|
||||
.catch(error => {
|
||||
// The logout request will receive a 401 response when the
|
||||
// backend has already detect inactivity on its side. In this case we
|
||||
// don't want any error to be displayed.
|
||||
if (error.response.status !== 401) {
|
||||
notify.error(error)
|
||||
}
|
||||
else this.tossOut()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets all user data
|
||||
* Resets all user data and push out
|
||||
*/
|
||||
reset() {
|
||||
tossOut() {
|
||||
this.$reset()
|
||||
this.initDataStores()
|
||||
this.applyUserPrefs()
|
||||
|
@ -27,7 +27,7 @@
|
||||
'register' => 'Register',
|
||||
'welcome_to_2fauth' => 'Welcome to 2FAuth',
|
||||
'autolock_triggered' => 'Auto lock triggered',
|
||||
'autolock_triggered_punchline' => 'Auto-lock triggered and logged you out',
|
||||
'autolock_triggered_punchline' => 'Auto-lock triggered, you\'ve been logged out',
|
||||
'already_authenticated' => 'Already authenticated, please log out first',
|
||||
'authentication' => 'Authentication',
|
||||
'maybe_later' => 'Maybe later',
|
||||
|
Loading…
Reference in New Issue
Block a user