mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
improve connection state detection
blocks all api calls until we are sure the user is connected. if session has expired, force reconnection.
This commit is contained in:
parent
bd148897f8
commit
88d7b736e2
5 changed files with 66 additions and 21 deletions
|
@ -9,7 +9,7 @@
|
||||||
{{ $t('user_interface_link') }} <icon iname="user" class="sm"/>
|
{{ $t('user_interface_link') }} <icon iname="user" class="sm"/>
|
||||||
</b-button>
|
</b-button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" v-bind:hidden="!connected">
|
<li class="nav-item" v-show="connected">
|
||||||
<b-button @click.prevent="logout" to="/logout" variant="outline-dark" block size="sm" >
|
<b-button @click.prevent="logout" to="/logout" variant="outline-dark" block size="sm" >
|
||||||
{{ $t('logout') }} <icon iname="sign-out" class="sm"/>
|
{{ $t('logout') }} <icon iname="sign-out" class="sm"/>
|
||||||
</b-button>
|
</b-button>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<router-view/>
|
<router-view v-if="isReady"/>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
|
@ -34,7 +34,11 @@
|
||||||
<b-nav-item href="https://donate.yunohost.org/" target="_blank" link-classes='text-secondary'>
|
<b-nav-item href="https://donate.yunohost.org/" target="_blank" link-classes='text-secondary'>
|
||||||
<icon iname="heart" class="sm"/> Donate
|
<icon iname="heart" class="sm"/> Donate
|
||||||
</b-nav-item>
|
</b-nav-item>
|
||||||
<b-nav-text class="ml-auto" id="yunohost-version">version</b-nav-text>
|
<i18n v-if="yunohostInfos" path="footer_version" tag="b-nav-text" class="ml-auto" id="yunohost-version">
|
||||||
|
<template v-slot:ynh><b-link href="https://yunohost.org">YunoHost</b-link></template>
|
||||||
|
<template v-slot:version>{{ yunohostInfos.version }}</template>
|
||||||
|
<template v-slot:repo>{{ yunohostInfos.repo }}</template>
|
||||||
|
</i18n>
|
||||||
</b-nav>
|
</b-nav>
|
||||||
</nav>
|
</nav>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -42,25 +46,54 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
import api from '@/helpers/api'
|
import api from '@/helpers/api'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
computed: {
|
data: () => {
|
||||||
connected: function () {
|
return {
|
||||||
return this.$store.state.connected
|
// isReady blocks the rendering of the rooter-view until we have a true info
|
||||||
|
// about the connected state of the user.
|
||||||
|
isReady: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['connected', 'yunohostInfos']),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async logout() {
|
async logout() {
|
||||||
const disconnected = await api.logout()
|
await api.logout()
|
||||||
if (disconnected) {
|
this.$store.commit('CONNECTED', false);
|
||||||
this.$store.commit('CONNECTED', false);
|
this.$router.push('/login')
|
||||||
this.$router.push('/login')
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
// This hook is only triggered at page reload so the value of state.connected
|
||||||
|
// always come from the localStorage
|
||||||
|
async created() {
|
||||||
|
if (!this.$store.state.connected) {
|
||||||
|
// user is not connected: allow the login view to be rendered.
|
||||||
|
this.isReady = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// localStorage 'connected' value may be true, but session may have expired.
|
||||||
|
// Try to get the yunohost version.
|
||||||
|
try {
|
||||||
|
const data = await api.getVersion()
|
||||||
|
this.$store.commit('YUNOHOST_INFOS', data.yunohost)
|
||||||
|
} catch (err) {
|
||||||
|
// Session expired, reset the 'connected' state and redirect with a query
|
||||||
|
// FIXME is there a case where the error may not be a 401 therefor requires
|
||||||
|
// better handling ?
|
||||||
|
this.$store.commit('CONNECTED', false);
|
||||||
|
this.$router.push({name: 'login', query: {redirect: this.$route.path}})
|
||||||
|
} finally {
|
||||||
|
// in any case allow the router-view to be rendered
|
||||||
|
this.isReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -99,12 +132,12 @@ footer {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
|
|
||||||
li {
|
.nav-item {
|
||||||
&:not(:first-child) a::before {
|
&:not(:first-child) a::before {
|
||||||
content: "•";
|
content: "•";
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: -1rem;
|
margin-left: -1.15rem;
|
||||||
}
|
}
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-left: -1rem;
|
margin-left: -1rem;
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
"everything_good": "Everything good!",
|
"everything_good": "Everything good!",
|
||||||
"experimental_warning": "Warning: this feature is experimental and not consider stable, you shouldn't be using it except if you know what you are doing.",
|
"experimental_warning": "Warning: this feature is experimental and not consider stable, you shouldn't be using it except if you know what you are doing.",
|
||||||
"firewall": "Firewall",
|
"firewall": "Firewall",
|
||||||
"footer_version": "Powered by <a href='https://yunohost.org'>YunoHost</a> %s (%s).",
|
"footer_version": "Powered by {ynh} {version} ({repo}).",
|
||||||
"form_input_example": "Example: %s",
|
"form_input_example": "Example: %s",
|
||||||
"from_to": "from %s to %s",
|
"from_to": "from %s to %s",
|
||||||
"good_practices_about_admin_password": "You are now about to define a new admin password. The password should be at least 8 characters - though it is good practice to use longer password (i.e. a passphrase) and/or to use various kind of characters (uppercase, lowercase, digits and special characters).",
|
"good_practices_about_admin_password": "You are now about to define a new admin password. The password should be at least 8 characters - though it is good practice to use longer password (i.e. a passphrase) and/or to use various kind of characters (uppercase, lowercase, digits and special characters).",
|
||||||
|
|
|
@ -18,7 +18,7 @@ router.beforeEach((to, from, next) => {
|
||||||
if (store.state.connected || to.meta.noAuth) {
|
if (store.state.connected || to.meta.noAuth) {
|
||||||
next()
|
next()
|
||||||
} else {
|
} else {
|
||||||
next({path: '/login', query: {redirect: to.path}})
|
next({name: 'login', query: {redirect: to.path}})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,24 @@ Vue.use(Vuex)
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
connected: localStorage.getItem('connected') === 'true'
|
connected: localStorage.getItem('connected') === 'true',
|
||||||
|
yunohostInfos: null
|
||||||
},
|
},
|
||||||
|
// Mutations must be synchronous. They are used to change the store state.
|
||||||
mutations: {
|
mutations: {
|
||||||
['CONNECTED'] (state, connected) {
|
['CONNECTED'] (state, connected) {
|
||||||
localStorage.setItem('connected', connected)
|
localStorage.setItem('connected', connected)
|
||||||
state.connected = connected
|
state.connected = connected
|
||||||
|
if (!connected) {
|
||||||
|
state.yunohostInfos = null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
['YUNOHOST_INFOS'] (state, data) {
|
||||||
|
console.log('version changed', data);
|
||||||
|
state.yunohostInfos = data
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
// Actions may be asynchronous. They are used to commit mutations.
|
||||||
actions: {
|
actions: {
|
||||||
},
|
},
|
||||||
modules: {
|
modules: {
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
v-model="password"
|
v-model="password"
|
||||||
type="password"
|
type="password"
|
||||||
:placeholder="$t('administration_password')"
|
:placeholder="$t('administration_password')"
|
||||||
:state="state"
|
:state="isValid"
|
||||||
></b-form-input>
|
></b-form-input>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<b-button type="submit" variant="success">{{ $t('login') }}</b-button>
|
<b-button type="submit" variant="success">{{ $t('login') }}</b-button>
|
||||||
</template>
|
</template>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
<b-form-invalid-feedback :state="state">
|
<b-form-invalid-feedback :state="isValid">
|
||||||
{{ $t('wrong_password') }}
|
{{ $t('wrong_password') }}
|
||||||
</b-form-invalid-feedback>
|
</b-form-invalid-feedback>
|
||||||
</b-form>
|
</b-form>
|
||||||
|
@ -33,7 +33,7 @@ export default {
|
||||||
data: () => {
|
data: () => {
|
||||||
return {
|
return {
|
||||||
password: '',
|
password: '',
|
||||||
state: null,
|
isValid: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -42,9 +42,11 @@ export default {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
this.$store.commit('CONNECTED', true);
|
this.$store.commit('CONNECTED', true);
|
||||||
this.$router.push(this.$route.query.redirect || '/')
|
this.$router.push(this.$route.query.redirect || '/')
|
||||||
|
const infos = await api.getVersion();
|
||||||
|
this.$store.commit('YUNOHOST_INFOS', infos.yunohost)
|
||||||
} else {
|
} else {
|
||||||
this.$store.commit('CONNECTED', false);
|
this.$store.commit('CONNECTED', false);
|
||||||
this.state = false
|
this.isValid = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue