flaschengeist-frontend/src/plugins/user/store/session.ts

200 lines
5.8 KiB
TypeScript

import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
import { LoginData, LoginResponse } from 'src/plugins/user/models';
import { api } from 'src/boot/axios';
import { AxiosError, AxiosResponse } from 'axios';
import { LocalStorage } from 'quasar';
import { UserSessionState } from '.';
import { Router } from 'src/router';
export interface SessionStateInterface {
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<FG.Session>('currentSession');
if (session) session.expires = new Date(session.expires);
return session;
}
const state: SessionStateInterface = {
sessions: [],
currentSession: loadCurrentSession() || undefined,
loading: false,
};
const mutations: MutationTree<SessionStateInterface> = {
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<SessionStateInterface, UserSessionState> = {
/** Used to authenticate the user
* Setting current Session, User and Permissions.
* @param param0 Context
* @param data Credentitals
*/
login({ commit }, data: LoginData) {
return api
.post('/auth', data)
.then((response: AxiosResponse<LoginResponse>) => {
response.data.session.expires = new Date(response.data.session.expires);
commit('setCurrentSession', response.data.session);
commit('users/setCurrentUser', response.data.user, { root: true });
commit('users/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.sessions.currentSession) {
dispatch('deleteSession', rootState.sessions.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);
api
.delete(`/auth/${token}`)
.then(() => {
if (token === rootState.sessions.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.value.fullPath } : {},
params: { logout: 'true' },
}).then(() => {
commit('clearCurrentSession');
commit('users/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);
api
.get('/auth')
.then((response: AxiosResponse<FG.Session[]>) => {
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);
api
.put(`auth/${data.token}`, { value: data.lifetime })
.then((response: AxiosResponse<FG.Session>) => {
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 api.post('/auth/reset', data);
},
resetPassword({}, data) {
return api.post('/auth/reset', data).catch((error: AxiosError) => {
return Promise.reject(error.response);
});
},
};
const getters: GetterTree<SessionStateInterface, UserSessionState> = {
currentSession(state) {
return state.currentSession;
},
sessions(state) {
return state.sessions;
},
loading(state) {
return state.loading;
},
};
const sessionsStore: Module<SessionStateInterface, UserSessionState> = {
namespaced: true,
state,
mutations,
actions,
getters,
};
export default sessionsStore;