removed crappy test login files
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './fake-backend';
|
||||
export * from './auth-header';
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
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;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './user.service';
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
104
src/store.ts
104
src/store.ts
@@ -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) {
|
||||
return fetchSurveys()
|
||||
.then((response) => {
|
||||
context.commit('setSurveys', { surveys: response.data })
|
||||
})
|
||||
context.commit('setSurveys', { surveys: response.data });
|
||||
});
|
||||
},
|
||||
// @ts-ignore
|
||||
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)
|
||||
return saveSurveyResponse(context.state.currentSurvey);
|
||||
},
|
||||
|
||||
login(context: any, userData: any) {
|
||||
context.commit('setUserData', { userData })
|
||||
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 })
|
||||
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)
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
// utils/index.js
|
||||
|
||||
import Vue from 'vue'
|
||||
import Vue from 'vue';
|
||||
|
||||
export const EventBus = new Vue();
|
||||
|
||||
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);
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user