Kaynağa Gözat

enhance: user token storage

Jacky 6 ay önce
ebeveyn
işleme
59947a35db

+ 1 - 1
app/src/components/TwoFA/Authorization.vue

@@ -46,7 +46,7 @@ async function passkeyAuthenticate() {
   passkeyLoading.value = true
   try {
     const begin = await twoFA.begin_start_secure_session_by_passkey()
-    const asseResp = await startAuthentication(begin.options.publicKey)
+    const asseResp = await startAuthentication({ optionsJSON: begin.options.publicKey })
 
     const r = await twoFA.finish_start_secure_session_by_passkey({
       session_id: begin.session_id,

+ 2 - 7
app/src/components/TwoFA/use2FAModal.ts

@@ -1,6 +1,5 @@
 import { createVNode, render } from 'vue'
 import { Modal, message } from 'ant-design-vue'
-import { useCookies } from '@vueuse/integrations/useCookies'
 import Authorization from '@/components/TwoFA/Authorization.vue'
 import twoFA from '@/api/2fa'
 import { useUserStore } from '@/pinia'
@@ -32,11 +31,8 @@ const use2FAModal = () => {
         return
       }
 
-      const cookies = useCookies(['nginx-ui-2fa'])
-      const ssid = cookies.get('secure_session_id')
-      if (ssid && secureSessionStatus) {
-        resolve(ssid)
-        secureSessionId.value = ssid
+      if (secureSessionId.value && secureSessionStatus) {
+        resolve(secureSessionId.value)
 
         return
       }
@@ -51,7 +47,6 @@ const use2FAModal = () => {
       }
 
       const setSessionId = (sessionId: string) => {
-        cookies.set('secure_session_id', sessionId, { maxAge: 60 * 3 })
         close()
         secureSessionId.value = sessionId
         resolve(sessionId)

+ 1 - 3
app/src/lib/http/index.ts

@@ -1,6 +1,5 @@
 import type { AxiosRequestConfig } from 'axios'
 import axios from 'axios'
-import { useCookies } from '@vueuse/integrations/useCookies'
 import { storeToRefs } from 'pinia'
 import NProgress from 'nprogress'
 import { useSettingsStore, useUserStore } from '@/pinia'
@@ -62,10 +61,9 @@ instance.interceptors.response.use(
     NProgress.done()
 
     const otpModal = use2FAModal()
-    const cookies = useCookies(['nginx-ui-2fa'])
     switch (error.response.status) {
       case 401:
-        cookies.remove('secure_session_id')
+        secureSessionId.value = ''
         await otpModal.open()
         break
       case 403:

+ 60 - 30
app/src/pinia/moudule/user.ts

@@ -1,34 +1,64 @@
 import { defineStore } from 'pinia'
+import { useCookies } from '@vueuse/integrations/useCookies'
+import type { CookieChangeOptions } from 'universal-cookie'
 
-export const useUserStore = defineStore('user', {
-  state: () => ({
-    token: '',
-    unreadCount: 0,
-    secureSessionId: '',
-    passkeyRawId: '',
-  }),
-  getters: {
-    isLogin(state): boolean {
-      return !!state.token
-    },
-    passkeyLoginAvailable(state): boolean {
-      return !!state.passkeyRawId
-    },
-  },
-  actions: {
-    passkeyLogin(rawId: string, token: string) {
-      this.passkeyRawId = rawId
-      this.login(token)
-    },
-    login(token: string) {
-      this.token = token
-    },
-    logout() {
-      this.token = ''
-      this.passkeyRawId = ''
-      this.secureSessionId = ''
-      this.unreadCount = 0
-    },
-  },
+export const useUserStore = defineStore('user', () => {
+  const cookies = useCookies(['nginx-ui'])
+
+  const token = ref('')
+
+  watch(token, v => {
+    cookies.set('token', v, { maxAge: 86400 })
+  })
+
+  const secureSessionId = ref('')
+
+  watch(secureSessionId, v => {
+    cookies.set('secure_session_id', v, { maxAge: 60 * 3 })
+  })
+
+  function handleCookieChange({ name, value }: CookieChangeOptions) {
+    if (name === 'token')
+      token.value = value
+    else if (name === 'secure_session_id')
+      secureSessionId.value = value
+  }
+
+  cookies.addChangeListener(handleCookieChange)
+
+  const passkeyRawId = ref('')
+
+  const unreadCount = ref(0)
+  const isLogin = computed(() => !!token.value)
+  const passkeyLoginAvailable = computed(() => !!passkeyRawId.value)
+
+  function passkeyLogin(rawId: string, tokenValue: string) {
+    passkeyRawId.value = rawId
+    login(tokenValue)
+  }
+
+  function login(tokenValue: string) {
+    token.value = tokenValue
+  }
+
+  function logout() {
+    token.value = ''
+    passkeyRawId.value = ''
+    secureSessionId.value = ''
+    unreadCount.value = 0
+  }
+
+  return {
+    token,
+    unreadCount,
+    secureSessionId,
+    passkeyRawId,
+    isLogin,
+    passkeyLoginAvailable,
+    passkeyLogin,
+    login,
+    logout,
+  }
+}, {
   persist: true,
 })

+ 2 - 7
app/src/views/other/Login.vue

@@ -1,7 +1,6 @@
 <script setup lang="ts">
 import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue'
 import { Form, message } from 'ant-design-vue'
-import { useCookies } from '@vueuse/integrations/useCookies'
 import { startAuthentication } from '@simplewebauthn/browser'
 import { useUserStore } from '@/pinia'
 import auth from '@/api/auth'
@@ -60,13 +59,12 @@ const onSubmit = () => {
 
     await auth.login(modelRef.username, modelRef.password, passcode.value, recoveryCode.value).then(async r => {
       const next = (route.query?.next || '').toString() || '/'
-      const cookies = useCookies(['nginx-ui-2fa'])
       switch (r.code) {
         case 200:
           message.success($gettext('Login successful'), 1)
           login(r.token)
+          await nextTick()
           secureSessionId.value = r.secure_session_id
-          cookies.set('secure_session_id', r.secure_session_id, { maxAge: 60 * 3 })
           await router.push(next)
           break
         case 199:
@@ -159,7 +157,7 @@ async function handlePasskeyLogin() {
   passkeyLoginLoading.value = true
   try {
     const begin = await auth.begin_passkey_login()
-    const asseResp = await startAuthentication(begin.options.publicKey)
+    const asseResp = await startAuthentication({ optionsJSON: begin.options.publicKey })
 
     const r = await auth.finish_passkey_login({
       session_id: begin.session_id,
@@ -167,13 +165,10 @@ async function handlePasskeyLogin() {
     })
 
     if (r.token) {
-      const cookies = useCookies(['nginx-ui-2fa'])
       const next = (route.query?.next || '').toString() || '/'
 
       passkeyLogin(asseResp.rawId, r.token)
       secureSessionId.value = r.secure_session_id
-      cookies.set('secure_session_id', r.secure_session_id, { maxAge: 60 * 3 })
-
       await router.push(next)
     }
   }