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>
|
<script setup>
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const kickUser = ref(null)
|
||||||
const kickUserAfter = ref(null)
|
const kickUserAfter = ref(null)
|
||||||
const isProtectedRoute = ref(null)
|
const isProtectedRoute = ref(route.meta.watchedByKicker)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.name,
|
() => 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 () => {
|
onBeforeMount(async () => {
|
||||||
const { useUserStore } = await import('./stores/user.js')
|
const { useUserStore } = await import('./stores/user.js')
|
||||||
@ -19,7 +20,7 @@
|
|||||||
const user = useUserStore()
|
const user = useUserStore()
|
||||||
|
|
||||||
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
||||||
isProtectedRoute.value = protectedRoute(route)
|
kickUser.value = user.isAuthenticated
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => user.preferences.kickUserAfter,
|
() => user.preferences.kickUserAfter,
|
||||||
@ -27,23 +28,17 @@
|
|||||||
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
kickUserAfter.value = parseInt(user.preferences.kickUserAfter)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
watch(
|
||||||
|
() => user.isAuthenticated,
|
||||||
|
() => {
|
||||||
|
kickUser.value = user.isAuthenticated
|
||||||
|
}
|
||||||
|
)
|
||||||
watch(language, () => {
|
watch(language, () => {
|
||||||
user.applyLanguage()
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -59,5 +54,5 @@
|
|||||||
<main class="main-section">
|
<main class="main-section">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</main>
|
</main>
|
||||||
<kicker v-if="kickInactiveUser" :kickAfter="kickUserAfter"></kicker>
|
<kicker v-if="kickUser && kickUserAfter > 0 && isProtectedRoute" :kickAfter="kickUserAfter"></kicker>
|
||||||
</template>
|
</template>
|
@ -2,7 +2,7 @@
|
|||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
const user = useUserStore()
|
const user = useUserStore()
|
||||||
const events = ref(['click', 'mousedown', 'scroll', 'keypress', 'load'])
|
const events = ref(['mousedown', 'scroll', 'keypress'])
|
||||||
const logoutTimer = ref(null)
|
const logoutTimer = ref(null)
|
||||||
// const elapsed = ref(0)
|
// const elapsed = ref(0)
|
||||||
// const counter = ref(null)
|
// const counter = ref(null)
|
||||||
@ -14,45 +14,54 @@
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.kickAfter,
|
||||||
|
() => {
|
||||||
|
restartTimer()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
events.value.forEach(function (event) {
|
events.value.forEach(function (event) {
|
||||||
window.addEventListener(event, resetTimer)
|
window.addEventListener(event, restartTimer)
|
||||||
}, this)
|
}, this)
|
||||||
|
|
||||||
setTimer()
|
startTimer()
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
events.value.forEach(function (event) {
|
events.value.forEach(function (event) {
|
||||||
window.removeEventListener(event, resetTimer)
|
window.removeEventListener(event, restartTimer)
|
||||||
}, this)
|
}, this)
|
||||||
|
|
||||||
clearTimeout(logoutTimer.value)
|
stopTimer()
|
||||||
// clearInterval(counter.value)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function setTimer() {
|
function startTimer() {
|
||||||
// elapsed.value = 0
|
|
||||||
// clearInterval(counter.value)
|
|
||||||
|
|
||||||
logoutTimer.value = setTimeout(logoutUser, props.kickAfter * 60 * 1000)
|
logoutTimer.value = setTimeout(logoutUser, props.kickAfter * 60 * 1000)
|
||||||
// counter.value = setInterval(() => {
|
// counter.value = setInterval(() => {
|
||||||
// elapsed.value += 1
|
// elapsed.value += 1
|
||||||
// console.log(elapsed.value + '/' + props.kickAfter * 60)
|
// console.log(elapsed.value + '/' + props.kickAfter * 60)
|
||||||
// }, 1000);
|
// }, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triggers the user logout
|
// Triggers the user logout
|
||||||
function logoutUser() {
|
function logoutUser() {
|
||||||
clearTimeout(logoutTimer.value)
|
clearTimeout(logoutTimer.value)
|
||||||
console.log('inativity detected, user kicked out')
|
|
||||||
|
|
||||||
user.logout({ kicked: true})
|
user.logout({ kicked: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetTimer() {
|
// Restarts the timer
|
||||||
|
function restartTimer() {
|
||||||
|
stopTimer()
|
||||||
|
startTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stops the timer
|
||||||
|
function stopTimer() {
|
||||||
clearTimeout(logoutTimer.value)
|
clearTimeout(logoutTimer.value)
|
||||||
setTimer()
|
// elapsed.value = 0
|
||||||
|
// clearInterval(counter.value)
|
||||||
}
|
}
|
||||||
</script>
|
</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({
|
const router = createRouter({
|
||||||
history: createWebHistory('/'),
|
history: createWebHistory('/'),
|
||||||
routes: [
|
routes: [
|
||||||
{ path: '/start', name: 'start', component: () => import('../views/Start.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] } },
|
{ 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: '/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] } },
|
{ 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] } },
|
{ 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] }, props: 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] } },
|
{ 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: '/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] } },
|
{ 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] }, props: 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/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], 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], showAbout: true, props: 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], 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], showAbout: 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: '/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 } },
|
{ 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/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: '/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: '/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] } },
|
{ path: '/error', name: 'genericError', component: () => import('../views/Error.vue'), meta: { middlewares: [noEmptyError], watchedByKicker: true } },
|
||||||
{ path: '/404', name: '404', component: () => import('../views/Error.vue'), props: true },
|
{ path: '/404', name: '404', component: () => import('../views/Error.vue'), meta: { watchedByKicker: true }, props: true },
|
||||||
{ path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('../views/Error.vue'), 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() {
|
logout(config = {}) {
|
||||||
return webClient.get('/user/logout')
|
return webClient.get('/user/logout', { ...config })
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +58,7 @@ export const httpClientFactory = (endpoint = 'api') => {
|
|||||||
|
|
||||||
if (error.response && [401].includes(error.response.status)) {
|
if (error.response && [401].includes(error.response.status)) {
|
||||||
const user = useUserStore()
|
const user = useUserStore()
|
||||||
user.reset()
|
user.tossOut()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always return the form validation errors
|
// 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 = {}) {
|
logout(options = {}) {
|
||||||
const { kicked } = options
|
const { kicked } = options
|
||||||
|
const notify = useNotifyStore()
|
||||||
|
|
||||||
// async appLogout(evt) {
|
// async appLogout(evt) {
|
||||||
if (this.$2fauth.config.proxyAuth) {
|
if (this.$2fauth.config.proxyAuth) {
|
||||||
@ -67,21 +68,29 @@ export const useUserStore = defineStore({
|
|||||||
else return false
|
else return false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return authService.logout().then(() => {
|
authService.logout({ returnError: true }).then(() => {
|
||||||
this.reset()
|
|
||||||
if (kicked) {
|
if (kicked) {
|
||||||
const notify = useNotifyStore()
|
|
||||||
notify.clear()
|
notify.clear()
|
||||||
notify.warn({ text: trans('auth.autolock_triggered_punchline'), duration:-1 })
|
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.$reset()
|
||||||
this.initDataStores()
|
this.initDataStores()
|
||||||
this.applyUserPrefs()
|
this.applyUserPrefs()
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
'register' => 'Register',
|
'register' => 'Register',
|
||||||
'welcome_to_2fauth' => 'Welcome to 2FAuth',
|
'welcome_to_2fauth' => 'Welcome to 2FAuth',
|
||||||
'autolock_triggered' => 'Auto lock triggered',
|
'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',
|
'already_authenticated' => 'Already authenticated, please log out first',
|
||||||
'authentication' => 'Authentication',
|
'authentication' => 'Authentication',
|
||||||
'maybe_later' => 'Maybe later',
|
'maybe_later' => 'Maybe later',
|
||||||
|
Loading…
Reference in New Issue
Block a user