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() {
|
created() {
|
||||||
// The basic app is created... Currently showing a loading screen (as soon as mounted)
|
// 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');
|
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>
|
</script>
|
||||||
|
@ -35,6 +35,10 @@ export default new class {
|
|||||||
return !!localStorage.getItem(LOCAL_STORAGE_KEY)
|
return !!localStorage.getItem(LOCAL_STORAGE_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearTokenFromLocalStorage() {
|
||||||
|
localStorage.removeItem(LOCAL_STORAGE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
_performApiCall(method, url, data, precheckToken, expectedStatus, errorTexts = COMMON_ERROR_CODES) {
|
_performApiCall(method, url, data, precheckToken, expectedStatus, errorTexts = COMMON_ERROR_CODES) {
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -86,7 +90,7 @@ export default new class {
|
|||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
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",
|
401: "Invalid credentials",
|
||||||
...COMMON_ERROR_CODES
|
...COMMON_ERROR_CODES
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
|
@ -16,20 +16,55 @@
|
|||||||
<b-nav-item to="/about">About</b-nav-item>
|
<b-nav-item to="/about">About</b-nav-item>
|
||||||
</b-navbar-nav>
|
</b-navbar-nav>
|
||||||
|
|
||||||
|
|
||||||
<b-navbar-nav class="ml-auto" v-if="$store.getters.isLoggedIn">
|
<b-navbar-nav class="ml-auto" v-if="$store.getters.isLoggedIn">
|
||||||
<b-nav-item-dropdown :text="$store.state.userdata.name" right>
|
<b-nav-item-dropdown right no-caret>
|
||||||
<b-dropdown-text>Lorem Ipsum dolor sit amaet</b-dropdown-text>
|
<template #button-content>
|
||||||
<b-dropdown-item href="#">Logout</b-dropdown-item>
|
<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-nav-item-dropdown>
|
||||||
</b-navbar-nav>
|
</b-navbar-nav>
|
||||||
|
|
||||||
|
|
||||||
</b-collapse>
|
</b-collapse>
|
||||||
</b-navbar>
|
</b-navbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
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>
|
</script>
|
||||||
|
|
||||||
|
35
src/main.js
35
src/main.js
@ -15,6 +15,41 @@ Vue.prototype.$api = api
|
|||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
Vue.use(IconsPlugin)
|
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({
|
new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
|
@ -2,13 +2,18 @@
|
|||||||
<b-container>
|
<b-container>
|
||||||
<b-row>
|
<b-row>
|
||||||
<b-col class="mx-auto" cols="12" lg="4" sm="8">
|
<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">
|
<b-card class="mt-5">
|
||||||
<div class="my-4 text-center">
|
<div class="my-4 text-center">
|
||||||
<b-img src="@/assets/musicbrainz.svg" id="provider-banner"/>
|
<b-img src="@/assets/musicbrainz.svg" id="provider-banner"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="my-2 text-center text-danger" v-if="authFailed">
|
||||||
|
Username or password invalid!
|
||||||
|
</div>
|
||||||
<div class="mt-4">
|
<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
|
<b-form-group
|
||||||
id="input-group-1"
|
id="input-group-1"
|
||||||
label="Username:"
|
label="Username:"
|
||||||
@ -20,6 +25,7 @@
|
|||||||
required
|
required
|
||||||
placeholder=""
|
placeholder=""
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
|
:state="formState"
|
||||||
></b-form-input>
|
></b-form-input>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
|
|
||||||
@ -33,6 +39,7 @@
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
type="password"
|
type="password"
|
||||||
|
:state="formState"
|
||||||
></b-form-input>
|
></b-form-input>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
|
|
||||||
@ -41,9 +48,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</b-form>
|
</b-form>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</b-card>
|
</b-card>
|
||||||
|
</b-overlay>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
</b-container>
|
</b-container>
|
||||||
@ -57,12 +64,43 @@ export default {
|
|||||||
form: {
|
form: {
|
||||||
username: "",
|
username: "",
|
||||||
password: ""
|
password: ""
|
||||||
}
|
},
|
||||||
|
processing: false,
|
||||||
|
authFailed: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
performLogin() {
|
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