persistant storage for vuex, logging instead of console.log, profile support
This commit is contained in:
39
package-lock.json
generated
39
package-lock.json
generated
@@ -4932,6 +4932,11 @@
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"es6-object-assign": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
|
||||
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -7546,6 +7551,11 @@
|
||||
"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
|
||||
"dev": true
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.0.tgz",
|
||||
"integrity": "sha1-Gywnmm7s44ChIWi5JIUmWzWx7/s="
|
||||
},
|
||||
"js-levenshtein": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
|
||||
@@ -11259,6 +11269,11 @@
|
||||
"nanoid": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"shvl": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/shvl/-/shvl-1.3.1.tgz",
|
||||
"integrity": "sha512-+rRPP46hloYUAEImJcqprUgXu+05Ikqr4h4V+w5i2zJy37nAqtkQKufs3+3S2fDq6JNRrHMIQhB/Vaex+jgAAw=="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
@@ -12962,11 +12977,35 @@
|
||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||
"dev": true
|
||||
},
|
||||
"vuejs-logger": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/vuejs-logger/-/vuejs-logger-1.5.3.tgz",
|
||||
"integrity": "sha512-jw+AQ+IMJBz18fA4opHsqaU7P7yQNugoGywT6i3DCd1BWqg9eUx03Fr21kayqGcP4dxUwhVkkjuOyeirxLJC8g==",
|
||||
"requires": {
|
||||
"es6-object-assign": "1.1.0"
|
||||
}
|
||||
},
|
||||
"vuex": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.0.tgz",
|
||||
"integrity": "sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg=="
|
||||
},
|
||||
"vuex-persistedstate": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/vuex-persistedstate/-/vuex-persistedstate-2.5.4.tgz",
|
||||
"integrity": "sha512-XYJhKIwO+ZVlTaXyxKxnplrJ88Fnvk5aDw753bxzRw5/yMKLQ6lq9CDCBex2fwZaQcLibhtgJOxGCHjy9GLSlQ==",
|
||||
"requires": {
|
||||
"deepmerge": "^2.1.0",
|
||||
"shvl": "^1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
|
||||
"integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vuex-typex": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/vuex-typex/-/vuex-typex-3.1.4.tgz",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"@vue/cli": "^3.4.1",
|
||||
"axios": "^0.18.0",
|
||||
"bootstrap-vue": "^2.0.0-rc.13",
|
||||
"js-cookie": "^2.2.0",
|
||||
"vue": "^2.6.6",
|
||||
"vue-axios": "^2.1.4",
|
||||
"vue-class-component": "^6.0.0",
|
||||
@@ -20,7 +21,9 @@
|
||||
"vue-i18n": "^8.9.0",
|
||||
"vue-property-decorator": "^7.0.0",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuejs-logger": "1.5.3",
|
||||
"vuex": "^3.0.1",
|
||||
"vuex-persistedstate": "^2.5.4",
|
||||
"vuex-typex": "^3.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
18
src/$log.d.ts
vendored
Normal file
18
src/$log.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import Vue from 'vue';
|
||||
/*
|
||||
Type augmentation for log plugin for typescript
|
||||
https://vuejs.org/v2/guide/typescript.html#Augmenting-Types-for-Use-with-Plugins
|
||||
https://github.com/justinkames/vuejs-logger/issues/24
|
||||
Tobias
|
||||
*/
|
||||
declare module 'vue/types/vue' {
|
||||
export interface VueConstructor<V extends Vue = Vue> {
|
||||
$log: {
|
||||
debug(...args: any[]): void;
|
||||
info(...args: any[]): void;
|
||||
warn(...args: any[]): void;
|
||||
error(...args: any[]): void;
|
||||
fatal(...args: any[]): void;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link> |
|
||||
<router-link to="/login">Login</router-link>
|
||||
<router-link to="/login">Login</router-link> |
|
||||
<router-link to="/profile">Profile</router-link>
|
||||
</div>
|
||||
<router-view/>
|
||||
</div>
|
||||
|
||||
@@ -1,46 +1,51 @@
|
||||
import Vue from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
const API_URL = 'http://localhost:5443/api';
|
||||
|
||||
export function fetchSurveys () {
|
||||
return axios.get(`${API_URL}/surveys/`)
|
||||
export function fetchSurveys() {
|
||||
return axios.get(`${API_URL}/surveys/`);
|
||||
}
|
||||
|
||||
export function fetchSurvey (surveyId: string) {
|
||||
return axios.get(`${API_URL}/surveys/${surveyId}/`)
|
||||
export function fetchSurvey(surveyId: string) {
|
||||
return axios.get(`${API_URL}/surveys/${surveyId}/`);
|
||||
}
|
||||
|
||||
export function saveSurveyResponse (surveyResponse: any) {
|
||||
return axios.put(`${API_URL}/surveys/${surveyResponse.id}/`, surveyResponse)
|
||||
export function saveSurveyResponse(surveyResponse: any) {
|
||||
return axios.put(`${API_URL}/surveys/${surveyResponse.id}/`, surveyResponse);
|
||||
}
|
||||
|
||||
export function postNewSurvey (survey: any, jwt: any) {
|
||||
return axios.post(`${API_URL}/surveys/`, survey, { headers: { Authorization: `Bearer ${jwt}` } })
|
||||
export function postNewSurvey(survey: any, jwt: any) {
|
||||
return axios.post(`${API_URL}/surveys/`, survey, { headers: { Authorization: `Bearer ${jwt}` } });
|
||||
}
|
||||
|
||||
export function authenticate (userData: any) {
|
||||
return axios.post(`${API_URL}/auth/login`, userData)
|
||||
export function authenticate(userData: any) {
|
||||
return axios.post(`${API_URL}/auth/login`, userData);
|
||||
}
|
||||
|
||||
export function register (userData: any) {
|
||||
return axios.post(`${API_URL}/auth/register`, userData)
|
||||
export function register(userData: any) {
|
||||
return axios.post(`${API_URL}/auth/register`, userData);
|
||||
}
|
||||
|
||||
// This function probably isn't really useful here, as a user must be redirected to the actual OIDC provider.
|
||||
// -> So login involves user interaction through the frontend (and not just API calls).
|
||||
export function oidc_login (redirection_url: any) {
|
||||
return axios.get(`${API_URL}/auth/oidc`, redirection_url)
|
||||
export function oidc_login(redirectionUrl: any) {
|
||||
return axios.get(`${API_URL}/auth/oidc`, redirectionUrl);
|
||||
}
|
||||
|
||||
export function getFreshToken (refresh_token: any) {
|
||||
return axios.get(`${API_URL}/auth/fresh`, refresh_token)
|
||||
export function getFreshToken(refreshToken: any) {
|
||||
return axios.get(`${API_URL}/auth/fresh`, refreshToken);
|
||||
}
|
||||
|
||||
export function getProviders () {
|
||||
return axios.get(`${API_URL}/auth/providers`)
|
||||
export function getProviders() {
|
||||
return axios.get(`${API_URL}/auth/providers`);
|
||||
}
|
||||
|
||||
export function fetchUsers (jwt: any) {
|
||||
console.log("JWT: " + jwt);
|
||||
return axios.get(`${API_URL}/v1/user`, { headers: { Authorization: `Bearer ${jwt}` } })
|
||||
export function fetchUsers(jwt: any) {
|
||||
return axios.get(`${API_URL}/v1/user`, { headers: { Authorization: `Bearer ${jwt}` } });
|
||||
}
|
||||
|
||||
export function fetchProfile(jwt: any) {
|
||||
Vue.$log.debug("JWT: "+ jwt);
|
||||
return axios.get(`${API_URL}/v1/user/profile`, { headers: { Authorization: `Bearer ${jwt}` } });
|
||||
}
|
||||
|
||||
58
src/components/Profile.vue
Normal file
58
src/components/Profile.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<!-- components/Profile.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
<h2 class="title">Profile</h2>
|
||||
<p>{{profile.id}}</p>
|
||||
<p class="subtitle error-msg">{{ errorMsg }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { EventBus } from '@/utils'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
email: '',
|
||||
errorMsg: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
authenticate () {
|
||||
this.$store.dispatch('login', { email: this.email, password: this.password })
|
||||
.then(() => this.$router.push('/'));
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.$log.debug("Profile: mounting...");
|
||||
EventBus.$on('failedLoadingProfile', (msg) => {
|
||||
this.errorMsg = msg;
|
||||
});
|
||||
this.$store.dispatch('loadProfile');
|
||||
|
||||
|
||||
},
|
||||
beforeDestroy () {
|
||||
EventBus.$off('failedLoadingProfile');
|
||||
},
|
||||
computed: {
|
||||
profile () {
|
||||
return this.$store.state.profile;
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.error-msg {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
19
src/main.ts
19
src/main.ts
@@ -4,16 +4,31 @@ import VueAxios from 'vue-axios';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import store from './store';
|
||||
import VueCookies from 'vue-cookies'
|
||||
import VueCookies from 'vue-cookies';
|
||||
import VueLogger from 'vuejs-logger';
|
||||
import i18n from '@/plugins/i18n';
|
||||
// @ts-ignore
|
||||
import FlagIcon from 'vue-flag-icon';
|
||||
// following is to avoid missing type definitions
|
||||
// const FlagIcon = require('vue-flag-icon');
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const options = {
|
||||
isEnabled: true,
|
||||
// logLevel : isProduction ? 'error' : 'debug',
|
||||
logLevel : 'debug',
|
||||
stringifyArguments : false,
|
||||
showLogLevel : true,
|
||||
showMethodName : true,
|
||||
separator: '|',
|
||||
showConsoleColors: true
|
||||
};
|
||||
|
||||
Vue.use(VueLogger, options);
|
||||
Vue.use(VueAxios, axios);
|
||||
Vue.use(FlagIcon);
|
||||
Vue.use(VueCookies)
|
||||
Vue.use(VueCookies);
|
||||
|
||||
// setup fake backend
|
||||
// import { configureFakeBackend } from './helpers';
|
||||
|
||||
@@ -6,6 +6,7 @@ import NotFound from './views/NotFound.vue';
|
||||
import Survey from '@/components/Survey.vue';
|
||||
import NewSurvey from '@/components/NewSurvey.vue';
|
||||
import Login from '@/components/Login.vue';
|
||||
import Profile from '@/components/Profile.vue';
|
||||
import store from '@/store';
|
||||
|
||||
Vue.use(Router);
|
||||
@@ -22,6 +23,7 @@ export const router = new Router({
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: Login,
|
||||
},
|
||||
{
|
||||
@@ -47,9 +49,9 @@ export const router = new Router({
|
||||
}
|
||||
},
|
||||
}, {
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: Login,
|
||||
path: '/profile',
|
||||
name: 'Profile',
|
||||
component: Profile,
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
|
||||
71
src/store.ts
71
src/store.ts
@@ -1,6 +1,6 @@
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import createPersistedState from 'vuex-persistedstate'
|
||||
|
||||
// imports of AJAX functions will go here
|
||||
import {
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
postNewSurvey,
|
||||
authenticate,
|
||||
register,
|
||||
oidc_login, fetchUsers, getFreshToken
|
||||
oidc_login, fetchUsers, getFreshToken, fetchProfile,
|
||||
} from '@/api';
|
||||
import { isValidJwt, EventBus } from '@/utils';
|
||||
|
||||
@@ -22,7 +22,7 @@ const state = {
|
||||
surveys: [],
|
||||
loginProviders: [],
|
||||
currentSurvey: {},
|
||||
user: {},
|
||||
profile: {},
|
||||
users: [],
|
||||
access_token: '',
|
||||
refresh_token: '',
|
||||
@@ -51,51 +51,64 @@ const actions = {
|
||||
loadUsers(context: any) {
|
||||
return fetchUsers(context.state.access_token)
|
||||
.then((response) => {
|
||||
console.log(response);
|
||||
console.log(response.data);
|
||||
Vue.$log.debug(response);
|
||||
Vue.$log.debug(response.data);
|
||||
context.commit('setUsers', { users: response.data });
|
||||
EventBus.$emit('usersLoaded', response.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('Error loading users!', error);
|
||||
Vue.$log.warn('Error loading users!', error);
|
||||
EventBus.$emit('failedLoadingUsers', error);
|
||||
});
|
||||
},
|
||||
loadProfile(context: any) {
|
||||
return fetchProfile(context.state.access_token)
|
||||
.then((response) => {
|
||||
Vue.$log.debug(response);
|
||||
Vue.$log.debug(response.data);
|
||||
context.commit('setProfile', { profile: response.data });
|
||||
EventBus.$emit('profileLoaded', response.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
Vue.$log.warn('Error loading profile!', error);
|
||||
EventBus.$emit('failedLoadingProfile', error);
|
||||
});
|
||||
},
|
||||
loadLoginProviders(context: any) {
|
||||
return getProviders()
|
||||
.then((response) => {
|
||||
context.commit('setLoginProviderData', {providers: response.data});
|
||||
EventBus.$emit('loginProvidersLoaded', response.data);
|
||||
})
|
||||
});
|
||||
},
|
||||
login(context: any, userData: any) {
|
||||
context.commit('setUserData', { userData });
|
||||
return authenticate(userData)
|
||||
.then((response) => context.commit('setJwtToken', { tokens: response.data }))
|
||||
.catch((error) => {
|
||||
console.log('Error Authenticating: ', error);
|
||||
Vue.$log.warn('Error Authenticating: ', error);
|
||||
EventBus.$emit('failedAuthentication', error);
|
||||
});
|
||||
},
|
||||
oidc_login(context: any, redirection_url: any) {
|
||||
//context.commit('setUserData', { userData });
|
||||
return oidc_login(redirection_url)
|
||||
oidc_login(context: any, redirectionUrl: any) {
|
||||
// context.commit('setUserData', { userData });
|
||||
return oidc_login(redirectionUrl)
|
||||
.then((response) => context.commit('setJwtToken', { tokens: response.data }))
|
||||
.catch((error) => {
|
||||
console.log('Error Authenticating: ', error);
|
||||
Vue.$log.warn('Error Authenticating: ', error);
|
||||
EventBus.$emit('failedAuthentication', error);
|
||||
});
|
||||
},
|
||||
refreshToken(context: any) {
|
||||
//context.commit('setUserData', { userData });
|
||||
// context.commit('setUserData', { userData });
|
||||
return getFreshToken(context.state.refresh_token)
|
||||
.then((response) => context.commit('setTokens', { tokens: response.data }))
|
||||
.catch((error) => {
|
||||
console.log('Error Refreshing token: ', error);
|
||||
Vue.$log.warn('Error Refreshing token: ', error);
|
||||
EventBus.$emit('failedRefreshingToken', error);
|
||||
});
|
||||
},
|
||||
storeTokens(context: any, tokens: any){
|
||||
storeTokens(context: any, tokens: any) {
|
||||
context.commit('setTokens', {tokens});
|
||||
EventBus.$emit('storedTokens');
|
||||
},
|
||||
@@ -104,7 +117,7 @@ const actions = {
|
||||
return register(userData)
|
||||
.then(context.dispatch('login', userData))
|
||||
.catch((error) => {
|
||||
console.log('Error Registering: ', error);
|
||||
Vue.$log.warn('Error Registering: ', error);
|
||||
EventBus.$emit('failedRegistering: ', error);
|
||||
});
|
||||
},
|
||||
@@ -138,33 +151,38 @@ const mutations = {
|
||||
}
|
||||
}
|
||||
},
|
||||
setLoginProviderData(sState: any, payload: any){
|
||||
console.log("got loginProviders = ", payload);
|
||||
setLoginProviderData(sState: any, payload: any) {
|
||||
Vue.$log.debug('got loginProviders = ', payload);
|
||||
sState.loginProviders = payload.providers;
|
||||
},
|
||||
// probably old ...
|
||||
setUserData(sState: any, payload: any) {
|
||||
console.log('setUserData payload = ', payload);
|
||||
Vue.$log.debug('setUserData payload = ', payload);
|
||||
sState.userData = payload.userData;
|
||||
},
|
||||
setProfile(sState: any, payload: any) {
|
||||
Vue.$log.debug('setProfile payload = ', payload);
|
||||
sState.profile = payload.profile;
|
||||
},
|
||||
setJwtToken(sState: any, payload: any) {
|
||||
console.log('setJwtToken payload = ', payload);
|
||||
Vue.$log.debug('setJwtToken payload = ', payload);
|
||||
localStorage.tokens = payload.tokens;
|
||||
sState.jwt = payload.tokens.access_token;
|
||||
sState.jwt_refresh_token = payload.tokens.refresh_token;
|
||||
},
|
||||
setTokens(sState: any, payload:any){
|
||||
console.log('setTokens payload = ', payload);
|
||||
setTokens(sState: any, payload: any) {
|
||||
Vue.$log.debug('setTokens payload = ', payload);
|
||||
sState.access_token = payload.tokens.access_token;
|
||||
sState.refresh_token = payload.tokens.refresh_token;
|
||||
console.log(sState.access_token);
|
||||
console.log(sState.access_token);
|
||||
}
|
||||
Vue.$log.debug(sState.access_token);
|
||||
Vue.$log.debug(sState.access_token);
|
||||
},
|
||||
};
|
||||
|
||||
const getters = {
|
||||
// reusable data accessors
|
||||
isAuthenticated(sState: any) {
|
||||
return isValidJwt(sState.jwt.token);
|
||||
return isValidJwt(sState.access_token);
|
||||
},
|
||||
getLoginProviders(sState: any) {
|
||||
return sState.loginProviders;
|
||||
@@ -176,6 +194,7 @@ const store = new Vuex.Store({
|
||||
actions,
|
||||
mutations,
|
||||
getters,
|
||||
plugins: [createPersistedState()],
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
||||
Reference in New Issue
Block a user