diff --git a/app/package.json b/app/package.json index 5ca186b0..88eaaf42 100644 --- a/app/package.json +++ b/app/package.json @@ -16,6 +16,7 @@ "@vue/reactivity": "^3.4.33", "@vue/shared": "^3.4.33", "@vueuse/core": "^10.11.0", + "@vueuse/integrations": "^10.11.0", "@xterm/addon-attach": "^0.11.0", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", @@ -31,6 +32,7 @@ "pinia-plugin-persistedstate": "^3.2.1", "reconnecting-websocket": "^4.4.0", "sortablejs": "^1.15.2", + "universal-cookie": "^7", "vite-plugin-build-id": "^0.2.9", "vue": "^3.4.33", "vue-github-button": "github:0xJacky/vue-github-button", diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index ac629e39..204d2df6 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@vueuse/core': specifier: ^10.11.0 version: 10.11.0(vue@3.4.33(typescript@5.3.3)) + '@vueuse/integrations': + specifier: ^10.11.0 + version: 10.11.0(async-validator@4.2.5)(axios@1.7.2)(nprogress@0.2.0)(sortablejs@1.15.2)(universal-cookie@7.2.0)(vue@3.4.33(typescript@5.3.3)) '@xterm/addon-attach': specifier: ^0.11.0 version: 0.11.0(@xterm/xterm@5.5.0) @@ -68,6 +71,9 @@ importers: sortablejs: specifier: ^1.15.2 version: 1.15.2 + universal-cookie: + specifier: ^7 + version: 7.2.0 vite-plugin-build-id: specifier: ^0.2.9 version: 0.2.9(less@4.2.0) @@ -698,6 +704,9 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -925,6 +934,47 @@ packages: '@vueuse/core@10.11.0': resolution: {integrity: sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==} + '@vueuse/integrations@10.11.0': + resolution: {integrity: sha512-Pp6MtWEIr+NDOccWd8j59Kpjy5YDXogXI61Kb1JxvSfVBO8NzFQkmrKmSZz47i+ZqHnIzxaT38L358yDHTncZg==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^4 + drauu: ^0.3 + focus-trap: ^7 + fuse.js: ^6 + idb-keyval: ^6 + jwt-decode: ^3 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^6 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + '@vueuse/metadata@10.11.0': resolution: {integrity: sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==} @@ -1200,6 +1250,10 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + copy-anything@2.0.6: resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} @@ -2827,6 +2881,9 @@ packages: unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + universal-cookie@7.2.0: + resolution: {integrity: sha512-PvcyflJAYACJKr28HABxkGemML5vafHmiL4ICe3e+BEKXRMt0GaFLZhAwgv637kFFnnfiSJ8e6jknrKkMrU+PQ==} + unplugin-auto-import@0.17.8: resolution: {integrity: sha512-CHryj6HzJ+n4ASjzwHruD8arhbdl+UXvhuAIlHDs15Y/IMecG3wrf7FVg4pVH/DIysbq/n0phIjNHAjl7TG7Iw==} engines: {node: '>=14'} @@ -3580,6 +3637,8 @@ snapshots: '@trysound/sax@0.2.0': {} + '@types/cookie@0.6.0': {} + '@types/estree@1.0.5': {} '@types/glob@7.2.0': @@ -3898,6 +3957,21 @@ snapshots: - '@vue/composition-api' - vue + '@vueuse/integrations@10.11.0(async-validator@4.2.5)(axios@1.7.2)(nprogress@0.2.0)(sortablejs@1.15.2)(universal-cookie@7.2.0)(vue@3.4.33(typescript@5.3.3))': + dependencies: + '@vueuse/core': 10.11.0(vue@3.4.33(typescript@5.3.3)) + '@vueuse/shared': 10.11.0(vue@3.4.33(typescript@5.3.3)) + vue-demi: 0.14.8(vue@3.4.33(typescript@5.3.3)) + optionalDependencies: + async-validator: 4.2.5 + axios: 1.7.2 + nprogress: 0.2.0 + sortablejs: 1.15.2 + universal-cookie: 7.2.0 + transitivePeerDependencies: + - '@vue/composition-api' + - vue + '@vueuse/metadata@10.11.0': {} '@vueuse/shared@10.11.0(vue@3.4.33(typescript@5.3.3))': @@ -4209,6 +4283,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie@0.6.0: {} + copy-anything@2.0.6: dependencies: is-what: 3.14.1 @@ -6017,6 +6093,11 @@ snapshots: dependencies: '@types/unist': 2.0.10 + universal-cookie@7.2.0: + dependencies: + '@types/cookie': 0.6.0 + cookie: 0.6.0 + unplugin-auto-import@0.17.8(@vueuse/core@10.11.0(vue@3.4.33(typescript@5.3.3)))(rollup@4.19.0): dependencies: '@antfu/utils': 0.7.10 diff --git a/app/src/components/OTP/useOTPModal.ts b/app/src/components/OTP/useOTPModal.ts index 6e2880c4..4f2bd466 100644 --- a/app/src/components/OTP/useOTPModal.ts +++ b/app/src/components/OTP/useOTPModal.ts @@ -1,5 +1,6 @@ import { createVNode, render } from 'vue' import { Modal, message } from 'ant-design-vue' +import { useCookies } from '@vueuse/integrations/useCookies' import OTPAuthorization from '@/components/OTP/OTPAuthorization.vue' import otp from '@/api/otp' @@ -24,6 +25,14 @@ const useOTPModal = () => { } const open = ({ onOk, onCancel }: OTPModalProps) => { + const cookies = useCookies(['nginx-ui-2fa']) + const ssid = cookies.get('secure_session_id') + if (ssid) { + onOk?.(ssid) + + return + } + injectStyles() let container: HTMLDivElement | null = document.createElement('div') document.body.appendChild(container) @@ -36,6 +45,7 @@ const useOTPModal = () => { const verify = (passcode: string, recovery: string) => { otp.start_secure_session(passcode, recovery).then(r => { + cookies.set('secure_session_id', r.session_id, { maxAge: 60 * 3 }) onOk?.(r.session_id) close() }).catch(async () => {