Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85649771
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js
index d4a05fc287..603f486653 100644
--- a/src/components/login_form/login_form.js
+++ b/src/components/login_form/login_form.js
@@ -1,79 +1,76 @@
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
import oauthApi from '../../services/new_api/oauth.js'
const LoginForm = {
data: () => ({
user: {},
error: false
}),
computed: {
- isPasswordAuth () { return this.authMethod === 'password' },
- isTokenAuth () { return this.authMethod === 'token' },
+ isPasswordAuth () { return this.requiredPassword },
+ isTokenAuth () { return this.requiredToken },
...mapState({
registrationOpen: state => state.instance.registrationOpen,
instance: state => state.instance,
loggingIn: state => state.users.loggingIn,
oauth: state => state.oauth
}),
- ...mapGetters({ authMethod: 'authFlow/authMethod' })
+ ...mapGetters(
+ 'authFlow', ['requiredPassword', 'requiredToken', 'requiredMFA']
+ )
},
methods: {
- ...mapMutations({ setStage: 'authFlow/setStage' }),
+ ...mapMutations('authFlow', ['requireMFA', 'setupMFA']),
...mapActions({ login: 'authFlow/login' }),
submit () {
- this.tokenMethod ? this.submitToken() : this.submitPassword()
+ this.isTokenMethod ? this.submitToken() : this.submitPassword()
},
submitToken () {
oauthApi.login({
oauth: this.oauth,
instance: this.instance.server,
commit: this.$store.commit
})
},
submitPassword () {
const data = {
oauth: this.oauth,
instance: this.instance.server
}
this.error = false
oauthApi.getOrCreateApp(data).then((app) => {
oauthApi.getTokenWithCredentials(
{
app,
instance: data.instance,
username: this.user.username,
password: this.user.password
}
).then((result) => {
if (result.error) {
if (result.error === 'mfa_required') {
- this.setStage({
- app: app,
- settings: result,
- stage: 'second',
- authMethod: 'totp'
- })
- return
+ this.setupMFA({app: app, settings: result})
+ this.requireMFA()
} else {
this.error = result.error
this.focusOnPasswordInput()
- return
}
+ return
}
this.login(result).then(() => {
this.$router.push({name: 'friends'})
})
})
})
},
clearError () { this.error = false },
focusOnPasswordInput () {
let passwordInput = this.$refs.passwordInput
passwordInput.focus()
passwordInput.setSelectionRange(0, passwordInput.value.length)
}
}
}
export default LoginForm
diff --git a/src/components/mfa_form/recovery_form.js b/src/components/mfa_form/recovery_form.js
index 2477e27372..af069f0342 100644
--- a/src/components/mfa_form/recovery_form.js
+++ b/src/components/mfa_form/recovery_form.js
@@ -1,41 +1,41 @@
import mfaApi from '../../services/new_api/mfa.js'
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
export default {
data: () => ({
code: null,
error: false
}),
computed: {
...mapGetters({
authApp: 'authFlow/app',
authSettings: 'authFlow/settings'
}),
...mapState({ instance: 'instance' })
},
methods: {
- ...mapMutations({ setMethod: 'authFlow/setMethod' }),
+ ...mapMutations({ requireTOTP: 'authFlow/requireTOTP' }),
...mapActions({ login: 'authFlow/login' }),
clearError () { this.error = false },
submit () {
const data = {
app: this.authApp,
instance: this.instance.server,
mfaToken: this.authSettings.mfa_token,
code: this.code
}
mfaApi.verifyRecoveryCode(data).then((result) => {
if (result.error) {
this.error = result.error
this.code = null
return
}
this.login(result).then(() => {
this.$router.push({name: 'friends'})
})
})
}
}
}
diff --git a/src/components/mfa_form/recovery_form.vue b/src/components/mfa_form/recovery_form.vue
index d2f0fb58be..4a5a517eb3 100644
--- a/src/components/mfa_form/recovery_form.vue
+++ b/src/components/mfa_form/recovery_form.vue
@@ -1,38 +1,38 @@
<template>
<div class="login panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">{{$t('login.heading.recovery')}}</div>
<div class="panel-body">
<form class='login-form' @submit.prevent='submit'>
<div class='form-group'>
<label for='code'>{{$t('login.recovery_code')}}</label>
<input v-model='code' class='form-control' id='code'>
</div>
<div class='form-group'>
<div class='login-bottom'>
<div>
- <a href="#" @click.prevent="setMethod('totp')">
+ <a href="#" @click.prevent="requireTOTP">
{{$t('login.enter_two_factor_code')}}
</a>
</div>
<button type='submit' class='btn btn-default'>
- {{$t('login.verify')}}
+ {{$t('general.verify')}}
</button>
</div>
</div>
</form>
</div>
<div v-if="error" class='form-group'>
<div class='alert error'>
{{error}}
<i class="button-icon icon-cancel" @click="clearError"></i>
</div>
</div>
</div>
</template>
<script src="./recovery_form.js" ></script>
diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js
index c6089b1b9c..2e1b7ce4ec 100644
--- a/src/components/mfa_form/totp_form.js
+++ b/src/components/mfa_form/totp_form.js
@@ -1,40 +1,40 @@
import mfaApi from '../../services/new_api/mfa.js'
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
export default {
data: () => ({
code: null,
error: false
}),
computed: {
...mapGetters({
authApp: 'authFlow/app',
authSettings: 'authFlow/settings'
}),
...mapState({ instance: 'instance' })
},
methods: {
- ...mapMutations({ setMethod: 'authFlow/setMethod' }),
+ ...mapMutations({ requireRecovery: 'authFlow/requireRecovery' }),
...mapActions({ login: 'authFlow/login' }),
clearError () { this.error = false },
submit () {
const data = {
app: this.authApp,
instance: this.instance.server,
mfaToken: this.authSettings.mfa_token,
code: this.code
}
mfaApi.verifyOTPCode(data).then((result) => {
if (result.error) {
this.error = result.error
this.code = null
return
}
this.login(result).then(() => {
this.$router.push({name: 'friends'})
})
})
}
}
}
diff --git a/src/components/mfa_form/totp_form.vue b/src/components/mfa_form/totp_form.vue
index 6507329373..d4a7c84a32 100644
--- a/src/components/mfa_form/totp_form.vue
+++ b/src/components/mfa_form/totp_form.vue
@@ -1,41 +1,41 @@
<template>
<div class="login panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">
{{$t('login.heading.totp')}}
</div>
<div class="panel-body">
<form class='login-form' @submit.prevent='submit'>
<div class='form-group'>
<label for='code'>
{{$t('login.authentication_code')}}
</label>
<input v-model='code' class='form-control' id='code'>
</div>
<div class='form-group'>
<div class='login-bottom'>
<div>
- <a href="#" @click.prevent="setMethod('recovery')">
+ <a href="#" @click.prevent="requireRecovery">
{{$t('login.enter_recovery_code')}}
</a>
</div>
<button type='submit' class='btn btn-default'>
{{$t('general.verify')}}
</button>
</div>
</div>
</form>
</div>
<div v-if="error" class='form-group'>
<div class='alert error'>
{{error}}
<i class="button-icon icon-cancel" @click="clearError"></i>
</div>
</div>
</div>
</template>
<script src="./totp_form.js"></script>
diff --git a/src/components/user_panel/user_panel.js b/src/components/user_panel/user_panel.js
index f41cc05794..1aeb965a14 100644
--- a/src/components/user_panel/user_panel.js
+++ b/src/components/user_panel/user_panel.js
@@ -1,37 +1,28 @@
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 PostStatusForm from '../post_status_form/post_status_form.vue'
import UserCard from '../user_card/user_card.vue'
import { mapState, mapGetters } from 'vuex'
const UserPanel = {
computed: {
signedIn () { return this.user },
authForm () {
- switch (this.authMethod) {
- case 'totp':
- return 'MFATOTPForm'
- case 'recovery':
- return 'MFARecoveryForm'
- default:
- return 'LoginForm'
- }
+ if (this.requiredTOTP) { return 'MFATOTPForm' }
+ if (this.requiredRecovery) { return 'MFARecoveryForm' }
+ return 'LoginForm'
},
- ...mapGetters({
- authMethod: 'authFlow/authMethod'
- }),
- ...mapState({
- user: state => state.users.currentUser
- })
+ ...mapGetters('authFlow', ['requiredTOTP', 'requiredRecovery']),
+ ...mapState({ user: state => state.users.currentUser })
},
components: {
MFARecoveryForm,
MFATOTPForm,
LoginForm,
PostStatusForm,
UserCard
}
}
export default UserPanel
diff --git a/src/modules/auth_flow.js b/src/modules/auth_flow.js
index a245117465..b03b4c90f2 100644
--- a/src/modules/auth_flow.js
+++ b/src/modules/auth_flow.js
@@ -1,60 +1,94 @@
+const PASSWORD_STRATEGY = 'password'
+const TOKEN_STRATEGY = 'token'
+
+// MFA strategies
+const TOTP_STRATEGY = 'totp'
+const RECOVERY_STRATEGY = 'recovery'
+
+
+const fetchStrategy = (state, rootState) => {
+ if (state.requiredMFA) {
+ return state.strategy || TOTP_STRATEGY
+ } else {
+ return state.strategy || rootState.instance.loginMethod || PASSWORD_STRATEGY
+ }
+}
+
// initial state
const state = {
app: null,
settings: {},
- stage: 'first', // first, second
- authMethod: 'password' // first (password, token), second (recovery, totp)
+ requiredMFA: false,
+ strategy: null
}
// getters
const getters = {
app: (state, getters) => {
return state.app
},
settings: (state, getters) => {
return state.settings
},
- authMethod: (state, getters, rootState) => {
- if (state.stage === 'first') {
- return state.authMethod || rootState.instance.loginMethod
- }
-
- if (state.stage === 'second') {
- return state.authMethod || 'totp'
- }
+ requiredPassword: (state, getters, rootState) => {
+ return fetchStrategy(state, rootState) === PASSWORD_STRATEGY
+ },
+ requiredToken: (state, getters, rootState) => {
+ return fetchStrategy(state, rootState) === TOKEN_STRATEGY
+ },
+ requiredTOTP: (state, getters, rootState) => {
+ return state.requiredMFA &&
+ fetchStrategy(state, rootState) === TOTP_STRATEGY
+ },
+ requiredRecovery: (state, getters, rootState) => {
+ return state.requiredMFA &&
+ fetchStrategy(state, rootState) === RECOVERY_STRATEGY
}
}
// mutations
const mutations = {
- setStage (state, {stage, authMethod, app, settings}) {
- state.stage = stage
- state.authMethod = authMethod
+ requirePassword (state) {
+ state.strategy = PASSWORD_STRATEGY
+ },
+ requireToken (state) {
+ state.strategy = TOKEN_STRATEGY
+ },
+ setupMFA (state, {app, settings}) { // sets MFA settings (token, supported strategies)
state.settings = settings
state.app = app
},
- setMethod (state, authMethod) {
- state.authMethod = authMethod
+ requireMFA (state) {
+ state.requiredMFA = true
+ state.strategy = TOTP_STRATEGY
+ },
+ requireRecovery (state) {
+ state.strategy = RECOVERY_STRATEGY
+ },
+ requireTOTP (state) {
+ state.strategy = TOTP_STRATEGY
+ },
+ reset (state) {
+ state.requiredMFA = false
+ state.strategy = null
+ state.settings = {}
+ state.app = null
}
}
// actions
const actions = {
async login ({state, dispatch, commit}, {access_token}) {
commit('setToken', access_token, { root: true })
await dispatch('loginUser', access_token, { root: true })
-
- state.stage = 'first'
- state.authMethod = 'password'
- state.settings = {}
- state.app = null
+ commit('reset')
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Aug 29, 8:10 PM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1737314
Default Alt Text
(12 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline
Log In to Comment