removed crappy test login files

This commit is contained in:
Tobias Kurze
2019-03-22 16:38:09 +01:00
parent 102db7ae0c
commit 1ee42cb01b
17 changed files with 86 additions and 769 deletions

View File

@@ -2,7 +2,8 @@
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
<router-link to="/about">About</router-link> |
<router-link to="/login">Login</router-link>
</div>
<router-view/>
</div>
@@ -16,7 +17,7 @@
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
}About
#nav {
padding: 30px;
a {

View File

@@ -43,31 +43,31 @@
return {
email: '',
password: '',
errorMsg: ''
}
errorMsg: '',
};
},
methods: {
authenticate () {
this.$store.dispatch('login', { email: this.email, password: this.password })
.then(() => this.$router.push('/'))
.then(() => this.$router.push('/'));
},
register () {
this.$store.dispatch('register', { email: this.email, password: this.password })
.then(() => this.$router.push('/'))
}
.then(() => this.$router.push('/'));
},
},
mounted () {
EventBus.$on('failedRegistering', (msg) => {
this.errorMsg = msg
})
});
EventBus.$on('failedAuthentication', (msg) => {
this.errorMsg = msg
})
});
},
beforeDestroy () {
EventBus.$off('failedRegistering')
EventBus.$off('failedAuthentication')
}
EventBus.$off('failedRegistering');
EventBus.$off('failedAuthentication');
},
}
</script>
@@ -76,4 +76,4 @@
color: red;
font-weight: bold;
}
</style>
</style>

View File

@@ -1,11 +0,0 @@
export function authHeader() {
// return authorization header with jwt token
// @ts-ignore
let user = JSON.parse(localStorage.getItem('user'));
if (user && user.token) {
return { 'Authorization': 'Bearer ' + user.token };
} else {
return {};
}
}

View File

@@ -1,148 +0,0 @@
// array in local storage for registered users
// @ts-ignore
let users = JSON.parse(localStorage.getItem('users')) || [];
export function configureFakeBackend() {
let realFetch = window.fetch;
window.fetch = function (url, opts) {
return new Promise((resolve, reject) => {
// wrap in timeout to simulate server api call
setTimeout(() => {
// authenticate
// @ts-ignore
if (url.endsWith('/users/authenticate') && opts.method === 'POST') {
// get parameters from post request
// @ts-ignore
let params = JSON.parse(opts.body);
// find if any user matches login credentials
let filteredUsers = users.filter((user: any) => {
return user.username === params.username && user.password === params.password;
});
if (filteredUsers.length) {
// if login details are valid return user details and fake jwt token
let user = filteredUsers[0];
let responseJson = {
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
token: 'fake-jwt-token'
};
// @ts-ignore
resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(responseJson)) });
} else {
// else return error
reject('Username or password is incorrect');
}
return;
}
// get users
// @ts-ignore
if (url.endsWith('/users') && opts.method === 'GET') {
// check for fake auth token in header and return users if valid, this security is implemented server side in a real application
// @ts-ignore
if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') {
// @ts-ignore
resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(users))});
} else {
// return 401 not authorised if token is null or invalid
reject('Unauthorised');
}
return;
}
// get user by id
// @ts-ignore
if (url.match(/\/users\/\d+$/) && opts.method === 'GET') {
// check for fake auth token in header and return user if valid, this security is implemented server side in a real application
// @ts-ignore
if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') {
// find user by id in users array
// @ts-ignore
let urlParts = url.split('/');
let id = parseInt(urlParts[urlParts.length - 1]);
// @ts-ignore
let matchedUsers = users.filter((user) => { return user.id === id; });
let user = matchedUsers.length ? matchedUsers[0] : null;
// respond 200 OK with user
// @ts-ignore
resolve({ ok: true, text: () => JSON.stringify(user)});
} else {
// return 401 not authorised if token is null or invalid
reject('Unauthorised');
}
return;
}
// register user
// @ts-ignore
if (url.endsWith('/users/register') && opts.method === 'POST') {
// get new user object from post body
// @ts-ignore
let newUser = JSON.parse(opts.body);
// validation
let duplicateUser = users.filter((user: any) => { return user.username === newUser.username; }).length;
if (duplicateUser) {
reject('Username "' + newUser.username + '" is already taken');
return;
}
// save new user
newUser.id = users.length ? Math.max(...users.map((user: any) => user.id)) + 1 : 1;
users.push(newUser);
localStorage.setItem('users', JSON.stringify(users));
// respond 200 OK
// @ts-ignore
resolve({ ok: true, text: () => Promise.resolve() });
return;
}
// delete user
// @ts-ignore
if (url.match(/\/users\/\d+$/) && opts.method === 'DELETE') {
// check for fake auth token in header and return user if valid, this security is implemented server side in a real application
// @ts-ignore
if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') {
// find user by id in users array
// @ts-ignore
let urlParts = url.split('/');
let id = parseInt(urlParts[urlParts.length - 1]);
for (let i = 0; i < users.length; i++) {
let user = users[i];
if (user.id === id) {
// delete user
users.splice(i, 1);
localStorage.setItem('users', JSON.stringify(users));
break;
}
}
// respond 200 OK
// @ts-ignore
resolve({ ok: true, text: () => Promise.resolve() });
} else {
// return 401 not authorised if token is null or invalid
reject('Unauthorised');
}
return;
}
// pass through any requests not handled above
realFetch(url, opts).then((response) => resolve(response));
}, 500);
});
};
}

View File

@@ -1,2 +0,0 @@
export * from './fake-backend';
export * from './auth-header';

View File

@@ -1,6 +1,6 @@
import Vue from 'vue';
import axios from 'axios'
import VueAxios from 'vue-axios'
import axios from 'axios';
import VueAxios from 'vue-axios';
import App from './App.vue';
import router from './router';
import store from './store';
@@ -10,7 +10,7 @@ import FlagIcon from 'vue-flag-icon';
// following is to avoid missing type definitions
// const FlagIcon = require('vue-flag-icon');
Vue.use(VueAxios, axios)
Vue.use(VueAxios, axios);
Vue.use(FlagIcon);
// setup fake backend

View File

@@ -2,13 +2,11 @@ import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';
import NotFound from './views/NotFound.vue';
import LoginPage from './views/LoginPage.vue';
import Survey from '@/components/Survey.vue';
import NewSurvey from '@/components/NewSurvey.vue';
import Login from '@/components/Login.vue';
import store from '@/store'
import store from '@/store';
Vue.use(Router);
@@ -24,7 +22,7 @@ export const router = new Router({
},
{
path: '/login',
component: LoginPage,
component: Login,
},
{
path: '/about',
@@ -36,22 +34,22 @@ export const router = new Router({
}, {
path: '/surveys/:id',
name: 'Survey',
component: Survey
component: Survey,
}, {
path: '/surveys',
name: 'NewSurvey',
component: NewSurvey,
beforeEnter (to, from, next) {
beforeEnter(to, from, next) {
if (!store.getters.isAuthenticated) {
next('/login')
next('/login');
} else {
next()
next();
}
}
},
}, {
path: '/login',
name: 'Login',
component: Login
component: Login,
},
{
path: '*',
@@ -61,15 +59,4 @@ export const router = new Router({
],
});
router.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/login', '/register'];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
if (authRequired && !loggedIn) {
return next('/login');
}
});
export default router;

View File

@@ -1 +0,0 @@
export * from './user.service';

View File

@@ -1,113 +0,0 @@
import { authHeader } from '@/helpers';
export const userService = {
login,
logout,
register,
getAll,
getById,
update,
delete: _delete,
};
// @ts-ignore
function login(username, password) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
};
return fetch(`${process.env.API_URL}/users/authenticate`, requestOptions)
.then(handleResponse)
.then((user) => {
// login successful if there's a jwt token in the response
if (user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('user', JSON.stringify(user));
}
return user;
});
}
function logout() {
// remove user from local storage to log user out
localStorage.removeItem('user');
}
// @ts-ignore
function register(user) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user),
};
return fetch(`${process.env.API_URL}/users/register`, requestOptions).then(handleResponse);
}
function getAll() {
const requestOptions = {
method: 'GET',
headers: authHeader(),
};
// @ts-ignore
return fetch(`${config.apiUrl}/users`, requestOptions).then(handleResponse);
}
// @ts-ignore
function getById(id) {
const requestOptions = {
method: 'GET',
headers: authHeader(),
};
// @ts-ignore
return fetch(`${config.apiUrl}/users/${id}`, requestOptions).then(handleResponse);
}
// @ts-ignore
function update(user) {
const requestOptions = {
method: 'PUT',
headers: { ...authHeader(), 'Content-Type': 'application/json' },
body: JSON.stringify(user),
};
// @ts-ignore
return fetch(`${config.apiUrl}/users/${user.id}`, requestOptions).then(handleResponse);
}
// prefixed function name with underscore because delete is a reserved word in javascript
// @ts-ignore
function _delete(id) {
const requestOptions = {
method: 'DELETE',
headers: authHeader(),
};
// @ts-ignore
return fetch(`${config.apiUrl}/users/${id}`, requestOptions).then(handleResponse);
}
// @ts-ignore
function handleResponse(response) {
return response.text().then((text: any) => {
const data = text && JSON.parse(text);
if (!response.ok) {
if (response.status === 401) {
// auto logout if 401 response returned from api
logout();
location.reload(true);
}
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
}

View File

@@ -3,8 +3,8 @@ import Vuex from 'vuex';
// imports of AJAX functions will go here
import { fetchSurveys, fetchSurvey, saveSurveyResponse, postNewSurvey, authenticate, register } from '@/api'
import { isValidJwt, EventBus } from '@/utils'
import { fetchSurveys, fetchSurvey, saveSurveyResponse, postNewSurvey, authenticate, register } from '@/api';
import { isValidJwt, EventBus } from '@/utils';
Vue.use(Vuex);
@@ -13,98 +13,96 @@ const state = {
surveys: [],
currentSurvey: {},
user: {},
jwt: ''
}
jwt: '',
};
const actions = {
// asynchronous operations
loadSurveys (context: any) {
loadSurveys(context: any) {
return fetchSurveys()
.then((response) => {
context.commit('setSurveys', { surveys: response.data })
})
context.commit('setSurveys', { surveys: response.data });
});
},
// @ts-ignore
loadSurvey (context: any, { id }) {
loadSurvey(context: any, { id }) {
return fetchSurvey(id)
.then((response) => {
context.commit('setSurvey', { survey: response.data })
})
context.commit('setSurvey', { survey: response.data });
});
},
addSurveyResponse (context: any) {
return saveSurveyResponse(context.state.currentSurvey)
addSurveyResponse(context: any) {
return saveSurveyResponse(context.state.currentSurvey);
},
login (context: any, userData: any) {
context.commit('setUserData', { userData })
login(context: any, userData: any) {
context.commit('setUserData', { userData });
return authenticate(userData)
.then(response => context.commit('setJwtToken', { jwt: response.data }))
.catch(error => {
console.log('Error Authenticating: ', error)
// @ts-ignore
EventBus.emit('failedAuthentication', error)
})
.then((response) => context.commit('setJwtToken', { jwt: response.data }))
.catch((error) => {
console.log('Error Authenticating: ', error);
EventBus.$emit('failedAuthentication', error);
});
},
register (context: any, userData: any) {
context.commit('setUserData', { userData })
register(context: any, userData: any) {
context.commit('setUserData', { userData });
return register(userData)
.then(context.dispatch('login', userData))
.catch(error => {
console.log('Error Registering: ', error)
// @ts-ignore
EventBus.emit('failedRegistering: ', error)
})
.catch((error) => {
console.log('Error Registering: ', error);
EventBus.$emit('failedRegistering: ', error);
});
},
submitNewSurvey (context: any, survey: any) {
return postNewSurvey(survey, context.state.jwt.token)
}
}
submitNewSurvey(context: any, survey: any) {
return postNewSurvey(survey, context.state.jwt.token);
},
};
const mutations = {
// isolated data mutations
setSurveys (state: any, payload: any) {
state.surveys = payload.surveys
setSurveys(sState: any, payload: any) {
sState.surveys = payload.surveys;
},
setSurvey (state: any, payload: any) {
const nQuestions = payload.survey.questions.length
setSurvey(sState: any, payload: any) {
const nQuestions = payload.survey.questions.length;
for (let i = 0; i < nQuestions; i++) {
payload.survey.questions[i].choice = null
payload.survey.questions[i].choice = null;
}
state.currentSurvey = payload.survey
sState.currentSurvey = payload.survey;
},
setChoice (state: any, payload: any) {
const { questionId, choice } = payload
const nQuestions = state.currentSurvey.questions.length
setChoice(sState: any, payload: any) {
const { questionId, choice } = payload;
const nQuestions = sState.currentSurvey.questions.length;
for (let i = 0; i < nQuestions; i++) {
if (state.currentSurvey.questions[i].id === questionId) {
state.currentSurvey.questions[i].choice = choice
break
if (sState.currentSurvey.questions[i].id === questionId) {
sState.currentSurvey.questions[i].choice = choice;
break;
}
}
},
setUserData (state: any, payload: any) {
console.log('setUserData payload = ', payload)
state.userData = payload.userData
setUserData(sState: any, payload: any) {
console.log('setUserData payload = ', payload);
sState.userData = payload.userData;
},
setJwtToken (state: any, payload: any) {
console.log('setJwtToken payload = ', payload)
localStorage.token = payload.jwt.token
state.jwt = payload.jwt
}
}
setJwtToken(sState: any, payload: any) {
console.log('setJwtToken payload = ', payload);
localStorage.token = payload.jwt.token;
sState.jwt = payload.jwt;
},
};
const getters = {
// reusable data accessors
isAuthenticated (state: any) {
return isValidJwt(state.jwt.token)
}
}
isAuthenticated(sState: any) {
return isValidJwt(sState.jwt.token);
},
};
const store = new Vuex.Store({
state,
actions,
mutations,
getters
})
getters,
});
export default store
export default store;

View File

@@ -1,94 +0,0 @@
import { userService } from '@/services';
import { router } from '@/router';
// @ts-ignore
const user = JSON.parse(localStorage.getItem('user'));
const state = user
? { status: { loggedIn: true }, user }
: { status: {}, user: null };
const actions = {
// @ts-ignore
login({ dispatch, commit }, { username, password }) {
commit('loginRequest', { username });
userService.login(username, password)
.then(
(loggedInUser) => {
commit('loginSuccess', loggedInUser);
router.push('/');
},
(error) => {
commit('loginFailure', error);
dispatch('alert/error', error, { root: true });
},
);
},
// @ts-ignore
logout({ commit }) {
userService.logout();
commit('logout');
},
// @ts-ignore
register({ dispatch, commit }, userToRegister) {
commit('registerRequest', userToRegister);
userService.register(userToRegister)
.then(
(registeredUser) => {
commit('registerSuccess', registeredUser);
router.push('/login');
setTimeout(() => {
// display success message after route change completes
dispatch('alert/success', 'Registration successful', { root: true });
});
},
(error) => {
commit('registerFailure', error);
dispatch('alert/error', error, { root: true });
},
);
},
};
const mutations = {
// @ts-ignore
loginRequest(mutState, userToLogin) {
mutState.status = { loggingIn: true };
mutState.user = userToLogin;
},
// @ts-ignore
loginSuccess(mutState, userToLogin) {
mutState.status = { loggedIn: true };
mutState.user = userToLogin;
},
// @ts-ignore
loginFailure(mutState) {
mutState.status = {};
mutState.user = null;
},
// @ts-ignore
logout(mutState) {
mutState.status = {};
mutState.user = null;
},
// @ts-ignore
registerRequest(mutState, userToRegister) {
mutState.status = { registering: true };
},
// @ts-ignore
registerSuccess(mutState, userToRegister) {
mutState.status = {};
},
// @ts-ignore
registerFailure(mutState, error) {
mutState.status = {};
},
};
export const account = {
namespaced: true,
state,
actions,
mutations,
};

View File

@@ -1,44 +0,0 @@
const state = {
type: null,
message: null,
};
const actions = {
// @ts-ignore
success({ commit }, message) {
commit('success', message);
},
// @ts-ignore
error({ commit }, message) {
commit('error', message);
},
// @ts-ignore
clear({ commit }, message) {
commit('success', message);
},
};
const mutations = {
// @ts-ignore
success(mutState, message) {
mutState.type = 'alert-success';
mutState.message = message;
},
// @ts-ignore
error(mutState, message) {
mutState.type = 'alert-danger';
mutState.message = message;
},
// @ts-ignore
clear(mutState) {
mutState.type = null;
mutState.message = null;
},
};
export const alert = {
namespaced: true,
state,
actions,
mutations,
};

View File

@@ -1,78 +0,0 @@
import { userService } from '@/services';
const state = {
all: {},
};
const actions = {
// @ts-ignore
getAll({ commit }) {
commit('getAllRequest');
userService.getAll()
.then(
(receivedUsers: any) => commit('getAllSuccess', receivedUsers),
(error: any) => commit('getAllFailure', error),
);
},
// @ts-ignore
delete({ commit }, id) {
commit('deleteRequest', id);
userService.delete(id)
.then(
(user: any) => commit('deleteSuccess', id),
(error: any) => commit('deleteSuccess', { id, error: error.toString() }),
);
},
};
const mutations = {
// @ts-ignore
getAllRequest(mutState) {
mutState.all = { loading: true };
},
// @ts-ignore
getAllSuccess(mutState, receivedUsers) {
mutState.all = { items: receivedUsers };
},
// @ts-ignore
getAllFailure(mutState, error) {
mutState.all = { error };
},
// @ts-ignore
deleteRequest(mutState, id) {
// add 'deleting:true' property to user being deleted
mutState.all.items = mutState.all.items.map((user: any) =>
user.id === id
? { ...user, deleting: true }
: user,
);
},
// @ts-ignore
deleteSuccess(mutState, id) {
// remove deleted user from state
mutState.all.items = mutState.all.items.filter((user: any) => user.id !== id);
},
// @ts-ignore
deleteFailure(mutState, { id, error }) {
// remove 'deleting:true' property and add 'deleteError:[error]' property to user
mutState.all.items = mutState.items.map((user: any) => {
if (user.id === id) {
// make copy of user without 'deleting:true' property
const { deleting, ...userCopy } = user;
// return copy of user with 'deleteError:[error]' property
return { ...userCopy, deleteError: error };
}
return user;
});
},
};
export const users = {
namespaced: true,
state,
actions,
mutations,
};

View File

@@ -1,15 +1,15 @@
// utils/index.js
import Vue from 'vue'
import Vue from 'vue';
export const EventBus = new Vue();
export function isValidJwt (jwt: any) {
export function isValidJwt(jwt: any) {
if (!jwt || jwt.split('.').length < 3) {
return false
return false;
}
const data = JSON.parse(atob(jwt.split('.')[1]));
const exp = new Date(data.exp * 1000);
const now = new Date();
return now < exp;
}
}

View File

@@ -1,42 +0,0 @@
<template>
<div>
<h1>Hi {{account.user.firstName}}!</h1>
<p>You're logged in with Vue + Vuex & JWT!!</p>
<h3>Users from secure api end point:</h3>
<em v-if="users.loading">Loading users...</em>
<span v-if="users.error" class="text-danger">ERROR: {{users.error}}</span>
<ul v-if="users.items">
<li v-for="user in users.items" :key="user.id">
{{user.firstName + ' ' + user.lastName}}
<span v-if="user.deleting"><em> - Deleting...</em></span>
<span v-else-if="user.deleteError" class="text-danger"> - ERROR: {{user.deleteError}}</span>
<span v-else> - <a @click="deleteUser(user.id)" class="text-danger">Delete</a></span>
</li>
</ul>
<p>
<router-link to="/login">Logout</router-link>
</p>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState({
account: (state) => state.account,
users: (state) => state.users.all,
}),
},
created() {
this.getAllUsers();
},
methods: {
...mapActions('users', {
getAllUsers: 'getAll',
deleteUser: 'delete',
}),
},
};
</script>

View File

@@ -1,72 +0,0 @@
<template>
<div>
<div class="alert alert-info">
Username: test<br />
Password: test
</div>
<h2>Login</h2>
<form @submit.prevent="handleSubmit">
<div class="form-group">
<label for="username">Username</label>
<input type="text" v-model="username" name="username" class="form-control" :class="{ 'is-invalid': submitted && !username }" />
<div v-show="submitted && !username" class="invalid-feedback">Username is required</div>
</div>
<div class="form-group">
<label htmlFor="password">Password</label>
<input type="password" v-model="password" name="password" class="form-control" :class="{ 'is-invalid': submitted && !password }" />
<div v-show="submitted && !password" class="invalid-feedback">Password is required</div>
</div>
<div class="form-group">
<button class="btn btn-primary" :disabled="loading">Login</button>
<img v-show="loading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
</div>
<div v-if="error" class="alert alert-danger">{{error}}</div>
</form>
</div>
</template>
<script>
import router from '@/router/';
import { userService } from '@/services';
export default {
data() {
return {
username: '',
password: '',
submitted: false,
loading: false,
returnUrl: '',
error: '',
};
},
created() {
// reset login status
userService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.$route.query.returnUrl || '/';
},
methods: {
handleSubmit(e) {
this.submitted = true;
const { username, password } = this;
// stop here if form is invalid
if (!(username && password)) {
return;
}
this.loading = true;
userService.login(username, password)
.then(
(user) => router.push(this.returnUrl),
(error) => {
this.error = error;
this.loading = false;
},
);
},
},
};
</script>

View File

@@ -1,64 +0,0 @@
<template>
<div>
<h2>Register</h2>
<form @submit.prevent="handleSubmit">
<div class="form-group">
<label for="firstName">First Name</label>
<input type="text" v-model="user.firstName" v-validate="'required'" name="firstName" class="form-control" :class="{ 'is-invalid': submitted && errors.has('firstName') }" />
<div v-if="submitted && errors.has('firstName')" class="invalid-feedback">{{ errors.first('firstName') }}</div>
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" v-model="user.lastName" v-validate="'required'" name="lastName" class="form-control" :class="{ 'is-invalid': submitted && errors.has('lastName') }" />
<div v-if="submitted && errors.has('lastName')" class="invalid-feedback">{{ errors.first('lastName') }}</div>
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" v-model="user.username" v-validate="'required'" name="username" class="form-control" :class="{ 'is-invalid': submitted && errors.has('username') }" />
<div v-if="submitted && errors.has('username')" class="invalid-feedback">{{ errors.first('username') }}</div>
</div>
<div class="form-group">
<label htmlFor="password">Password</label>
<input type="password" v-model="user.password" v-validate="{ required: true, min: 6 }" name="password" class="form-control" :class="{ 'is-invalid': submitted && errors.has('password') }" />
<div v-if="submitted && errors.has('password')" class="invalid-feedback">{{ errors.first('password') }}</div>
</div>
<div class="form-group">
<button class="btn btn-primary" :disabled="status.registering">Register</button>
<img v-show="status.registering" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
<router-link to="/login" class="btn btn-link">Cancel</router-link>
</div>
</form>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
data() {
return {
user: {
firstName: '',
lastName: '',
username: '',
password: '',
},
submitted: false,
};
},
computed: {
...mapState('account', ['status']),
},
methods: {
...mapActions('account', ['register']),
handleSubmit(e) {
this.submitted = true;
this.$validator.validate().then((valid) => {
if (valid) {
this.register(this.user);
}
});
},
},
};
</script>