Implemented login/logout
This commit is contained in:
parent
53e8aa9a9c
commit
f85f16e2a5
@ -1 +1 @@
|
||||
VUE_APP_API_LOCATION=http://localhost:5000/
|
||||
VUE_APP_API_LOCATION=http://localhost:5000/api/
|
27
src/App.vue
27
src/App.vue
@ -31,9 +31,34 @@ export default {
|
||||
},
|
||||
created() {
|
||||
// The basic app is created... Currently showing a loading screen (as soon as mounted)
|
||||
this.$store.dispatch('storeUserData','testuser').then(() => {
|
||||
|
||||
if (this.$api.haveToken) {
|
||||
|
||||
this.$api.getMyInfo().then(({name}) => {
|
||||
|
||||
this.$store.dispatch('storeUserData', name).then(() => {
|
||||
this.$router.push('/').catch(() => {});
|
||||
this.$store.dispatch('setAppReady');
|
||||
|
||||
});
|
||||
|
||||
}).catch(({status, text}) => {
|
||||
if (status === 401) {
|
||||
this.$api.clearTokenFromLocalStorage();
|
||||
this.$router.push('/login').catch(() => {});
|
||||
this.$store.dispatch('setAppReady');
|
||||
|
||||
} else {
|
||||
this.$showToast(text);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
this.$router.push('/login').catch(() => {});
|
||||
this.$store.dispatch('setAppReady');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -35,6 +35,10 @@ export default new class {
|
||||
return !!localStorage.getItem(LOCAL_STORAGE_KEY)
|
||||
}
|
||||
|
||||
clearTokenFromLocalStorage() {
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEY);
|
||||
}
|
||||
|
||||
_performApiCall(method, url, data, precheckToken, expectedStatus, errorTexts = COMMON_ERROR_CODES) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -86,7 +90,7 @@ export default new class {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
this._performApiCall('post', '/auth/login', {name, password}, false, 201, {
|
||||
this._performApiCall('post', '/auth/login', {name, password}, false, 200, {
|
||||
401: "Invalid credentials",
|
||||
...COMMON_ERROR_CODES
|
||||
}).then((data) => {
|
||||
|
@ -16,20 +16,55 @@
|
||||
<b-nav-item to="/about">About</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
|
||||
|
||||
<b-navbar-nav class="ml-auto" v-if="$store.getters.isLoggedIn">
|
||||
<b-nav-item-dropdown :text="$store.state.userdata.name" right>
|
||||
<b-dropdown-text>Lorem Ipsum dolor sit amaet</b-dropdown-text>
|
||||
<b-dropdown-item href="#">Logout</b-dropdown-item>
|
||||
<b-nav-item-dropdown right no-caret>
|
||||
<template #button-content>
|
||||
<b-icon icon="person-fill"/>
|
||||
{{ $store.state.userdata.name }}
|
||||
</template>
|
||||
<b-overlay :show="logoutProcessing">
|
||||
|
||||
<b-dropdown-text>Logged in to...</b-dropdown-text>
|
||||
<b-dropdown-text>
|
||||
<b-img src="@/assets/musicbrainz.svg" width="200px"/>
|
||||
</b-dropdown-text>
|
||||
<b-dropdown-divider></b-dropdown-divider>
|
||||
<b-dropdown-item @click="performLogout">Logout</b-dropdown-item>
|
||||
|
||||
</b-overlay>
|
||||
</b-nav-item-dropdown>
|
||||
</b-navbar-nav>
|
||||
|
||||
|
||||
</b-collapse>
|
||||
</b-navbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Navbar"
|
||||
name: "Navbar",
|
||||
data() {
|
||||
return {
|
||||
logoutProcessing: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
performLogout() {
|
||||
this.logoutProcessing = true;
|
||||
this.$api.performLogout().then(() => {
|
||||
this.$store.dispatch('storeUserData', null).then(() => {
|
||||
this.$router.push('/login').catch(() => {
|
||||
});
|
||||
|
||||
this.logoutProcessing = false;
|
||||
})
|
||||
}).catch(({text}) => {
|
||||
this.$showToast(text);
|
||||
this.logoutProcessing = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
35
src/main.js
35
src/main.js
@ -15,6 +15,41 @@ Vue.prototype.$api = api
|
||||
Vue.use(BootstrapVue)
|
||||
Vue.use(IconsPlugin)
|
||||
|
||||
|
||||
Vue.prototype.$showToast = function (text, type = 'error', local=true) {
|
||||
|
||||
let options = {}
|
||||
switch (type) {
|
||||
case "error":
|
||||
options = {
|
||||
title: "Error!",
|
||||
variant: "danger"
|
||||
}
|
||||
break;
|
||||
case "user_error":
|
||||
options = {
|
||||
title: "Warning!",
|
||||
variant: "warning"
|
||||
}
|
||||
break;
|
||||
case "success":
|
||||
options = {
|
||||
title: "Success!",
|
||||
variant: "success"
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const bvToast = local ? this.$bvToast : this.$root.$bvToast
|
||||
|
||||
bvToast.toast(text, {
|
||||
...options,
|
||||
toaster: 'b-toaster-top-center',
|
||||
solid: true,
|
||||
appendToast: false
|
||||
})
|
||||
}
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
|
@ -2,13 +2,18 @@
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-col class="mx-auto" cols="12" lg="4" sm="8">
|
||||
<b-overlay :show="processing" spinner-type="grow" spinner-variant="success" rounded="sm">
|
||||
<b-card class="mt-5">
|
||||
<div class="my-4 text-center">
|
||||
<b-img src="@/assets/musicbrainz.svg" id="provider-banner"/>
|
||||
</div>
|
||||
|
||||
<div class="my-2 text-center text-danger" v-if="authFailed">
|
||||
Username or password invalid!
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
|
||||
<b-form @submit.prevent="performLogin" v-if="true">
|
||||
<b-form @submit.prevent="performLogin" @input="formChanged" v-if="true">
|
||||
<b-form-group
|
||||
id="input-group-1"
|
||||
label="Username:"
|
||||
@ -20,6 +25,7 @@
|
||||
required
|
||||
placeholder=""
|
||||
autocomplete="off"
|
||||
:state="formState"
|
||||
></b-form-input>
|
||||
</b-form-group>
|
||||
|
||||
@ -33,6 +39,7 @@
|
||||
placeholder=""
|
||||
autocomplete="off"
|
||||
type="password"
|
||||
:state="formState"
|
||||
></b-form-input>
|
||||
</b-form-group>
|
||||
|
||||
@ -41,9 +48,9 @@
|
||||
</div>
|
||||
</b-form>
|
||||
|
||||
|
||||
</div>
|
||||
</b-card>
|
||||
</b-overlay>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-container>
|
||||
@ -57,12 +64,43 @@ export default {
|
||||
form: {
|
||||
username: "",
|
||||
password: ""
|
||||
}
|
||||
},
|
||||
processing: false,
|
||||
authFailed: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
performLogin() {
|
||||
this.processing = true;
|
||||
this.$api.performLogin(this.form.username, this.form.password).then(({name}) => {
|
||||
|
||||
this.$store.dispatch('storeUserData', name).then(() => {
|
||||
|
||||
this.$router.push('/').catch(() => {
|
||||
});
|
||||
this.processing = false;
|
||||
|
||||
});
|
||||
|
||||
|
||||
}).catch(({status, text}) => {
|
||||
|
||||
if (status === 401) {
|
||||
this.authFailed = true;
|
||||
} else {
|
||||
this.$showToast(text);
|
||||
}
|
||||
|
||||
this.processing = false;
|
||||
});
|
||||
},
|
||||
formChanged() {
|
||||
this.authFailed = false;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formState() {
|
||||
return this.authFailed ? false : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user