import {HTTPFactory} from '@/http-common' import {ERROR_MESSAGE, LOADING} from '../mutation-types' import UserModel from '../../models/user' export default { namespaced: true, state: () => ({ authenticated: false, isLinkShareAuth: false, info: {}, needsTotpPasscode: false, avatarUrl: '', }), mutations: { info(state, info) { state.info = info state.avatarUrl = info.getAvatarUrl() }, setUserSettings(state, {name, emailRemindersEnabled}) { state.info.name = name state.info.emailRemindersEnabled = emailRemindersEnabled }, authenticated(state, authenticated) { state.authenticated = authenticated }, isLinkShareAuth(state, is) { state.isLinkShareAuth = is }, needsTotpPasscode(state, needs) { state.needsTotpPasscode = needs }, reloadAvatar(state) { state.avatarUrl = `${state.info.getAvatarUrl()}&=${+new Date()}` }, }, actions: { // Logs a user in with a set of credentials. login(ctx, credentials) { const HTTP = HTTPFactory() ctx.commit(LOADING, true, {root: true}) // Delete an eventually preexisting old token localStorage.removeItem('token') const data = { username: credentials.username, password: credentials.password, } if (credentials.totpPasscode) { data.totp_passcode = credentials.totpPasscode } return HTTP.post('login', data) .then(response => { // Save the token to local storage for later use localStorage.setItem('token', response.data.token) // Tell others the user is autheticated ctx.commit('isLinkShareAuth', false) ctx.dispatch('checkAuth') return Promise.resolve() }) .catch(e => { if (e.response) { if (e.response.data.code === 1017 && !credentials.totpPasscode) { ctx.commit('needsTotpPasscode', true) return Promise.reject() } let errorMsg = e.response.data.message if (e.response.status === 401) { errorMsg = 'Wrong username or password.' } ctx.commit(ERROR_MESSAGE, errorMsg, {root: true}) } return Promise.reject() }) .finally(() => { ctx.commit(LOADING, false, {root: true}) }) }, // Registers a new user and logs them in. // Not sure if this is the right place to put the logic in, maybe a seperate js component would be better suited. register(ctx, credentials) { const HTTP = HTTPFactory() return HTTP.post('register', { username: credentials.username, email: credentials.email, password: credentials.password, }) .then(() => { return ctx.dispatch('login', credentials) }) .catch(e => { if (e.response) { ctx.commit(ERROR_MESSAGE, e.response.data.message, {root: true}) } return Promise.reject() }) .finally(() => { ctx.commit(LOADING, false, {root: true}) }) }, openIdAuth(ctx, {provider, code}) { const HTTP = HTTPFactory() ctx.commit(LOADING, true, {root: true}) const data = { code: code, } // Delete an eventually preexisting old token localStorage.removeItem('token') return HTTP.post(`/auth/openid/${provider}/callback`, data) .then(response => { // Save the token to local storage for later use localStorage.setItem('token', response.data.token) // Tell others the user is autheticated ctx.commit('isLinkShareAuth', false) ctx.dispatch('checkAuth') return Promise.resolve() }) .catch(e => { if (e.response) { let errorMsg = e.response.data.message if (e.response.status === 401) { errorMsg = 'Wrong username or password.' } ctx.commit(ERROR_MESSAGE, errorMsg, {root: true}) } return Promise.reject() }) .finally(() => { ctx.commit(LOADING, false, {root: true}) }) }, linkShareAuth(ctx, hash) { const HTTP = HTTPFactory() return HTTP.post('/shares/' + hash + '/auth') .then(r => { localStorage.setItem('token', r.data.token) ctx.dispatch('checkAuth') return Promise.resolve(r.data) }).catch(e => { return Promise.reject(e) }) }, // Populates user information from jwt token saved in local storage in store checkAuth(ctx) { const jwt = localStorage.getItem('token') let authenticated = false if (jwt) { const base64 = jwt .split('.')[1] .replace('-', '+') .replace('_', '/') const info = new UserModel(JSON.parse(window.atob(base64))) const ts = Math.round((new Date()).getTime() / 1000) if (info.exp >= ts) { authenticated = true } ctx.commit('info', info) } ctx.commit('authenticated', authenticated) return Promise.resolve() }, // Renews the api token and saves it to local storage renewToken(ctx) { const HTTP = HTTPFactory() if (!ctx.state.authenticated) { return } HTTP.post('user/token', null, { headers: { Authorization: 'Bearer ' + localStorage.getItem('token'), }, }) .then(r => { localStorage.setItem('token', r.data.token) ctx.dispatch('checkAuth') }) .catch(e => { // eslint-disable-next-line console.log('Error renewing token: ', e) ctx.dispatch('logout') }) }, logout(ctx) { localStorage.removeItem('token') ctx.dispatch('checkAuth') }, }, }