import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'; import { LoginData, LoginResponse } from 'src/plugins/user/models'; import { StateInterface } from 'src/store'; import { axios } from 'src/boot/axios'; import { AxiosError, AxiosResponse } from 'axios'; import { Router } from 'src/router'; import { LocalStorage } from 'quasar'; export interface SessionInterface { currentSession?: FG.Session; sessions: FG.Session[]; loading: boolean; } /** * Load current session from LocalStorage * Used when we were already authenticated using this browser */ function loadCurrentSession() { const session = LocalStorage.getItem('currentSession'); if (session) session.expires = new Date(session.expires); return session; } const state: SessionInterface = { sessions: [], currentSession: loadCurrentSession() || undefined, loading: false, }; const mutations: MutationTree = { setCurrentSession(state, session: FG.Session) { LocalStorage.set('currentSession', session); state.currentSession = session; }, clearCurrentSession(state) { LocalStorage.remove('currentSession'); state.currentSession = undefined; }, setSessions(state, sessions: FG.Session[]) { state.sessions = sessions; }, setLoading(state, value: boolean) { state.loading = value; }, updateSession(state, session: FG.Session) { const index = state.sessions.findIndex((x) => x.token == session.token); if (index > -1) { state.sessions[index] = session; } }, }; const actions: ActionTree = { /** Used to authenticate the user * Setting current Session, User and Permissions. * @param param0 Context * @param data Credentitals */ login({ commit }, data: LoginData) { return axios .post('/auth', data) .then((response: AxiosResponse) => { response.data.session.expires = new Date(response.data.session.expires); commit('setCurrentSession', response.data.session); commit('user/setCurrentUser', response.data.user, { root: true }); commit('user/setCurrentPermissions', response.data.permissions, { root: true, }); }) .catch((error: AxiosError) => { return Promise.reject(error.response); }); }, /** * Logout from current session * Alias of deleteSession with current session as target */ logout({ dispatch, rootState }) { if (rootState.session.currentSession) { dispatch('deleteSession', rootState.session.currentSession.token).catch((error) => { console.log(error); void dispatch('clearCurrent', false); }); } else { void dispatch('clearCurrent', false); } }, /** * Delete a given session */ deleteSession({ commit, dispatch, rootState }, token: string) { commit('setLoading', true); axios .delete(`/auth/${token}`) .then(() => { if (token === rootState.session.currentSession?.token) { void dispatch('clearCurrent', false); } else { dispatch('getSessions').catch((error) => { throw error; }); } }) .catch((error: AxiosError) => { if (!error.response || error.response.status != 401) throw error; }) .finally(() => { commit('setLoading', false); }); }, /** * Clear current session and logged in user */ clearCurrent({ commit }, redirect = true) { void Router.push({ name: 'login', query: redirect ? { redirect: Router.currentRoute.fullPath } : {}, params: { logout: 'true' }, }).then(() => { commit('clearCurrentSession'); commit('user/clearCurrentUser', null, { root: true }); // ensure also volatile store gets cleared by refreshing the site Router.go(0); }); }, /** * Get all sessions from current User */ getSessions({ commit, state }) { commit('setLoading', true); axios .get('/auth') .then((response: AxiosResponse) => { response.data.forEach((session) => { session.expires = new Date(session.expires); }); commit('setSessions', response.data); const currentSession = response.data.find((session: FG.Session) => { return session.token === state.currentSession?.token; }); if (currentSession) { commit('setCurrentSession', currentSession); } }) .catch((error) => { throw error; }) .finally(() => { commit('setLoading', false); }); }, updateSession({ commit, state }, data: { lifetime: number; token: string }) { commit('setLoading', true); axios .put(`auth/${data.token}`, { value: data.lifetime }) .then((response: AxiosResponse) => { response.data.expires = new Date(response.data.expires); if (state.currentSession?.token == response.data.token) { commit('setCurrentSession', response.data); } }) .catch((err) => console.log(err)) .finally(() => { commit('setLoading', false); }); console.log('updateSession', data); }, requestPasswordReset({}, data) { return axios.post('/auth/reset', data); }, resetPassword({}, data) { return axios.post('/auth/reset', data).catch((error: AxiosError) => { return Promise.reject(error.response); }); }, }; const getters: GetterTree = { currentSession(state) { return state.currentSession; }, sessions(state) { return state.sessions; }, loading(state) { return state.loading; }, }; const sessions: Module = { namespaced: true, state, mutations, actions, getters, }; export default sessions;