From 39a80c39cf3e34e0bef58f5bd6c0efccf689983c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 10:17:37 +0100 Subject: [PATCH 1/7] change from root guard to route specific guards --- web/package.json | 10 +- web/pnpm-lock.yaml | 174 +++++++++--------- .../components/GroupsTable/GroupsTable.tsx | 1 + .../LocationOverviewNetworkDevicesTable.tsx | 1 + .../LocationOverviewUsersTable.tsx | 1 + .../NetworkDevicesTable.tsx | 1 + web/src/pages/OpenIdPage/OpenIdTable.tsx | 2 + web/src/pages/WebhooksPage/WebhooksTable.tsx | 1 + .../ProfileApiTokensTable.tsx | 1 + .../ProfileAuthKeysTable.tsx | 1 + .../ProfileDevicesTable.tsx | 1 + web/src/routes/__root.tsx | 80 +------- web/src/routes/_authorized.tsx | 25 ++- web/src/routes/_wizard/setup-wizard.tsx | 42 ++++- web/src/shared/defguard-ui | 2 +- 15 files changed, 167 insertions(+), 176 deletions(-) diff --git a/web/package.json b/web/package.json index bf3d10575a..e800c00d70 100644 --- a/web/package.json +++ b/web/package.json @@ -22,7 +22,7 @@ "@stablelib/x25519": "^2.0.1", "@tanstack/react-form": "^1.28.0", "@tanstack/react-query": "^5.90.20", - "@tanstack/react-router": "^1.158.0", + "@tanstack/react-router": "^1.158.1", "@tanstack/react-table": "^8.21.3", "@tanstack/react-virtual": "^3.13.18", "@uidotdev/usehooks": "^2.4.1", @@ -34,7 +34,7 @@ "humanize-duration": "^3.33.2", "ipaddr.js": "^2.3.0", "lodash-es": "^4.17.23", - "motion": "^12.31.0", + "motion": "^12.31.1", "qrcode.react": "^4.2.0", "qs": "^6.14.1", "radashi": "^12.7.1", @@ -56,14 +56,14 @@ "@tanstack/devtools-vite": "^0.5.0", "@tanstack/react-devtools": "^0.9.4", "@tanstack/react-query-devtools": "^5.91.3", - "@tanstack/react-router-devtools": "^1.158.0", - "@tanstack/router-plugin": "^1.158.0", + "@tanstack/react-router-devtools": "^1.158.1", + "@tanstack/router-plugin": "^1.158.1", "@types/byte-size": "^8.1.2", "@types/humanize-duration": "^3.27.4", "@types/lodash-es": "^4.17.12", "@types/node": "^25.2.0", "@types/qs": "^6.14.0", - "@types/react": "^19.2.10", + "@types/react": "^19.2.11", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react-swc": "^4.2.3", "autoprefixer": "^10.4.24", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 45b9c5c50a..e1c32e8ba3 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@axa-ch/react-polymorphic-types': specifier: ^1.4.1 - version: 1.4.1(@types/react@19.2.10)(react@19.2.4) + version: 1.4.1(@types/react@19.2.11)(react@19.2.4) '@floating-ui/react': specifier: ^0.27.17 version: 0.27.17(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -36,8 +36,8 @@ importers: specifier: ^5.90.20 version: 5.90.20(react@19.2.4) '@tanstack/react-router': - specifier: ^1.158.0 - version: 1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^1.158.1 + version: 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/react-table': specifier: ^8.21.3 version: 8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -72,8 +72,8 @@ importers: specifier: ^4.17.23 version: 4.17.23 motion: - specifier: ^12.31.0 - version: 12.31.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^12.31.1 + version: 12.31.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) qrcode.react: specifier: ^4.2.0 version: 4.2.0(react@19.2.4) @@ -97,10 +97,10 @@ importers: version: 3.5.0(react@19.2.4) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.10)(react@19.2.4) + version: 10.1.0(@types/react@19.2.11)(react@19.2.4) recharts: specifier: ^3.7.0 - version: 3.7.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.0)(react@19.2.4)(redux@5.0.1) + version: 3.7.0(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.0)(react@19.2.4)(redux@5.0.1) rehype-raw: specifier: ^7.0.0 version: 7.0.0 @@ -115,7 +115,7 @@ importers: version: 4.3.6 zustand: specifier: ^5.0.11 - version: 5.0.11(@types/react@19.2.10)(immer@11.1.3)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) + version: 5.0.11(@types/react@19.2.11)(immer@11.1.3)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: '@biomejs/biome': specifier: 2.3.14 @@ -125,16 +125,16 @@ importers: version: 0.5.0(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0)) '@tanstack/react-devtools': specifier: ^0.9.4 - version: 0.9.4(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(solid-js@1.9.9) + version: 0.9.4(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(solid-js@1.9.9) '@tanstack/react-query-devtools': specifier: ^5.91.3 version: 5.91.3(@tanstack/react-query@5.90.20(react@19.2.4))(react@19.2.4) '@tanstack/react-router-devtools': - specifier: ^1.158.0 - version: 1.158.0(@tanstack/react-router@1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.0)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^1.158.1 + version: 1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.1)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/router-plugin': - specifier: ^1.158.0 - version: 1.158.0(@tanstack/react-router@1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0)) + specifier: ^1.158.1 + version: 1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0)) '@types/byte-size': specifier: ^8.1.2 version: 8.1.2 @@ -151,11 +151,11 @@ importers: specifier: ^6.14.0 version: 6.14.0 '@types/react': - specifier: ^19.2.10 - version: 19.2.10 + specifier: ^19.2.11 + version: 19.2.11 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.10) + version: 19.2.3(@types/react@19.2.11) '@vitejs/plugin-react-swc': specifier: ^4.2.3 version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0)) @@ -213,8 +213,8 @@ packages: resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.0': - resolution: {integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==} + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.28.6': @@ -1251,20 +1251,20 @@ packages: peerDependencies: react: ^18 || ^19 - '@tanstack/react-router-devtools@1.158.0': - resolution: {integrity: sha512-uhciBlsPW67xbDCFyc2RQS00OergfNXYxendGUO2HGy4uTr79aQSCb4l6v+sdlPwUTlzwkAtM6e1illIexF15Q==} + '@tanstack/react-router-devtools@1.158.1': + resolution: {integrity: sha512-H0iTfsLNkadF/JhJnu/pUxlxOiLjE0866vFqXK/7EYVcyYwx2uWQuGxEkyF7a04oXXrbEImAOoXDRBQcZ9T5Zw==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.158.0 - '@tanstack/router-core': ^1.158.0 + '@tanstack/react-router': ^1.158.1 + '@tanstack/router-core': ^1.158.1 react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' peerDependenciesMeta: '@tanstack/router-core': optional: true - '@tanstack/react-router@1.158.0': - resolution: {integrity: sha512-kvTaO6zjq9WWPyo1wwSZx95AjJ9KOvu23cOMgKeDdDQWKF3Z9q3fwhToKMKJoC11T2Vuivz+o/anrxCcOvdRzw==} + '@tanstack/react-router@1.158.1': + resolution: {integrity: sha512-ZRBhs0tJDPeYGVrBhXPkGs+mOKqKKMM4OfvYSNvWIYZGfs8KQcqxPaN8OnUvKsnAGtzwusVWDpBipqVZWJd0lA==} engines: {node: '>=12'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -1289,30 +1289,30 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.158.0': - resolution: {integrity: sha512-dRMcWY0UB/6OZqSCx/7iUvom0ol18rHSQladygVT8mlth7uxYx3n5BNse8C03efIE8y1Bx+VDOBAKpAZ9BgKog==} + '@tanstack/router-core@1.158.1': + resolution: {integrity: sha512-8B9X3GzN1JWsqa+OTgg2k+LrayLQYmgtv26b96difyrRS32DaDBvEpU3xXDaLNmi/+zoqG1ffAcDT4D6tyC2hw==} engines: {node: '>=12'} - '@tanstack/router-devtools-core@1.158.0': - resolution: {integrity: sha512-8FUKfjh8Xz9T9O5yYaiVE0Va5aCMncQyVPKb7yy5M/buDnx9Kh0bPjw/eUZJWftOyxW6/WeR605yjOdx/PnqNw==} + '@tanstack/router-devtools-core@1.158.1': + resolution: {integrity: sha512-iGCqmIJ5NXMIuyFwJgfikEmRrceT3tmynMTMSuVxFiv9+Dlk1tsp8bsYS+UGhyY4beoASsRnlikAeNAMsCjhwA==} engines: {node: '>=12'} peerDependencies: - '@tanstack/router-core': ^1.158.0 + '@tanstack/router-core': ^1.158.1 csstype: ^3.0.10 peerDependenciesMeta: csstype: optional: true - '@tanstack/router-generator@1.158.0': - resolution: {integrity: sha512-hVkXQSN/fMD9q3Zn3wNa4PV0Y9VNwQB2bLaecA5i4vc43GX75vmgyiKoMr44BJheUssfVoL/po9a/7sv+N6lKA==} + '@tanstack/router-generator@1.158.1': + resolution: {integrity: sha512-geBpsIxJNvdjw2kt/Ii/j68hIUvfGnra0HKlGrDZw8/Ny4AJ2nnOcszUlZRbuQyxByk05r4lneOShKy5V5MUCQ==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.158.0': - resolution: {integrity: sha512-FxTOo/icU373jlOu9nlzR0B1vqc47tKZLw3HwOQwCBL4P4EihOBz+L7dcGyKR8bRBL0rCRWvHQTSHNMOr+fGYQ==} + '@tanstack/router-plugin@1.158.1': + resolution: {integrity: sha512-IPCnf1CBc0jnczuy65+3iBaoABv5TKhOJ1YLzwel4kb9D8Abcq0vF8ooR5FiPmaGnree/z3SvjgHe5eQtgcsSQ==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.158.0 + '@tanstack/react-router': ^1.158.1 vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' vite-plugin-solid: ^2.11.10 webpack: '>=5.92.0' @@ -1417,8 +1417,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.10': - resolution: {integrity: sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==} + '@types/react@19.2.11': + resolution: {integrity: sha512-tORuanb01iEzWvMGVGv2ZDhYZVeRMrw453DCSAIn/5yvcSVnMoUMTyf33nQJLahYEnv9xqrTNbgz4qY5EfSh0g==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1555,8 +1555,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001767: - resolution: {integrity: sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==} + caniuse-lite@1.0.30001768: + resolution: {integrity: sha512-qY3aDRZC5nWPgHUgIB84WL+nySuo19wk0VJpp/XI9T34lrvkyhRvNVOFJOp2kxClQhiFBu+TaUSudf6oa3vkSA==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1862,8 +1862,8 @@ packages: fraction.js@5.3.4: resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} - framer-motion@12.31.0: - resolution: {integrity: sha512-Tnd0FU05zGRFI3JJmBegXonF1rfuzYeuXd1QSdQ99Ysnppk0yWBWSW2wUsqzRpS5nv0zPNx+y0wtDj4kf0q5RQ==} + framer-motion@12.31.1: + resolution: {integrity: sha512-cMwCU/k6k7ktHbIXE5NFCgG+BLW2CmCahPMw2MuZuIUHOy1HEa4wnYXBWz4l16eQc8eRGHpO5umWQ0QDl+evPw==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -2272,8 +2272,8 @@ packages: motion-utils@12.29.2: resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==} - motion@12.31.0: - resolution: {integrity: sha512-KpZQik3LLFdsiaLdFXQGnty84KcDvvdvBCHSvA9aH+RjQTP6jkJGyngRPSngau13ARUI6TbPphf/Vv/QxwxRJQ==} + motion@12.31.1: + resolution: {integrity: sha512-xbw2pNRmZkunHSEqcPQEOU7KbMmy8GJ52/sd81NlSFM3MWWNGMrpwKZzUQQ/TYtWyDIkWkNGzQRZ61g5MHlREw==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -2961,9 +2961,9 @@ packages: snapshots: - '@axa-ch/react-polymorphic-types@1.4.1(@types/react@19.2.10)(react@19.2.4)': + '@axa-ch/react-polymorphic-types@1.4.1(@types/react@19.2.11)(react@19.2.4)': dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.11 react: 19.2.4 '@babel/code-frame@7.29.0': @@ -2977,7 +2977,7 @@ snapshots: '@babel/core@7.29.0': dependencies: '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.0 + '@babel/generator': 7.29.1 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helpers': 7.28.6 @@ -2994,7 +2994,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.0': + '@babel/generator@7.29.1': dependencies: '@babel/parser': 7.29.0 '@babel/types': 7.29.0 @@ -3064,7 +3064,7 @@ snapshots: '@babel/traverse@7.29.0': dependencies: '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.0 + '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 '@babel/parser': 7.29.0 '@babel/template': 7.28.6 @@ -3504,7 +3504,7 @@ snapshots: '@react-hook/passive-layout-effect': 1.2.1(react@19.2.4) react: 19.2.4 - '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.10)(react@19.2.4)(redux@5.0.1))(react@19.2.4)': + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.11)(react@19.2.4)(redux@5.0.1))(react@19.2.4)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 @@ -3514,7 +3514,7 @@ snapshots: reselect: 5.1.1 optionalDependencies: react: 19.2.4 - react-redux: 9.2.0(@types/react@19.2.10)(react@19.2.4)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.11)(react@19.2.4)(redux@5.0.1) '@rolldown/pluginutils@1.0.0-rc.2': {} @@ -3742,7 +3742,7 @@ snapshots: '@tanstack/devtools-vite@0.5.0(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0))': dependencies: '@babel/core': 7.29.0 - '@babel/generator': 7.29.0 + '@babel/generator': 7.29.1 '@babel/parser': 7.29.0 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 @@ -3787,11 +3787,11 @@ snapshots: '@tanstack/query-devtools@5.93.0': {} - '@tanstack/react-devtools@0.9.4(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(solid-js@1.9.9)': + '@tanstack/react-devtools@0.9.4(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(solid-js@1.9.9)': dependencies: '@tanstack/devtools': 0.10.5(csstype@3.2.3)(solid-js@1.9.9) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@types/react': 19.2.11 + '@types/react-dom': 19.2.3(@types/react@19.2.11) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) transitivePeerDependencies: @@ -3819,22 +3819,22 @@ snapshots: '@tanstack/query-core': 5.90.20 react: 19.2.4 - '@tanstack/react-router-devtools@1.158.0(@tanstack/react-router@1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.0)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@tanstack/react-router-devtools@1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.1)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@tanstack/react-router': 1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@tanstack/router-devtools-core': 1.158.0(@tanstack/router-core@1.158.0)(csstype@3.2.3) + '@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tanstack/router-devtools-core': 1.158.1(@tanstack/router-core@1.158.1)(csstype@3.2.3) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) optionalDependencies: - '@tanstack/router-core': 1.158.0 + '@tanstack/router-core': 1.158.1 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@tanstack/history': 1.154.14 '@tanstack/react-store': 0.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@tanstack/router-core': 1.158.0 + '@tanstack/router-core': 1.158.1 isbot: 5.1.34 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -3860,7 +3860,7 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@tanstack/router-core@1.158.0': + '@tanstack/router-core@1.158.1': dependencies: '@tanstack/history': 1.154.14 '@tanstack/store': 0.8.0 @@ -3870,18 +3870,18 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.158.0(@tanstack/router-core@1.158.0)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.158.1(@tanstack/router-core@1.158.1)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.158.0 + '@tanstack/router-core': 1.158.1 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) tiny-invariant: 1.3.3 optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.158.0': + '@tanstack/router-generator@1.158.1': dependencies: - '@tanstack/router-core': 1.158.0 + '@tanstack/router-core': 1.158.1 '@tanstack/router-utils': 1.158.0 '@tanstack/virtual-file-routes': 1.154.7 prettier: 3.8.1 @@ -3892,7 +3892,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.158.0(@tanstack/react-router@1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0))': + '@tanstack/router-plugin@1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) @@ -3900,15 +3900,15 @@ snapshots: '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 - '@tanstack/router-core': 1.158.0 - '@tanstack/router-generator': 1.158.0 + '@tanstack/router-core': 1.158.1 + '@tanstack/router-generator': 1.158.1 '@tanstack/router-utils': 1.158.0 '@tanstack/virtual-file-routes': 1.154.7 chokidar: 3.6.0 unplugin: 2.3.11 zod: 3.25.76 optionalDependencies: - '@tanstack/react-router': 1.158.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) vite: 7.3.1(@types/node@25.2.0)(sass@1.97.3)(tsx@4.21.0) transitivePeerDependencies: - supports-color @@ -3916,7 +3916,7 @@ snapshots: '@tanstack/router-utils@1.158.0': dependencies: '@babel/core': 7.29.0 - '@babel/generator': 7.29.0 + '@babel/generator': 7.29.1 '@babel/parser': 7.29.0 '@babel/types': 7.29.0 ansis: 4.2.0 @@ -3997,11 +3997,11 @@ snapshots: '@types/qs@6.14.0': {} - '@types/react-dom@19.2.3(@types/react@19.2.10)': + '@types/react-dom@19.2.3(@types/react@19.2.11)': dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.11 - '@types/react@19.2.10': + '@types/react@19.2.11': dependencies: csstype: 3.2.3 @@ -4067,7 +4067,7 @@ snapshots: autoprefixer@10.4.24(postcss@8.5.6): dependencies: browserslist: 4.28.1 - caniuse-lite: 1.0.30001767 + caniuse-lite: 1.0.30001768 fraction.js: 5.3.4 picocolors: 1.1.1 postcss: 8.5.6 @@ -4105,7 +4105,7 @@ snapshots: browserslist@4.28.1: dependencies: baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001767 + caniuse-lite: 1.0.30001768 electron-to-chromium: 1.5.286 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) @@ -4132,7 +4132,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001767: {} + caniuse-lite@1.0.30001768: {} ccount@2.0.1: {} @@ -4404,7 +4404,7 @@ snapshots: fraction.js@5.3.4: {} - framer-motion@12.31.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + framer-motion@12.31.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: motion-dom: 12.30.1 motion-utils: 12.29.2 @@ -4934,9 +4934,9 @@ snapshots: motion-utils@12.29.2: {} - motion@12.31.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + motion@12.31.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: - framer-motion: 12.31.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + framer-motion: 12.31.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) tslib: 2.8.1 optionalDependencies: react: 19.2.4 @@ -5052,11 +5052,11 @@ snapshots: dependencies: react: 19.2.4 - react-markdown@10.1.0(@types/react@19.2.10)(react@19.2.4): + react-markdown@10.1.0(@types/react@19.2.11)(react@19.2.4): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@types/react': 19.2.10 + '@types/react': 19.2.11 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 @@ -5070,13 +5070,13 @@ snapshots: transitivePeerDependencies: - supports-color - react-redux@9.2.0(@types/react@19.2.10)(react@19.2.4)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.11)(react@19.2.4)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 react: 19.2.4 use-sync-external-store: 1.6.0(react@19.2.4) optionalDependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.11 redux: 5.0.1 react@19.2.4: {} @@ -5095,9 +5095,9 @@ snapshots: tiny-invariant: 1.3.3 tslib: 2.8.1 - recharts@3.7.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.0)(react@19.2.4)(redux@5.0.1): + recharts@3.7.0(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.0)(react@19.2.4)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.10)(react@19.2.4)(redux@5.0.1))(react@19.2.4) + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.11)(react@19.2.4)(redux@5.0.1))(react@19.2.4) clsx: 2.1.1 decimal.js-light: 2.5.1 es-toolkit: 1.44.0 @@ -5106,7 +5106,7 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) react-is: 19.2.0 - react-redux: 9.2.0(@types/react@19.2.10)(react@19.2.4)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.11)(react@19.2.4)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 use-sync-external-store: 1.6.0(react@19.2.4) @@ -5700,9 +5700,9 @@ snapshots: zod@4.3.6: {} - zustand@5.0.11(@types/react@19.2.10)(immer@11.1.3)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): + zustand@5.0.11(@types/react@19.2.11)(immer@11.1.3)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): optionalDependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.11 immer: 11.1.3 react: 19.2.4 use-sync-external-store: 1.6.0(react@19.2.4) diff --git a/web/src/pages/GroupsPage/components/GroupsTable/GroupsTable.tsx b/web/src/pages/GroupsPage/components/GroupsTable/GroupsTable.tsx index cc329160f3..1265dad2a6 100644 --- a/web/src/pages/GroupsPage/components/GroupsTable/GroupsTable.tsx +++ b/web/src/pages/GroupsPage/components/GroupsTable/GroupsTable.tsx @@ -151,6 +151,7 @@ export const GroupsTable = ({ groups, users }: Props) => { getSortedRowModel: getSortedRowModel(), enableSorting: true, enableRowSelection: false, + columnResizeMode: 'onChange', }); return ( diff --git a/web/src/pages/LocationOverviewPage/LocationOverviewNetworkDevicesTable.tsx b/web/src/pages/LocationOverviewPage/LocationOverviewNetworkDevicesTable.tsx index 6b9e410446..a3f9e65b5d 100644 --- a/web/src/pages/LocationOverviewPage/LocationOverviewNetworkDevicesTable.tsx +++ b/web/src/pages/LocationOverviewPage/LocationOverviewNetworkDevicesTable.tsx @@ -114,6 +114,7 @@ export const LocationOverviewNetworkDevicesTable = ({ enableExpanding: false, enableSorting: true, enableRowSelection: false, + columnResizeMode: 'onChange', }); if (data.length === 0) diff --git a/web/src/pages/LocationOverviewPage/LocationOverviewUsersTable.tsx b/web/src/pages/LocationOverviewPage/LocationOverviewUsersTable.tsx index 99373bc9dc..92317a7b64 100644 --- a/web/src/pages/LocationOverviewPage/LocationOverviewUsersTable.tsx +++ b/web/src/pages/LocationOverviewPage/LocationOverviewUsersTable.tsx @@ -215,6 +215,7 @@ export const LocationOverviewUsersTable = ({ data }: Props) => { enableSorting: true, enableExpanding: true, enableRowSelection: false, + columnResizeMode: 'onChange', }); if (data.length === 0) diff --git a/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx b/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx index 6277ff0932..ab9309f09c 100644 --- a/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx +++ b/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx @@ -246,6 +246,7 @@ export const NetworkDevicesTable = ({ networkDevices }: Props) => { <> {networkDevices.length === 0 && ( { getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), enableRowSelection: false, + columnResizeMode: 'onChange', }); return ( @@ -186,6 +187,7 @@ export const OpenIdClientTable = ({ data }: Props) => { )} {data.length === 0 && ( { data: webhooks, getCoreRowModel: getCoreRowModel(), enableRowSelection: false, + columnResizeMode: 'onChange', }); return ( <> diff --git a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileApiTokensTab/components/ProfileApiTokensTable/ProfileApiTokensTable.tsx b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileApiTokensTab/components/ProfileApiTokensTable/ProfileApiTokensTable.tsx index 0dc066558f..4b27159346 100644 --- a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileApiTokensTab/components/ProfileApiTokensTable/ProfileApiTokensTable.tsx +++ b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileApiTokensTab/components/ProfileApiTokensTable/ProfileApiTokensTable.tsx @@ -120,6 +120,7 @@ export const ProfileApiTokensTable = () => { getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), enableRowSelection: false, + columnResizeMode: 'onChange', }); return ; diff --git a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileAuthKeysTab/ProfileAuthKeysTable.tsx b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileAuthKeysTab/ProfileAuthKeysTable.tsx index c3b4117b8c..7922574357 100644 --- a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileAuthKeysTab/ProfileAuthKeysTable.tsx +++ b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileAuthKeysTab/ProfileAuthKeysTable.tsx @@ -220,6 +220,7 @@ export const ProfileAuthKeysTable = () => { getSortedRowModel: getSortedRowModel(), enableSorting: true, enableRowSelection: false, + columnResizeMode: 'onChange', }); return ; diff --git a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx index 08227ae807..dd5c4b5c01 100644 --- a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx +++ b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx @@ -287,6 +287,7 @@ const DevicesTable = ({ rowData }: { rowData: RowData[] }) => { enableExpanding: true, enableRowSelection: false, enableSorting: true, + columnResizeMode: 'onChange', }); return ( diff --git a/web/src/routes/__root.tsx b/web/src/routes/__root.tsx index 5227977542..f438f903c6 100644 --- a/web/src/routes/__root.tsx +++ b/web/src/routes/__root.tsx @@ -1,92 +1,14 @@ import type { QueryClient } from '@tanstack/react-query'; -import { - createRootRouteWithContext, - Outlet, - type ParsedLocation, - redirect, -} from '@tanstack/react-router'; +import { createRootRouteWithContext, Outlet } from '@tanstack/react-router'; import { AppLoaderPage } from '../pages/AppLoaderPage/AppLoaderPage'; -import { useSetupWizardStore } from '../pages/SetupPage/useSetupWizardStore'; import { SnackbarManager } from '../shared/defguard-ui/providers/snackbar/SnackbarManager'; -import { useAuth } from '../shared/hooks/useAuth'; -import { - getSettingsEssentialsQueryOptions, - getUserMeQueryOptions, -} from '../shared/query'; interface RouterContext { queryClient: QueryClient; } -// Handles the initial wizard redirect. -// All routes should redirect to the setup wizard if the initial setup is not completed. -const handleWizardRedirect = async ({ - location, - context, -}: { - location: ParsedLocation; - context: RouterContext; -}) => { - const settingsEssentials = ( - await ( - await context.queryClient.ensureQueryData(getSettingsEssentialsQueryOptions) - )() - ).data; - - // Tries to access any route but setup is not completed - const setupNotCompletedAnyAccess = - !settingsEssentials.initial_setup_completed && - !location.pathname.startsWith('/setup-wizard'); - - // Tries to access setup wizard but setup is already completed - const setupCompletedButAccessingWizard = - settingsEssentials.initial_setup_completed && - location.pathname.startsWith('/setup-wizard'); - - if (setupNotCompletedAnyAccess) { - useSetupWizardStore.getState().reset(); - throw redirect({ to: '/setup-wizard', replace: true }); - } else if (setupCompletedButAccessingWizard) { - throw redirect({ to: '/auth/login', replace: true }); - } -}; - export const Route = createRootRouteWithContext()({ component: RootComponent, - beforeLoad: async ({ location, context }) => { - await handleWizardRedirect({ - location, - context, - }); - - if ( - location.pathname.startsWith('/auth') || - location.pathname.startsWith('/setup-wizard') - ) { - return; - } - - try { - const user = ( - await ( - await context.queryClient.ensureQueryData(getUserMeQueryOptions) - )() - ).data; - - // Invalid user object - if (!user.id) { - throw redirect({ to: '/auth/login', replace: true }); - } - - useAuth.getState().setUser(user); - } catch (_) { - useAuth.getState().reset(); - throw redirect({ - to: '/auth/login', - replace: true, - }); - } - }, pendingComponent: AppLoaderPage, pendingMs: 100, }); diff --git a/web/src/routes/_authorized.tsx b/web/src/routes/_authorized.tsx index 3be00be0b3..c3b753a2fe 100644 --- a/web/src/routes/_authorized.tsx +++ b/web/src/routes/_authorized.tsx @@ -5,13 +5,32 @@ import { UpgradePlanModalManager } from '../shared/components/modals/UpgradePlan import { useAuth } from '../shared/hooks/useAuth'; import { AppConfigProvider } from '../shared/providers/AppConfigProvider'; import { AppUserProvider } from '../shared/providers/AppUserProvider'; +import { getUserMeQueryOptions } from '../shared/query'; export const Route = createFileRoute('/_authorized')({ component: RouteComponent, - beforeLoad: () => { + beforeLoad: async ({ context }) => { if (!useAuth.getState().user) { - console.error('No auth session in store.'); - throw redirect({ to: '/auth', replace: true }); + try { + const user = ( + await ( + await context.queryClient.ensureQueryData(getUserMeQueryOptions) + )() + ).data; + + // Invalid user object + if (!user.id) { + useAuth.getState().reset(); + throw redirect({ to: '/auth/login', replace: true }); + } + useAuth.getState().setUser(user); + } catch (_) { + useAuth.getState().reset(); + throw redirect({ + to: '/auth/login', + replace: true, + }); + } } }, }); diff --git a/web/src/routes/_wizard/setup-wizard.tsx b/web/src/routes/_wizard/setup-wizard.tsx index 74949383a8..ab8796f7ab 100644 --- a/web/src/routes/_wizard/setup-wizard.tsx +++ b/web/src/routes/_wizard/setup-wizard.tsx @@ -1,6 +1,46 @@ -import { createFileRoute } from '@tanstack/react-router'; +import type { QueryClient } from '@tanstack/react-query'; +import { createFileRoute, type ParsedLocation, redirect } from '@tanstack/react-router'; import { SetupPage } from '../../pages/SetupPage/SetupPage'; +import { useSetupWizardStore } from '../../pages/SetupPage/useSetupWizardStore'; +import { getSettingsEssentialsQueryOptions } from '../../shared/query'; + +const handleWizardRedirect = async ({ + location, + client, +}: { + location: ParsedLocation; + client: QueryClient; +}) => { + const settingsEssentials = ( + await ( + await client.ensureQueryData(getSettingsEssentialsQueryOptions) + )() + ).data; + + // Tries to access any route but setup is not completed + const setupNotCompletedAnyAccess = + !settingsEssentials.initial_setup_completed && + !location.pathname.startsWith('/setup-wizard'); + + // Tries to access setup wizard but setup is already completed + const setupCompletedButAccessingWizard = + settingsEssentials.initial_setup_completed && + location.pathname.startsWith('/setup-wizard'); + + if (setupNotCompletedAnyAccess) { + useSetupWizardStore.getState().reset(); + throw redirect({ to: '/setup-wizard', replace: true }); + } else if (setupCompletedButAccessingWizard) { + throw redirect({ to: '/auth/login', replace: true }); + } +}; export const Route = createFileRoute('/_wizard/setup-wizard')({ + beforeLoad: async ({ context, location }) => { + await handleWizardRedirect({ + client: context.queryClient, + location, + }); + }, component: SetupPage, }); diff --git a/web/src/shared/defguard-ui b/web/src/shared/defguard-ui index 3537bba6cf..6296e38544 160000 --- a/web/src/shared/defguard-ui +++ b/web/src/shared/defguard-ui @@ -1 +1 @@ -Subproject commit 3537bba6cf2e9f74290b09001b0548f947027ec0 +Subproject commit 6296e3854464d725f9860f546041ab2be19f7592 From a8b484f8607409e6c99fa9f8b0174ef7023f6de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 10:36:02 +0100 Subject: [PATCH 2/7] add _auth guard for unconfigured instance scenario --- web/src/routes/__root.tsx | 5 +++- web/src/routes/_authorized.tsx | 6 ++--- web/src/routes/auth.tsx | 23 ++++++++++++++++++- web/src/shared/api/types.ts | 1 + ...ConfigProvider.tsx => AppInfoProvider.tsx} | 20 ++-------------- .../AppSettingsEssentialsProvider.tsx | 18 +++++++++++++++ web/src/shared/query.ts | 6 ++--- 7 files changed, 53 insertions(+), 26 deletions(-) rename web/src/shared/providers/{AppConfigProvider.tsx => AppInfoProvider.tsx} (59%) create mode 100644 web/src/shared/providers/AppSettingsEssentialsProvider.tsx diff --git a/web/src/routes/__root.tsx b/web/src/routes/__root.tsx index f438f903c6..f4abb1e345 100644 --- a/web/src/routes/__root.tsx +++ b/web/src/routes/__root.tsx @@ -2,6 +2,7 @@ import type { QueryClient } from '@tanstack/react-query'; import { createRootRouteWithContext, Outlet } from '@tanstack/react-router'; import { AppLoaderPage } from '../pages/AppLoaderPage/AppLoaderPage'; import { SnackbarManager } from '../shared/defguard-ui/providers/snackbar/SnackbarManager'; +import { AppSettingsEssentialsProvider } from '../shared/providers/AppSettingsEssentialsProvider'; interface RouterContext { queryClient: QueryClient; @@ -16,7 +17,9 @@ export const Route = createRootRouteWithContext()({ function RootComponent() { return ( - + + + ); } diff --git a/web/src/routes/_authorized.tsx b/web/src/routes/_authorized.tsx index c3b753a2fe..e8096e26da 100644 --- a/web/src/routes/_authorized.tsx +++ b/web/src/routes/_authorized.tsx @@ -3,7 +3,7 @@ import { DisplayListModal } from '../shared/components/DisplayListModal/DisplayL import { SelectionModal } from '../shared/components/modals/SelectionModal/SelectionModal'; import { UpgradePlanModalManager } from '../shared/components/modals/UpgradePlanModalManager/UpgradePlanModalManager'; import { useAuth } from '../shared/hooks/useAuth'; -import { AppConfigProvider } from '../shared/providers/AppConfigProvider'; +import { AppInfoProvider } from '../shared/providers/AppInfoProvider'; import { AppUserProvider } from '../shared/providers/AppUserProvider'; import { getUserMeQueryOptions } from '../shared/query'; @@ -38,12 +38,12 @@ export const Route = createFileRoute('/_authorized')({ function RouteComponent() { return ( - + - + ); } diff --git a/web/src/routes/auth.tsx b/web/src/routes/auth.tsx index 9e14c6246c..5c9dbc8c0e 100644 --- a/web/src/routes/auth.tsx +++ b/web/src/routes/auth.tsx @@ -1,10 +1,12 @@ import { useQueryClient } from '@tanstack/react-query'; -import { createFileRoute, Outlet, useNavigate } from '@tanstack/react-router'; +import { createFileRoute, Outlet, redirect, useNavigate } from '@tanstack/react-router'; import { useCallback, useEffect } from 'react'; import z from 'zod'; import { type User, UserMfaMethod } from '../shared/api/types'; import { isPresent } from '../shared/defguard-ui/utils/isPresent'; +import { useApp } from '../shared/hooks/useApp'; import { useAuth } from '../shared/hooks/useAuth'; +import { getSettingsEssentialsQueryOptions } from '../shared/query'; const basicSchema = z.object({ url: z.string().nullable().optional(), @@ -19,6 +21,25 @@ const mfaSchema = z.object({ }); export const Route = createFileRoute('/auth')({ + beforeLoad: async ({ context }) => { + // ensure that login is possible on the instance + let settings = useApp.getState().settingsEssentials; + // fill settings + if (!settings) { + settings = ( + await context.queryClient.ensureQueryData(getSettingsEssentialsQueryOptions) + ).data; + useApp.setState({ + settingsEssentials: settings, + }); + } + if (!settings.initial_setup_completed) { + throw redirect({ + to: '/setup-wizard', + replace: true, + }); + } + }, component: RouteComponent, }); diff --git a/web/src/shared/api/types.ts b/web/src/shared/api/types.ts index 23ca107f44..bd00e35167 100644 --- a/web/src/shared/api/types.ts +++ b/web/src/shared/api/types.ts @@ -631,6 +631,7 @@ export interface SettingsEnterprise { } export interface SettingsEssentials { + instance_name: string; initial_setup_completed: boolean; } diff --git a/web/src/shared/providers/AppConfigProvider.tsx b/web/src/shared/providers/AppInfoProvider.tsx similarity index 59% rename from web/src/shared/providers/AppConfigProvider.tsx rename to web/src/shared/providers/AppInfoProvider.tsx index 24ea130872..ac6a58e760 100644 --- a/web/src/shared/providers/AppConfigProvider.tsx +++ b/web/src/shared/providers/AppInfoProvider.tsx @@ -5,8 +5,9 @@ import { isPresent } from '../defguard-ui/utils/isPresent'; import { useApp } from '../hooks/useApp'; import { useAuth } from '../hooks/useAuth'; -export const AppConfigProvider = ({ children }: PropsWithChildren) => { +export const AppInfoProvider = ({ children }: PropsWithChildren) => { const isAuthenticated = useAuth((s) => isPresent(s.user)); + const { data: appInfoResponse } = useQuery({ queryFn: api.app.info, queryKey: ['info'], @@ -24,22 +25,5 @@ export const AppConfigProvider = ({ children }: PropsWithChildren) => { } }, [appInfoResponse]); - const { data: settingsEssentials } = useQuery({ - queryFn: api.settings.getSettingsEssentials, - queryKey: ['settings-essentials'], - enabled: isAuthenticated, - refetchOnWindowFocus: true, - refetchOnReconnect: true, - refetchOnMount: true, - }); - - useEffect(() => { - if (isPresent(settingsEssentials)) { - useApp.setState({ - settingsEssentials: settingsEssentials.data, - }); - } - }, [settingsEssentials]); - return <>{children}; }; diff --git a/web/src/shared/providers/AppSettingsEssentialsProvider.tsx b/web/src/shared/providers/AppSettingsEssentialsProvider.tsx new file mode 100644 index 0000000000..a6dbae5bad --- /dev/null +++ b/web/src/shared/providers/AppSettingsEssentialsProvider.tsx @@ -0,0 +1,18 @@ +import { useQuery } from '@tanstack/react-query'; +import { type PropsWithChildren, useEffect } from 'react'; +import { useApp } from '../hooks/useApp'; +import { getSettingsEssentialsQueryOptions } from '../query'; + +export const AppSettingsEssentialsProvider = ({ children }: PropsWithChildren) => { + const { data: settingsEssentials } = useQuery(getSettingsEssentialsQueryOptions); + + useEffect(() => { + if (settingsEssentials) { + useApp.setState({ + settingsEssentials, + }); + } + }, [settingsEssentials]); + + return children; +}; diff --git a/web/src/shared/query.ts b/web/src/shared/query.ts index 68fa20f71e..bfbbd73220 100644 --- a/web/src/shared/query.ts +++ b/web/src/shared/query.ts @@ -170,12 +170,12 @@ export const getActivityLogStreamsQueryOptions = queryOptions({ }); export const getSettingsEssentialsQueryOptions = queryOptions({ - queryFn: () => api.settings.getSettingsEssentials, - queryKey: ['settings-essentials'], - throwOnError: false, + queryFn: api.settings.getSettingsEssentials, + queryKey: ['settings_essentials'], retry: false, refetchOnWindowFocus: false, refetchOnMount: true, refetchOnReconnect: true, staleTime: 60_000, + select: (resp) => resp.data, }); From 93cd6ee7abe870af986d4d5092efa82a4d80a7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 10:38:49 +0100 Subject: [PATCH 3/7] Update setup-wizard.tsx --- web/src/routes/_wizard/setup-wizard.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/routes/_wizard/setup-wizard.tsx b/web/src/routes/_wizard/setup-wizard.tsx index ab8796f7ab..21c3d25ac5 100644 --- a/web/src/routes/_wizard/setup-wizard.tsx +++ b/web/src/routes/_wizard/setup-wizard.tsx @@ -2,6 +2,7 @@ import type { QueryClient } from '@tanstack/react-query'; import { createFileRoute, type ParsedLocation, redirect } from '@tanstack/react-router'; import { SetupPage } from '../../pages/SetupPage/SetupPage'; import { useSetupWizardStore } from '../../pages/SetupPage/useSetupWizardStore'; +import { useApp } from '../../shared/hooks/useApp'; import { getSettingsEssentialsQueryOptions } from '../../shared/query'; const handleWizardRedirect = async ({ @@ -11,12 +12,11 @@ const handleWizardRedirect = async ({ location: ParsedLocation; client: QueryClient; }) => { - const settingsEssentials = ( - await ( - await client.ensureQueryData(getSettingsEssentialsQueryOptions) - )() - ).data; - + let settingsEssentials = useApp.getState().settingsEssentials; + if (!settingsEssentials) { + settingsEssentials = (await client.ensureQueryData(getSettingsEssentialsQueryOptions)) + .data; + } // Tries to access any route but setup is not completed const setupNotCompletedAnyAccess = !settingsEssentials.initial_setup_completed && From 406fd5159ccbc8e4c4b6a4206306a62c1bdd3030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 10:39:38 +0100 Subject: [PATCH 4/7] Update Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2a92b9e3d5..61f6aa7a21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ humantime = "2.1" # match version used by sqlx ipnetwork = "0.20" jsonwebkey = { version = "0.4", features = ["pkcs-convert"] } -jsonwebtoken = "9.3" +jsonwebtoken = "10.3" ldap3 = { version = "0.12", default-features = false, features = ["tls"] } lettre = { version = "0.11", features = ["tokio1-native-tls"] } matches = "0.1" From 1922263016db58b4a6c65c5bbe078069b4c6a6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 10:44:13 +0100 Subject: [PATCH 5/7] update-cargo-lock --- Cargo.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76b3c3d9fd..d307411afb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2758,16 +2758,17 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" dependencies = [ "base64 0.22.1", + "getrandom 0.2.17", "js-sys", "pem", - "ring", "serde", "serde_json", + "signature", "simple_asn1", ] @@ -3277,7 +3278,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d" dependencies = [ - "base64 0.22.1", + "base64 0.21.7", "chrono", "getrandom 0.2.17", "http", @@ -3823,7 +3824,7 @@ dependencies = [ "aes-gcm", "aes-kw", "argon2", - "base64 0.22.1", + "base64 0.21.7", "bitfields", "block-padding", "blowfish", From b1fb32de1294aa4dcf720c6086f1bb0f630622fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 10:45:21 +0100 Subject: [PATCH 6/7] Update useApp.tsx --- web/src/shared/hooks/useApp.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/src/shared/hooks/useApp.tsx b/web/src/shared/hooks/useApp.tsx index 8be265f222..247a6961b7 100644 --- a/web/src/shared/hooks/useApp.tsx +++ b/web/src/shared/hooks/useApp.tsx @@ -32,6 +32,7 @@ const defaults: StoreValues = { version: '', }, settingsEssentials: { + instance_name: '', initial_setup_completed: false, }, }; From c5b35d89867bf2db275dd9ce60c043e1c1b98dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 5 Feb 2026 11:05:24 +0100 Subject: [PATCH 7/7] add rust_crypto feature from jsonwebtoken crate --- Cargo.lock | 7 +++++++ Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index d307411afb..495325ccb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2763,11 +2763,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" dependencies = [ "base64 0.22.1", + "ed25519-dalek", "getrandom 0.2.17", + "hmac", "js-sys", + "p256", + "p384", "pem", + "rand 0.8.5", + "rsa", "serde", "serde_json", + "sha2", "signature", "simple_asn1", ] diff --git a/Cargo.toml b/Cargo.toml index 61f6aa7a21..a76bcd6b28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ humantime = "2.1" # match version used by sqlx ipnetwork = "0.20" jsonwebkey = { version = "0.4", features = ["pkcs-convert"] } -jsonwebtoken = "10.3" +jsonwebtoken = { version = "10.3", features = ["rust_crypto"] } ldap3 = { version = "0.12", default-features = false, features = ["tls"] } lettre = { version = "0.11", features = ["tokio1-native-tls"] } matches = "0.1"