diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d349f5e56..2e51cc7b87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -698,6 +698,9 @@ importers: '@pinia/nuxt': specifier: ^0.10.0 version: 0.10.1(magicast@0.3.5)(pinia@3.0.1(typescript@5.8.2)(vue@3.5.13(typescript@5.8.2))) + '@unraid/shared-callbacks': + specifier: ^1.0.1 + version: 1.0.1(@vueuse/core@13.0.0(vue@3.5.13(typescript@5.8.2))) '@unraid/ui': specifier: link:../unraid-ui version: link:../unraid-ui @@ -3769,8 +3772,14 @@ packages: '@unraid/libvirt@1.1.3': resolution: {integrity: sha512-aZNHkwgQ/0e+5BE7i3Ru4GC3Ev8fEUlnU0wmTcuSbpN0r74rMpiGwzA/4cqIJU8X+Kj//I80pkUufzXzHmMWwQ==} engines: {node: '>=14'} + cpu: [x64, arm64] os: [linux, darwin] + '@unraid/shared-callbacks@1.0.1': + resolution: {integrity: sha512-dBUsfCShYzSVHjRMSVXhfu81GKJqLTKKSbfGcKAFScI2Po+GL3ITcI5gaGFryiIzfR2mlIsRCgul+1y8nYNrzA==} + peerDependencies: + '@vueuse/core': ^10.9.0 + '@unraid/tailwind-rem-to-rem@1.1.0': resolution: {integrity: sha512-lc5tqdSs5zwBStlC18lK+pg+iX0/i/JtO8qWOqHNT5KHt66Ba6nwDr+mfKekQq7Bsi8noXMBQJDB5b2J/OmDsw==} peerDependencies: @@ -9317,6 +9326,7 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} deprecated: |- You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) qs@6.13.0: @@ -11745,7 +11755,7 @@ snapshots: '@babel/traverse': 7.26.10 '@babel/types': 7.26.10 convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -12120,7 +12130,7 @@ snapshots: '@babel/parser': 7.27.0 '@babel/template': 7.26.9 '@babel/types': 7.26.10 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -12132,7 +12142,7 @@ snapshots: '@babel/parser': 7.26.8 '@babel/template': 7.26.8 '@babel/types': 7.26.8 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -12450,7 +12460,7 @@ snapshots: '@eslint/config-array@0.19.2': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -12464,7 +12474,7 @@ snapshots: bundle-require: 5.1.0(esbuild@0.25.1) cac: 6.7.14 chokidar: 4.0.3 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) esbuild: 0.25.1 eslint: 9.23.0(jiti@2.4.2) find-up: 7.0.0 @@ -12487,7 +12497,7 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) espree: 10.3.0 globals: 14.0.0 ignore: 5.3.2 @@ -13058,12 +13068,12 @@ snapshots: '@types/js-yaml': 4.0.9 '@whatwg-node/fetch': 0.10.3 chalk: 4.1.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) dotenv: 16.4.7 graphql: 16.10.0 graphql-request: 6.1.0(graphql@16.10.0) http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@9.4.0) + https-proxy-agent: 7.0.6 jose: 5.10.0 js-yaml: 4.1.0 lodash: 4.17.21 @@ -13308,7 +13318,7 @@ snapshots: '@koa/router@12.0.2': dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) http-errors: 2.0.0 koa-compose: 4.1.0 methods: 1.1.2 @@ -13318,7 +13328,7 @@ snapshots: '@kwsites/file-exists@1.1.1': dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -13359,7 +13369,7 @@ snapshots: dependencies: consola: 3.4.2 detect-libc: 2.0.3 - https-proxy-agent: 7.0.6(supports-color@9.4.0) + https-proxy-agent: 7.0.6 node-fetch: 2.7.0 nopt: 8.1.0 semver: 7.7.1 @@ -14088,7 +14098,7 @@ snapshots: '@pm2/pm2-version-check@1.0.4': dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -14968,7 +14978,7 @@ snapshots: '@typescript-eslint/types': 8.28.0 '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) '@typescript-eslint/visitor-keys': 8.28.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) eslint: 9.23.0(jiti@2.4.2) typescript: 5.8.2 transitivePeerDependencies: @@ -14983,7 +14993,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) '@typescript-eslint/utils': 8.28.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) eslint: 9.23.0(jiti@2.4.2) ts-api-utils: 2.1.0(typescript@5.8.2) typescript: 5.8.2 @@ -14998,7 +15008,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.28.0 '@typescript-eslint/visitor-keys': 8.28.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -15050,6 +15060,11 @@ snapshots: tsx: 4.19.3 xml2js: 0.6.2 + '@unraid/shared-callbacks@1.0.1(@vueuse/core@13.0.0(vue@3.5.13(typescript@5.8.2)))': + dependencies: + '@vueuse/core': 13.0.0(vue@3.5.13(typescript@5.8.2)) + crypto-js: 4.2.0 + '@unraid/tailwind-rem-to-rem@1.1.0(tailwindcss@3.4.17)': dependencies: tailwindcss: 3.4.17 @@ -15131,7 +15146,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -17164,14 +17179,14 @@ snapshots: docker-event-emitter@0.3.0(dockerode@3.3.5): dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) dockerode: 3.3.5 transitivePeerDependencies: - supports-color docker-modem@3.0.8: dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) readable-stream: 3.6.2 split-ca: 1.0.1 ssh2: 1.16.0 @@ -17480,7 +17495,7 @@ snapshots: esbuild-register@3.6.0(esbuild@0.25.1): dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) esbuild: 0.25.1 transitivePeerDependencies: - supports-color @@ -17645,7 +17660,7 @@ snapshots: dependencies: '@types/doctrine': 0.0.9 '@typescript-eslint/utils': 8.28.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2) - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) doctrine: 3.0.0 eslint: 9.23.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 @@ -17693,7 +17708,7 @@ snapshots: '@es-joy/jsdoccomment': 0.49.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) escape-string-regexp: 4.0.0 eslint: 9.23.0(jiti@2.4.2) espree: 10.3.0 @@ -17819,7 +17834,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) escape-string-regexp: 4.0.0 eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 @@ -18361,7 +18376,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -18824,7 +18839,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -18868,6 +18883,13 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6(supports-color@9.4.0): dependencies: agent-base: 7.1.3 @@ -18918,7 +18940,7 @@ snapshots: importx@0.4.4: dependencies: bundle-require: 5.1.0(esbuild@0.23.1) - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) esbuild: 0.23.1 jiti: 2.0.0-beta.3 jiti-v1: jiti@1.21.7 @@ -19012,7 +19034,7 @@ snapshots: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -19299,7 +19321,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -19386,7 +19408,7 @@ snapshots: form-data: 4.0.2 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@9.4.0) + https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 nwsapi: 2.2.16 parse5: 7.2.1 @@ -19501,7 +19523,7 @@ snapshots: koa-send@5.0.1: dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) http-errors: 1.8.1 resolve-path: 1.4.0 transitivePeerDependencies: @@ -19521,7 +19543,7 @@ snapshots: content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) delegates: 1.0.0 depd: 2.0.0 destroy: 1.2.0 @@ -20636,10 +20658,10 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.3 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) get-uri: 6.0.4 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@9.4.0) + https-proxy-agent: 7.0.6 pac-resolver: 7.0.1 socks-proxy-agent: 8.0.5 transitivePeerDependencies: @@ -20903,7 +20925,7 @@ snapshots: pm2-axon-rpc@0.7.1: dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -20911,7 +20933,7 @@ snapshots: dependencies: amp: 0.3.1 amp-message: 0.1.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) escape-string-regexp: 4.0.0 transitivePeerDependencies: - supports-color @@ -20928,7 +20950,7 @@ snapshots: pm2-sysmonit@1.2.8: dependencies: async: 3.2.6 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) pidusage: 2.0.21 systeminformation: 5.25.11 tx2: 1.0.5 @@ -20950,7 +20972,7 @@ snapshots: commander: 2.15.1 croner: 4.1.97 dayjs: 1.11.13 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) enquirer: 2.3.6 eventemitter2: 5.0.1 fclone: 1.0.11 @@ -20989,7 +21011,7 @@ snapshots: portfinder@1.0.35: dependencies: async: 3.2.6 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -21194,7 +21216,7 @@ snapshots: postcss-styl@0.12.3: dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) fast-diff: 1.3.0 lodash.sortedlastindex: 4.1.0 postcss: 8.5.3 @@ -21289,9 +21311,9 @@ snapshots: proxy-agent@6.4.0: dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@9.4.0) + https-proxy-agent: 7.0.6 lru-cache: 7.18.3 pac-proxy-agent: 7.1.0 proxy-from-env: 1.1.0 @@ -21678,7 +21700,7 @@ snapshots: require-in-the-middle@5.2.0: dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) module-details-from-path: 1.0.3 resolve: 1.22.10 transitivePeerDependencies: @@ -22082,7 +22104,7 @@ snapshots: dependencies: '@kwsites/file-exists': 1.1.1 '@kwsites/promise-deferred': 1.1.1 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -22140,7 +22162,7 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) socks: 2.8.4 transitivePeerDependencies: - supports-color @@ -22396,7 +22418,7 @@ snapshots: stylus@0.57.0: dependencies: css: 3.0.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) glob: 7.2.3 safer-buffer: 2.1.2 sax: 1.2.4 @@ -23125,7 +23147,7 @@ snapshots: vite-node@3.0.9(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0): dependencies: cac: 6.7.14 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) es-module-lexer: 1.6.0 pathe: 2.0.3 vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) @@ -23167,7 +23189,7 @@ snapshots: '@microsoft/api-extractor': 7.43.0(@types/node@22.13.13) '@rollup/pluginutils': 5.1.4(rollup@4.37.0) '@vue/language-core': 1.8.27(typescript@5.8.2) - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) kolorist: 1.8.0 magic-string: 0.30.17 typescript: 5.8.2 @@ -23183,7 +23205,7 @@ snapshots: dependencies: '@antfu/utils': 0.7.10 '@rollup/pluginutils': 5.1.4(rollup@4.37.0) - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) error-stack-parser-es: 0.1.5 fs-extra: 11.3.0 open: 10.1.0 @@ -23198,7 +23220,7 @@ snapshots: vite-plugin-inspect@11.0.0(@nuxt/kit@3.16.1(magicast@0.3.5))(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: ansis: 3.17.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) error-stack-parser-es: 1.0.5 ohash: 2.0.11 open: 10.1.0 @@ -23216,7 +23238,7 @@ snapshots: dependencies: '@rollup/pluginutils': 4.2.1 chalk: 4.1.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) optionalDependencies: '@swc/core': 1.11.13(@swc/helpers@0.5.15) @@ -23269,7 +23291,7 @@ snapshots: vite-plugin-vuetify@2.1.0(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))(vuetify@3.7.18): dependencies: '@vuetify/loader-shared': 2.1.0(vue@3.5.13(typescript@5.8.2))(vuetify@3.7.18) - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) upath: 2.0.1 vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) vue: 3.5.13(typescript@5.8.2) @@ -23279,7 +23301,7 @@ snapshots: vite-tsconfig-paths@5.1.4(typescript@5.8.2)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(stylus@0.57.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)): dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.8.2) optionalDependencies: @@ -23312,7 +23334,7 @@ snapshots: '@vitest/spy': 3.0.9 '@vitest/utils': 3.0.9 chai: 5.2.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) expect-type: 1.2.0 magic-string: 0.30.17 pathe: 2.0.3 @@ -23395,7 +23417,7 @@ snapshots: vue-eslint-parser@10.1.1(eslint@9.23.0(jiti@2.4.2)): dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) eslint: 9.23.0(jiti@2.4.2) eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 @@ -23408,7 +23430,7 @@ snapshots: vue-eslint-parser@9.4.3(eslint@9.23.0(jiti@2.4.2)): dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0(supports-color@5.5.0) eslint: 9.23.0(jiti@2.4.2) eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 diff --git a/web/.env.example b/web/.env.example index adb0fc96bc..69dbf7e822 100644 --- a/web/.env.example +++ b/web/.env.example @@ -2,7 +2,7 @@ VITE_ACCOUNT=http://localhost:5555 VITE_CONNECT=https://connect.myunraid.net VITE_UNRAID_NET=https://unraid.ddev.site VITE_OS_RELEASES="https://releases.unraid.net/os" -VITE_CALLBACK_KEY=aNotSoSecretKeyUsedToObfuscateQueryParams +VITE_CALLBACK_KEY=Uyv2o8e*FiQe8VeLekTqyX6Z*8XonB VITE_ALLOW_CONSOLE_LOGS=true # Base font size in pixels for Tailwind CSS. Used by the tailwind-rem-to-rem plugin to scale rem values. # This lets us use rem's in our css instead of pixels while remaining webgui-compatible without additional hacks. diff --git a/web/_data/serverState.ts b/web/_data/serverState.ts index f2700a511d..a7ec6a2cd0 100644 --- a/web/_data/serverState.ts +++ b/web/_data/serverState.ts @@ -108,7 +108,7 @@ switch (state) { // const connectPluginInstalled = 'dynamix.unraid.net.staging.plg'; const connectPluginInstalled = 'dynamix.unraid.net.staging.plg'; -const osVersion = '7.0.0-beta.2.10'; +const osVersion = '7.0.0'; const osVersionBranch = 'stable'; // const parsedRegExp = regExp ? dayjs(regExp).format('YYYY-MM-DD') : undefined; diff --git a/web/components/CallbackHandler.ce.vue b/web/components/CallbackHandler.ce.vue index 8f4da77807..e780c60842 100644 --- a/web/components/CallbackHandler.ce.vue +++ b/web/components/CallbackHandler.ce.vue @@ -1,7 +1,7 @@ + + diff --git a/web/store/account.ts b/web/store/account.ts index 54cb72b50c..c64b3a666a 100644 --- a/web/store/account.ts +++ b/web/store/account.ts @@ -3,13 +3,13 @@ import { logErrorMessages } from '@vue/apollo-util'; import { defineStore, createPinia, setActivePinia } from 'pinia'; import { CONNECT_SIGN_IN, CONNECT_SIGN_OUT } from './account.fragment'; -import { useCallbackStore } from '~/store/callbackActions'; +import { useCallbackActionsStore } from '~/store/callbackActions'; import { useErrorsStore } from '~/store/errors'; import { useReplaceRenewStore } from '~/store/replaceRenew'; import { useServerStore } from '~/store/server'; import { useUnraidApiStore } from '~/store/unraidApi'; import { ACCOUNT_CALLBACK } from '~/helpers/urls'; -import type { ExternalSignIn, ExternalSignOut } from '~/store/callback'; +import type { ExternalSignIn, ExternalSignOut } from '@unraid/shared-callbacks'; /** * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components * @see https://github.com/vuejs/pinia/discussions/1085 @@ -23,7 +23,7 @@ export interface ConnectSignInMutationPayload { } export const useAccountStore = defineStore('account', () => { - const callbackStore = useCallbackStore(); + const callbackStore = useCallbackActionsStore(); const errorsStore = useErrorsStore(); const replaceRenewStore = useReplaceRenewStore(); const serverStore = useServerStore(); diff --git a/web/store/callback.ts b/web/store/callback.ts deleted file mode 100644 index dfec3c9843..0000000000 --- a/web/store/callback.ts +++ /dev/null @@ -1,230 +0,0 @@ -/** - * This file is used to handle callbacks from the server. - * It is used in the following apps: - * - auth - * - craft-unraid - * - connect @todo - * - connect-components - */ -import AES from 'crypto-js/aes'; -import Utf8 from 'crypto-js/enc-utf8'; -import { defineStore, createPinia, setActivePinia } from 'pinia'; - -export type SignIn = 'signIn'; -export type SignOut = 'signOut'; -export type OemSignOut = 'oemSignOut'; -export type Troubleshoot = 'troubleshoot'; -export type Recover = 'recover'; -export type Replace = 'replace'; -export type TrialExtend = 'trialExtend'; -export type TrialStart = 'trialStart'; -export type Purchase = 'purchase'; -export type Redeem = 'redeem'; -export type Renew = 'renew'; -export type Upgrade = 'upgrade'; -export type UpdateOs = 'updateOs'; -export type DowngradeOs = 'downgradeOs'; -export type Manage = 'manage'; -export type MyKeys = 'myKeys'; -export type LinkKey = 'linkKey'; -export type Activate = 'activate'; -export type AccountActionTypes = Troubleshoot | SignIn | SignOut | OemSignOut | Manage | MyKeys | LinkKey; -export type AccountKeyActionTypes = Recover | Replace | TrialExtend | TrialStart | UpdateOs | DowngradeOs; -export type PurchaseActionTypes = Purchase | Redeem | Renew | Upgrade | Activate; - -export type ServerActionTypes = AccountActionTypes | AccountKeyActionTypes | PurchaseActionTypes; - -export type ServerState = 'BASIC' - | 'PLUS' - | 'PRO' - | 'TRIAL' - | 'EEXPIRED' - | 'ENOKEYFILE' - | 'EGUID' - | 'EGUID1' - | 'ETRIAL' - | 'ENOKEYFILE2' - | 'ENOKEYFILE1' - | 'ENOFLASH' - | 'ENOFLASH1' - | 'ENOFLASH2' - | 'ENOFLASH3' - | 'ENOFLASH4' - | 'ENOFLASH5' - | 'ENOFLASH6' - | 'ENOFLASH7' - | 'EBLACKLISTED' - | 'EBLACKLISTED1' - | 'EBLACKLISTED2' - | 'ENOCONN' - | 'STARTER' - | 'UNLEASHED' - | 'LIFETIME' - | 'STALE' - | undefined; - -export interface ServerData { - description?: string; - deviceCount?: number; - expireTime?: number; - flashProduct?: string; - flashVendor?: string; - guid?: string; - keyfile?: string; - locale?: string; - name?: string; - osVersion?: string; - osVersionBranch?: 'stable' | 'next' | 'preview' | 'test'; - registered: boolean; - regExp?: number; - regUpdatesExpired?: boolean; - regGen?: number; - regGuid?: string; - regTy?: string; - state: ServerState; - wanFQDN?: string; -} - -export interface UserInfo { - 'custom:ips_id'?: string; - email?: string; - email_verifed?: 'true' | 'false'; - preferred_username?: string; - sub?: string; - username?: string; - /** - * @param identities {string} JSON string containing @type Identity[] - */ - identities?: string; - /** - * @param cognito:groups {string[]} JSON string containing @type string[] - * - * Will contain all groups for the signed in user, used for determining which branch to use - * @example ["download-preview", "unraidPOOLID_Google"] - */ - 'cognito:groups'?: string[]; -} - -export interface ExternalSignIn { - type: SignIn; - apiKey: string; - user: UserInfo; -} - -export interface ExternalSignOut { - type: SignOut | OemSignOut; -} - -export interface ExternalKeyActions { - type: PurchaseActionTypes | AccountKeyActionTypes; - keyUrl: string; -} - -export interface ExternalUpdateOsAction { - type: DowngradeOs | UpdateOs; - sha256: string; -} - -export interface ServerPayload { - type: ServerActionTypes; - server: ServerData; -} - -export interface ServerTroubleshoot { - type: Troubleshoot; - server: ServerData; -} - -export type ExternalActions = ExternalSignIn | ExternalSignOut | ExternalKeyActions | ExternalUpdateOsAction; - -export type UpcActions = ServerPayload | ServerTroubleshoot; - -export type SendPayloads = ExternalActions[] | UpcActions[]; - -/** - * Payload containing all actions that are sent from account.unraid.net to the server - */ -export interface ExternalPayload { - type: 'forUpc'; - actions: ExternalActions[]; - sender: string; -} - -/** - * Payload containing all actions that are sent from a server to account.unraid.net - */ -export interface UpcPayload { - actions: UpcActions[]; - sender: string; - type: 'fromUpc'; -} - -export type QueryPayloads = ExternalPayload | UpcPayload; - -export interface CallbackActionsStore { - saveCallbackData: (decryptedData: QueryPayloads) => void; - encryptionKey: string; - sendType: 'fromUpc' | 'forUpc'; -} - -/** - * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components - * @see https://github.com/vuejs/pinia/discussions/1085 - */ -setActivePinia(createPinia()); - -export const useCallbackStoreGeneric = ( - useCallbackActions: () => CallbackActionsStore -) => - defineStore('callback', () => { - const callbackActions = useCallbackActions(); - - const send = (url: string, payload: SendPayloads, redirectType?: 'newTab' | 'replace', sendType?: string) => { - console.debug('[callback.send]'); - const stringifiedData = JSON.stringify({ - actions: [...payload], - sender: window.location.href.replace('/Tools/Update', '/Tools'), - type: sendType ?? callbackActions.sendType, - }); - const encryptedMessage = AES.encrypt( - stringifiedData, - callbackActions.encryptionKey, - ).toString(); - /** - * Build and go to url - */ - const destinationUrl = new URL(url.replace('/Tools/Update', '/Tools')); - destinationUrl.searchParams.set('data', encodeURI(encryptedMessage)); - console.debug('[callback.send]', encryptedMessage, destinationUrl); - if (redirectType === 'newTab') { // helpful when webgui is in an iframe and callbacks need to be opened in a new tab - window.open(destinationUrl.toString(), '_blank'); - return; - } - if (redirectType === 'replace') { // helpful when autoredirecting and we want to replace the current url to prevent back button issues with auto redirect loops - window.location.replace(destinationUrl.toString()); - return; - } - window.location.href = destinationUrl.toString(); - }; - - const watcher = () => { - console.debug('[callback.watcher]'); - const currentUrl = new URL(window.location.toString()); - const callbackValue = decodeURI(currentUrl.searchParams.get('data') ?? ''); - console.debug('[callback.watcher]', { callbackValue }); - if (!callbackValue) { - return console.debug('[callback.watcher] no callback to handle'); - } - - const decryptedMessage = AES.decrypt(callbackValue, callbackActions.encryptionKey); - const decryptedData: QueryPayloads = JSON.parse(decryptedMessage.toString(Utf8)); - console.debug('[callback.watcher]', decryptedMessage, decryptedData); - // Parse the data and perform actions - callbackActions.saveCallbackData(decryptedData); - }; - - return { - send, - watcher, - }; - }); diff --git a/web/store/callbackActions.ts b/web/store/callbackActions.ts index 075d3466de..e7b8d5b1c9 100644 --- a/web/store/callbackActions.ts +++ b/web/store/callbackActions.ts @@ -1,4 +1,15 @@ -import { defineStore } from 'pinia'; +import { createPinia, defineStore, setActivePinia } from 'pinia'; + +import { useCallback } from '@unraid/shared-callbacks'; + +import type { + ExternalActions, + ExternalKeyActions, + ExternalSignIn, + ExternalSignOut, + ExternalUpdateOsAction, + QueryPayloads, +} from '@unraid/shared-callbacks'; import { addPreventClose, removePreventClose } from '~/composables/preventClose'; import { useAccountStore } from '~/store/account'; @@ -6,17 +17,15 @@ import { useInstallKeyStore } from '~/store/installKey'; import { useServerStore } from '~/store/server'; import { useUpdateOsStore } from '~/store/updateOs'; import { useUpdateOsActionsStore } from '~/store/updateOsActions'; -import { - useCallbackStoreGeneric, - type CallbackActionsStore, - type ExternalKeyActions, - type ExternalSignIn, - type ExternalSignOut, - type ExternalUpdateOsAction, - type QueryPayloads, -} from '~/store/callback'; + +type CallbackStatus = 'closing' | 'error' | 'loading' | 'ready' | 'success'; + +setActivePinia(createPinia()); export const useCallbackActionsStore = defineStore('callbackActions', () => { + const { send, watcher: providedWatcher } = useCallback({ + encryptionKey: import.meta.env.VITE_CALLBACK_KEY, + }); const accountStore = useAccountStore(); const installKeyStore = useInstallKeyStore(); const serverStore = useServerStore(); @@ -24,15 +33,18 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => { const updateOsStore = useUpdateOsStore(); // if we remove this line, the store things break… const updateOsActionsStore = useUpdateOsActionsStore(); - type CallbackStatus = 'closing' | 'error' | 'loading' | 'ready' | 'success'; const callbackStatus = ref('ready'); - const callbackData = ref(); const callbackError = ref(); - const saveCallbackData = ( - decryptedData?: QueryPayloads, - ) => { + const watcher = () => { + const result = providedWatcher(); + if (result) { + saveCallbackData(result); + } + }; + + const saveCallbackData = (decryptedData?: QueryPayloads) => { if (decryptedData) { callbackData.value = decryptedData; } @@ -54,9 +66,15 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => { 'renew', 'upgrade', ]; + const redirectToCallbackType = () => { console.debug('[redirectToCallbackType]'); - if (!callbackData.value || !callbackData.value.type || callbackData.value.type !== 'forUpc' || !callbackData.value.actions?.length) { + if ( + !callbackData.value || + !callbackData.value.type || + callbackData.value.type !== 'forUpc' || + !callbackData.value.actions?.length + ) { callbackError.value = 'Callback redirect type not present or incorrect'; callbackStatus.value = 'ready'; // default status return console.error('[redirectToCallbackType]', callbackError.value); @@ -65,56 +83,64 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => { callbackStatus.value = 'loading'; // Parse the data and perform actions - callbackData.value.actions.forEach(async (action, index, array) => { - console.debug('[redirectToCallbackType]', { action, index, array }); - - if (actionTypesWithKey.includes(action.type)) { - await installKeyStore.install(action as ExternalKeyActions); - } + callbackData.value.actions.forEach( + async (action: ExternalActions, index: number, array: ExternalActions[]) => { + console.debug('[redirectToCallbackType]', { action, index, array }); - if (action.type === 'signIn' && action?.user) { - accountStore.setAccountAction(action as ExternalSignIn); - await accountStore.setConnectSignInPayload({ - apiKey: action?.apiKey ?? '', - email: action.user?.email ?? '', - preferred_username: action.user?.preferred_username ?? '', - }); - } + if (actionTypesWithKey.includes(action.type)) { + await installKeyStore.install(action as ExternalKeyActions); + } - if (action.type === 'signOut' || action.type === 'oemSignOut') { - accountStore.setAccountAction(action as ExternalSignOut); - await accountStore.setQueueConnectSignOut(true); - } + if (action.type === 'signIn' && action?.user) { + accountStore.setAccountAction(action as ExternalSignIn); + await accountStore.setConnectSignInPayload({ + apiKey: action?.apiKey ?? '', + email: action.user?.email ?? '', + preferred_username: action.user?.preferred_username ?? '', + }); + } - if (action.type === 'updateOs' || action.type === 'downgradeOs') { - updateOsActionsStore.setUpdateOsAction(action as ExternalUpdateOsAction); - await updateOsActionsStore.actOnUpdateOsAction(action.type === 'downgradeOs'); + if (action.type === 'signOut' || action.type === 'oemSignOut') { + accountStore.setAccountAction(action as ExternalSignOut); + await accountStore.setQueueConnectSignOut(true); + } - if (array.length === 1) { // only 1 action, skip refresh server state - console.debug('[redirectToCallbackType] updateOs done'); - // removing query string relase is set so users can't refresh the page and go through the same actions - window.history.replaceState(null, '', window.location.pathname); - return; + if (action.type === 'updateOs' || action.type === 'downgradeOs') { + updateOsActionsStore.setUpdateOsAction(action as ExternalUpdateOsAction); + await updateOsActionsStore.actOnUpdateOsAction(action.type === 'downgradeOs'); + + if (array.length === 1) { + // only 1 action, skip refresh server state + console.debug('[redirectToCallbackType] updateOs done'); + // removing query string relase is set so users can't refresh the page and go through the same actions + window.history.replaceState(null, '', window.location.pathname); + return; + } } - } - if (array.length === (index + 1)) { // all actions have run - await serverStore.refreshServerState(); - // callbackStatus.value = 'done'; + if (array.length === index + 1) { + // all actions have run + await serverStore.refreshServerState(); + } } - }); + ); }; + // Wait until we have a refreshServerStateStatus value to determine callbackStatus const refreshServerStateStatus = computed(() => serverStore.refreshServerStateStatus); watchEffect(() => { if (callbackData.value?.actions && refreshServerStateStatus.value === 'done') { if (callbackData.value.actions.length > 1) { // if we have more than 1 action it means there was a key install and an account action so both need to be successful - const allSuccess = accountStore.accountActionStatus === 'success' && installKeyStore.keyInstallStatus === 'success'; + const allSuccess = + accountStore.accountActionStatus === 'success' && + installKeyStore.keyInstallStatus === 'success'; callbackStatus.value = allSuccess ? 'success' : 'error'; } else { // only 1 action needs to be successful - const oneSuccess = accountStore.accountActionStatus === 'success' || installKeyStore.keyInstallStatus === 'success'; + const oneSuccess = + accountStore.accountActionStatus === 'success' || + installKeyStore.keyInstallStatus === 'success'; callbackStatus.value = oneSuccess ? 'success' : 'error'; } } @@ -124,7 +150,10 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => { } }); - const setCallbackStatus = (status: CallbackStatus) => { callbackStatus.value = status; }; + const setCallbackStatus = (status: CallbackStatus) => { + callbackStatus.value = status; + }; + watch(callbackStatus, (newVal, oldVal) => { if (newVal === 'loading') { addPreventClose(); @@ -144,10 +173,10 @@ export const useCallbackActionsStore = defineStore('callbackActions', () => { redirectToCallbackType, saveCallbackData, setCallbackStatus, + send, + watcher, // helpers sendType: 'fromUpc', encryptionKey: import.meta.env.VITE_CALLBACK_KEY, }; }); - -export const useCallbackStore = useCallbackStoreGeneric(useCallbackActionsStore as unknown as () => CallbackActionsStore); diff --git a/web/store/installKey.ts b/web/store/installKey.ts index ae5db1cc51..10a0c92e12 100644 --- a/web/store/installKey.ts +++ b/web/store/installKey.ts @@ -1,7 +1,7 @@ import { defineStore, createPinia, setActivePinia } from 'pinia'; import { WebguiInstallKey } from '~/composables/services/webgui'; import { useErrorsStore } from '~/store/errors'; -import type { ExternalKeyActions } from '~/store/callback'; +import type { ExternalKeyActions } from '@unraid/shared-callbacks'; /** * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components * @see https://github.com/vuejs/pinia/discussions/1085 diff --git a/web/store/purchase.ts b/web/store/purchase.ts index e1c9fceed7..625d4be26d 100644 --- a/web/store/purchase.ts +++ b/web/store/purchase.ts @@ -1,7 +1,7 @@ import { defineStore, createPinia, setActivePinia } from 'pinia'; import { PURCHASE_CALLBACK } from '~/helpers/urls'; -import { useCallbackStore } from '~/store/callbackActions'; +import { useCallbackActionsStore } from '~/store/callbackActions'; import { useServerStore } from '~/store/server'; /** @@ -11,7 +11,7 @@ import { useServerStore } from '~/store/server'; setActivePinia(createPinia()); export const usePurchaseStore = defineStore('purchase', () => { - const callbackStore = useCallbackStore(); + const callbackStore = useCallbackActionsStore(); const serverStore = useServerStore(); const activate = () => { diff --git a/web/store/replaceRenew.ts b/web/store/replaceRenew.ts index 06b3a3ba51..908f34f2ad 100644 --- a/web/store/replaceRenew.ts +++ b/web/store/replaceRenew.ts @@ -16,17 +16,10 @@ import { import { BrandLoading } from '@unraid/ui'; import type { BadgeProps } from '@unraid/ui'; -import type { - // type KeyLatestResponse, - ValidateGuidResponse, -} from '~/composables/services/keyServer'; +import type { ValidateGuidResponse } from '~/composables/services/keyServer'; import type { WretchError } from 'wretch'; -import { - // keyLatest, - validateGuid, -} from '~/composables/services/keyServer'; -// import { useCallbackStore } from '~/store/callbackActions'; +import { validateGuid } from '~/composables/services/keyServer'; import { useServerStore } from '~/store/server'; /** @@ -49,7 +42,6 @@ const BrandLoadingIcon = () => h(BrandLoading, { variant: 'white' }); export const REPLACE_CHECK_LOCAL_STORAGE_KEY = 'unraidReplaceCheck'; export const useReplaceRenewStore = defineStore('replaceRenewCheck', () => { - // const callbackStore = useCallbackStore(); const serverStore = useServerStore(); const guid = computed(() => serverStore.guid); diff --git a/web/store/trial.ts b/web/store/trial.ts index 3d11866308..43c4f8f577 100644 --- a/web/store/trial.ts +++ b/web/store/trial.ts @@ -6,7 +6,7 @@ import { startTrial, type StartTrialResponse } from '~/composables/services/keyS import { useCallbackActionsStore } from '~/store/callbackActions'; import { useDropdownStore } from '~/store/dropdown'; import { useServerStore } from '~/store/server'; -import type { ExternalPayload, TrialExtend, TrialStart } from '~/store/callback'; +import type { ExternalPayload, TrialExtend, TrialStart } from '@unraid/shared-callbacks'; /** * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components diff --git a/web/store/updateOsActions.ts b/web/store/updateOsActions.ts index 292fa8aad6..6b81197947 100644 --- a/web/store/updateOsActions.ts +++ b/web/store/updateOsActions.ts @@ -11,7 +11,7 @@ import { useAccountStore } from '~/store/account'; import { useServerStore } from '~/store/server'; import { useUpdateOsStore } from '~/store/updateOs'; -import type { ExternalUpdateOsAction } from '~/store/callback'; +import type { ExternalUpdateOsAction } from '@unraid/shared-callbacks'; import type { UserProfileLink } from '~/types/userProfile'; /** diff --git a/web/store/updateOsChangelog.ts b/web/store/updateOsChangelog.ts index 23572b48bf..4bd1ab5cda 100644 --- a/web/store/updateOsChangelog.ts +++ b/web/store/updateOsChangelog.ts @@ -1,18 +1,18 @@ +import { computed, ref, watch } from 'vue'; +import { defineStore } from 'pinia'; + import { Markdown } from '@/helpers/markdown'; -import { request } from '~/composables/services/request'; import { DOCS_RELEASE_NOTES } from '~/helpers/urls'; -import { useCallbackStore } from '~/store/callbackActions'; -// import { useServerStore } from '~/store/server'; -import type { ServerUpdateOsResponse } from '~/types/server'; import { baseUrl } from 'marked-base-url'; -import { defineStore } from 'pinia'; import prerelease from 'semver/functions/prerelease'; -import { computed, ref, watch } from 'vue'; + +import type { ServerUpdateOsResponse } from '~/types/server'; + +import { request } from '~/composables/services/request'; +import { useCallbackActionsStore } from '~/store/callbackActions'; export const useUpdateOsChangelogStore = defineStore('updateOsChangelog', () => { - const callbackStore = useCallbackStore(); - // const serverStore = useServerStore(); - // const osVersionBranch = computed(() => serverStore.osVersionBranch); + const callbackStore = useCallbackActionsStore(); const releaseForUpdate = ref(null); watch(releaseForUpdate, async (newVal, oldVal) => {