UNPKG

@hperchec/scorpion-ui-template-default

Version:
299 lines (295 loc) 10.8 kB
import { Core, utils } from '@hperchec/scorpion-ui' const { safeAsync } = utils const log = (msg) => Core.context.services['store'].options.log(`"Auth" module: ${msg}`, { type: 'store' }) // eslint-disable-line dot-notation const logError = (msg) => Core.context.services['store'].options.log(`Store "Auth" module: ${msg}`, { type: 'error' }) // eslint-disable-line dot-notation /** * Auth * @alias module:store/modules/Auth * @type {Object} */ export default { /** * @private */ namespaced: true, /** * state * @type {Object} * @readonly * @description Store module state * @example * // Access to the module state * Store.state.Core.Auth */ state: { /** * currentUser * @description Current / Authenticated User * @type {?User} * @default null */ currentUser: null, // default guest /** * currentUserLoading * @description Indicates if current user is loading from API * @type {boolean} * @default false */ currentUserLoading: false, /** * passwordForSecurity * @description When user enter password for securized features * @type {string} * @default '' (empty string) */ passwordForSecurity: '' }, /** * getters * @type {Object} * @readonly * @description Store module getters * @example * // Access to the module getters, where <name> is the getter name * Store.getters['Core/Auth/<name>'] */ getters: { // Nothing here... }, /** * actions * @type {Object} * @protected * @description Store module actions * @example * // Access to the module action, where <name> is the action name * Store.dispatch('Core/Auth/<name>') */ actions: { /** * login * @description Request `[POST] /api/login` with credentials data. * If server side success, save tokens in LocalStorage and dispatch 'check' * @param {Object} context - vuex context * @param {Object} payload - Method payload * @param {Object} payload.data - Request data * @param {string} payload.data.username - Username * @param {string} payload.data.password - Password * @return {(boolean|Error)} Return value of 'check' */ login: async function ({ commit, dispatch }, { data }) { const ServerAPI = Core.service('api-manager').use('ServerAPI') const localStorageManager = Core.context.services['store'].options.localStorageManager() // eslint-disable-line dot-notation // Set currentUserLoading to true commit('SET_CURRENT_USER_LOADING', true) // Define URL const method = 'POST' const path = '/login' const url = `${ServerAPI.options.baseURL}${path}` log(`Login request - Request [${method}] "${url}" ...`) // Request server const response = await safeAsync(() => ServerAPI.request(method, path, { data: data })) // Set currentUserLoading to false commit('SET_CURRENT_USER_LOADING', false) // If error if (response instanceof Error) { logError(`Login request error - Server response [${method}] "${url}" ...`) // Return error return response } // Everything is okay const accessToken = response.data.access_token // const refreshToken = response.data.refresh_token log('Set access token in localStorage') // Save tokens in localStorage localStorageManager.items[Core.config.auth.accessTokenKey] = accessToken // localStorageManager.items[Core.config.auth.refreshTokenKey] = refreshToken // Get user return dispatch('check') }, /** * logout * @description Remove tokens from the local storage and reset current user * @param {Object} context - vuex context * @return {void} */ logout: async function ({ commit }) { const ServerAPI = Core.service('api-manager').use('ServerAPI') const localStorageManager = Core.context.services['store'].options.localStorageManager() // eslint-disable-line dot-notation // Set currentUserLoading to true commit('SET_CURRENT_USER_LOADING', true) // Define URL const method = 'POST' const path = '/logout' const url = `${ServerAPI.options.baseURL}${path}` log(`Logout request - Request [${method}] "${url}" ...`) // Request server const response = await safeAsync(() => ServerAPI.request(method, path)) // Set currentUserLoading to false commit('SET_CURRENT_USER_LOADING', false) // If error if (response instanceof Error) { logError(`Logout request error - Server response [${method}] "${url}" ...`) // Return error return response } // Everything is okay log('Remove tokens from localStorage') // Remove access token delete localStorageManager.items[Core.config.auth.accessTokenKey] delete localStorageManager.items[Core.config.auth.refreshTokenKey] // Reset currentUser commit('RESET_CURRENT_USER') }, /** * check * @description Check if user is authenticated. * First, check if token is set in the local storage, * set authorization header and request for user data from server. * Else, call 'logout' and return false. * @param {Object} context - vuex context * @return {(boolean|Error)} False or return value of 'loadCurrentUserData' */ check: async function ({ commit, dispatch }) { const localStorageManager = Core.context.services['store'].options.localStorageManager() // eslint-disable-line dot-notation log('Check access token in localStorage...') // Retrieve token in localStorage const accessToken = localStorageManager.items[Core.config.auth.accessTokenKey] // const refreshToken = localStorageManager.items[Core.config.auth.refreshTokenKey] // If no access token if (!accessToken) { log('Not authenticated ❌') return false } log('Access token found ✔') // Set token to headers for each future requests dispatch('setAuthorizationHeader', { token: accessToken }) // Get User data return dispatch('loadCurrentUserData') }, /** * loadCurrentUserData * @description Load current user data from API server. * Request `[GET] /api/me` (See [API Server documentation](/guide/system/api-server/)). * @param {Object} context - vuex context * @return {(boolean|Error)} If success: true, else Error */ loadCurrentUserData: async function ({ commit, dispatch }) { const ServerAPI = Core.service('api-manager').use('ServerAPI') // Set currentUserLoading to true commit('SET_CURRENT_USER_LOADING', true) // Define URL const method = 'GET' const path = '/me' const url = `${ServerAPI.options.baseURL}${path}` log(`Load current user data - Request [${method}] "${url}" ...`) // Request server const response = await safeAsync(() => ServerAPI.request(method, path)) // Set currentUserLoading to false commit('SET_CURRENT_USER_LOADING', false) // If error if (response instanceof Error) { // Authentication token error logError(`Authentication token error - Server response [${method}] "${url}" ...`) // Remove token and reset user dispatch('logout') // Return error return response } // Everything is okay // Set user in state commit('SET_CURRENT_USER', response.data) log('Authenticated ✔') // Return true return true }, /** * setAuthorizationHeader * @description Set the authorization token header for the API instance (ServerAPI). * @param {Object} context - vuex context * @param {Object} payload - Method payload * @param {string} payload.token - The access token * @return {void} */ setAuthorizationHeader: function ({ commit }, { token }) { const ServerAPI = Core.service('api-manager').use('ServerAPI') log('Set authorization headers (token) for future requests to Server API') // Set authorization token ServerAPI.driver.defaults.headers.common.Authorization = `Bearer ${token}` }, /** * resetAuthorizationHeader * @description Delete the authorization token header for the API instance (ServerAPI). * @param {Object} context - vuex context * @return {void} */ resetAuthorizationHeader ({ commit }) { const ServerAPI = Core.service('api-manager').use('ServerAPI') log('Reset authorization headers of Server API') // Delete header delete ServerAPI.driver.defaults.headers.common.Authorization } }, /** * mutations * @type {Object} * @protected * @description Store module mutations * @example * // Dispatch a module mutation, where <mutation_name> is the mutation name * Store.commit('Auth/<mutation_name>', [payload]) */ mutations: { /** * SET_CURRENT_USER * @description Mutate state.currentUser * @param {Object} state - vuex store state * @param {Object} user - Data received from server * @return {void} */ SET_CURRENT_USER (state, user) { state.currentUser = new Core.context.models.User(user) state.currentUser.authenticated = true }, /** * RESET_CURRENT_USER * @description Mutate state.currentUser * @param {Object} state - vuex store state * @return {void} */ RESET_CURRENT_USER (state) { state.currentUser = new Core.context.models.User() }, /** * SET_CURRENT_USER_LOADING * @description Mutate state.currentUserLoading * @param {Object} state - vuex store state * @param {boolean} value - True or false * @return {void} */ SET_CURRENT_USER_LOADING (state, value) { state.currentUserLoading = value }, /** * SET_PASSWORD_FOR_SECURITY * @description Mutate state.passwordForSecurity * @param {Object} state - vuex store state * @param {string} value - Password * @return {void} */ SET_PASSWORD_FOR_SECURITY (state, value) { state.passwordForSecurity = value }, /** * RESET_PASSWORD_FOR_SECURITY * @description Mutate state.passwordForSecurity * @param {Object} state - vuex store state * @return {void} */ RESET_PASSWORD_FOR_SECURITY (state) { state.passwordForSecurity = '' } } }