Allow multiple identities (accounts actors) for one user.
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -12,24 +12,24 @@
|
||||
<v-list-group
|
||||
value="false"
|
||||
>
|
||||
<v-list-tile avatar v-if="$store.state.user" slot="activator">
|
||||
<v-list-tile avatar v-if="$store.state.actor" slot="activator">
|
||||
<v-list-tile-avatar>
|
||||
<img v-if="!getUser().actor.avatar_url"
|
||||
<img v-if="!$store.state.actor.avatar"
|
||||
class="img-circle elevation-7 mb-1"
|
||||
src="https://picsum.photos/125/125/"
|
||||
>
|
||||
<img v-else
|
||||
class="img-circle elevation-7 mb-1"
|
||||
:src="getUser().actor.avatar_url"
|
||||
:src="$store.state.actor.avatar"
|
||||
>
|
||||
</v-list-tile-avatar>
|
||||
|
||||
<v-list-tile-content @click="$router.push({name: 'Account', params: { name: getUser().actor.username }})">
|
||||
<v-list-tile-content @click="$router.push({name: 'Account', params: { name: $store.state.actor.username }})">
|
||||
<v-list-tile-title>{{ this.displayed_name }}</v-list-tile-title>
|
||||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-tile avatar v-if="$store.state.user">
|
||||
<v-list-tile avatar v-if="$store.state.actor">
|
||||
<v-list-tile-avatar>
|
||||
<img
|
||||
class="img-circle elevation-7 mb-1"
|
||||
@@ -177,7 +177,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
displayed_name() {
|
||||
return this.$store.state.user.actor.display_name === null ? this.$store.state.user.actor.username : this.$store.state.user.actor.display_name
|
||||
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { API_ORIGIN, API_PATH } from '../api/_entrypoint';
|
||||
import { LOGIN_USER, LOAD_USER, CHANGE_ACTOR } from '../store/mutation-types';
|
||||
|
||||
// URL and endpoint constants
|
||||
const LOGIN_URL = `${API_ORIGIN}${API_PATH}/login`;
|
||||
@@ -53,7 +54,7 @@ export default {
|
||||
.then((response) => {
|
||||
console.log('We have a new token');
|
||||
this.authenticated = true;
|
||||
store.commit('LOGIN_USER', response);
|
||||
store.commit(LOGIN_USER, response);
|
||||
localStorage.setItem('token', response.token);
|
||||
console.log("Let's try to auth again");
|
||||
successHandler();
|
||||
@@ -104,9 +105,10 @@ export default {
|
||||
}).then((response) => {
|
||||
this.authenticated = true;
|
||||
console.log(response);
|
||||
store.commit('LOAD_USER', response.data);
|
||||
store.commit(LOAD_USER, response.data);
|
||||
store.commit(CHANGE_ACTOR, response.data.actors[0]);
|
||||
return successHandler();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// The object to be passed as a header for authenticated requests
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<v-icon>chevron_left</v-icon>
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.user.actor.id === actor.id">
|
||||
<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.actor.id === actor.id">
|
||||
<v-icon>edit</v-icon>
|
||||
</v-btn>
|
||||
<v-menu bottom left>
|
||||
@@ -18,10 +18,10 @@
|
||||
<v-icon>more_vert</v-icon>
|
||||
</v-btn>
|
||||
<v-list>
|
||||
<v-list-tile @click="logoutUser()" v-if="$store.state.user && $store.state.user.actor.id === actor.id">
|
||||
<v-list-tile @click="logoutUser()" v-if="$store.state.user && $store.state.actor.id === actor.id">
|
||||
<v-list-tile-title>User logout</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
<v-list-tile @click="deleteAccount()" v-if="$store.state.user && $store.state.user.actor.id === actor.id">
|
||||
<v-list-tile @click="deleteAccount()" v-if="$store.state.user && $store.state.actor.id === actor.id">
|
||||
<v-list-tile-title>Delete</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
@@ -30,13 +30,13 @@
|
||||
<v-spacer></v-spacer>
|
||||
<div class="text-xs-center">
|
||||
<v-avatar size="125px">
|
||||
<img v-if="!actor.avatar_url"
|
||||
<img v-if="!actor.avatar"
|
||||
class="img-circle elevation-7 mb-1"
|
||||
src="https://picsum.photos/125/125/"
|
||||
>
|
||||
<img v-else
|
||||
class="img-circle elevation-7 mb-1"
|
||||
:src="actor.avatar_url"
|
||||
:src="actor.avatar"
|
||||
>
|
||||
</v-avatar>
|
||||
</div>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
import { LOGIN_USER } from '@/store/mutation-types';
|
||||
import auth from '@/auth/index';
|
||||
import Gravatar from 'vue-gravatar';
|
||||
import RegisterAvatar from './RegisterAvatar';
|
||||
@@ -119,7 +120,7 @@
|
||||
loginAction(e) {
|
||||
e.preventDefault();
|
||||
auth.login(JSON.stringify(this.credentials), (data) => {
|
||||
this.$store.commit('LOGIN_USER', data.user);
|
||||
this.$store.commit(LOGIN_USER, data.user);
|
||||
this.$router.push({ name: 'Home' });
|
||||
}, (error) => {
|
||||
Promise.resolve(error).then((errorMsg) => {
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<b-container>
|
||||
<v-container>
|
||||
<h1 v-if="loading">{{ $t('registration.validation.process') }}</h1>
|
||||
<div v-else>
|
||||
<div v-if="failed">
|
||||
<b-alert show variant="danger">{{ $t('registration.success.validation_failure') }}</b-alert>
|
||||
<v-alert :value="true" variant="danger">Error while validating account</v-alert>
|
||||
</div>
|
||||
<h1 v-else>{{ $t('registration.validation.finished') }}</h1>
|
||||
</div>
|
||||
</b-container>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import fetchStory from '@/api/eventFetch';
|
||||
import { LOGIN_USER } from '@/store/mutation-types';
|
||||
|
||||
export default {
|
||||
name: 'Validate',
|
||||
@@ -36,7 +37,7 @@ export default {
|
||||
this.loading = false;
|
||||
localStorage.setItem('token', data.token);
|
||||
localStorage.setItem('refresh_token', data.refresh_token);
|
||||
this.$store.commit('LOGIN_USER', data.account);
|
||||
this.$store.commit(LOGIN_USER, data.account);
|
||||
this.$snotify.success(this.$t('registration.success.login', { username: data.account.username }));
|
||||
this.$router.push({ name: 'Home' });
|
||||
}).catch((err) => {
|
||||
|
||||
@@ -120,8 +120,8 @@
|
||||
// });
|
||||
// });
|
||||
this.event.category_id = this.event.category;
|
||||
this.event.organizer_actor_id = this.$store.state.user.actor.id;
|
||||
this.event.participants = [this.$store.state.user.actor.id];
|
||||
this.event.organizer_actor_id = this.$store.state.actor.id;
|
||||
this.event.participants = [this.$store.state.actor.id];
|
||||
// this.event.price = parseFloat(this.event.price);
|
||||
|
||||
if (this.id === undefined) {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<v-icon>chevron_left</v-icon>
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon class="mr-3 white--text" v-if="event.organizer.id === $store.state.user.actor.id" :to="{ name: 'EditEvent', params: {id: event.id}}">
|
||||
<v-btn icon class="mr-3 white--text" v-if="actorIsOrganizer()" :to="{ name: 'EditEvent', params: {id: event.id}}">
|
||||
<v-icon>edit</v-icon>
|
||||
</v-btn>
|
||||
<v-menu bottom left>
|
||||
@@ -27,7 +27,7 @@
|
||||
<v-list-tile @click="downloadIcsEvent()">
|
||||
<v-list-tile-title>Download</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
<v-list-tile @click="deleteEvent()" v-if="$store.state.user.actor.id === event.organizer.id">
|
||||
<v-list-tile @click="deleteEvent()" v-if="actorIsOrganizer()">
|
||||
<v-list-tile-title>Delete</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
@@ -217,10 +217,10 @@
|
||||
})
|
||||
},
|
||||
actorIsParticipant() {
|
||||
return this.event.participants.map(participant => participant.id).includes(this.$store.state.user.actor.id) || this.actorIsOrganizer();
|
||||
return this.$store.state.actor && this.event.participants.map(participant => participant.id).includes(this.$store.state.actor.id) || this.actorIsOrganizer();
|
||||
},
|
||||
actorIsOrganizer() {
|
||||
return this.$store.state.user.actor.id === this.event.organizer.id;
|
||||
return this.$store.state.actor && this.$store.state.actor.id === this.event.organizer.id;
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<v-icon>chevron_left</v-icon>
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<!--<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.user.actor.id === actor.id">-->
|
||||
<!--<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.actor.id === actor.id">-->
|
||||
<!--<v-icon>edit</v-icon>-->
|
||||
<!--</v-btn>-->
|
||||
<v-btn icon>
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-jumbotron>
|
||||
<v-layout>
|
||||
<v-layout v-else>
|
||||
<v-flex xs12 sm8 offset-sm2>
|
||||
<v-layout row wrap>
|
||||
<v-flex xs12 sm6>
|
||||
<h1>Welcome back {{ $store.state.user.actor.username }}</h1>
|
||||
<h1>Welcome back {{ $store.state.actor.username }}</h1>
|
||||
</v-flex>
|
||||
<v-flex xs12 sm6>
|
||||
<v-layout align-center>
|
||||
@@ -51,7 +51,7 @@
|
||||
</v-card-media>
|
||||
<v-card-title primary-title>
|
||||
<div>
|
||||
<span class="grey--text">{{ event.begins_on | formatDate }}</span><br>
|
||||
<span class="grey--text">{{ event.begins_on | formatDay }}</span><br>
|
||||
<router-link :to="{name: 'Account', params: { name: event.organizer.username } }">
|
||||
<v-avatar size="25px">
|
||||
<img class="img-circle elevation-7 mb-1"
|
||||
@@ -100,8 +100,8 @@ export default {
|
||||
this.fetchData();
|
||||
},
|
||||
computed: {
|
||||
displayed_name: function() {
|
||||
return this.$store.state.user.actor.display_name === null ? this.$store.state.user.actor.username : this.$store.state.user.actor.display_name
|
||||
displayed_name() {
|
||||
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -75,8 +75,7 @@
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
<v-btn flat @click="$router.push({name: 'Account', params: { name: getUser().actor.username }})" v-if="$store.state.user">{{ this.displayed_name }}</v-btn>
|
||||
<v-btn v-else :to="{ name: 'Login' }">Se connecter</v-btn>
|
||||
<v-btn v-if="!$store.state.user" :to="{ name: 'Login' }">Se connecter</v-btn>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
|
||||
@@ -123,7 +122,10 @@
|
||||
},
|
||||
computed: {
|
||||
displayed_name: function() {
|
||||
return this.$store.state.user.actor.display_name === null ? this.$store.state.user.actor.username : this.$store.state.user.actor.display_name
|
||||
console.log('displayed name', this.$store.state.actor);
|
||||
if (this.$store.state.actor) {
|
||||
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -3,36 +3,21 @@
|
||||
import Vue from 'vue';
|
||||
// import * as VueGoogleMaps from 'vue2-google-maps';
|
||||
import VueMarkdown from 'vue-markdown';
|
||||
import VuetifyGoogleAutocomplete from 'vuetify-google-autocomplete';
|
||||
import Vuetify from 'vuetify';
|
||||
import Vuex from 'vuex';
|
||||
import moment from 'moment';
|
||||
import VuexI18n from 'vuex-i18n';
|
||||
import 'material-design-icons/iconfont/material-icons.css';
|
||||
import 'vuetify/dist/vuetify.min.css';
|
||||
import App from '@/App';
|
||||
import router from '@/router';
|
||||
import storeData from '@/store/index';
|
||||
import translations from '@/i18n/index';
|
||||
import auth from '@/auth';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import store from './store';
|
||||
import translations from './i18n';
|
||||
import auth from './auth';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
Vue.use(VuetifyGoogleAutocomplete, {
|
||||
apiKey: 'AIzaSyBF37pw38j0giICt73TCAPNogc07Upe_Q4', // Can also be an object. E.g, for Google Maps Premium API, pass `{ client: <YOUR-CLIENT-ID> }`
|
||||
});
|
||||
|
||||
/*Vue.use(VueGoogleMaps, {
|
||||
load: {
|
||||
key: 'AIzaSyBF37pw38j0giICt73TCAPNogc07Upe_Q4',
|
||||
libraries: 'places',
|
||||
installComponents: false,
|
||||
},
|
||||
});*/
|
||||
|
||||
Vue.use(VueMarkdown);
|
||||
Vue.use(Vuetify);
|
||||
Vue.use(Vuex);
|
||||
let language = window.navigator.userLanguage || window.navigator.language;
|
||||
moment.locale(language);
|
||||
|
||||
@@ -43,8 +28,6 @@ if (!(language in translations)) {
|
||||
[language] = language.split('-', 1);
|
||||
}
|
||||
|
||||
const store = new Vuex.Store(storeData);
|
||||
|
||||
Vue.use(VuexI18n.plugin, store);
|
||||
|
||||
Object.entries(translations).forEach((key) => {
|
||||
@@ -55,17 +38,21 @@ Vue.i18n.set(language);
|
||||
Vue.i18n.fallback('en');
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (to.matched.some(record => record.meta.requiredAuth) && store.state.user === undefined || store.state.user == null) {
|
||||
if (to.matched.some(record => record.meta.requiredAuth)) {
|
||||
next({
|
||||
name: 'Login',
|
||||
query: { redirect: to.fullPath }
|
||||
query: { redirect: to.fullPath },
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
auth.getUser(store, () => {}, () => {});
|
||||
auth.getUser(store, () => {}, (error) => {
|
||||
console.warn(error);
|
||||
});
|
||||
|
||||
console.log('store', store);
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { LOGIN_USER, LOGOUT_USER, LOAD_USER } from './mutation-types';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import { LOGIN_USER, LOGOUT_USER, LOAD_USER, CHANGE_ACTOR } from './mutation-types';
|
||||
|
||||
const state = {
|
||||
isLogged: !!localStorage.getItem('token'),
|
||||
user: false,
|
||||
actor: false,
|
||||
defaultActor: localStorage.getItem('defaultActor') || null,
|
||||
};
|
||||
|
||||
/* eslint-disable */
|
||||
@@ -20,7 +24,21 @@ const mutations = {
|
||||
state.isLogged = false;
|
||||
state.user = null;
|
||||
},
|
||||
|
||||
[CHANGE_ACTOR](state, actor) {
|
||||
state.actor = actor;
|
||||
state.defaultActor = actor.username;
|
||||
}
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
||||
export default { state, mutations };
|
||||
Vue.use(Vuex);
|
||||
const store = new Vuex.Store({ state, mutations });
|
||||
|
||||
store.subscribe((mutation, localState) => {
|
||||
if (mutation === CHANGE_ACTOR) {
|
||||
localStorage.setItem('defaultActor', localState.actor.username);
|
||||
}
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export const LOGIN_USER = 'LOGIN_USER';
|
||||
export const LOAD_USER = 'LOAD_USER';
|
||||
export const LOGOUT_USER = 'LOGOUT_USER';
|
||||
export const CHANGE_ACTOR = 'CHANGE_ACTOR';
|
||||
|
||||
Reference in New Issue
Block a user