Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot] cf7e03c9e0 Bump the npm-dependencies group across 1 directory with 74 updates
Bumps the npm-dependencies group with 74 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@asteasolutions/zod-to-openapi](https://github.com/asteasolutions/zod-to-openapi) | `8.5.0` | `9.1.0` |
| [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) | `3.1056.0` | `3.1121.0` |
| [@hookform/resolvers](https://github.com/react-hook-form/resolvers) | `5.4.0` | `5.9.1` |
| [@node-rs/argon2](https://github.com/napi-rs/node-rs) | `2.0.2` | `2.1.0` |
| [@radix-ui/react-avatar](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/avatar) | `1.1.11` | `1.2.6` |
| [@radix-ui/react-checkbox](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/checkbox) | `1.3.3` | `1.3.11` |
| [@radix-ui/react-collapsible](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/collapsible) | `1.1.12` | `1.1.20` |
| [@radix-ui/react-dialog](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/dialog) | `1.1.15` | `1.1.23` |
| [@radix-ui/react-dropdown-menu](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/dropdown-menu) | `2.1.16` | `2.1.24` |
| [@radix-ui/react-label](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/label) | `2.1.8` | `2.1.15` |
| [@radix-ui/react-popover](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/popover) | `1.1.15` | `1.1.23` |
| [@radix-ui/react-progress](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/progress) | `1.1.8` | `1.1.16` |
| [@radix-ui/react-radio-group](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/radio-group) | `1.3.8` | `1.4.7` |
| [@radix-ui/react-scroll-area](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/scroll-area) | `1.2.10` | `1.2.18` |
| [@radix-ui/react-select](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/select) | `2.2.6` | `2.3.7` |
| [@radix-ui/react-separator](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/separator) | `1.1.8` | `1.1.15` |
| [@radix-ui/react-slot](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/slot) | `1.2.4` | `1.3.3` |
| [@radix-ui/react-switch](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/switch) | `1.2.6` | `1.3.7` |
| [@radix-ui/react-tabs](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/tabs) | `1.1.13` | `1.1.21` |
| [@radix-ui/react-toast](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/toast) | `1.2.15` | `1.2.23` |
| [@radix-ui/react-tooltip](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/tooltip) | `1.2.8` | `1.2.16` |
| [@react-email/render](https://github.com/resend/react-email/tree/HEAD/packages/render) | `2.0.8` | `2.1.0` |
| [@simplewebauthn/server](https://github.com/MasterKale/SimpleWebAuthn/tree/HEAD/packages/server) | `13.3.1` | `13.3.3` |
| [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.100.14` | `5.102.8` |
| [@tanstack/react-table](https://github.com/TanStack/table/tree/HEAD/packages/react-table) | `8.21.3` | `9.2.4` |
| [axios](https://github.com/axios/axios) | `1.18.0` | `1.20.0` |
| [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit) | `8.5.2` | `8.7.0` |
| [gpt-tokenizer](https://github.com/niieani/gpt-tokenizer) | `3.4.0` | `4.0.0` |
| [helmet](https://github.com/helmetjs/helmet) | `8.2.0` | `8.3.0` |
| [input-otp](https://github.com/guilhermerodz/input-otp/tree/HEAD/packages/input-otp) | `1.4.2` | `1.5.0` |
| [ioredis](https://github.com/redis/ioredis) | `5.11.0` | `6.0.0` |
| [js-yaml](https://github.com/nodeca/js-yaml) | `4.3.1` | `5.4.1` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.17.0` | `1.35.0` |
| [maxmind](https://github.com/runk/node-maxmind) | `5.0.6` | `5.0.7` |
| [next](https://github.com/vercel/next.js) | `16.3.1` | `16.3.3` |
| [next-intl](https://github.com/amannn/next-intl) | `4.13.0` | `4.14.1` |
| [nodemailer](https://github.com/nodemailer/nodemailer) | `9.0.1` | `9.0.6` |
| [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) | `8.21.0` | `8.23.0` |
| [@types/pg](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/pg) | `8.20.0` | `8.23.1` |
| [posthog-node](https://github.com/PostHog/posthog-js/tree/HEAD/packages/node) | `5.35.6` | `5.51.4` |
| [react](https://github.com/react/react/tree/HEAD/packages/react) | `19.2.6` | `19.2.8` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.15` | `19.2.18` |
| [react-day-picker](https://github.com/gpbl/react-day-picker/tree/HEAD/packages/react-day-picker) | `9.14.0` | `10.0.1` |
| [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) | `19.2.6` | `19.2.8` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.3` | `19.2.5` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.76.1` | `7.86.0` |
| [react-icons](https://github.com/react-icons/react-icons) | `5.6.0` | `5.7.0` |
| [recharts](https://github.com/recharts/recharts) | `3.8.1` | `3.10.1` |
| [semver](https://github.com/npm/node-semver) | `7.8.1` | `7.8.5` |
| [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) | `7.7.1` | `7.8.0` |
| [stripe](https://github.com/stripe/stripe-node) | `22.2.0` | `22.6.0` |
| [uuid](https://github.com/uuidjs/uuid) | `14.0.0` | `14.0.2` |
| [ws](https://github.com/websockets/ws) | `8.21.0` | `8.21.3` |
| [yargs](https://github.com/yargs/yargs) | `18.0.0` | `18.1.0` |
| [zod](https://github.com/colinhacks/zod) | `4.4.3` | `4.5.2` |
| [@dotenvx/dotenvx](https://github.com/dotenvx/dotenvx) | `1.69.1` | `2.22.0` |
| [@react-email/ui](https://github.com/resend/react-email/tree/HEAD/packages/ui) | `6.9.2` | `6.9.3` |
| [@tailwindcss/postcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-postcss) | `4.3.0` | `4.3.3` |
| [@tanstack/react-query-devtools](https://github.com/TanStack/query/tree/HEAD/packages/react-query-devtools) | `5.100.14` | `5.102.8` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.9.1` | `26.4.0` |
| [@types/nodemailer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/nodemailer) | `8.0.0` | `8.0.1` |
| [@types/sshpk](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/sshpk) | `1.17.4` | `1.17.5` |
| [esbuild](https://github.com/evanw/esbuild) | `0.28.0` | `0.28.2` |
| [esbuild-node-externals](https://github.com/pradel/esbuild-node-externals) | `1.22.0` | `2.0.0` |
| [eslint](https://github.com/eslint/eslint) | `10.4.0` | `10.9.1` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `16.2.6` | `16.3.3` |
| [postcss](https://github.com/postcss/postcss) | `8.5.23` | `8.5.26` |
| [prettier](https://github.com/prettier/prettier) | `3.8.3` | `3.9.6` |
| [react-email](https://github.com/resend/react-email/tree/HEAD/packages/react-email) | `6.5.0` | `6.9.3` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.0` | `4.3.3` |
| [tsc-alias](https://github.com/justkey007/tsc-alias) | `1.8.17` | `1.9.2` |
| [tsx](https://github.com/privatenumber/tsx) | `4.22.3` | `4.23.12` |
| [typescript](https://github.com/microsoft/TypeScript) | `6.0.3` | `7.0.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.60.0` | `8.68.0` |



Updates `@asteasolutions/zod-to-openapi` from 8.5.0 to 9.1.0
- [Release notes](https://github.com/asteasolutions/zod-to-openapi/releases)
- [Commits](https://github.com/asteasolutions/zod-to-openapi/compare/v8.5.0...v9.1.0)

Updates `@aws-sdk/client-s3` from 3.1056.0 to 3.1121.0
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.1121.0/clients/client-s3)

Updates `@hookform/resolvers` from 5.4.0 to 5.9.1
- [Release notes](https://github.com/react-hook-form/resolvers/releases)
- [Commits](https://github.com/react-hook-form/resolvers/compare/v5.4.0...v5.9.1)

Updates `@node-rs/argon2` from 2.0.2 to 2.1.0
- [Release notes](https://github.com/napi-rs/node-rs/releases)
- [Commits](https://github.com/napi-rs/node-rs/compare/@node-rs/argon2@2.0.2...@node-rs/argon2@2.1.0)

Updates `@radix-ui/react-avatar` from 1.1.11 to 1.2.6
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/avatar/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/avatar)

Updates `@radix-ui/react-checkbox` from 1.3.3 to 1.3.11
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/checkbox/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/checkbox)

Updates `@radix-ui/react-collapsible` from 1.1.12 to 1.1.20
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/collapsible/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/collapsible)

Updates `@radix-ui/react-dialog` from 1.1.15 to 1.1.23
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/dialog/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/dialog)

Updates `@radix-ui/react-dropdown-menu` from 2.1.16 to 2.1.24
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/dropdown-menu/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/dropdown-menu)

Updates `@radix-ui/react-label` from 2.1.8 to 2.1.15
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/label/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/label)

Updates `@radix-ui/react-popover` from 1.1.15 to 1.1.23
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/popover/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/popover)

Updates `@radix-ui/react-progress` from 1.1.8 to 1.1.16
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/progress/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/progress)

Updates `@radix-ui/react-radio-group` from 1.3.8 to 1.4.7
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/radio-group/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/radio-group)

Updates `@radix-ui/react-scroll-area` from 1.2.10 to 1.2.18
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/scroll-area/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/scroll-area)

Updates `@radix-ui/react-select` from 2.2.6 to 2.3.7
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/select/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/select)

Updates `@radix-ui/react-separator` from 1.1.8 to 1.1.15
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/separator/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/separator)

Updates `@radix-ui/react-slot` from 1.2.4 to 1.3.3
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/slot/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/slot)

Updates `@radix-ui/react-switch` from 1.2.6 to 1.3.7
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/switch/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/switch)

Updates `@radix-ui/react-tabs` from 1.1.13 to 1.1.21
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/tabs/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/tabs)

Updates `@radix-ui/react-toast` from 1.2.15 to 1.2.23
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/toast/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/toast)

Updates `@radix-ui/react-tooltip` from 1.2.8 to 1.2.16
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/tooltip/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/tooltip)

Updates `@react-email/render` from 2.0.8 to 2.1.0
- [Release notes](https://github.com/resend/react-email/releases)
- [Changelog](https://github.com/resend/react-email/blob/canary/packages/render/CHANGELOG.md)
- [Commits](https://github.com/resend/react-email/commits/@react-email/render@2.1.0/packages/render)

Updates `@simplewebauthn/server` from 13.3.1 to 13.3.3
- [Release notes](https://github.com/MasterKale/SimpleWebAuthn/releases)
- [Changelog](https://github.com/MasterKale/SimpleWebAuthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/MasterKale/SimpleWebAuthn/commits/v13.3.3/packages/server)

Updates `@tanstack/react-query` from 5.100.14 to 5.102.8
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.102.8/packages/react-query)

Updates `@tanstack/react-table` from 8.21.3 to 9.2.4
- [Release notes](https://github.com/TanStack/table/releases)
- [Changelog](https://github.com/TanStack/table/blob/main/packages/react-table/CHANGELOG.md)
- [Commits](https://github.com/TanStack/table/commits/@tanstack/react-table@9.2.4/packages/react-table)

Updates `axios` from 1.18.0 to 1.20.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.18.0...v1.20.0)

Updates `express-rate-limit` from 8.5.2 to 8.7.0
- [Release notes](https://github.com/express-rate-limit/express-rate-limit/releases)
- [Commits](https://github.com/express-rate-limit/express-rate-limit/compare/v8.5.2...v8.7.0)

Updates `gpt-tokenizer` from 3.4.0 to 4.0.0
- [Release notes](https://github.com/niieani/gpt-tokenizer/releases)
- [Commits](https://github.com/niieani/gpt-tokenizer/compare/3.4.0...4.0.0)

Updates `helmet` from 8.2.0 to 8.3.0
- [Changelog](https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/helmetjs/helmet/compare/v8.2.0...v8.3.0)

Updates `input-otp` from 1.4.2 to 1.5.0
- [Release notes](https://github.com/guilhermerodz/input-otp/releases)
- [Changelog](https://github.com/guilhermerodz/input-otp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/guilhermerodz/input-otp/commits/v1.5.0/packages/input-otp)

Updates `ioredis` from 5.11.0 to 6.0.0
- [Release notes](https://github.com/redis/ioredis/releases)
- [Changelog](https://github.com/redis/ioredis/blob/main/CHANGELOG.md)
- [Commits](https://github.com/redis/ioredis/compare/v5.11.0...v6.0.0)

Updates `js-yaml` from 4.3.1 to 5.4.1
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.3.1...5.4.1)

Updates `lucide-react` from 1.17.0 to 1.35.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.35.0/packages/lucide-react)

Updates `maxmind` from 5.0.6 to 5.0.7
- [Release notes](https://github.com/runk/node-maxmind/releases)
- [Commits](https://github.com/runk/node-maxmind/compare/v5.0.6...v5.0.7)

Updates `next` from 16.3.1 to 16.3.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/compare/v16.3.1...v16.3.3)

Updates `next-intl` from 4.13.0 to 4.14.1
- [Release notes](https://github.com/amannn/next-intl/releases)
- [Changelog](https://github.com/amannn/next-intl/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amannn/next-intl/compare/v4.13.0...v4.14.1)

Updates `nodemailer` from 9.0.1 to 9.0.6
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v9.0.1...v9.0.6)

Updates `pg` from 8.21.0 to 8.23.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.23.0/packages/pg)

Updates `@types/pg` from 8.20.0 to 8.23.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/pg)

Updates `posthog-node` from 5.35.6 to 5.51.4
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/main/packages/node/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/commits/posthog-node@5.51.4/packages/node)

Updates `react` from 19.2.6 to 19.2.8
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.2.8/packages/react)

Updates `@types/react` from 19.2.15 to 19.2.18
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `react-day-picker` from 9.14.0 to 10.0.1
- [Release notes](https://github.com/gpbl/react-day-picker/releases)
- [Changelog](https://github.com/gpbl/react-day-picker/blob/main/packages/react-day-picker/CHANGELOG.md)
- [Commits](https://github.com/gpbl/react-day-picker/commits/v10.0.1/packages/react-day-picker)

Updates `react-dom` from 19.2.6 to 19.2.8
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.2.8/packages/react-dom)

Updates `@types/react-dom` from 19.2.3 to 19.2.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `react-hook-form` from 7.76.1 to 7.86.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.76.1...v7.86.0)

Updates `react-icons` from 5.6.0 to 5.7.0
- [Release notes](https://github.com/react-icons/react-icons/releases)
- [Commits](https://github.com/react-icons/react-icons/compare/v5.6.0...v5.7.0)

Updates `recharts` from 3.8.1 to 3.10.1
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.8.1...v3.10.1)

Updates `semver` from 7.8.1 to 7.8.5
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.8.1...v7.8.5)

Updates `@types/semver` from 7.7.1 to 7.8.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Updates `stripe` from 22.2.0 to 22.6.0
- [Release notes](https://github.com/stripe/stripe-node/releases)
- [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-node/compare/v22.2.0...v22.6.0)

Updates `uuid` from 14.0.0 to 14.0.2
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v14.0.0...v14.0.2)

Updates `ws` from 8.21.0 to 8.21.3
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.21.0...8.21.3)

Updates `yargs` from 18.0.0 to 18.1.0
- [Release notes](https://github.com/yargs/yargs/releases)
- [Changelog](https://github.com/yargs/yargs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/yargs/yargs/compare/v18.0.0...v18.1.0)

Updates `zod` from 4.4.3 to 4.5.2
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v4.4.3...v4.5.2)

Updates `@dotenvx/dotenvx` from 1.69.1 to 2.22.0
- [Release notes](https://github.com/dotenvx/dotenvx/releases)
- [Changelog](https://github.com/dotenvx/dotenvx/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dotenvx/dotenvx/compare/v1.69.1...v2.22.0)

Updates `@react-email/ui` from 6.9.2 to 6.9.3
- [Release notes](https://github.com/resend/react-email/releases)
- [Changelog](https://github.com/resend/react-email/blob/canary/packages/ui/CHANGELOG.md)
- [Commits](https://github.com/resend/react-email/commits/@react-email/ui@6.9.3/packages/ui)

Updates `@tailwindcss/postcss` from 4.3.0 to 4.3.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/@tailwindcss-postcss)

Updates `@tanstack/react-query-devtools` from 5.100.14 to 5.102.8
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-devtools@5.102.8/packages/react-query-devtools)

Updates `@types/node` from 25.9.1 to 26.4.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/nodemailer` from 8.0.0 to 8.0.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/nodemailer)

Updates `@types/pg` from 8.20.0 to 8.23.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/pg)

Updates `@types/react` from 19.2.15 to 19.2.18
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 19.2.3 to 19.2.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `@types/semver` from 7.7.1 to 7.8.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Updates `@types/sshpk` from 1.17.4 to 1.17.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/sshpk)

Updates `esbuild` from 0.28.0 to 0.28.2
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.28.0...v0.28.2)

Updates `esbuild-node-externals` from 1.22.0 to 2.0.0
- [Release notes](https://github.com/pradel/esbuild-node-externals/releases)
- [Commits](https://github.com/pradel/esbuild-node-externals/compare/esbuild-node-externals-v1.22.0...esbuild-node-externals-v2.0.0)

Updates `eslint` from 10.4.0 to 10.9.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.4.0...v10.9.1)

Updates `eslint-config-next` from 16.2.6 to 16.3.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Commits](https://github.com/vercel/next.js/commits/v16.3.3/packages/eslint-config-next)

Updates `postcss` from 8.5.23 to 8.5.26
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.23...8.5.26)

Updates `prettier` from 3.8.3 to 3.9.6
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.3...3.9.6)

Updates `react-email` from 6.5.0 to 6.9.3
- [Release notes](https://github.com/resend/react-email/releases)
- [Changelog](https://github.com/resend/react-email/blob/canary/packages/react-email/CHANGELOG.md)
- [Commits](https://github.com/resend/react-email/commits/react-email@6.9.3/packages/react-email)

Updates `tailwindcss` from 4.3.0 to 4.3.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/tailwindcss)

Updates `tsc-alias` from 1.8.17 to 1.9.2
- [Release notes](https://github.com/justkey007/tsc-alias/releases)
- [Commits](https://github.com/justkey007/tsc-alias/compare/v1.8.17...v1.9.2)

Updates `tsx` from 4.22.3 to 4.23.12
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.22.3...v4.23.12)

Updates `typescript` from 6.0.3 to 7.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.3...v7.0.2)

Updates `typescript-eslint` from 8.60.0 to 8.68.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.68.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@asteasolutions/zod-to-openapi"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: "@aws-sdk/client-s3"
  dependency-version: 3.1121.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@hookform/resolvers"
  dependency-version: 5.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@node-rs/argon2"
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-avatar"
  dependency-version: 1.2.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-checkbox"
  dependency-version: 1.3.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-collapsible"
  dependency-version: 1.1.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-dialog"
  dependency-version: 1.1.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-dropdown-menu"
  dependency-version: 2.1.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-label"
  dependency-version: 2.1.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-popover"
  dependency-version: 1.1.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-progress"
  dependency-version: 1.1.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-radio-group"
  dependency-version: 1.4.7
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-scroll-area"
  dependency-version: 1.2.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-select"
  dependency-version: 2.3.7
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-separator"
  dependency-version: 1.1.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-slot"
  dependency-version: 1.3.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-switch"
  dependency-version: 1.3.7
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-tabs"
  dependency-version: 1.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-toast"
  dependency-version: 1.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@radix-ui/react-tooltip"
  dependency-version: 1.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@react-email/render"
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@simplewebauthn/server"
  dependency-version: 13.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.102.8
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@tanstack/react-table"
  dependency-version: 9.2.4
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: axios
  dependency-version: 1.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: express-rate-limit
  dependency-version: 8.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: gpt-tokenizer
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: helmet
  dependency-version: 8.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: input-otp
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: ioredis
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: js-yaml
  dependency-version: 5.4.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: lucide-react
  dependency-version: 1.35.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: maxmind
  dependency-version: 5.0.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: next
  dependency-version: 16.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: next-intl
  dependency-version: 4.14.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: nodemailer
  dependency-version: 9.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: pg
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@types/pg"
  dependency-version: 8.23.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: posthog-node
  dependency-version: 5.51.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: react
  dependency-version: 19.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@types/react"
  dependency-version: 19.2.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: react-day-picker
  dependency-version: 10.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: react-dom
  dependency-version: 19.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@types/react-dom"
  dependency-version: 19.2.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: react-hook-form
  dependency-version: 7.86.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: react-icons
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: recharts
  dependency-version: 3.10.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: semver
  dependency-version: 7.8.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@types/semver"
  dependency-version: 7.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: stripe
  dependency-version: 22.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: uuid
  dependency-version: 14.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: ws
  dependency-version: 8.21.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: yargs
  dependency-version: 18.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: zod
  dependency-version: 4.5.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@dotenvx/dotenvx"
  dependency-version: 2.22.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: "@react-email/ui"
  dependency-version: 6.9.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@tailwindcss/postcss"
  dependency-version: 4.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@tanstack/react-query-devtools"
  dependency-version: 5.102.8
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@types/node"
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: "@types/nodemailer"
  dependency-version: 8.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@types/pg"
  dependency-version: 8.23.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@types/react"
  dependency-version: 19.2.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@types/react-dom"
  dependency-version: 19.2.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: "@types/semver"
  dependency-version: 7.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: "@types/sshpk"
  dependency-version: 1.17.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: esbuild
  dependency-version: 0.28.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: esbuild-node-externals
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: eslint
  dependency-version: 10.9.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: eslint-config-next
  dependency-version: 16.3.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: postcss
  dependency-version: 8.5.26
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: prettier
  dependency-version: 3.9.6
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: react-email
  dependency-version: 6.9.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: tailwindcss
  dependency-version: 4.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: tsc-alias
  dependency-version: 1.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: tsx
  dependency-version: 4.23.12
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
- dependency-name: typescript
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
- dependency-name: typescript-eslint
  dependency-version: 8.68.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-01 01:46:12 +00:00
22 changed files with 2346 additions and 3981 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ experimental:
version: "{{.BadgerVersion}}" version: "{{.BadgerVersion}}"
crowdsec: # CrowdSec plugin configuration added crowdsec: # CrowdSec plugin configuration added
moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
version: "v1.7.1" version: "v1.4.4"
log: log:
level: "INFO" level: "INFO"
+1 -8
View File
@@ -1176,10 +1176,6 @@
"idpJmespathAboutDescriptionLink": "Learn more about JMESPath", "idpJmespathAboutDescriptionLink": "Learn more about JMESPath",
"idpJmespathLabel": "Identifier Path", "idpJmespathLabel": "Identifier Path",
"idpJmespathLabelDescription": "The path to the user identifier in the ID token", "idpJmespathLabelDescription": "The path to the user identifier in the ID token",
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
"idpIdentifierChangeConfirmMessage": "I confirm",
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
"idpJmespathEmailPathOptional": "Email Path (Optional)", "idpJmespathEmailPathOptional": "Email Path (Optional)",
"idpJmespathEmailPathOptionalDescription": "The path to the user's email in the ID token", "idpJmespathEmailPathOptionalDescription": "The path to the user's email in the ID token",
"idpJmespathNamePathOptional": "Name Path (Optional)", "idpJmespathNamePathOptional": "Name Path (Optional)",
@@ -1577,8 +1573,6 @@
"search": "Search…", "search": "Search…",
"searchPlaceholder": "Search...", "searchPlaceholder": "Search...",
"emptySearchOptions": "No options found", "emptySearchOptions": "No options found",
"ipFilterSearchPlaceholder": "Enter an IP address…",
"ipFilterEmptyMessage": "Enter an IP address to filter by",
"create": "Create", "create": "Create",
"orgs": "Organizations", "orgs": "Organizations",
"loginError": "An unexpected error occurred. Please try again.", "loginError": "An unexpected error occurred. Please try again.",
@@ -2602,7 +2596,6 @@
"createDomainType": "Type:", "createDomainType": "Type:",
"createDomainName": "Name:", "createDomainName": "Name:",
"createDomainValue": "Value:", "createDomainValue": "Value:",
"multiSelectFilterCount": "{count} selected",
"createDomainCnameRecords": "CNAME Records", "createDomainCnameRecords": "CNAME Records",
"createDomainARecords": "A Records", "createDomainARecords": "A Records",
"createDomainRecordNumber": "Record {number}", "createDomainRecordNumber": "Record {number}",
@@ -3000,7 +2993,7 @@
"remoteExitNodeNetworkingSubnetsPlaceholder": "Add a CIDR range (e.g. 10.0.0.0/8)", "remoteExitNodeNetworkingSubnetsPlaceholder": "Add a CIDR range (e.g. 10.0.0.0/8)",
"remoteExitNodeNetworkingSubnetsLoadError": "Failed to load subnets", "remoteExitNodeNetworkingSubnetsLoadError": "Failed to load subnets",
"remoteExitNodeNetworkingLabelsTitle": "Preference Labels", "remoteExitNodeNetworkingLabelsTitle": "Preference Labels",
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.", "remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will be enforced to connect through this remote exit node.",
"remoteExitNodeNetworkingLabelsButtonText": "Select labels...", "remoteExitNodeNetworkingLabelsButtonText": "Select labels...",
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Search labels...", "remoteExitNodeNetworkingLabelsSearchPlaceholder": "Search labels...",
"remoteExitNodeNetworkingLabelsLoadError": "Failed to load labels", "remoteExitNodeNetworkingLabelsLoadError": "Failed to load labels",
+2052 -3386
View File
File diff suppressed because it is too large Load Diff
+76 -76
View File
@@ -32,49 +32,49 @@
"format": "prettier --write ." "format": "prettier --write ."
}, },
"dependencies": { "dependencies": {
"@asteasolutions/zod-to-openapi": "8.5.0", "@asteasolutions/zod-to-openapi": "9.1.0",
"@aws-sdk/client-s3": "3.1056.0", "@aws-sdk/client-s3": "3.1121.0",
"@devolutions/iron-remote-desktop": "https://static.pangolin.net/packages/devolutions-iron-remote-desktop-0.0.0.tgz", "@devolutions/iron-remote-desktop": "https://static.pangolin.net/packages/devolutions-iron-remote-desktop-0.0.0.tgz",
"@devolutions/iron-remote-desktop-rdp": "https://static.pangolin.net/packages/devolutions-iron-remote-desktop-rdp-0.0.1.tgz", "@devolutions/iron-remote-desktop-rdp": "https://static.pangolin.net/packages/devolutions-iron-remote-desktop-rdp-0.0.1.tgz",
"@headlessui/react": "2.2.10", "@headlessui/react": "2.2.10",
"@hookform/resolvers": "5.4.0", "@hookform/resolvers": "5.9.1",
"@monaco-editor/react": "4.7.0", "@monaco-editor/react": "4.7.0",
"@node-rs/argon2": "2.0.2", "@node-rs/argon2": "2.1.0",
"@novnc/novnc": "^1.7.0", "@novnc/novnc": "^1.7.0",
"@oslojs/crypto": "1.0.1", "@oslojs/crypto": "1.0.1",
"@oslojs/encoding": "1.1.0", "@oslojs/encoding": "1.1.0",
"@radix-ui/react-avatar": "1.1.11", "@radix-ui/react-avatar": "1.2.6",
"@radix-ui/react-checkbox": "1.3.3", "@radix-ui/react-checkbox": "1.3.11",
"@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collapsible": "1.1.20",
"@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-dialog": "1.1.23",
"@radix-ui/react-dropdown-menu": "2.1.16", "@radix-ui/react-dropdown-menu": "2.1.24",
"@radix-ui/react-icons": "1.3.2", "@radix-ui/react-icons": "1.3.2",
"@radix-ui/react-label": "2.1.8", "@radix-ui/react-label": "2.1.15",
"@radix-ui/react-popover": "1.1.15", "@radix-ui/react-popover": "1.1.23",
"@radix-ui/react-progress": "1.1.8", "@radix-ui/react-progress": "1.1.16",
"@radix-ui/react-radio-group": "1.3.8", "@radix-ui/react-radio-group": "1.4.7",
"@radix-ui/react-scroll-area": "1.2.10", "@radix-ui/react-scroll-area": "1.2.18",
"@radix-ui/react-select": "2.2.6", "@radix-ui/react-select": "2.3.7",
"@radix-ui/react-separator": "1.1.8", "@radix-ui/react-separator": "1.1.15",
"@radix-ui/react-slot": "1.2.4", "@radix-ui/react-slot": "1.3.3",
"@radix-ui/react-switch": "1.2.6", "@radix-ui/react-switch": "1.3.7",
"@radix-ui/react-tabs": "1.1.13", "@radix-ui/react-tabs": "1.1.21",
"@radix-ui/react-toast": "1.2.15", "@radix-ui/react-toast": "1.2.23",
"@radix-ui/react-tooltip": "1.2.8", "@radix-ui/react-tooltip": "1.2.16",
"@react-email/body": "0.3.0", "@react-email/body": "0.3.0",
"@react-email/components": "1.0.12", "@react-email/components": "1.0.12",
"@react-email/render": "2.0.8", "@react-email/render": "2.1.0",
"@react-email/tailwind": "2.0.7", "@react-email/tailwind": "2.0.7",
"@simplewebauthn/browser": "13.3.0", "@simplewebauthn/browser": "13.3.0",
"@simplewebauthn/server": "13.3.1", "@simplewebauthn/server": "13.3.3",
"@tailwindcss/forms": "0.5.11", "@tailwindcss/forms": "0.5.11",
"@tanstack/react-query": "5.100.14", "@tanstack/react-query": "5.102.8",
"@tanstack/react-table": "8.21.3", "@tanstack/react-table": "9.2.4",
"@xterm/addon-fit": "^0.11.0", "@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0", "@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0", "@xterm/xterm": "^6.0.0",
"arctic": "3.7.0", "arctic": "3.7.0",
"axios": "1.18.0", "axios": "1.20.0",
"better-sqlite3": "11.9.1", "better-sqlite3": "11.9.1",
"canvas-confetti": "1.9.4", "canvas-confetti": "1.9.4",
"class-variance-authority": "0.7.1", "class-variance-authority": "0.7.1",
@@ -86,62 +86,62 @@
"d3": "7.9.0", "d3": "7.9.0",
"drizzle-orm": "0.45.2", "drizzle-orm": "0.45.2",
"express": "5.2.1", "express": "5.2.1",
"express-rate-limit": "8.5.2", "express-rate-limit": "8.7.0",
"glob": "13.0.6", "glob": "13.0.6",
"gpt-tokenizer": "^3.4.0", "gpt-tokenizer": "^4.0.0",
"helmet": "8.2.0", "helmet": "8.3.0",
"http-errors": "2.0.1", "http-errors": "2.0.1",
"input-otp": "1.4.2", "input-otp": "1.5.0",
"ioredis": "5.11.0", "ioredis": "6.0.0",
"jmespath": "0.16.0", "jmespath": "0.16.0",
"js-yaml": "4.3.1", "js-yaml": "5.4.1",
"jsonwebtoken": "9.0.3", "jsonwebtoken": "9.0.3",
"lucide-react": "1.17.0", "lucide-react": "1.35.0",
"maxmind": "5.0.6", "maxmind": "5.0.7",
"moment": "2.30.1", "moment": "2.30.1",
"next": "16.3.1", "next": "16.3.3",
"next-intl": "4.13.0", "next-intl": "4.14.1",
"next-themes": "0.4.6", "next-themes": "0.4.6",
"nextjs-toploader": "3.9.17", "nextjs-toploader": "3.9.17",
"node-cache": "5.1.2", "node-cache": "5.1.2",
"nodemailer": "9.0.1", "nodemailer": "9.0.6",
"oslo": "1.2.1", "oslo": "1.2.1",
"pg": "8.21.0", "pg": "8.23.0",
"posthog-node": "5.35.6", "posthog-node": "5.51.4",
"qrcode.react": "4.2.0", "qrcode.react": "4.2.0",
"react": "19.2.6", "react": "19.2.8",
"react-day-picker": "9.14.0", "react-day-picker": "10.0.1",
"react-dom": "19.2.6", "react-dom": "19.2.8",
"react-easy-sort": "1.8.0", "react-easy-sort": "1.8.0",
"react-hook-form": "7.76.1", "react-hook-form": "7.86.0",
"react-icons": "5.6.0", "react-icons": "5.7.0",
"recharts": "3.8.1", "recharts": "3.10.1",
"reodotdev": "1.1.0", "reodotdev": "1.1.0",
"semver": "7.8.1", "semver": "7.8.5",
"sshpk": "1.18.0", "sshpk": "1.18.0",
"stripe": "22.2.0", "stripe": "22.6.0",
"swagger-ui-express": "5.0.1", "swagger-ui-express": "5.0.1",
"tailwind-merge": "3.6.0", "tailwind-merge": "3.6.0",
"topojson-client": "3.1.0", "topojson-client": "3.1.0",
"tw-animate-css": "1.4.0", "tw-animate-css": "1.4.0",
"use-debounce": "10.1.1", "use-debounce": "10.1.1",
"uuid": "14.0.0", "uuid": "14.0.2",
"vaul": "1.1.2", "vaul": "1.1.2",
"visionscarto-world-atlas": "1.0.0", "visionscarto-world-atlas": "1.0.0",
"winston": "3.19.0", "winston": "3.19.0",
"winston-daily-rotate-file": "5.0.0", "winston-daily-rotate-file": "5.0.0",
"ws": "8.21.0", "ws": "8.21.3",
"yaml": "2.9.0", "yaml": "2.9.0",
"yargs": "18.0.0", "yargs": "18.1.0",
"zod": "4.4.3", "zod": "4.5.2",
"zod-validation-error": "5.0.0" "zod-validation-error": "5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@dotenvx/dotenvx": "1.69.1", "@dotenvx/dotenvx": "2.22.0",
"@esbuild-plugins/tsconfig-paths": "0.1.2", "@esbuild-plugins/tsconfig-paths": "0.1.2",
"@react-email/ui": "^6.9.2", "@react-email/ui": "^6.9.3",
"@tailwindcss/postcss": "4.3.0", "@tailwindcss/postcss": "4.3.3",
"@tanstack/react-query-devtools": "5.100.14", "@tanstack/react-query-devtools": "5.102.8",
"@types/better-sqlite3": "7.6.13", "@types/better-sqlite3": "7.6.13",
"@types/cookie-parser": "1.4.10", "@types/cookie-parser": "1.4.10",
"@types/cors": "2.8.19", "@types/cors": "2.8.19",
@@ -152,36 +152,36 @@
"@types/jmespath": "0.15.2", "@types/jmespath": "0.15.2",
"@types/js-yaml": "4.0.9", "@types/js-yaml": "4.0.9",
"@types/jsonwebtoken": "9.0.10", "@types/jsonwebtoken": "9.0.10",
"@types/node": "25.9.1", "@types/node": "26.4.0",
"@types/nodemailer": "8.0.0", "@types/nodemailer": "8.0.1",
"@types/nprogress": "0.2.3", "@types/nprogress": "0.2.3",
"@types/pg": "8.20.0", "@types/pg": "8.23.1",
"@types/react": "19.2.15", "@types/react": "19.2.18",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.5",
"@types/semver": "7.7.1", "@types/semver": "7.8.0",
"@types/sshpk": "1.17.4", "@types/sshpk": "1.17.5",
"@types/swagger-ui-express": "4.1.8", "@types/swagger-ui-express": "4.1.8",
"@types/topojson-client": "3.1.5", "@types/topojson-client": "3.1.5",
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
"@types/yargs": "17.0.35", "@types/yargs": "17.0.35",
"babel-plugin-react-compiler": "1.0.0", "babel-plugin-react-compiler": "1.0.0",
"drizzle-kit": "0.31.10", "drizzle-kit": "0.31.10",
"esbuild": "0.28.0", "esbuild": "0.28.2",
"esbuild-node-externals": "1.22.0", "esbuild-node-externals": "2.0.0",
"eslint": "10.4.0", "eslint": "10.9.1",
"eslint-config-next": "16.2.6", "eslint-config-next": "16.3.3",
"postcss": "8.5.23", "postcss": "8.5.26",
"prettier": "3.8.3", "prettier": "3.9.6",
"react-email": "6.5.0", "react-email": "6.9.3",
"tailwindcss": "4.3.0", "tailwindcss": "4.3.3",
"tsc-alias": "1.8.17", "tsc-alias": "1.9.2",
"tsx": "4.22.3", "tsx": "4.23.12",
"typescript": "6.0.3", "typescript": "7.0.2",
"typescript-eslint": "8.60.0" "typescript-eslint": "8.68.0"
}, },
"overrides": { "overrides": {
"esbuild": "0.28.0", "esbuild": "0.28.2",
"dompurify": "3.4.0", "dompurify": "3.4.0",
"postcss": "8.5.23" "postcss": "8.5.26"
} }
} }
-38
View File
@@ -1,38 +0,0 @@
import { and, asc, eq, or } from "drizzle-orm";
import { Transaction, User, userOrgs, users } from "@server/db";
export async function findOrgUserByIdentifier(
trx: Transaction,
orgId: string,
identifier: string
): Promise<User | null> {
const [match] = await trx
.select()
.from(users)
.innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(eq(users.username, identifier), eq(users.email, identifier)),
eq(userOrgs.orgId, orgId)
)
)
.orderBy(asc(users.dateCreated), asc(users.userId))
.limit(1);
return match?.user ?? null;
}
export async function resolveOrgUserIds(
trx: Transaction,
orgId: string,
identifiers: string[]
): Promise<string[]> {
const userIds = new Set<string>();
for (const identifier of identifiers) {
const user = await findOrgUserByIdentifier(trx, orgId, identifier);
if (user) {
userIds.add(user.userId);
}
}
return [...userIds];
}
+45 -32
View File
@@ -11,14 +11,15 @@ import {
siteNetworks, siteNetworks,
siteResources, siteResources,
Transaction, Transaction,
userOrgs,
users,
userSiteResources, userSiteResources,
networks networks
} from "@server/db"; } from "@server/db";
import { sites } from "@server/db"; import { sites } from "@server/db";
import { eq, and, ne, inArray, isNotNull } from "drizzle-orm"; import { eq, and, ne, inArray, or, isNotNull } from "drizzle-orm";
import { Config } from "./types"; import { Config } from "./types";
import { getOrCreateLabelIds, syncSiteResourceLabels } from "./labels"; import { getOrCreateLabelIds, syncSiteResourceLabels } from "./labels";
import { resolveOrgUserIds } from "./findOrgUser";
import logger from "@server/logger"; import logger from "@server/logger";
import { defaultRoleAllowedActions } from "@server/routers/role/createRole"; import { defaultRoleAllowedActions } from "@server/routers/role/createRole";
import { getNextAvailableAliasAddress } from "../ip"; import { getNextAvailableAliasAddress } from "../ip";
@@ -388,22 +389,28 @@ export async function updatePrivateResources(
.where(eq(userSiteResources.siteResourceId, siteResourceId)); .where(eq(userSiteResources.siteResourceId, siteResourceId));
if (resourceData.users.length > 0) { if (resourceData.users.length > 0) {
const userIds = await resolveOrgUserIds( // get userIds from username
trx, const usersToUpdate = await trx
orgId, .select()
resourceData.users .from(users)
); .innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(
inArray(users.username, resourceData.users),
inArray(users.email, resourceData.users)
),
eq(userOrgs.orgId, orgId)
)
);
if (userIds.length > 0) { const userIds = usersToUpdate.map((user) => user.user.userId);
await trx
.insert(userSiteResources) await trx
.values( .insert(userSiteResources)
userIds.map((userId) => ({ .values(
userId, userIds.map((userId) => ({ userId, siteResourceId }))
siteResourceId );
}))
);
}
} }
// Get all admin role IDs for this org to exclude from deletion // Get all admin role IDs for this org to exclude from deletion
@@ -714,22 +721,28 @@ export async function updatePrivateResources(
} }
if (resourceData.users.length > 0) { if (resourceData.users.length > 0) {
const userIds = await resolveOrgUserIds( // get userIds from username
trx, const usersToUpdate = await trx
orgId, .select()
resourceData.users .from(users)
); .innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(
inArray(users.username, resourceData.users),
inArray(users.email, resourceData.users)
),
eq(userOrgs.orgId, orgId)
)
);
if (userIds.length > 0) { const userIds = usersToUpdate.map((user) => user.user.userId);
await trx
.insert(userSiteResources) await trx
.values( .insert(userSiteResources)
userIds.map((userId) => ({ .values(
userId, userIds.map((userId) => ({ userId, siteResourceId }))
siteResourceId );
}))
);
}
} }
if (resourceData.machines.length > 0) { if (resourceData.machines.length > 0) {
+27 -8
View File
@@ -46,12 +46,11 @@ import { encrypt } from "@server/lib/crypto";
import logger from "@server/logger"; import logger from "@server/logger";
import { defaultRoleAllowedActions } from "@server/routers/role/createRole"; import { defaultRoleAllowedActions } from "@server/routers/role/createRole";
import { pickPort } from "@server/routers/target/helpers"; import { pickPort } from "@server/routers/target/helpers";
import { and, asc, eq, isNotNull, ne } from "drizzle-orm"; import { and, asc, eq, isNotNull, ne, or } from "drizzle-orm";
import { tierMatrix } from "../billing/tierMatrix"; import { tierMatrix } from "../billing/tierMatrix";
import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators"; import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators";
import { Config, isTargetsOnlyResource, TargetData } from "./types"; import { Config, isTargetsOnlyResource, TargetData } from "./types";
import { getOrCreateLabelIds, syncResourceLabels } from "./labels"; import { getOrCreateLabelIds, syncResourceLabels } from "./labels";
import { findOrgUserByIdentifier } from "./findOrgUser";
import { LimitId } from "../billing"; import { LimitId } from "../billing";
import { usageService } from "../billing/usageService"; import { usageService } from "../billing/usageService";
import { syncInferenceAiConfig } from "./aiProviders"; import { syncInferenceAiConfig } from "./aiProviders";
@@ -1564,19 +1563,29 @@ async function syncUserResources(
.where(eq(userResources.resourceId, resourceId)); .where(eq(userResources.resourceId, resourceId));
for (const username of ssoUsers) { for (const username of ssoUsers) {
const user = await findOrgUserByIdentifier(trx, orgId, username); const [user] = await trx
.select()
.from(users)
.innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(eq(users.username, username), eq(users.email, username)),
eq(userOrgs.orgId, orgId)
)
)
.limit(1);
if (!user) { if (!user) {
throw new Error(`User not found: ${username} in org ${orgId}`); throw new Error(`User not found: ${username} in org ${orgId}`);
} }
const existingUserResource = existingUserResources.find( const existingUserResource = existingUserResources.find(
(rr) => rr.userId === user.userId (rr) => rr.userId === user.user.userId
); );
if (!existingUserResource) { if (!existingUserResource) {
await trx.insert(userResources).values({ await trx.insert(userResources).values({
userId: user.userId, userId: user.user.userId,
resourceId: resourceId resourceId: resourceId
}); });
} }
@@ -1946,19 +1955,29 @@ async function syncUserPolicies(
.where(eq(userPolicies.resourcePolicyId, policyId)); .where(eq(userPolicies.resourcePolicyId, policyId));
for (const username of ssoUsers) { for (const username of ssoUsers) {
const user = await findOrgUserByIdentifier(trx, orgId, username); const [user] = await trx
.select()
.from(users)
.innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(eq(users.username, username), eq(users.email, username)),
eq(userOrgs.orgId, orgId)
)
)
.limit(1);
if (!user) { if (!user) {
throw new Error(`User not found: ${username} in org ${orgId}`); throw new Error(`User not found: ${username} in org ${orgId}`);
} }
const existingUserPolicy = existingUserPoliciesList.find( const existingUserPolicy = existingUserPoliciesList.find(
(up) => up.userId === user.userId (up) => up.userId === user.user.userId
); );
if (!existingUserPolicy) { if (!existingUserPolicy) {
await trx.insert(userPolicies).values({ await trx.insert(userPolicies).values({
userId: user.userId, userId: user.user.userId,
resourcePolicyId: policyId resourcePolicyId: policyId
}); });
} }
+26 -7
View File
@@ -13,7 +13,7 @@ import {
userPolicies, userPolicies,
users users
} from "@server/db"; } from "@server/db";
import { eq, and } from "drizzle-orm"; import { eq, and, or } from "drizzle-orm";
import { Config, ResourcePolicyData } from "./types"; import { Config, ResourcePolicyData } from "./types";
import logger from "@server/logger"; import logger from "@server/logger";
import { getUniqueResourcePolicyName } from "@server/db/names"; import { getUniqueResourcePolicyName } from "@server/db/names";
@@ -22,7 +22,6 @@ import { idpExistsForOrg } from "@server/lib/idp/idpExistsForOrg";
import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators"; import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators";
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { tierMatrix } from "../billing/tierMatrix"; import { tierMatrix } from "../billing/tierMatrix";
import { findOrgUserByIdentifier } from "./findOrgUser";
export type ResourcePoliciesResults = { export type ResourcePoliciesResults = {
resourcePolicyId: number; resourcePolicyId: number;
@@ -467,7 +466,17 @@ async function syncUserPolicies(
.where(eq(userPolicies.resourcePolicyId, policyId)); .where(eq(userPolicies.resourcePolicyId, policyId));
for (const username of ssoUsers) { for (const username of ssoUsers) {
const user = await findOrgUserByIdentifier(trx, orgId, username); const [user] = await trx
.select()
.from(users)
.innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(eq(users.username, username), eq(users.email, username)),
eq(userOrgs.orgId, orgId)
)
)
.limit(1);
if (!user) { if (!user) {
logger.warn( logger.warn(
@@ -477,12 +486,12 @@ async function syncUserPolicies(
} }
const alreadyExists = existingUserPolicies.some( const alreadyExists = existingUserPolicies.some(
(up) => up.userId === user.userId (up) => up.userId === user.user.userId
); );
if (!alreadyExists) { if (!alreadyExists) {
await trx.insert(userPolicies).values({ await trx.insert(userPolicies).values({
userId: user.userId, userId: user.user.userId,
resourcePolicyId: policyId resourcePolicyId: policyId
}); });
} }
@@ -527,7 +536,17 @@ async function addUserPolicies(
trx: Transaction trx: Transaction
) { ) {
for (const username of ssoUsers) { for (const username of ssoUsers) {
const user = await findOrgUserByIdentifier(trx, orgId, username); const [user] = await trx
.select()
.from(users)
.innerJoin(userOrgs, eq(users.userId, userOrgs.userId))
.where(
and(
or(eq(users.username, username), eq(users.email, username)),
eq(userOrgs.orgId, orgId)
)
)
.limit(1);
if (!user) { if (!user) {
logger.warn( logger.warn(
@@ -537,7 +556,7 @@ async function addUserPolicies(
} }
await trx.insert(userPolicies).values({ await trx.insert(userPolicies).values({
userId: user.userId, userId: user.user.userId,
resourcePolicyId: policyId resourcePolicyId: policyId
}); });
} }
@@ -88,27 +88,7 @@ export const queryAccessAuditLogsQuery = z.object({
.optional() .optional()
.default("0") .default("0")
.transform(Number) .transform(Number)
.pipe(z.int().nonnegative()), .pipe(z.int().nonnegative())
ip: z
.preprocess((val) => {
if (val === undefined || val === null || val === "") {
return undefined;
}
if (Array.isArray(val)) {
return val;
}
// the array is returned as this
if (typeof val === "string") {
return val.split(",");
}
return undefined;
}, z.array(z.string()))
.optional()
.catch([])
.openapi({
type: "array",
description: "Filter by IP adresses"
})
}); });
export const queryAccessAuditLogsParams = z.object({ export const queryAccessAuditLogsParams = z.object({
@@ -154,9 +134,6 @@ function getWhere(data: Q) {
data.type ? eq(accessAuditLog.type, data.type) : undefined, data.type ? eq(accessAuditLog.type, data.type) : undefined,
data.action !== undefined data.action !== undefined
? eq(accessAuditLog.action, data.action) ? eq(accessAuditLog.action, data.action)
: undefined,
data.ip && data.ip.length > 0
? inArray(accessAuditLog.ip, data.ip)
: undefined : undefined
); );
} }
+4 -2
View File
@@ -16,10 +16,12 @@ import {
handleRemoteExitNodePingMessage handleRemoteExitNodePingMessage
} from "#private/routers/remoteExitNode"; } from "#private/routers/remoteExitNode";
import { MessageHandler } from "@server/routers/ws"; import { MessageHandler } from "@server/routers/ws";
import { handleConnectionLogMessage } from "#private/routers/newt"; import {
handleConnectionLogMessage,
} from "#private/routers/newt";
export const messageHandlers: Record<string, MessageHandler> = { export const messageHandlers: Record<string, MessageHandler> = {
"remoteExitNode/register": handleRemoteExitNodeRegisterMessage, "remoteExitNode/register": handleRemoteExitNodeRegisterMessage,
"remoteExitNode/ping": handleRemoteExitNodePingMessage, "remoteExitNode/ping": handleRemoteExitNodePingMessage,
"newt/access-log": handleConnectionLogMessage "newt/access-log": handleConnectionLogMessage,
}; };
@@ -81,27 +81,7 @@ export const queryAccessAuditLogsQuery = z.strictObject({
.optional() .optional()
.default("0") .default("0")
.transform(Number) .transform(Number)
.pipe(z.int().nonnegative()), .pipe(z.int().nonnegative())
ip: z
.preprocess((val) => {
if (val === undefined || val === null || val === "") {
return undefined;
}
if (Array.isArray(val)) {
return val;
}
// the array is returned as this
if (typeof val === "string") {
return val.split(",");
}
return undefined;
}, z.array(z.string()))
.optional()
.catch([])
.openapi({
type: "array",
description: "Filter by IP adresses"
})
}); });
export const queryRequestAuditLogsParams = z.object({ export const queryRequestAuditLogsParams = z.object({
@@ -146,9 +126,6 @@ function getWhere(data: Q) {
data.path ? eq(requestAuditLog.path, data.path) : undefined, data.path ? eq(requestAuditLog.path, data.path) : undefined,
data.action !== undefined data.action !== undefined
? eq(requestAuditLog.action, data.action) ? eq(requestAuditLog.action, data.action)
: undefined,
data.ip && data.ip.length > 0
? inArray(requestAuditLog.ip, data.ip)
: undefined : undefined
); );
} }
+4 -9
View File
@@ -533,23 +533,18 @@ export async function startAuthentication(
// If email is provided, get security keys for that specific user // If email is provided, get security keys for that specific user
if (email) { if (email) {
const matchingUsers = await db const [user] = await db
.select() .select()
.from(users) .from(users)
.where( .where(eq(users.email, email))
and( .limit(1);
eq(users.email, email.toLowerCase()),
eq(users.type, UserType.Internal)
)
);
if (matchingUsers.length !== 1) { if (!user || user.type !== UserType.Internal) {
return next( return next(
createHttpError(HttpCode.BAD_REQUEST, "Invalid credentials") createHttpError(HttpCode.BAD_REQUEST, "Invalid credentials")
); );
} }
const user = matchingUsers[0];
userId = user.userId; userId = user.userId;
const userSecurityKeys = await db const userSecurityKeys = await db
+38 -49
View File
@@ -42,62 +42,54 @@ export async function setServerAdmin(
const { email, password, setupToken } = parsedBody.data; const { email, password, setupToken } = parsedBody.data;
// Validate setup token
const [validToken] = await db
.select()
.from(setupTokens)
.where(
and(
eq(setupTokens.token, setupToken),
eq(setupTokens.used, false)
)
);
if (!validToken) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid or expired setup token"
)
);
}
const [existing] = await db
.select()
.from(users)
.where(eq(users.serverAdmin, true));
if (existing) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Server admin already exists"
)
);
}
const passwordHash = await hashPassword(password); const passwordHash = await hashPassword(password);
const userId = generateId(15); const userId = generateId(15);
await db.transaction(async (trx) => { await db.transaction(async (trx) => {
const consumed = await trx // Mark the token as used
await trx
.update(setupTokens) .update(setupTokens)
.set({ .set({
used: true, used: true,
dateUsed: moment().toISOString() dateUsed: moment().toISOString()
}) })
.where( .where(eq(setupTokens.tokenId, validToken.tokenId));
and(
eq(setupTokens.token, setupToken),
eq(setupTokens.used, false)
)
)
.returning({ tokenId: setupTokens.tokenId });
if (!consumed.length) {
throw createHttpError(
HttpCode.BAD_REQUEST,
"Invalid setup token"
);
}
const [existingAdmin] = await trx
.select({ userId: users.userId })
.from(users)
.where(eq(users.serverAdmin, true))
.limit(1);
if (existingAdmin) {
throw createHttpError(
HttpCode.BAD_REQUEST,
"Server admin already exists"
);
}
const [existingUser] = await trx
.select({ userId: users.userId })
.from(users)
.where(
and(
eq(users.email, email),
eq(users.type, UserType.Internal)
)
)
.limit(1);
if (existingUser) {
throw createHttpError(
HttpCode.BAD_REQUEST,
"A user with that email address already exists"
);
}
// Create the server admin user
await trx.insert(users).values({ await trx.insert(users).values({
userId: userId, userId: userId,
email: email, email: email,
@@ -119,9 +111,6 @@ export async function setServerAdmin(
status: HttpCode.OK status: HttpCode.OK
}); });
} catch (e) { } catch (e) {
if (createHttpError.isHttpError(e)) {
return next(e);
}
logger.error(e); logger.error(e);
return next( return next(
createHttpError( createHttpError(
+1 -1
View File
@@ -48,7 +48,7 @@ export async function validateSetupToken(
return response<ValidateSetupTokenResponse>(res, { return response<ValidateSetupTokenResponse>(res, {
data: { data: {
valid: false, valid: false,
message: "Invalid setup token" message: "Invalid or expired setup token"
}, },
success: true, success: true,
error: false, error: false,
@@ -46,7 +46,6 @@ import { AxiosResponse } from "axios";
import { ListRolesResponse } from "@server/routers/role"; import { ListRolesResponse } from "@server/routers/role";
import AutoProvisionConfigWidget from "@app/components/AutoProvisionConfigWidget"; import AutoProvisionConfigWidget from "@app/components/AutoProvisionConfigWidget";
import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription"; import IdpAutoProvisionUsersDescription from "@app/components/IdpAutoProvisionUsersDescription";
import IdpIdentifierChangeDialog from "@app/components/IdpIdentifierChangeDialog";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert"; import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
import { tierMatrix } from "@server/lib/billing/tierMatrix"; import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { import {
@@ -76,12 +75,6 @@ export default function GeneralPage() {
>([createMappingBuilderRule()]); >([createMappingBuilderRule()]);
const [rawRoleExpression, setRawRoleExpression] = useState(""); const [rawRoleExpression, setRawRoleExpression] = useState("");
const [variant, setVariant] = useState<"oidc" | "google" | "azure">("oidc"); const [variant, setVariant] = useState<"oidc" | "google" | "azure">("oidc");
const [originalIdentifierPath, setOriginalIdentifierPath] = useState("");
const [identifierConfirmOpen, setIdentifierConfirmOpen] = useState(false);
const [pendingPayload, setPendingPayload] = useState<Record<
string,
unknown
> | null>(null);
const dashboardRedirectUrl = `${env.app.dashboardUrl}/auth/idp/${idpId}/oidc/callback`; const dashboardRedirectUrl = `${env.app.dashboardUrl}/auth/idp/${idpId}/oidc/callback`;
const [redirectUrl, setRedirectUrl] = useState( const [redirectUrl, setRedirectUrl] = useState(
@@ -191,9 +184,6 @@ export default function GeneralPage() {
const data = res.data.data; const data = res.data.data;
const roleMapping = data.idpOrg.roleMapping; const roleMapping = data.idpOrg.roleMapping;
const idpVariant = data.idpOidcConfig?.variant || "oidc"; const idpVariant = data.idpOidcConfig?.variant || "oidc";
setOriginalIdentifierPath(
data.idpOidcConfig?.identifierPath ?? "sub"
);
setRedirectUrl(res.data.data.redirectUrl); setRedirectUrl(res.data.data.redirectUrl);
// Set the variant // Set the variant
@@ -388,56 +378,18 @@ export default function GeneralPage() {
}; };
} }
const nextIdentifierPath = const res = await api.post(
variant === "oidc" `/org/${orgId}/idp/${idpId}/oidc`,
? (data as OidcFormValues).identifierPath payload
: undefined; );
if ( if (res.status === 200) {
typeof nextIdentifierPath === "string" && toast({
nextIdentifierPath !== originalIdentifierPath title: t("success"),
) { description: t("idpUpdatedDescription")
setPendingPayload(payload); });
setIdentifierConfirmOpen(true); router.refresh();
return;
} }
await persistIdp(payload);
} catch (e) {
toast({
title: t("error"),
description: formatAxiosError(e),
variant: "destructive"
});
} finally {
setLoading(false);
}
}
async function persistIdp(payload: Record<string, unknown>) {
const res = await api.post(`/org/${orgId}/idp/${idpId}/oidc`, payload);
if (res.status === 200) {
if (typeof payload.identifierPath === "string") {
setOriginalIdentifierPath(payload.identifierPath);
}
toast({
title: t("success"),
description: t("idpUpdatedDescription")
});
router.refresh();
}
}
async function confirmIdentifierChange() {
if (!pendingPayload) {
return;
}
setLoading(true);
try {
await persistIdp(pendingPayload);
setPendingPayload(null);
} catch (e) { } catch (e) {
toast({ toast({
title: t("error"), title: t("error"),
@@ -455,16 +407,6 @@ export default function GeneralPage() {
return ( return (
<> <>
<IdpIdentifierChangeDialog
open={identifierConfirmOpen}
setOpen={(open) => {
setIdentifierConfirmOpen(open);
if (!open) {
setPendingPayload(null);
}
}}
onConfirm={confirmIdentifierChange}
/>
<SettingsContainer> <SettingsContainer>
<SettingsSection> <SettingsSection>
<SettingsSectionHeader> <SettingsSectionHeader>
+13 -46
View File
@@ -12,7 +12,6 @@ import { DateTimeValue } from "@app/components/DateTimePicker";
import { ArrowUpRight, Key, User } from "lucide-react"; import { ArrowUpRight, Key, User } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { ColumnFilterButton } from "@app/components/ColumnFilterButton"; import { ColumnFilterButton } from "@app/components/ColumnFilterButton";
import { ColumnMultiFilterButton } from "@app/components/ColumnMultiFilterButton";
import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
import { build } from "@server/build"; import { build } from "@server/build";
import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo"; import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo";
@@ -27,7 +26,6 @@ import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { logQueries } from "@app/lib/queries"; import { logQueries } from "@app/lib/queries";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import type { QueryAccessAuditLogResponse } from "@server/routers/auditLogs/types"; import type { QueryAccessAuditLogResponse } from "@server/routers/auditLogs/types";
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
export default function GeneralPage() { export default function GeneralPage() {
const router = useRouter(); const router = useRouter();
@@ -47,14 +45,12 @@ export default function GeneralPage() {
resourceId?: string; resourceId?: string;
location?: string; location?: string;
actor?: string; actor?: string;
ip?: string[];
}>({ }>({
action: searchParams.get("action") || undefined, action: searchParams.get("action") || undefined,
type: searchParams.get("type") || undefined, type: searchParams.get("type") || undefined,
resourceId: searchParams.get("resourceId") || undefined, resourceId: searchParams.get("resourceId") || undefined,
location: searchParams.get("location") || undefined, location: searchParams.get("location") || undefined,
actor: searchParams.get("actor") || undefined, actor: searchParams.get("actor") || undefined
ip: searchParams.getAll("ip") || undefined
}); });
const [currentPage, setCurrentPage] = useState<number>(0); const [currentPage, setCurrentPage] = useState<number>(0);
@@ -180,7 +176,7 @@ export default function GeneralPage() {
const handleFilterChange = ( const handleFilterChange = (
filterType: keyof typeof filters, filterType: keyof typeof filters,
value: string | string[] | undefined value: string | undefined
) => { ) => {
const newFilters = { ...filters, [filterType]: value }; const newFilters = { ...filters, [filterType]: value };
setFilters(newFilters); setFilters(newFilters);
@@ -198,13 +194,10 @@ export default function GeneralPage() {
) => { ) => {
const params = new URLSearchParams(searchParams); const params = new URLSearchParams(searchParams);
Object.entries(newFilters).forEach(([key, value]) => { Object.entries(newFilters).forEach(([key, value]) => {
params.delete(key); if (value) {
if (typeof value === "string") {
params.set(key, value); params.set(key, value);
} else if (typeof value !== "undefined" && "length" in value) { } else {
for (const element of value) { params.delete(key);
params.append(key, element);
}
} }
}); });
router.replace(`?${params.toString()}`, { scroll: false }); router.replace(`?${params.toString()}`, { scroll: false });
@@ -212,7 +205,6 @@ export default function GeneralPage() {
const exportData = async () => { const exportData = async () => {
try { try {
const { ip, ...restFilters } = filters;
const params: any = { const params: any = {
timeStart: dateRange.startDate?.date timeStart: dateRange.startDate?.date
? new Date(dateRange.startDate.date).toISOString() ? new Date(dateRange.startDate.date).toISOString()
@@ -220,20 +212,13 @@ export default function GeneralPage() {
timeEnd: dateRange.endDate?.date timeEnd: dateRange.endDate?.date
? new Date(dateRange.endDate.date).toISOString() ? new Date(dateRange.endDate.date).toISOString()
: undefined, : undefined,
...restFilters ...filters
}; };
// axios serializes arrays as `ip[]=…`, which express's query const response = await api.get(`/org/${orgId}/logs/access/export`, {
// parser does not read back as `ip`, so pass them in the URL responseType: "blob",
const sp = new URLSearchParams((ip ?? []).map((ip) => ["ip", ip])); params
});
const response = await api.get(
`/org/${orgId}/logs/access/export?${sp.toString()}`,
{
responseType: "blob",
params
}
);
const url = window.URL.createObjectURL(new Blob([response.data])); const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a"); const link = document.createElement("a");
@@ -312,24 +297,7 @@ export default function GeneralPage() {
}, },
{ {
accessorKey: "ip", accessorKey: "ip",
header: () => ( header: () => <span className="px-2">{t("ip")}</span>,
<span className="px-2">
<ColumnMultiFilterButton
options={(filters.ip ?? []).map((ip) => ({
label: ip,
value: ip
}))}
label={t("ip")}
allowArbitraryValues
searchPlaceholder={t("ipFilterSearchPlaceholder")}
emptyMessage={t("ipFilterEmptyMessage")}
selectedValues={filters.ip ?? []}
onSelectedValuesChange={(value) =>
handleFilterChange("ip", value)
}
/>
</span>
),
cell: ({ row }) => { cell: ({ row }) => {
return row.original.ip ? ( return row.original.ip ? (
row.original.ip row.original.ip
@@ -347,7 +315,7 @@ export default function GeneralPage() {
options={filterAttributes.locations.map( options={filterAttributes.locations.map(
(location) => ({ (location) => ({
value: location, value: location,
label: `${location} ${countryCodeToFlagEmoji(location)}` label: location
}) })
)} )}
label={t("location")} label={t("location")}
@@ -366,8 +334,7 @@ export default function GeneralPage() {
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
{row.original.location ? ( {row.original.location ? (
<span className="text-muted-foreground text-xs"> <span className="text-muted-foreground text-xs">
{row.original.location}{" "} {row.original.location}
{countryCodeToFlagEmoji(row.original.location)}
</span> </span>
) : ( ) : (
<span className="text-muted-foreground text-xs"> <span className="text-muted-foreground text-xs">
+10 -40
View File
@@ -23,8 +23,6 @@ import { useMemo, useState, useTransition } from "react";
import { useStoredPageSize } from "@app/hooks/useStoredPageSize"; import { useStoredPageSize } from "@app/hooks/useStoredPageSize";
import type { QueryRequestAuditLogResponse } from "@server/routers/auditLogs/types"; import type { QueryRequestAuditLogResponse } from "@server/routers/auditLogs/types";
import { ColumnFilterButton } from "@app/components/ColumnFilterButton"; import { ColumnFilterButton } from "@app/components/ColumnFilterButton";
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
import { ColumnMultiFilterButton } from "@app/components/ColumnMultiFilterButton";
export default function GeneralPage() { export default function GeneralPage() {
const router = useRouter(); const router = useRouter();
@@ -49,7 +47,6 @@ export default function GeneralPage() {
method?: string; method?: string;
reason?: string; reason?: string;
path?: string; path?: string;
ip?: string[];
}>({ }>({
action: searchParams.get("action") || undefined, action: searchParams.get("action") || undefined,
host: searchParams.get("host") || undefined, host: searchParams.get("host") || undefined,
@@ -58,8 +55,7 @@ export default function GeneralPage() {
actor: searchParams.get("actor") || undefined, actor: searchParams.get("actor") || undefined,
method: searchParams.get("method") || undefined, method: searchParams.get("method") || undefined,
reason: searchParams.get("reason") || undefined, reason: searchParams.get("reason") || undefined,
path: searchParams.get("path") || undefined, path: searchParams.get("path") || undefined
ip: searchParams.getAll("ip") || undefined
}); });
const getDefaultDateRange = () => { const getDefaultDateRange = () => {
@@ -183,7 +179,7 @@ export default function GeneralPage() {
const handleFilterChange = ( const handleFilterChange = (
filterType: keyof typeof filters, filterType: keyof typeof filters,
value: string | string[] | undefined value: string | undefined
) => { ) => {
const newFilters = { ...filters, [filterType]: value }; const newFilters = { ...filters, [filterType]: value };
setFilters(newFilters); setFilters(newFilters);
@@ -201,13 +197,10 @@ export default function GeneralPage() {
) => { ) => {
const params = new URLSearchParams(searchParams); const params = new URLSearchParams(searchParams);
Object.entries(newFilters).forEach(([key, value]) => { Object.entries(newFilters).forEach(([key, value]) => {
params.delete(key); if (value) {
if (typeof value === "string") {
params.set(key, value); params.set(key, value);
} else if (typeof value !== "undefined" && "length" in value) { } else {
for (const element of value) { params.delete(key);
params.append(key, element);
}
} }
}); });
router.replace(`?${params.toString()}`, { scroll: false }); router.replace(`?${params.toString()}`, { scroll: false });
@@ -216,7 +209,6 @@ export default function GeneralPage() {
const exportData = async () => { const exportData = async () => {
try { try {
// Prepare query params for export // Prepare query params for export
const { ip, ...restFilters } = filters;
const params: any = { const params: any = {
timeStart: dateRange.startDate?.date timeStart: dateRange.startDate?.date
? new Date(dateRange.startDate.date).toISOString() ? new Date(dateRange.startDate.date).toISOString()
@@ -224,15 +216,11 @@ export default function GeneralPage() {
timeEnd: dateRange.endDate?.date timeEnd: dateRange.endDate?.date
? new Date(dateRange.endDate.date).toISOString() ? new Date(dateRange.endDate.date).toISOString()
: undefined, : undefined,
...restFilters ...filters
}; };
// axios serializes arrays as `ip[]=…`, which express's query
// parser does not read back as `ip`, so pass them in the URL
const sp = new URLSearchParams((ip ?? []).map((ip) => ["ip", ip]));
const response = await api.get( const response = await api.get(
`/org/${orgId}/logs/request/export?${sp.toString()}`, `/org/${orgId}/logs/request/export`,
{ {
responseType: "blob", responseType: "blob",
params params
@@ -363,24 +351,7 @@ export default function GeneralPage() {
}, },
{ {
accessorKey: "ip", accessorKey: "ip",
header: ({ column }) => ( header: ({ column }) => <span className="px-2">{t("ip")}</span>,
<span className="px-2">
<ColumnMultiFilterButton
options={(filters.ip ?? []).map((ip) => ({
label: ip,
value: ip
}))}
label={t("ip")}
allowArbitraryValues
searchPlaceholder={t("ipFilterSearchPlaceholder")}
emptyMessage={t("ipFilterEmptyMessage")}
selectedValues={filters.ip ?? []}
onSelectedValuesChange={(value) =>
handleFilterChange("ip", value)
}
/>
</span>
),
cell: ({ row }) => { cell: ({ row }) => {
return row.original.ip ? ( return row.original.ip ? (
row.original.ip row.original.ip
@@ -398,7 +369,7 @@ export default function GeneralPage() {
options={filterAttributes.locations.map( options={filterAttributes.locations.map(
(location) => ({ (location) => ({
value: location, value: location,
label: `${location} ${countryCodeToFlagEmoji(location)}` label: location
}) })
)} )}
selectedValue={filters.location} selectedValue={filters.location}
@@ -418,8 +389,7 @@ export default function GeneralPage() {
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
{row.original.location ? ( {row.original.location ? (
<span className="text-muted-foreground text-xs"> <span className="text-muted-foreground text-xs">
{row.original.location}{" "} {row.original.location}
{countryCodeToFlagEmoji(row.original.location)}
</span> </span>
) : ( ) : (
<span className="text-muted-foreground text-xs"> <span className="text-muted-foreground text-xs">
+7 -68
View File
@@ -41,7 +41,6 @@ import {
} from "@app/components/InfoSection"; } from "@app/components/InfoSection";
import CopyToClipboard from "@app/components/CopyToClipboard"; import CopyToClipboard from "@app/components/CopyToClipboard";
import IdpTypeBadge from "@app/components/IdpTypeBadge"; import IdpTypeBadge from "@app/components/IdpTypeBadge";
import IdpIdentifierChangeDialog from "@app/components/IdpIdentifierChangeDialog";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
export default function GeneralPage() { export default function GeneralPage() {
@@ -52,12 +51,6 @@ export default function GeneralPage() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [initialLoading, setInitialLoading] = useState(true); const [initialLoading, setInitialLoading] = useState(true);
const [variant, setVariant] = useState<"oidc" | "google" | "azure">("oidc"); const [variant, setVariant] = useState<"oidc" | "google" | "azure">("oidc");
const [originalIdentifierPath, setOriginalIdentifierPath] = useState("");
const [identifierConfirmOpen, setIdentifierConfirmOpen] = useState(false);
const [pendingPayload, setPendingPayload] = useState<Record<
string,
unknown
> | null>(null);
const redirectUrl = `${env.app.dashboardUrl}/auth/idp/${idpId}/oidc/callback`; const redirectUrl = `${env.app.dashboardUrl}/auth/idp/${idpId}/oidc/callback`;
const t = useTranslations(); const t = useTranslations();
@@ -148,9 +141,6 @@ export default function GeneralPage() {
| "google" | "google"
| "azure") || "oidc"; | "azure") || "oidc";
setVariant(idpVariant); setVariant(idpVariant);
setOriginalIdentifierPath(
data.idpOidcConfig?.identifierPath ?? "sub"
);
let tenantId = ""; let tenantId = "";
if (idpVariant === "azure" && data.idpOidcConfig?.authUrl) { if (idpVariant === "azure" && data.idpOidcConfig?.authUrl) {
@@ -268,56 +258,15 @@ export default function GeneralPage() {
}; };
} }
const nextIdentifierPath = const res = await api.post(`/idp/${idpId}/oidc`, payload);
variant === "oidc"
? (data as OidcFormValues).identifierPath
: undefined;
if ( if (res.status === 200) {
typeof nextIdentifierPath === "string" && toast({
nextIdentifierPath !== originalIdentifierPath title: t("success"),
) { description: t("idpUpdatedDescription")
setPendingPayload(payload); });
setIdentifierConfirmOpen(true); router.refresh();
return;
} }
await persistIdp(payload);
} catch (e) {
toast({
title: t("error"),
description: formatAxiosError(e),
variant: "destructive"
});
} finally {
setLoading(false);
}
}
async function persistIdp(payload: Record<string, unknown>) {
const res = await api.post(`/idp/${idpId}/oidc`, payload);
if (res.status === 200) {
if (typeof payload.identifierPath === "string") {
setOriginalIdentifierPath(payload.identifierPath);
}
toast({
title: t("success"),
description: t("idpUpdatedDescription")
});
router.refresh();
}
}
async function confirmIdentifierChange() {
if (!pendingPayload) {
return;
}
setLoading(true);
try {
await persistIdp(pendingPayload);
setPendingPayload(null);
} catch (e) { } catch (e) {
toast({ toast({
title: t("error"), title: t("error"),
@@ -335,16 +284,6 @@ export default function GeneralPage() {
return ( return (
<> <>
<IdpIdentifierChangeDialog
open={identifierConfirmOpen}
setOpen={(open) => {
setIdentifierConfirmOpen(open);
if (!open) {
setPendingPayload(null);
}
}}
onConfirm={confirmIdentifierChange}
/>
<SettingsContainer> <SettingsContainer>
<SettingsSection> <SettingsSection>
<SettingsSectionHeader> <SettingsSectionHeader>
+3 -5
View File
@@ -21,7 +21,7 @@ import { useTranslations } from "next-intl";
interface FilterOption { interface FilterOption {
value: string; value: string;
label: React.ReactNode; label: string;
} }
interface ColumnFilterButtonProps { interface ColumnFilterButtonProps {
@@ -32,7 +32,6 @@ interface ColumnFilterButtonProps {
emptyMessage?: string; emptyMessage?: string;
className?: string; className?: string;
label: string; label: string;
allowArbitraryValues?: boolean;
} }
export function ColumnFilterButton({ export function ColumnFilterButton({
@@ -42,8 +41,7 @@ export function ColumnFilterButton({
searchPlaceholder = "Search...", searchPlaceholder = "Search...",
emptyMessage = "No options found", emptyMessage = "No options found",
className, className,
label, label
allowArbitraryValues
}: ColumnFilterButtonProps) { }: ColumnFilterButtonProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -103,7 +101,7 @@ export function ColumnFilterButton({
{options.map((option) => ( {options.map((option) => (
<CommandItem <CommandItem
key={option.value} key={option.value}
value={option.value} value={option.label}
onSelect={() => { onSelect={() => {
onValueChange( onValueChange(
selectedValue === option.value selectedValue === option.value
+4 -24
View File
@@ -35,7 +35,6 @@ type ColumnMultiFilterButtonProps = {
emptyMessage?: string; emptyMessage?: string;
className?: string; className?: string;
label: string; label: string;
allowArbitraryValues?: boolean;
}; };
export function ColumnMultiFilterButton({ export function ColumnMultiFilterButton({
@@ -45,26 +44,11 @@ export function ColumnMultiFilterButton({
searchPlaceholder = "Search...", searchPlaceholder = "Search...",
emptyMessage = "No options found", emptyMessage = "No options found",
className, className,
label, label
allowArbitraryValues
}: ColumnMultiFilterButtonProps) { }: ColumnMultiFilterButtonProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const t = useTranslations(); const t = useTranslations();
const visibleOptions = useMemo<FilterOption[]>(() => {
const newOptions = [...options];
if (allowArbitraryValues && searchQuery.trim().length > 0) {
newOptions.push({
label: searchQuery,
value: searchQuery
});
}
return newOptions;
}, [options, allowArbitraryValues, searchQuery]);
const selectedSet = useMemo( const selectedSet = useMemo(
() => new Set(selectedValues), () => new Set(selectedValues),
[selectedValues] [selectedValues]
@@ -80,7 +64,7 @@ export function ColumnMultiFilterButton({
selectedValues[0] selectedValues[0]
); );
} }
return t("multiSelectFilterCount", { return t("accessUsersRoleFilterCount", {
count: selectedValues.length count: selectedValues.length
}); });
}, [selectedValues, options, t]); }, [selectedValues, options, t]);
@@ -124,11 +108,7 @@ export function ColumnMultiFilterButton({
align="start" align="start"
> >
<Command> <Command>
<CommandInput <CommandInput placeholder={searchPlaceholder} />
placeholder={searchPlaceholder}
value={searchQuery}
onValueChange={setSearchQuery}
/>
<CommandList> <CommandList>
<CommandEmpty>{emptyMessage}</CommandEmpty> <CommandEmpty>{emptyMessage}</CommandEmpty>
<CommandGroup> <CommandGroup>
@@ -143,7 +123,7 @@ export function ColumnMultiFilterButton({
{t("accessFilterClear")} {t("accessFilterClear")}
</CommandItem> </CommandItem>
)} )}
{visibleOptions.map((option) => ( {options.map((option) => (
<CommandItem <CommandItem
key={option.value} key={option.value}
value={option.label} value={option.label}
@@ -1,35 +0,0 @@
"use client";
import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
import { useTranslations } from "next-intl";
type IdpIdentifierChangeDialogProps = {
open: boolean;
setOpen: (open: boolean) => void;
onConfirm: () => Promise<void>;
};
export default function IdpIdentifierChangeDialog({
open,
setOpen,
onConfirm
}: IdpIdentifierChangeDialogProps) {
const t = useTranslations();
return (
<ConfirmDeleteDialog
open={open}
setOpen={setOpen}
dialog={
<div className="space-y-2">
<p>{t("idpIdentifierChangeDescription")}</p>
</div>
}
buttonText={t("saveGeneralSettings")}
onConfirm={onConfirm}
string={t("idpIdentifierChangeConfirmMessage")}
title={t("idpIdentifierChangeTitle")}
warningText={t("idpIdentifierChangeWarningText")}
/>
);
}
+22 -30
View File
@@ -1,8 +1,3 @@
import {
getAiBudgetScopeListPath,
type AiBudgetScope
} from "@app/lib/aiBudgetScope";
import type { AiProviderType } from "@app/lib/aiProviderDefaults";
import type { LauncherQueryFilters } from "@app/lib/launcherSearchParams"; import type { LauncherQueryFilters } from "@app/lib/launcherSearchParams";
import { buildLauncherSearchParams } from "@app/lib/launcherSearchParams"; import { buildLauncherSearchParams } from "@app/lib/launcherSearchParams";
import { build } from "@server/build"; import { build } from "@server/build";
@@ -10,21 +5,15 @@ import {
StatusHistoryResponse, StatusHistoryResponse,
type BatchedStatusHistoryResponse type BatchedStatusHistoryResponse
} from "@server/lib/statusHistory"; } from "@server/lib/statusHistory";
import type { ListAiBudgetsByScopeResponse } from "@server/routers/aiBudget/types";
import type {
ListAiModelsResponse,
ListAiProvidersResponse,
ListCatalogModelsResponse
} from "@server/routers/aiProvider/types";
import type { ListAlertRulesResponse } from "@server/routers/alertRule/types"; import type { ListAlertRulesResponse } from "@server/routers/alertRule/types";
import type { import type {
QueryRequestAnalyticsResponse,
QueryAiUsageFilterOptionsResponse, QueryAiUsageFilterOptionsResponse,
QueryAiUsageOverviewResponse, QueryAiUsageOverviewResponse,
QueryAiUsageProvidersResponse, QueryAiUsageProvidersResponse,
QueryAiUsageResourcesResponse, QueryAiUsageResourcesResponse,
QueryAiUsageUsersRolesResponse, QueryAiUsageUsersRolesResponse,
QueryAiUsageVirtualApiKeysResponse, QueryAiUsageVirtualApiKeysResponse
QueryRequestAnalyticsResponse
} from "@server/routers/auditLogs"; } from "@server/routers/auditLogs";
import type { import type {
QueryAccessAuditLogResponse, QueryAccessAuditLogResponse,
@@ -45,7 +34,6 @@ import type {
import type { GetDomainResponse } from "@server/routers/domain/getDomain"; import type { GetDomainResponse } from "@server/routers/domain/getDomain";
import { ListHealthChecksResponse } from "@server/routers/healthChecks/types"; import { ListHealthChecksResponse } from "@server/routers/healthChecks/types";
import type { ListOrgLabelsResponse } from "@server/routers/labels/types"; import type { ListOrgLabelsResponse } from "@server/routers/labels/types";
import type { ListLauncherAiModelsResponse } from "@server/routers/launcher/listLauncherAiModels";
import type { import type {
LauncherResource, LauncherResource,
ListLauncherGroupsResponse, ListLauncherGroupsResponse,
@@ -55,8 +43,9 @@ import type {
ListLauncherSitesResponse, ListLauncherSitesResponse,
ListLauncherViewsResponse ListLauncherViewsResponse
} from "@server/routers/launcher/types"; } from "@server/routers/launcher/types";
import type { ListLauncherAiModelsResponse } from "@server/routers/launcher/listLauncherAiModels";
import type { ListMyVirtualApiKeysResponse } from "@server/routers/virtualApiKey/types";
import type { GetResourcePolicyResponse } from "@server/routers/policy"; import type { GetResourcePolicyResponse } from "@server/routers/policy";
import type { ListRemoteExitNodesResponse } from "@server/routers/remoteExitNode/types";
import type { import type {
GetResourcePoliciesResponse, GetResourcePoliciesResponse,
GetResourceWhitelistResponse, GetResourceWhitelistResponse,
@@ -70,6 +59,7 @@ import type {
import type { GetResourceResponse } from "@server/routers/resource/getResource"; import type { GetResourceResponse } from "@server/routers/resource/getResource";
import type { GetResourceAuthInfoResponse } from "@server/routers/resource/getResourceAuthInfo"; import type { GetResourceAuthInfoResponse } from "@server/routers/resource/getResourceAuthInfo";
import type { ListResourcePoliciesResponse } from "@server/routers/resource/types"; import type { ListResourcePoliciesResponse } from "@server/routers/resource/types";
import type { ListRemoteExitNodesResponse } from "@server/routers/remoteExitNode/types";
import type { ListRolesResponse } from "@server/routers/role"; import type { ListRolesResponse } from "@server/routers/role";
import type { ListSitesResponse } from "@server/routers/site"; import type { ListSitesResponse } from "@server/routers/site";
import type { import type {
@@ -81,8 +71,18 @@ import type {
} from "@server/routers/siteResource"; } from "@server/routers/siteResource";
import type { GetSiteResourceResponse } from "@server/routers/siteResource/getSiteResource"; import type { GetSiteResourceResponse } from "@server/routers/siteResource/getSiteResource";
import type { ListTargetsResponse } from "@server/routers/target"; import type { ListTargetsResponse } from "@server/routers/target";
import type {
ListAiModelsResponse,
ListAiProvidersResponse,
ListCatalogModelsResponse
} from "@server/routers/aiProvider/types";
import type { AiProviderType } from "@app/lib/aiProviderDefaults";
import type { ListAiBudgetsByScopeResponse } from "@server/routers/aiBudget/types";
import {
getAiBudgetScopeListPath,
type AiBudgetScope
} from "@app/lib/aiBudgetScope";
import type { ListUsersResponse } from "@server/routers/user"; import type { ListUsersResponse } from "@server/routers/user";
import type { ListMyVirtualApiKeysResponse } from "@server/routers/virtualApiKey/types";
import type ResponseT from "@server/types/Response"; import type ResponseT from "@server/types/Response";
import { import {
infiniteQueryOptions, infiniteQueryOptions,
@@ -1000,8 +1000,7 @@ export const httpLogsFiltersSchema = z.object({
actor: z.string().optional().catch(undefined), actor: z.string().optional().catch(undefined),
method: z.string().optional().catch(undefined), method: z.string().optional().catch(undefined),
reason: z.string().optional().catch(undefined), reason: z.string().optional().catch(undefined),
path: z.string().optional().catch(undefined), path: z.string().optional().catch(undefined)
ip: z.array(z.string()).optional().catch(undefined)
}); });
export type HttpLogFilters = z.output<typeof httpLogsFiltersSchema>; export type HttpLogFilters = z.output<typeof httpLogsFiltersSchema>;
@@ -1027,8 +1026,7 @@ export const accessLogsFiltersSchema = z.object({
action: z.string().optional().catch(undefined), action: z.string().optional().catch(undefined),
location: z.string().optional().catch(undefined), location: z.string().optional().catch(undefined),
actor: z.string().optional().catch(undefined), actor: z.string().optional().catch(undefined),
type: z.string().optional().catch(undefined), type: z.string().optional().catch(undefined)
ip: z.array(z.string()).optional().catch(undefined)
}); });
export type AccessLogFilters = z.output<typeof accessLogsFiltersSchema>; export type AccessLogFilters = z.output<typeof accessLogsFiltersSchema>;
@@ -1141,13 +1139,10 @@ export const logQueries = {
queryOptions({ queryOptions({
queryKey: ["REQUEST_LOGS", orgId, "ALL", filters] as const, queryKey: ["REQUEST_LOGS", orgId, "ALL", filters] as const,
queryFn: async ({ signal, meta }) => { queryFn: async ({ signal, meta }) => {
const { page, pageSize, ip, ...rest } = filters; const { page, pageSize, ...rest } = filters;
const sp = new URLSearchParams(
(ip ?? []).map((ip) => ["ip", ip])
);
const res = await meta!.api.get< const res = await meta!.api.get<
AxiosResponse<QueryRequestAuditLogResponse> AxiosResponse<QueryRequestAuditLogResponse>
>(`/org/${orgId}/logs/request?${sp.toString()}`, { >(`/org/${orgId}/logs/request`, {
params: { params: {
...rest, ...rest,
limit: pageSize, limit: pageSize,
@@ -1169,13 +1164,10 @@ export const logQueries = {
queryOptions({ queryOptions({
queryKey: ["ACCESS_LOGS", orgId, "ALL", filters] as const, queryKey: ["ACCESS_LOGS", orgId, "ALL", filters] as const,
queryFn: async ({ signal, meta }) => { queryFn: async ({ signal, meta }) => {
const { page, pageSize, ip, ...rest } = filters; const { page, pageSize, ...rest } = filters;
const sp = new URLSearchParams(
(ip ?? []).map((ip) => ["ip", ip])
);
const res = await meta!.api.get< const res = await meta!.api.get<
AxiosResponse<QueryAccessAuditLogResponse> AxiosResponse<QueryAccessAuditLogResponse>
>(`/org/${orgId}/logs/access?${sp.toString()}`, { >(`/org/${orgId}/logs/access`, {
params: { params: {
...rest, ...rest,
limit: pageSize, limit: pageSize,