add login and token !
This commit is contained in:
parent
b28c897f5d
commit
0cf8ca8597
21
hn-vue/package-lock.json
generated
21
hn-vue/package-lock.json
generated
@ -9500,6 +9500,11 @@
|
||||
"integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
|
||||
"dev": true
|
||||
},
|
||||
"shvl": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/shvl/-/shvl-2.0.2.tgz",
|
||||
"integrity": "sha512-G3KkIXPza3dgkt6Bo8zIl5K/KvAAhbG6o9KfAjhPvrIIzzAhnfc2ztv1i+iPTbNNM43MaBUqIaZwqVjkSgY/rw=="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
@ -11031,6 +11036,22 @@
|
||||
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.0.tgz",
|
||||
"integrity": "sha512-W74OO2vCJPs9/YjNjW8lLbj+jzT24waTo2KShI8jLvJW8OaIkgb3wuAMA7D+ZiUxDOx3ubwSZTaJBip9G8a3aQ=="
|
||||
},
|
||||
"vuex-persistedstate": {
|
||||
"version": "4.0.0-beta.3",
|
||||
"resolved": "https://registry.npmjs.org/vuex-persistedstate/-/vuex-persistedstate-4.0.0-beta.3.tgz",
|
||||
"integrity": "sha512-T4IRD27qoUWh+8qr6T6zVp15xO7x/nPgnU13OD0C2uUwA7U9PhGozrj6lvVmMYDyRgc36J0msMXn3GvwHjkIhA==",
|
||||
"requires": {
|
||||
"deepmerge": "^4.2.2",
|
||||
"shvl": "^2.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.4.9",
|
||||
"vuelidate": "^0.7.6",
|
||||
"vuex": "^3.6.0"
|
||||
"vuex": "^3.6.0",
|
||||
"vuex-persistedstate": "^4.0.0-beta.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
<router-link :to="{ name: 'links' }">Derniers liens publiés</router-link>
|
||||
/
|
||||
<router-link :to="{ name: 'register' }">Créer un compte</router-link>
|
||||
/
|
||||
<router-link :to="{ name: 'login' }">Se connecter</router-link>
|
||||
</nav>
|
||||
<router-view></router-view>
|
||||
<notifications-panel />
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
class Api {
|
||||
constructor(baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
this._baseUrl = baseUrl;
|
||||
this._getToken = null;
|
||||
}
|
||||
|
||||
useToken(cb) {
|
||||
this._getToken = cb;
|
||||
}
|
||||
|
||||
getLinks() {
|
||||
@ -19,10 +24,29 @@ class Api {
|
||||
return this._post("/api/accounts", data);
|
||||
}
|
||||
|
||||
login(data) {
|
||||
return this._post("/api/accounts/token", data);
|
||||
}
|
||||
|
||||
_authorizationHeader() {
|
||||
if (!this._getToken) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const token = this._getToken();
|
||||
|
||||
if (!token) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return { Authorization: `Bearer ${token}` };
|
||||
}
|
||||
|
||||
_get(path) {
|
||||
return fetch(this.baseUrl + path, {
|
||||
return fetch(this._baseUrl + path, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
...this._authorizationHeader(),
|
||||
},
|
||||
}).then((r) => {
|
||||
if (!r.ok) {
|
||||
@ -34,11 +58,12 @@ class Api {
|
||||
}
|
||||
|
||||
_post(path, data) {
|
||||
return fetch(this.baseUrl + path, {
|
||||
return fetch(this._baseUrl + path, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
...this._authorizationHeader(),
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}).then((r) => {
|
||||
@ -50,6 +75,8 @@ class Api {
|
||||
return r;
|
||||
}
|
||||
|
||||
// if (!r.headers['Content-Length'] === '0') {
|
||||
|
||||
return r.json();
|
||||
});
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
...mapState(["messages"]),
|
||||
...mapState("notification", ["messages"]),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -4,6 +4,7 @@ import Layout from "./Layout.vue";
|
||||
import createRouter from "./router";
|
||||
import createStore from "./store";
|
||||
import Notifications from "./plugins/Notifications";
|
||||
import api from "./api";
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.use(Vuelidate);
|
||||
@ -12,6 +13,8 @@ Vue.use(Notifications);
|
||||
const router = createRouter();
|
||||
const store = createStore();
|
||||
|
||||
api.useToken(() => store.state.auth.token);
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
|
||||
52
hn-vue/src/pages/Login.vue
Normal file
52
hn-vue/src/pages/Login.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Connexion</h1>
|
||||
<form @submit.prevent="login">
|
||||
<error v-if="err" :error="err" />
|
||||
<textfield label="Nom d'utilisteur" :field="$v.username" />
|
||||
<textfield label="Mot de passe" type="password" :field="$v.password" />
|
||||
|
||||
<button type="submit" :disabled="$v.$invalid">Se connecter</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Textfield from "../components/Textfield";
|
||||
import Error from "../components/Error";
|
||||
import { required } from "vuelidate/lib/validators";
|
||||
|
||||
export default {
|
||||
components: { Textfield, Error },
|
||||
data() {
|
||||
return {
|
||||
err: null,
|
||||
username: "",
|
||||
password: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async login() {
|
||||
this.err = null;
|
||||
|
||||
try {
|
||||
await this.$store.dispatch("auth/login", {
|
||||
username: this.username,
|
||||
password: this.password,
|
||||
});
|
||||
this.$redirectWithMessage({ name: "links" }, "Vous êtes authentifié !");
|
||||
} catch (e) {
|
||||
this.err = e;
|
||||
}
|
||||
},
|
||||
},
|
||||
validations: {
|
||||
username: {
|
||||
required,
|
||||
},
|
||||
password: {
|
||||
required,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -1,7 +1,7 @@
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.prototype.$message = function(message) {
|
||||
this.$store.dispatch("addMessage", message);
|
||||
this.$store.dispatch("notification/addMessage", message);
|
||||
};
|
||||
|
||||
Vue.prototype.$redirectWithMessage = function(to, message) {
|
||||
|
||||
@ -2,6 +2,7 @@ import Vue from "vue";
|
||||
import VueRouter from "vue-router";
|
||||
import Links from "./pages/Links.vue";
|
||||
import Register from "./pages/Register.vue";
|
||||
import Login from "./pages/Login.vue";
|
||||
import LinkDetail from "./pages/LinkDetail.vue";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
@ -17,6 +18,7 @@ export default function createRouter() {
|
||||
props: true,
|
||||
},
|
||||
{ path: "/register", name: "register", component: Register },
|
||||
{ path: "/login", name: "login", component: Login },
|
||||
{ path: "*", redirect: "/" },
|
||||
],
|
||||
});
|
||||
|
||||
@ -1,27 +1,58 @@
|
||||
import Vue from "vue";
|
||||
import Vuex from "vuex";
|
||||
import createPersistedState from "vuex-persistedstate";
|
||||
import api from "./api";
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export default function createStore() {
|
||||
return new Vuex.Store({
|
||||
state: {
|
||||
messages: [],
|
||||
},
|
||||
mutations: {
|
||||
pushMessage(state, message) {
|
||||
state.messages = [...state.messages, message];
|
||||
},
|
||||
removeMessage(state, message) {
|
||||
state.messages = state.messages.filter((m) => m !== message);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
addMessage({ commit }, message) {
|
||||
commit("pushMessage", message);
|
||||
modules: {
|
||||
notification: {
|
||||
namespaced: true,
|
||||
state: {
|
||||
messages: [],
|
||||
},
|
||||
mutations: {
|
||||
pushMessage(state, message) {
|
||||
state.messages = [...state.messages, message];
|
||||
},
|
||||
removeMessage(state, message) {
|
||||
state.messages = state.messages.filter((m) => m !== message);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
addMessage({ commit }, message) {
|
||||
commit("pushMessage", message);
|
||||
|
||||
setTimeout(() => commit("removeMessage", message), 3000);
|
||||
setTimeout(() => commit("removeMessage", message), 3000);
|
||||
},
|
||||
},
|
||||
},
|
||||
auth: {
|
||||
namespaced: true,
|
||||
state: {
|
||||
token: null,
|
||||
username: null,
|
||||
},
|
||||
mutations: {
|
||||
setUser(state, { token, username }) {
|
||||
state.token = token;
|
||||
state.username = username;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async login({ commit }, data) {
|
||||
const result = await api.login(data);
|
||||
commit("setUser", result);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
createPersistedState({
|
||||
paths: ["auth"],
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user