123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- import { createVNode, render } from 'vue'
- import { Modal, message } from 'ant-design-vue'
- import { useCookies } from '@vueuse/integrations/useCookies'
- import Authorization from '@/components/2FA/Authorization.vue'
- import twoFA from '@/api/2fa'
- import { useUserStore } from '@/pinia'
- const use2FAModal = () => {
- const refOTPAuthorization = ref<typeof Authorization>()
- const randomId = Math.random().toString(36).substring(2, 8)
- const { secureSessionId } = storeToRefs(useUserStore())
- const injectStyles = () => {
- const style = document.createElement('style')
- style.innerHTML = `
- .${randomId} .ant-modal-title {
- font-size: 1.125rem;
- }
- `
- document.head.appendChild(style)
- }
- const open = async (): Promise<string> => {
- const twoFAStatus = await twoFA.status()
- const { status: secureSessionStatus } = await twoFA.secure_session_status()
- return new Promise((resolve, reject) => {
- if (!twoFAStatus.enabled) {
- resolve('')
- return
- }
- const cookies = useCookies(['nginx-ui-2fa'])
- const ssid = cookies.get('secure_session_id')
- if (ssid && secureSessionStatus) {
- resolve(ssid)
- secureSessionId.value = ssid
- return
- }
- injectStyles()
- let container: HTMLDivElement | null = document.createElement('div')
- document.body.appendChild(container)
- const close = () => {
- render(null, container!)
- document.body.removeChild(container!)
- container = null
- }
- const setSessionId = (sessionId: string) => {
- cookies.set('secure_session_id', sessionId, { maxAge: 60 * 3 })
- close()
- secureSessionId.value = sessionId
- resolve(sessionId)
- }
- const verifyOTP = (passcode: string, recovery: string) => {
- twoFA.start_secure_session_by_otp(passcode, recovery).then(async r => {
- setSessionId(r.session_id)
- }).catch(async () => {
- refOTPAuthorization.value?.clearInput()
- await message.error($gettext('Invalid passcode or recovery code'))
- })
- }
- const vnode = createVNode(Modal, {
- open: true,
- title: $gettext('Two-factor authentication required'),
- centered: true,
- maskClosable: false,
- class: randomId,
- footer: false,
- onCancel: () => {
- close()
- // eslint-disable-next-line prefer-promise-reject-errors
- reject()
- },
- }, {
- default: () => h(
- Authorization,
- {
- ref: refOTPAuthorization,
- twoFAStatus,
- class: 'mt-3',
- onSubmitOTP: verifyOTP,
- onSubmitSecureSessionID: setSessionId,
- },
- ),
- })
- render(vnode, container!)
- })
- }
- return { open }
- }
- export default use2FAModal
|