Migrate auth flow module to pinia store

This commit is contained in:
Sean King 2025-05-15 23:33:49 -06:00
commit 4ee26c6041
No known key found for this signature in database
GPG key ID: 510C52BACD6E7257
8 changed files with 91 additions and 110 deletions

View file

@ -21,6 +21,7 @@ import { useOAuthStore } from 'src/stores/oauth'
import { useI18nStore } from 'src/stores/i18n'
import { useInterfaceStore } from 'src/stores/interface'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useAuthFlowStore } from 'src/stores/auth_flow'
let staticInitialResults = null
@ -153,7 +154,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
: config.logoMargin
})
copyInstanceOption('logoLeft')
store.commit('authFlow/setInitialStrategy', config.loginMethod)
useAuthFlowStore().setInitialStrategy(config.loginMethod)
copyInstanceOption('redirectRootNoLogin')
copyInstanceOption('redirectRootLogin')

View file

@ -2,7 +2,8 @@ import { h, resolveComponent } from 'vue'
import LoginForm from '../login_form/login_form.vue'
import MFARecoveryForm from '../mfa_form/recovery_form.vue'
import MFATOTPForm from '../mfa_form/totp_form.vue'
import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
import { useAuthFlowStore } from 'src/stores/auth_flow'
const AuthForm = {
name: 'AuthForm',
@ -15,7 +16,7 @@ const AuthForm = {
if (this.requiredRecovery) { return 'MFARecoveryForm' }
return 'LoginForm'
},
...mapGetters('authFlow', ['requiredTOTP', 'requiredRecovery'])
...mapState(useAuthFlowStore, ['requiredTOTP', 'requiredRecovery'])
},
components: {
MFARecoveryForm,

View file

@ -1,7 +1,8 @@
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import { mapStores } from 'pinia'
import { mapState } from 'vuex'
import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia'
import oauthApi from '../../services/new_api/oauth.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useAuthFlowStore } from 'src/stores/auth_flow.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
@ -25,13 +26,10 @@ const LoginForm = {
instance: state => state.instance,
loggingIn: state => state.users.loggingIn,
}),
...mapGetters(
'authFlow', ['requiredPassword', 'requiredToken', 'requiredMFA']
)
...mapPiniaState(useAuthFlowStore, ['requiredPassword', 'requiredToken', 'requiredMFA'])
},
methods: {
...mapMutations('authFlow', ['requireMFA']),
...mapActions({ login: 'authFlow/login' }),
...mapActions(useAuthFlowStore, ['requireMFA', 'login']),
submit () {
this.isTokenAuth ? this.submitToken() : this.submitPassword()
},

View file

@ -1,7 +1,8 @@
import mfaApi from '../../services/new_api/mfa.js'
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import { mapStores } from 'pinia'
import { mapState } from 'vuex'
import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useAuthFlowStore } from 'src/stores/auth_flow.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
@ -17,8 +18,8 @@ export default {
error: false
}),
computed: {
...mapGetters({
authSettings: 'authFlow/settings'
...mapPiniaState(useAuthFlowStore, {
authSettings: store => store.settings
}),
...mapStores(useOAuthStore),
...mapState({
@ -26,8 +27,7 @@ export default {
})
},
methods: {
...mapMutations('authFlow', ['requireTOTP', 'abortMFA']),
...mapActions({ login: 'authFlow/login' }),
...mapActions(useAuthFlowStore, ['requireTOTP', 'abortMFA', 'login']),
clearError () { this.error = false },
focusOnCodeInput () {

View file

@ -1,7 +1,8 @@
import mfaApi from '../../services/new_api/mfa.js'
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import { mapStores } from 'pinia'
import { mapState } from 'vuex'
import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useAuthFlowStore } from 'src/stores/auth_flow.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faTimes
@ -17,8 +18,8 @@ export default {
error: false
}),
computed: {
...mapGetters({
authSettings: 'authFlow/settings'
...mapPiniaState(useAuthFlowStore, {
authSettings: store => store.settings
}),
...mapStores(useOAuthStore),
...mapState({
@ -26,8 +27,7 @@ export default {
})
},
methods: {
...mapMutations('authFlow', ['requireRecovery', 'abortMFA']),
...mapActions({ login: 'authFlow/login' }),
...mapActions(useAuthFlowStore, ['requireRecovery', 'abortMFA', 'login']),
clearError () { this.error = false },
focusOnCodeInput () {

View file

@ -1,86 +0,0 @@
import { useOAuthStore } from 'src/stores/oauth.js'
const PASSWORD_STRATEGY = 'password'
const TOKEN_STRATEGY = 'token'
// MFA strategies
const TOTP_STRATEGY = 'totp'
const RECOVERY_STRATEGY = 'recovery'
// initial state
const state = {
settings: {},
strategy: PASSWORD_STRATEGY,
initStrategy: PASSWORD_STRATEGY // default strategy from config
}
const resetState = (state) => {
state.strategy = state.initStrategy
state.settings = {}
}
// getters
const getters = {
settings: (state) => {
return state.settings
},
requiredPassword: (state) => {
return state.strategy === PASSWORD_STRATEGY
},
requiredToken: (state) => {
return state.strategy === TOKEN_STRATEGY
},
requiredTOTP: (state) => {
return state.strategy === TOTP_STRATEGY
},
requiredRecovery: (state) => {
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, { settings }) {
state.settings = settings
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 }, { access_token: accessToken }) {
useOAuthStore().setToken(accessToken)
await dispatch('loginUser', accessToken, { root: true })
resetState(state)
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
}

View file

@ -6,7 +6,6 @@ import api from './api.js'
import config from './config.js'
import profileConfig from './profileConfig.js'
import adminSettings from './adminSettings.js'
import authFlow from './auth_flow.js'
import drafts from './drafts.js'
import chats from './chats.js'
@ -19,7 +18,6 @@ export default {
config,
profileConfig,
adminSettings,
authFlow,
drafts,
chats
}

69
src/stores/auth_flow.js Normal file
View file

@ -0,0 +1,69 @@
import { useOAuthStore } from 'src/stores/oauth.js'
import { defineStore } from 'pinia'
const PASSWORD_STRATEGY = 'password'
const TOKEN_STRATEGY = 'token'
// MFA strategies
const TOTP_STRATEGY = 'totp'
const RECOVERY_STRATEGY = 'recovery'
export const useAuthFlowStore = defineStore('authFlow', {
// initial state
state: () => ({
settings: {},
strategy: PASSWORD_STRATEGY,
initStrategy: PASSWORD_STRATEGY // default strategy from config
}),
// getters
getters: {
requiredPassword: (state) => {
return state.strategy === PASSWORD_STRATEGY
},
requiredToken: (state) => {
return state.strategy === TOKEN_STRATEGY
},
requiredTOTP: (state) => {
return state.strategy === TOTP_STRATEGY
},
requiredRecovery: (state) => {
return state.strategy === RECOVERY_STRATEGY
},
},
actions: {
setInitialStrategy (strategy) {
if (strategy) {
this.initStrategy = strategy
this.strategy = strategy
}
},
requirePassword () {
this.strategy = PASSWORD_STRATEGY
},
requireToken () {
this.strategy = TOKEN_STRATEGY
},
requireMFA ({ settings }) {
this.settings = settings
this.strategy = TOTP_STRATEGY // default strategy of MFA
},
requireRecovery () {
this.strategy = RECOVERY_STRATEGY
},
requireTOTP () {
this.strategy = TOTP_STRATEGY
},
abortMFA () {
this.resetState()
},
resetState () {
this.strategy = this.initStrategy
this.settings = {}
},
async login ({ access_token: accessToken }) {
useOAuthStore().setToken(accessToken)
await window.vuex.dispatch('loginUser', accessToken, { root: true })
this.resetState()
}
}
})