#54 user accounts - vuex store and localStorage

This commit is contained in:
Avris 2020-10-15 18:50:32 +02:00
parent 7ac9348396
commit 7453a26773
6 changed files with 217 additions and 82 deletions

View File

@ -39,50 +39,106 @@
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
computed: {
...mapState([
'user',
]),
links() {
const links = [];
links.push({ link: '/', icon: 'home', text: this.$t('home.header'), textLong: this.$t('home.headerLong'), extra: ['all', this.config.template.any.route] });
links.push({
link: '/',
icon: 'home',
text: this.$t('home.header'),
textLong: this.$t('home.headerLong'),
extra: ['all', this.config.template.any.route],
});
if (this.config.sources.enabled) {
links.push({ link: '/' + this.config.sources.route, icon: 'books', text: this.$t('sources.header'), textLong: this.$t('sources.headerLong') });
links.push({
link: '/' + this.config.sources.route,
icon: 'books',
text: this.$t('sources.header'),
textLong: this.$t('sources.headerLong'),
});
}
if (this.config.nouns.enabled) {
links.push({ link: '/' + this.config.nouns.route, icon: 'atom-alt', text: this.$t('nouns.header'), textLong: this.$t('nouns.headerLong') });
links.push({
link: '/' + this.config.nouns.route,
icon: 'atom-alt',
text: this.$t('nouns.header'),
textLong: this.$t('nouns.headerLong'),
});
}
if (this.config.names.enabled) {
links.push({ link: '/' + this.config.names.route, icon: 'signature', text: this.$t('names.header'), textLong: this.$t('names.headerLong') });
links.push({
link: '/' + this.config.names.route,
icon: 'signature',
text: this.$t('names.header'),
textLong: this.$t('names.headerLong'),
});
}
if (this.config.faq.enabled) {
links.push({ link: '/' + this.config.faq.route, icon: 'map-marker-question', text: this.$t('faq.header'), textLong: this.$t('faq.headerLong') });
links.push({
link: '/' + this.config.faq.route,
icon: 'map-marker-question',
text: this.$t('faq.header'),
textLong: this.$t('faq.headerLong'),
});
}
if (this.config.links.enabled) {
links.push({ link: '/' + this.config.links.route, icon: 'bookmark', text: this.$t('links.header'), textLong: this.$t('links.headerLong') });
links.push({
link: '/' + this.config.links.route,
icon: 'bookmark',
text: this.$t('links.header'),
textLong: this.$t('links.headerLong'),
});
}
if (this.config.people.enabled) {
links.push({ link: '/' + this.config.people.route, icon: 'user-friends', text: this.$t('people.header'), textLong: this.$t('people.headerLong') });
links.push({
link: '/' + this.config.people.route,
icon: 'user-friends',
text: this.$t('people.header'),
textLong: this.$t('people.headerLong'),
});
}
if (this.config.english.enabled) {
links.push({ link: '/' + this.config.english.route, icon: 'globe-americas', text: this.$t('english.header'), textLong: this.$t('english.headerLong') });
links.push({
link: '/' + this.config.english.route,
icon: 'globe-americas',
text: this.$t('english.header'),
textLong: this.$t('english.headerLong'),
});
}
if (this.config.contact.enabled) {
links.push({ link: '/' + this.config.contact.route, icon: 'comment-alt-smile', text: this.$t('contact.header')});
links.push({
link: '/' + this.config.contact.route,
icon: 'comment-alt-smile',
text: this.$t('contact.header'),
});
}
if (this.config.user.enabled) {
links.push({ link: '/' + this.config.user.route, icon: 'user', text: this.$t('user.header'), textLong: this.$t('user.headerLong')});
links.push({
link: '/' + this.config.user.route,
icon: 'user',
text: this.user ? '@' + this.user.username : this.$t('user.header'),
textLong: this.user ? '@' + this.user.username : this.$t('user.headerLong'),
});
}
return {
links,
};
return links;
},
},
methods: {
isActiveRoute(link) {

View File

@ -44,6 +44,7 @@ export default {
plugins: [
{ src: '~/plugins/vue-matomo.js', ssr: false },
{ src: '~/plugins/globals.js' },
{ src: '~/plugins/auth.js' },
],
components: true,
buildModules: [],

10
plugins/auth.js Normal file
View File

@ -0,0 +1,10 @@
import { Session } from "../src/helpers";
export default ({store}) => {
if (Session.isAvailable()) {
const token = Session.get('token');
if (token) {
store.commit('setToken', token);
}
}
}

View File

@ -5,6 +5,7 @@
<T>user.headerLong</T>
</h2>
<section>
<div v-if="error" class="alert alert-danger">
<p class="mb-0">
<Icon v="exclamation-triangle"/>
@ -12,8 +13,13 @@
</p>
</div>
<div v-if="payload && payload.authenticated">
Logged in as <strong>{{payload.uid}}</strong>.
<div v-if="$store.state.user">
Logged in as <strong>@{{$store.state.user.username}}</strong>.
<button class="btn btn-outline-secondary btn-sm" @click="logout">
<Icon v="sign-out"/>
Log out
</button>
</div>
<div v-else-if="token === null">
<form @submit.prevent="login">
@ -52,11 +58,7 @@
</div>
</form>
</div>
<div v-if="token">
<pre><code>{{JSON.stringify(token)}}</code></pre>
<pre>{{JSON.stringify(payload, null, 4)}}</pre>
</div>
</section>
</div>
</template>
@ -80,6 +82,8 @@
return null;
}
this.$store.commit('setToken', this.token);
return jwt.verify(this.token, process.env.PUBLIC_KEY, {
algorithm: 'RS256',
audience: process.env.BASE_URL,
@ -107,14 +111,19 @@
const response = await this.$axios.$post(url, data, options);
if (response.error) {
this.error = response.error;
this.usernameOrEmail = '';
this.code = '';
if (response.error) {
this.error = response.error;
return;
}
this.token = response.token;
},
logout() {
this.token = null;
this.$store.commit('setToken', null);
}
},
head() {

View File

@ -72,3 +72,27 @@ export const makeId = (length, characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi
return result;
}
export class Session {
static isAvailable() {
return typeof localStorage !== 'undefined';
}
static set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
}
static get(key) {
const value = localStorage.getItem(key);
return key === null ? null : JSON.parse(value);
}
static has(key) {
return localStorage.getItem(key) !== null;
}
static remove(key) {
localStorage.removeItem(key);
}
}

35
store/index.js Normal file
View File

@ -0,0 +1,35 @@
import jwt from 'jsonwebtoken';
import { Session } from '../src/helpers';
export const state = () => ({
token: null,
user: null,
})
export const mutations = {
setToken(state, token) {
if (!token) {
state.token = null;
state.user = null;
Session.remove('token');
return;
}
const user = jwt.verify(token, process.env.PUBLIC_KEY, {
algorithm: 'RS256',
audience: process.env.BASE_URL,
issuer: process.env.BASE_URL,
});
if (user && user.authenticated) {
state.token = token;
state.user = user;
Session.set('token', token);
return;
}
state.token = null;
state.user = null;
Session.remove('token');
}
}