Add Starter middleware & Restore the Data have changed notification

This commit is contained in:
Bubka 2023-10-25 17:26:32 +02:00
parent 4dbbae24dc
commit 8c23aa884f
6 changed files with 73 additions and 30 deletions

View File

@ -47,7 +47,16 @@
</script>
<template>
<notifications id="vueNotification" role="alert" width="100%" position="top" :duration="4000" :speed="0" :max="1" classes="notification is-radiusless" />
<notifications
id="vueNotification"
role="alert"
width="100%"
position="top"
:duration="4000"
:speed="0"
:max="1"
classes="notification is-radiusless"
:dangerouslySetInnerHtml="true" />
<main class="main-section">
<RouterView />
</main>

View File

@ -27,7 +27,8 @@ import EditCredential from '../views/settings/Credentials/Edit.vue'
import Errors from '../views/Error.vue'
import About from '../views/About.vue'
import authGuard from './middlewares/authGuard'
import authGuard from './middlewares/authGuard'
import starter from './middlewares/starter'
import noEmptyError from './middlewares/noEmptyError'
const router = createRouter({
@ -36,7 +37,7 @@ const router = createRouter({
{ path: '/start', name: 'start', component: Start, meta: { middlewares: [authGuard] } },
{ path: '/capture', name: 'capture', component: Capture, meta: { middlewares: [authGuard] } },
{ path: '/accounts', name: 'accounts', component: Accounts, meta: { middlewares: [authGuard] }, alias: '/' },
{ path: '/accounts', name: 'accounts', component: Accounts, meta: { middlewares: [authGuard, starter] }, alias: '/' },
{ path: '/account/create', name: 'createAccount', component: CreateAccount, meta: { middlewares: [authGuard] } },
{ path: '/account/import', name: 'importAccounts', component: ImportAccount, meta: { middlewares: [authGuard] } },
{ path: '/account/:twofaccountId/edit', name: 'editAccount', component: EditAccount, meta: { middlewares: [authGuard] } },

View File

@ -0,0 +1,19 @@
import { useTwofaccounts } from '@/stores/twofaccounts'
/**
* Allows the user to access the main view only if he owns at least one twofaccount.
* Push to the starter view otherwise.
*/
export default function starter({ to, next }) {
const twofaccounts = useTwofaccounts()
if (twofaccounts.isEmpty) {
twofaccounts.refresh().then(() => {
if (twofaccounts.isEmpty) {
next({ name: 'start' });
}
else next()
})
}
else next()
}

View File

@ -51,8 +51,8 @@ export const useTwofaccounts = defineStore({
return state.items.map(a => a.id)
},
isNotEmpty(state) {
return state.items.length > 0
isEmpty(state) {
return state.items.length == 0
},
count(state) {
@ -83,6 +83,32 @@ export const useTwofaccounts = defineStore({
})
},
/**
* Tells if the store is up-to-date with the backend
*/
async isUpToDateWithBackend() {
let isUpToDate = true
await twofaccountService.getAll().then(response => {
isUpToDate = response.data.length === this.items.length
this.items.forEach((item) => {
let matchingBackendItem = response.data.find(e => e.id === item.id)
if (matchingBackendItem == undefined) {
isUpToDate = false
return;
}
for (const field in item) {
if (item[field] != matchingBackendItem[field]) {
isUpToDate = false
return;
}
}
})
})
return isUpToDate
},
/**
* Adds an account to the current selection
*/

View File

@ -51,32 +51,20 @@
* Returns whether or not the accounts should be displayed
*/
const showAccounts = computed(() => {
return twofaccounts.isNotEmpty && !showGroupSwitch.value && !showDestinationGroupSelector.value
return !twofaccounts.isEmpty && !showGroupSwitch.value && !showDestinationGroupSelector.value
})
onMounted(() => {
// we don't have to fetch fresh data so we try to load them from localstorage to avoid display latency
// if( user.preferences.getOtpOnRequest && !this.toRefresh && !this.$route.params.isFirstLoad ) {
// const accounts = this.$storage.get('accounts', null) // use null as fallback if localstorage is empty
// if( accounts ) this.accounts = accounts
// const groups = this.$storage.get('groups', null) // use null as fallback if localstorage is empty
// if( groups ) this.groups = groups
// }
// We fetch fresh data whatever. The user will be notified to reload the page if there are any data changes
twofaccounts.refresh()
groups.refresh()
// if (twofaccounts.count === 0) {
// // No account yet, we force user to land on the start view.
// router.push({ name: 'start' });
// }
// stop OTP generation on modal close
// this.$on('modalClose', function() {
// this.$refs.OtpDisplayer.clearOTP()
// })
onMounted(async () => {
// This SFC is reached only if the user has some twofaccounts in the store (see the starter middleware).
// This allows to display accounts without latency.
// We now check the twofaccounts store state in case the backend data have changed.
const isUpToDate = await twofaccounts.isUpToDateWithBackend()
if (! isUpToDate) {
notify.action({
text: '<span class="is-size-7">' + trans('commons.data_have_changed_on_server_side') + '</span><br /><a href="." class="button is-rounded is-warning is-small">' + trans('commons.reload') + '</a>',
duration: -1
})
}
})
/**

View File

@ -110,7 +110,7 @@
<!-- Footer -->
<VueFooter :showButtons="true" >
<!-- back button -->
<p class="control" v-if="twofaccounts.length > 0">
<p class="control" v-if="! twofaccounts.isEmpty">
<UseColorMode v-slot="{ mode }">
<RouterLink id="lnkBack" class="button is-rounded" :class="{'is-dark' : mode == 'dark'}" :to="{ name: 'accounts' }" >
{{ $t('commons.back') }}