[frontend]: Базовый логин

This commit is contained in:
2022-09-11 15:41:14 +03:00
parent f922daaa80
commit 818bb9db81
14 changed files with 470 additions and 79 deletions

View File

@@ -11,7 +11,11 @@
"axios": "^0.27.2",
"bootstrap": "^5.2.1",
"core-js": "^3.8.3",
"vue": "^3.2.13"
"vee-validate": "^4.6.7",
"vue": "^3.2.13",
"vue-router": "^4.1.5",
"vuex": "^4.0.2",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.12.16",
@@ -1665,7 +1669,6 @@
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dev": true,
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
@@ -2182,6 +2185,11 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true
},
"node_modules/@types/lodash": {
"version": "4.14.185",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.185.tgz",
"integrity": "sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA=="
},
"node_modules/@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -2880,6 +2888,11 @@
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
"dev": true
},
"node_modules/@vue/devtools-api": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
"integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
},
"node_modules/@vue/reactivity": {
"version": "3.2.39",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.39.tgz",
@@ -7176,8 +7189,12 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
@@ -7757,6 +7774,11 @@
"thenify-all": "^1.0.0"
}
},
"node_modules/nanoclone": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
},
"node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -8995,6 +9017,11 @@
"webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0"
}
},
"node_modules/property-expr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -9207,8 +9234,7 @@
"node_modules/regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
"dev": true
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"node_modules/regenerator-transform": {
"version": "0.15.0",
@@ -10314,6 +10340,11 @@
"node": ">=0.6"
}
},
"node_modules/toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
},
"node_modules/totalist": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz",
@@ -10517,6 +10548,17 @@
"node": ">= 0.8"
}
},
"node_modules/vee-validate": {
"version": "4.6.7",
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.6.7.tgz",
"integrity": "sha512-8W9cR/EGqPuHJpodYriAlp5BndQf/IWFifZLyIWeNs7RGB+B0jr50TACjzgtwtp5qE6hgRskOToEhcfhWJdgyw==",
"dependencies": {
"@vue/devtools-api": "^6.1.4"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue": {
"version": "3.2.39",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.2.39.tgz",
@@ -10720,6 +10762,20 @@
"node": ">=8"
}
},
"node_modules/vue-router": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.5.tgz",
"integrity": "sha512-IsvoF5D2GQ/EGTs/Th4NQms9gd2NSqV+yylxIyp/OYp8xOwxmU8Kj/74E9DTSYAyH5LX7idVUngN3JSj1X4xcQ==",
"dependencies": {
"@vue/devtools-api": "^6.1.4"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@@ -10742,6 +10798,17 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"node_modules/vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"dependencies": {
"@vue/devtools-api": "^6.0.0-beta.11"
},
"peerDependencies": {
"vue": "^3.0.2"
}
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
@@ -11470,6 +11537,23 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
"dev": true
},
"node_modules/yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
"dependencies": {
"@babel/runtime": "^7.15.4",
"@types/lodash": "^4.14.175",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nanoclone": "^0.2.1",
"property-expr": "^2.0.4",
"toposort": "^2.0.2"
},
"engines": {
"node": ">=10"
}
}
},
"dependencies": {
@@ -12605,7 +12689,6 @@
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
}
@@ -13040,6 +13123,11 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true
},
"@types/lodash": {
"version": "4.14.185",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.185.tgz",
"integrity": "sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA=="
},
"@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -13605,6 +13693,11 @@
}
}
},
"@vue/devtools-api": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
"integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
},
"@vue/reactivity": {
"version": "3.2.39",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.39.tgz",
@@ -16800,8 +16893,12 @@
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash.debounce": {
"version": "4.0.8",
@@ -17252,6 +17349,11 @@
"thenify-all": "^1.0.0"
}
},
"nanoclone": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
},
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -18105,6 +18207,11 @@
"log-update": "^2.3.0"
}
},
"property-expr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
},
"proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -18264,8 +18371,7 @@
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
"dev": true
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regenerator-transform": {
"version": "0.15.0",
@@ -19115,6 +19221,11 @@
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"dev": true
},
"toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
},
"totalist": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz",
@@ -19263,6 +19374,14 @@
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"dev": true
},
"vee-validate": {
"version": "4.6.7",
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.6.7.tgz",
"integrity": "sha512-8W9cR/EGqPuHJpodYriAlp5BndQf/IWFifZLyIWeNs7RGB+B0jr50TACjzgtwtp5qE6hgRskOToEhcfhWJdgyw==",
"requires": {
"@vue/devtools-api": "^6.1.4"
}
},
"vue": {
"version": "3.2.39",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.2.39.tgz",
@@ -19413,6 +19532,14 @@
}
}
},
"vue-router": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.5.tgz",
"integrity": "sha512-IsvoF5D2GQ/EGTs/Th4NQms9gd2NSqV+yylxIyp/OYp8xOwxmU8Kj/74E9DTSYAyH5LX7idVUngN3JSj1X4xcQ==",
"requires": {
"@vue/devtools-api": "^6.1.4"
}
},
"vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@@ -19437,6 +19564,14 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.11"
}
},
"watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
@@ -19977,6 +20112,20 @@
"dev": true
}
}
},
"yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
"requires": {
"@babel/runtime": "^7.15.4",
"@types/lodash": "^4.14.175",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nanoclone": "^0.2.1",
"property-expr": "^2.0.4",
"toposort": "^2.0.2"
}
}
}
}

View File

@@ -11,7 +11,11 @@
"axios": "^0.27.2",
"bootstrap": "^5.2.1",
"core-js": "^3.8.3",
"vue": "^3.2.13"
"vee-validate": "^4.6.7",
"vue": "^3.2.13",
"vue-router": "^4.1.5",
"vuex": "^4.0.2",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.12.16",

View File

@@ -1,11 +1,69 @@
<template>
<div id="app" class="app">
<NavigationBar />
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">WhereToGo</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<div v-if="!currentUser" class="navbar-nav ml-auto">
<li class="nav-item">
<router-link to="/register" class="nav-link">
Sign Up
</router-link>
</li>
<li class="nav-item">
<router-link to="/login" class="nav-link">
Login
</router-link>
</li>
</div>
<div v-if="currentUser" class="navbar-nav ml-auto">
<li class="nav-item">
<router-link to="/profile" class="nav-link">
{{ currentUser.username }}
</router-link>
</li>
<li class="nav-item">
<a class="nav-link" @click.prevent="logOut">
LogOut
</a>
</li>
</div>
</ul>
</div>
</div>
</nav>
<div class="container">
<router-view />
</div>
</div>
</template>
<script>
export default {
name: "App",
computed: {
currentUser() {
return this.$store.state.auth.user;
},
showAdminBoard() {
if (this.currentUser && this.currentUser["roles"]) {
return this.currentUser["roles"].includes("ROLE_ADMIN");
}
return false;
},
showModeratorBoard() {
if (this.currentUser && this.currentUser["roles"]) {
return this.currentUser["roles"].includes("ROLE_MODERATOR");
}
return false;
},
},
methods: {
logOut() {
this.$store.dispatch("auth/logout");
this.$router.push("/login");
},
},
};
</script>

View File

@@ -0,0 +1,87 @@
<template>
<div class="container col-xl-10 col-xxl-8 px-4 py-5">
<div class="row align-items-center g-lg-5 py-5">
<div class="col-md-10 mx-auto col-lg-5">
<div class="card card-container">
<Form @submit="handleLogin" :validation-schema="schema"
class="p-4 p-md-5 border rounded-3 bg-light">
<div class="form-group">
<label for="username">Username</label>
<Field name="username" type="text" class="form-control" />
<ErrorMessage name="username" class="error-feedback" />
</div>
<div class="form-group">
<label for="password">Password</label>
<Field name="password" type="password" class="form-control" />
<ErrorMessage name="password" class="error-feedback" />
</div>
<br>
<div class="form-group">
<button class="btn btn-primary btn-block" :disabled="loading">
<span v-show="loading" class="spinner-border spinner-border-sm"></span>
<span>Login</span>
</button>
</div>
<div class="form-group">
<div v-if="message" class="alert alert-danger" role="alert">
{{ message }}
</div>
</div>
</Form>
</div>
</div>
</div>
</div>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
name: "LoginPage",
components: {
Form,
Field,
ErrorMessage,
},
data() {
const schema = yup.object().shape({
username: yup.string().required("Username is required!"),
password: yup.string().required("Password is required!"),
});
return {
loading: false,
message: "",
schema,
};
},
computed: {
loggedIn() {
return this.$store.state.auth.status.loggedIn;
},
},
created() {
if (this.loggedIn) {
this.$router.push("/profile");
}
},
methods: {
handleLogin(user) {
this.loading = true;
this.$store.dispatch("auth/login", user).then(
() => {
this.$router.push("/profile");
},
(error) => {
this.loading = false;
this.message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
}
);
},
},
};
</script>

View File

@@ -0,0 +1,12 @@
<template>
<div class="container">
<header class="jumbotron">
<h3>Тест</h3>
</header>
</div>
</template>
<script>
export default {
name: "MapPAge",
};
</script>

View File

@@ -1,54 +0,0 @@
<template>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">WhereToGo</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="">Map</a>
</li>
</ul>
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item dropdown">
<a
class="nav-link dropdown-toggle"
href="#"
id="navbarDropdownMenuLink"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Username
</a>
<ul
class="dropdown-menu dropdown-menu-end"
aria-labelledby="navbarDropdownMenuLink"
>
<li>
<a class="dropdown-item" href="">Admin page</a>
</li>
<li>
<a class="dropdown-item" href="">Change E-Mail</a>
</li>
<li>
<a class="dropdown-item" href="">Sign Out</a>
</li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="">Sign In</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">Sign Up</a>
</li>
</ul>
</div>
</div>
</nav>
</template>
<script>
export default {
name: "NavigationBar",
};
</script>

View File

@@ -1,15 +1,10 @@
import { createApp } from "vue";
import App from "./App.vue";
import axios from "axios";
import App from "@/App.vue";
import router from "./router";
import store from "./store";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.min.js";
import NavigationBar from "./components/NavigationBar.vue";
const app = createApp(App);
app.config.globalProperties.axios = axios;
app.component("NavigationBar", NavigationBar);
const app = createApp(App).use(router).use(store);
app.mount("#app");

View File

@@ -0,0 +1,19 @@
import { createWebHistory, createRouter } from "vue-router";
import MapPage from "./components/MapPage.vue";
import LoginPage from "./components/LoginPage.vue";
const routes = [
{
path: "/",
name: "map",
component: MapPage,
},
{
path: "/login",
component: LoginPage,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;

View File

@@ -0,0 +1,8 @@
export default function authHeader() {
let user = JSON.parse(localStorage.getItem('user'));
if (user && user.accessToken) {
return { Authorization: 'Bearer ' + user.accessToken };
} else {
return {};
}
}

View File

@@ -0,0 +1,28 @@
import axios from "axios";
const API_URL = "http://localhost:8000/api/auth/";
class AuthService {
login(user) {
return axios
.post(API_URL + "token", {
username: user.username,
password: user.password,
})
.then((response) => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
logout() {
localStorage.removeItem("user");
}
register(user) {
return axios.post(API_URL + "signup", {
username: user.username,
email: user.email,
password: user.password,
});
}
}
export default new AuthService();

View File

@@ -0,0 +1,18 @@
import axios from 'axios';
import authHeader from './auth-header';
const API_URL = 'http://localhost:8000/api/auth/user/';
class UserService {
getPublicContent() {
return axios.get(API_URL + 'all');
}
getUserBoard() {
return axios.get(API_URL + 'user', { headers: authHeader() });
}
getModeratorBoard() {
return axios.get(API_URL + 'mod', { headers: authHeader() });
}
getAdminBoard() {
return axios.get(API_URL + 'admin', { headers: authHeader() });
}
}
export default new UserService();

View File

@@ -0,0 +1,59 @@
import AuthService from '../services/auth.service.js';
const user = JSON.parse(localStorage.getItem('user'));
const initialState = user
? { status: { loggedIn: true }, user }
: { status: { loggedIn: false }, user: null };
export const auth = {
namespaced: true,
state: initialState,
actions: {
login({ commit }, user) {
return AuthService.login(user).then(
user => {
commit('loginSuccess', user);
return Promise.resolve(user);
},
error => {
commit('loginFailure');
return Promise.reject(error);
}
);
},
logout({ commit }) {
AuthService.logout();
commit('logout');
},
register({ commit }, user) {
return AuthService.register(user).then(
response => {
commit('registerSuccess');
return Promise.resolve(response.data);
},
error => {
commit('registerFailure');
return Promise.reject(error);
}
);
}
},
mutations: {
loginSuccess(state, user) {
state.status.loggedIn = true;
state.user = user;
},
loginFailure(state) {
state.status.loggedIn = false;
state.user = null;
},
logout(state) {
state.status.loggedIn = false;
state.user = null;
},
registerSuccess(state) {
state.status.loggedIn = false;
},
registerFailure(state) {
state.status.loggedIn = false;
}
}
};

View File

@@ -0,0 +1,8 @@
import { createStore } from "vuex";
import { auth } from "./auth.module.js";
const store = createStore({
modules: {
auth,
},
});
export default store;