diff options
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/auth_flow.js | 89 | ||||
| -rw-r--r-- | src/modules/instance.js | 2 | ||||
| -rw-r--r-- | src/modules/oauth.js | 37 | ||||
| -rw-r--r-- | src/modules/users.js | 45 |
4 files changed, 139 insertions, 34 deletions
diff --git a/src/modules/auth_flow.js b/src/modules/auth_flow.js new file mode 100644 index 00000000..86328cf3 --- /dev/null +++ b/src/modules/auth_flow.js @@ -0,0 +1,89 @@ +const PASSWORD_STRATEGY = 'password' +const TOKEN_STRATEGY = 'token' + +// MFA strategies +const TOTP_STRATEGY = 'totp' +const RECOVERY_STRATEGY = 'recovery' + +// initial state +const state = { + app: null, + settings: {}, + strategy: PASSWORD_STRATEGY, + initStrategy: PASSWORD_STRATEGY // default strategy from config +} + +const resetState = (state) => { + state.strategy = state.initStrategy + state.settings = {} + state.app = null +} + +// getters +const getters = { + app: (state, getters) => { + return state.app + }, + settings: (state, getters) => { + return state.settings + }, + requiredPassword: (state, getters, rootState) => { + return state.strategy === PASSWORD_STRATEGY + }, + requiredToken: (state, getters, rootState) => { + return state.strategy === TOKEN_STRATEGY + }, + requiredTOTP: (state, getters, rootState) => { + return state.strategy === TOTP_STRATEGY + }, + requiredRecovery: (state, getters, rootState) => { + return state.strategy === RECOVERY_STRATEGY + } +} + +// mutations +const mutations = { + setInitialStrategy (state, strategy) { + if (strategy) { + state.initStrategy = strategy + state.strategy = strategy + } + }, + requirePassword (state) { + state.strategy = PASSWORD_STRATEGY + }, + requireToken (state) { + state.strategy = TOKEN_STRATEGY + }, + requireMFA (state, {app, settings}) { + state.settings = settings + state.app = app + state.strategy = TOTP_STRATEGY // default strategy of MFA + }, + requireRecovery (state) { + state.strategy = RECOVERY_STRATEGY + }, + requireTOTP (state) { + state.strategy = TOTP_STRATEGY + }, + abortMFA (state) { + resetState(state) + } +} + +// actions +const actions = { + async login ({state, dispatch, commit}, {access_token}) { + commit('setToken', access_token, { root: true }) + await dispatch('loginUser', access_token, { root: true }) + resetState(state) + } +} + +export default { + namespaced: true, + state, + getters, + mutations, + actions +} diff --git a/src/modules/instance.js b/src/modules/instance.js index d4185f6a..59beb23c 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -16,7 +16,6 @@ const defaultState = { redirectRootNoLogin: '/main/all', redirectRootLogin: '/main/friends', showInstanceSpecificPanel: false, - formattingOptionsEnabled: false, alwaysShowSubjectInput: true, hideMutedPosts: false, collapseMessageWithSubject: false, @@ -27,7 +26,6 @@ const defaultState = { scopeCopy: true, subjectLineBehavior: 'email', postContentType: 'text/plain', - loginMethod: 'password', nsfwCensorImage: undefined, vapidPublicKey: undefined, noAttachmentLinks: false, diff --git a/src/modules/oauth.js b/src/modules/oauth.js index 144ff830..11cb10fe 100644 --- a/src/modules/oauth.js +++ b/src/modules/oauth.js @@ -1,16 +1,39 @@ const oauth = { state: { - client_id: false, - client_secret: false, - token: false + clientId: false, + clientSecret: false, + /* App token is authentication for app without any user, used mostly for + * MastoAPI's registration of new users, stored so that we can fall back to + * it on logout + */ + appToken: false, + /* User token is authentication for app with user, this is for every calls + * that need authorized user to be successful (i.e. posting, liking etc) + */ + userToken: false }, mutations: { - setClientData (state, data) { - state.client_id = data.client_id - state.client_secret = data.client_secret + setClientData (state, { clientId, clientSecret }) { + state.clientId = clientId + state.clientSecret = clientSecret + }, + setAppToken (state, token) { + state.appToken = token }, setToken (state, token) { - state.token = token + state.userToken = token + } + }, + getters: { + getToken: state => () => { + // state.token is userToken with older name, coming from persistent state + // added here for smoother transition, otherwise user will be logged out + return state.userToken || state.token || state.appToken + }, + getUserToken: state => () => { + // state.token is userToken with older name, coming from persistent state + // added here for smoother transition, otherwise user will be logged out + return state.userToken || state.token } } } diff --git a/src/modules/users.js b/src/modules/users.js index e72a657c..22340271 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -3,7 +3,6 @@ import userSearchApi from '../services/new_api/user_search.js' import { compact, map, each, merge, last, concat, uniq } from 'lodash' import { set } from 'vue' import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js' -import oauthApi from '../services/new_api/oauth' import { humanizeErrors } from './errors' // TODO: Unify with mergeOrAdd in statuses.js @@ -357,7 +356,13 @@ const users = { }, searchUsers (store, query) { // TODO: Move userSearch api into api.service - return userSearchApi.search({query, store: { state: store.rootState }}) + return userSearchApi.search({ + query, + store: { + state: store.rootState, + getters: store.rootGetters + } + }) .then((users) => { store.commit('addNewUsers', users) return users @@ -368,31 +373,21 @@ const users = { let rootState = store.rootState - let response = await rootState.api.backendInteractor.register(userInfo) - if (response.ok) { - const data = { - oauth: rootState.oauth, - instance: rootState.instance.server - } - let app = await oauthApi.getOrCreateApp(data) - let result = await oauthApi.getTokenWithCredentials({ - app, - instance: data.instance, - username: userInfo.username, - password: userInfo.password - }) + try { + let data = await rootState.api.backendInteractor.register(userInfo) store.commit('signUpSuccess') - store.commit('setToken', result.access_token) - store.dispatch('loginUser', result.access_token) - } else { - const data = await response.json() - let errors = JSON.parse(data.error) + store.commit('setToken', data.access_token) + store.dispatch('loginUser', data.access_token) + } catch (e) { + let errors = e.message // replace ap_id with username - if (errors.ap_id) { - errors.username = errors.ap_id - delete errors.ap_id + if (typeof errors === 'object') { + if (errors.ap_id) { + errors.username = errors.ap_id + delete errors.ap_id + } + errors = humanizeErrors(errors) } - errors = humanizeErrors(errors) store.commit('signUpFailure', errors) throw Error(errors) } @@ -406,7 +401,7 @@ const users = { store.dispatch('disconnectFromChat') store.commit('setToken', false) store.dispatch('stopFetching', 'friends') - store.commit('setBackendInteractor', backendInteractorService()) + store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken())) store.dispatch('stopFetching', 'notifications') store.commit('clearNotifications') store.commit('resetStatuses') |
