jcloud/dashboard/src2/components/auth/Configure2FA.vue
2025-04-12 17:39:38 +08:00

212 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div
class="mt-6 flex items-center justify-center"
v-if="$resources.qrUrl.loading"
>
<LoadingText />
</div>
<div
v-else-if="is2FAEnabled && $route.name !== 'Enable2FA'"
class="space-y-4"
>
<AlertBanner
title="如果禁用双重认证,您的账户将变得不安全"
type="error"
/>
<!-- 用户需要遵循的步骤 -->
<div class="rounded border border-gray-200 bg-gray-50 p-4">
<h3 class="text-lg font-semibold">禁用双重认证的步骤</h3>
<ol class="mt-2 list-disc pl-2 text-sm">
<li>打开认证器应用</li>
<li>在下方输入应用中的代码</li>
</ol>
</div>
<FormControl
label="验证应用中的代码以禁用双重认证"
v-model="totpCode"
/>
</div>
<div v-else class="space-y-4">
<div class="w-full">
<VueQrcode
v-if="qrUrl"
class="mx-auto"
:value="qrUrl"
type="image/png"
:color="{ dark: '#000000ff', light: '#ffffffff' }"
/>
</div>
<!-- 用户需要遵循的步骤 -->
<div class="rounded border border-gray-200 bg-gray-50 p-4">
<h3 class="text-lg font-semibold">启用双重认证的步骤</h3>
<ol class="ml-1 mt-2 list-disc pl-2 text-sm text-gray-700">
<li>在手机上下载认证器应用例如阿里云APP等</li>
<li>扫描二维码</li>
<li>在下方输入认证器应用中的代码</li>
</ol>
<p class="mt-4 text-sm text-gray-700">
<strong>注意</strong> 如果您无法访问认证器应用您的账户将被锁定请确保备份您的保险库/密钥
</p>
</div>
<div
v-if="showSetupKey"
class="rounded border border-gray-200 bg-gray-50 p-4"
>
<h3 class="text-lg font-semibold">设置密钥</h3>
<p class="mt-2 text-sm">
{{ setupKey }}
</p>
</div>
<FormControl
label="验证应用中的代码以启用双重认证"
v-model="totpCode"
/>
</div>
<div class="!mt-8 flex justify-center">
<Button
v-if="!is2FAEnabled"
class="w-full"
variant="solid"
label="启用双重认证"
:disabled="!totpCode"
:loading="$resources.enable2FA.loading"
@click="enable2FA"
/>
<Button
v-else
class="w-full"
variant="solid"
label="禁用双重认证"
:disabled="!totpCode"
:loading="$resources.disable2FA.loading"
@click="disable2FA"
/>
</div>
</div>
</template>
<script>
import VueQrcode from 'vue-qrcode';
import { toast } from 'vue-sonner';
import AlertBanner from '../AlertBanner.vue';
export default {
emits: ['enabled', 'disabled'],
data() {
return {
qrUrl: '', // not storing as computed property to avoid re-fetching on dialog close
totpCode: '',
showSetupKey: false
};
},
components: {
AlertBanner,
VueQrcode
},
methods: {
enable2FA() {
toast.promise(
this.$resources.enable2FA.submit({
totp_code: this.totpCode
}),
{
loading: '正在启用双因素认证...',
success: () => {
this.totpCode = '';
// avoid flickering of 2FA dialog
setTimeout(() => {
this.$team.reload();
}, 500);
this.$emit('enabled');
return '双因素认证已成功启用';
},
error(err) {
if (err.messages) {
if (err.messages.includes('Invalid TOTP code')) {
return '无效的TOTP验证码请重试';
} else {
return err.messages.join('.');
}
} else {
return '启用双因素认证失败';
}
}
}
);
},
disable2FA() {
toast.promise(
this.$resources.disable2FA.submit({
totp_code: this.totpCode
}),
{
loading: '正在禁用双因素认证...',
success: () => {
this.totpCode = '';
// avoid flickering of 2FA dialog
setTimeout(() => {
this.$team.reload();
}, 500);
this.$emit('disabled');
return '双因素认证已成功禁用';
},
error(err) {
if (err.messages) {
if (err.messages.includes('Invalid TOTP code')) {
return '无效的TOTP验证码请重试';
} else {
return err.messages.join('.');
}
} else {
return '禁用双因素认证失败';
}
}
}
);
}
},
resources: {
qrUrl() {
return {
url: 'jcloud.api.account.get_2fa_qr_code_url',
auto: true,
onSuccess(qr_code_url) {
this.qrUrl = qr_code_url;
}
};
},
enable2FA() {
return {
url: 'jcloud.api.account.enable_2fa'
};
},
disable2FA() {
return {
url: 'jcloud.api.account.disable_2fa'
};
}
},
computed: {
setupKey() {
if (!this.qrUrl) return null;
return this.qrUrl.match(/secret=(.*?)&issuer/)[1];
},
is2FAEnabled() {
return this.$team.pg?.user_info?.is_2fa_enabled;
}
}
};
</script>