chamesu
Version:
This package contains all packages of the chat application.
375 lines (301 loc) • 10.4 kB
text/typescript
/*
* Copyright (c) 2022.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/
import Vue from 'vue';
import {ActionTree, GetterTree, MutationTree} from "vuex";
import {RootState} from "~/store/index";
import {loadAndApplyContactData} from "~/domains/contact-data/utils";
import {Oauth2TokenResponse} from "@typescript-auth/core";
export type AuthStoreToken = Oauth2TokenResponse & {
expire_date: string
}
export const AuthStoreKey = {
user: 'user',
permissions: 'permissions',
token: 'token',
provider: 'provider'
}
export interface AuthState {
provider: string | undefined,
user: Record<string, any> | undefined,
permissions: Record<string, any>[],
token: AuthStoreToken | undefined,
tokenPromise: Promise<any> | undefined,
required: boolean,
inProgress: boolean,
error: undefined | { code: string, message: string },
}
const state = () : AuthState => ({
provider: undefined,
user: undefined,
permissions: [],
token: undefined,
tokenPromise: undefined,
required: false,
inProgress: false,
error: undefined
});
export const getters : GetterTree<AuthState, RootState> = {
user: (state: AuthState) => {
return state.user
},
userId: (state: AuthState) => {
return state.user ? state.user.id : undefined;
},
provider: (state: AuthState) => {
return state.provider;
},
permissions: (state: AuthState) => {
return state.permissions
},
permission: (state: AuthState) => (id: number | string) => {
let items = state.permissions.filter((item: Record<string, any>) => {
if(typeof id === 'number') {
return item.id === id;
} else {
return item.name === id;
}
});
return items.length === 1 ? items[0] : undefined;
},
loggedIn: (state : AuthState) => {
return !!state.token;
},
token: (state: AuthState) => {
return state.token;
}
};
export const actions : ActionTree<AuthState, RootState> = {
// --------------------------------------------------------------------
triggerSetLoginRequired({commit}, required: boolean) {
commit('setLoginRequired', required);
},
// --------------------------------------------------------------------
triggerSetProvider({commit}, provider) {
this.$authWarehouse.set(AuthStoreKey.provider, provider);
commit('setProvider', provider);
},
triggerUnsetProvider({commit}) {
this.$authWarehouse.remove(AuthStoreKey.provider);
commit('unsetProvider');
},
// --------------------------------------------------------------------
triggerSetToken({commit}, token) {
this.$authWarehouse.set(AuthStoreKey.token, token);
if(typeof token === 'object' && token.hasOwnProperty('accessToken')) {
this.$auth.setRequestToken(token.accessToken);
}
commit('setToken', token);
},
triggerUnsetToken({commit}) {
this.$authWarehouse.remove(AuthStoreKey.token);
this.$auth.unsetRequestToken();
commit('unsetToken');
},
// --------------------------------------------------------------------
triggerSetUser({commit}, user) {
if(typeof user.avatarMeta !== 'undefined') delete user.avatarMeta;
if(typeof user.coverMeta !== 'undefined') delete user.coverMeta;
this.$authWarehouse.set(AuthStoreKey.user, user);
commit('setUser', user);
},
triggerUnsetUser({commit}) {
this.$authWarehouse.remove(AuthStoreKey.user);
commit('unsetUser');
},
// --------------------------------------------------------------------
triggerSetPermissions({commit}, permissions) {
this.$authWarehouse.setLocalStorageItem(AuthStoreKey.permissions, permissions);
commit('setPermissions', permissions);
},
triggerUnsetPermissions({commit}) {
this.$authWarehouse.removeLocalStorageItem(AuthStoreKey.permissions);
commit('unsetPermissions');
},
// --------------------------------------------------------------------
/**
* Try to trigger user refresh.
*
* @param state
* @param dispatch
*
* @returns {Promise<boolean>}
*/
async triggerRefreshMe ({ state, dispatch }) {
if (state.token) {
try {
const { permissions, ...user } = await this.$auth.getUserInfo(state.token.access_token);
await loadAndApplyContactData(user.id);
dispatch('triggerUnsetUser');
dispatch('triggerSetUser', user);
dispatch('triggerSetPermissions', permissions);
} catch (e) {
dispatch('triggerLogout');
throw e;
}
}
},
// --------------------------------------------------------------------
/**
* Try to login the user with given credentials.
*
* @return {Promise<boolean>}
*/
async triggerLogin ({ commit, dispatch }, credentials: {[key: string] : any}) {
commit('loginRequest');
try {
const token = await this.$auth.getTokenWithPassword(credentials.name, credentials.password);
commit('loginSuccess');
dispatch('triggerSetToken', token);
await dispatch('triggerRefreshMe');
this.dispatch('layout/update');
} catch (e) {
dispatch('triggerUnsetToken');
throw e;
}
},
// --------------------------------------------------------------------
triggerRefreshToken ({ commit, state, dispatch }) {
if(
typeof state.provider === 'undefined' ||
typeof state.token === 'undefined' ||
typeof state.token.refresh_token === 'undefined'
) {
throw new Error('It is not possible to receive a new access token');
}
if (!state.tokenPromise) {
commit('loginRequest');
try {
const p = this.$auth.getTokenWithRefreshToken(
state.token.refresh_token
);
commit('setTokenPromise', p);
p.then(
(token) => {
commit('setTokenPromise', null);
commit('loginSuccess');
dispatch('triggerSetToken', token);
dispatch('triggerRefreshMe');
},
() => {
commit('setTokenPromise', null)
}
)
} catch (e) {
commit('setTokenPromise', null);
dispatch('triggerAuthError', e.message);
throw new Error('An error occured on the token refresh request.');
}
}
return state.tokenPromise
},
// --------------------------------------------------------------------
async triggerTokenExpired({dispatch, commit}) {
try {
await dispatch('triggerRefreshToken');
} catch (e) {
dispatch('triggerSetLoginRequired', true);
}
},
// --------------------------------------------------------------------
/**
* Try to logout the user.
* @param commit
*/
triggerLogout ({ dispatch }) {
dispatch('triggerUnsetToken');
dispatch('triggerUnsetUser');
dispatch('triggerUnsetPermissions');
dispatch('triggerSetLoginRequired', false);
this.dispatch('layout/update');
},
// --------------------------------------------------------------------
/**
* Trigger custom authentication error by
* another service or component.
*
* @param commit
* @param message
*/
triggerAuthError ({ commit }, message) {
commit('loginError', { errorCode: 'internal', errorMessage: message })
},
//--------------------------------------------------------
/**
* Trigger user property change.
*
* @param commit
* @param property
* @param value
*/
triggerSetUserProperty ({ commit, state }, {property, value}) {
commit('setUserProperty', { property, value});
this.$authWarehouse.remove(AuthStoreKey.user);
this.$authWarehouse.set(AuthStoreKey.user, state.user);
}
};
export const mutations : MutationTree<AuthState> = {
// Login mutations
loginRequest (state) {
state.inProgress = true;
state.error = undefined
},
loginSuccess (state) {
state.inProgress = false;
state.required = false;
},
loginError (state, { errorCode, errorMessage }) {
state.inProgress = false;
state.error = {
code: errorCode,
message: errorMessage
}
},
setLoginRequired (state, required) {
state.required = required;
},
// --------------------------------------------------------------------
setProvider(state,provider) {
state.provider = provider;
},
// --------------------------------------------------------------------
setTokenPromise (state, promise) {
state.tokenPromise = promise;
},
// --------------------------------------------------------------------
setUser (state, user) {
state.user = user;
},
unsetUser(state) {
state.user = undefined;
},
// --------------------------------------------------------------------
setUserProperty(state, {property, value}) {
if(typeof state.user === 'undefined') return;
Vue.set(state.user, property, value);
},
// --------------------------------------------------------------------
setPermissions (state, permissions) {
state.permissions = permissions;
},
unsetPermissions(state) {
state.permissions = [];
},
// --------------------------------------------------------------------
setToken (state, token) {
state.token = token;
},
unsetToken(state) {
state.token = undefined;
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
}