feat: 更新应用标题和描述,调整谷歌验证和登录流程以支持二步验证
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { computed, h, reactive, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { defineStore } from 'pinia';
|
||||
import { NInputOtp } from 'naive-ui';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import { fetchLogin } from '@/service/api';
|
||||
import { authClient, fetchLogin, safeClient } from '@/service/api';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { SetupStoreId } from '@/enum';
|
||||
@@ -102,24 +103,40 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
|
||||
const res = await fetchLogin(userName, password);
|
||||
if (!res.error) {
|
||||
const pass = await loginByToken(res.data);
|
||||
if ('twoFactorRedirect' in res.data && res.data.twoFactorRedirect) {
|
||||
const topt = ref('');
|
||||
window.$dialog?.create({
|
||||
title: '谷歌验证',
|
||||
content: () =>
|
||||
h(NInputOtp, {
|
||||
style: { margin: '30px 0' },
|
||||
size: 'large',
|
||||
allowInput: value => !value || /^\d+$/.test(value),
|
||||
onUpdateValue: value => {
|
||||
topt.value = value.join('');
|
||||
}
|
||||
}),
|
||||
positiveText: '下一步',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (!topt.value) {
|
||||
window.$message?.error('请输入密码');
|
||||
} else {
|
||||
const { data } = await safeClient(
|
||||
authClient.twoFactor.verifyTotp({
|
||||
code: topt.value, // required
|
||||
trustDevice: false // 管理员登录不建议信任设备,以提高安全性
|
||||
})
|
||||
);
|
||||
|
||||
if (pass) {
|
||||
// Check if the tab needs to be cleared
|
||||
const isClear = checkTabClear();
|
||||
let needRedirect = redirect;
|
||||
|
||||
if (isClear) {
|
||||
// If the tab needs to be cleared,it means we don't need to redirect.
|
||||
needRedirect = false;
|
||||
}
|
||||
await redirectFromLogin(needRedirect);
|
||||
|
||||
window.$notification?.success({
|
||||
title: $t('page.login.common.loginSuccess'),
|
||||
content: $t('page.login.common.welcomeBack', { userName: userInfo.name }),
|
||||
duration: 4500
|
||||
if (data.value) {
|
||||
saveLogin(data.value, redirect);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
saveLogin(res.data, redirect);
|
||||
}
|
||||
} else {
|
||||
resetStore();
|
||||
@@ -128,6 +145,28 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
endLoading();
|
||||
}
|
||||
|
||||
async function saveLogin(data: Api.Auth.LoginToken, redirect = true) {
|
||||
const pass = await loginByToken(data);
|
||||
|
||||
if (pass) {
|
||||
// Check if the tab needs to be cleared
|
||||
const isClear = checkTabClear();
|
||||
let needRedirect = redirect;
|
||||
|
||||
if (isClear) {
|
||||
// If the tab needs to be cleared,it means we don't need to redirect.
|
||||
needRedirect = false;
|
||||
}
|
||||
await redirectFromLogin(needRedirect);
|
||||
|
||||
window.$notification?.success({
|
||||
title: $t('page.login.common.loginSuccess'),
|
||||
content: $t('page.login.common.welcomeBack', { userName: userInfo.name }),
|
||||
duration: 4500
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function loginByToken(data: Api.Auth.LoginToken) {
|
||||
// 1. stored in the localStorage, the later requests need it in headers
|
||||
localStg.set('token', data.token);
|
||||
|
||||
Reference in New Issue
Block a user