mirror of
https://github.com/tinyauthapp/tinyauth.git
synced 2026-08-24 05:43:32 +08:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f1abbf64d | ||
|
|
447b8410ff | ||
|
|
9da7d3c7be | ||
|
|
8614f8768b | ||
|
|
61d372b288 | ||
|
|
4dc12c677c | ||
|
|
cf5d5cab6e | ||
|
|
75c7aad40e | ||
|
|
3052cc0da3 |
+2
-8
@@ -171,14 +171,6 @@ TINYAUTH_OAUTH_PROVIDERS_name_USERINFOURL=
|
|||||||
TINYAUTH_OAUTH_PROVIDERS_name_INSECURE=false
|
TINYAUTH_OAUTH_PROVIDERS_name_INSECURE=false
|
||||||
# Provider name in UI.
|
# Provider name in UI.
|
||||||
TINYAUTH_OAUTH_PROVIDERS_name_NAME=
|
TINYAUTH_OAUTH_PROVIDERS_name_NAME=
|
||||||
# Username claim.
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_name_CLAIMS_USERNAME=
|
|
||||||
# Email claim.
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_name_CLAIMS_EMAIL=
|
|
||||||
# Name claim.
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_name_CLAIMS_NAME=
|
|
||||||
# Groups claim.
|
|
||||||
TINYAUTH_OAUTH_PROVIDERS_name_CLAIMS_GROUPS=
|
|
||||||
|
|
||||||
# oidc config
|
# oidc config
|
||||||
|
|
||||||
@@ -235,6 +227,8 @@ TINYAUTH_LDAP_GROUPCACHETTL=900
|
|||||||
|
|
||||||
# Enable the OAuth bridge, uses a new way to format OAuth user information.
|
# Enable the OAuth bridge, uses a new way to format OAuth user information.
|
||||||
TINYAUTH_EXPERIMENTAL_OAUTHBRIDGEENABLED=false
|
TINYAUTH_EXPERIMENTAL_OAUTHBRIDGEENABLED=false
|
||||||
|
# Disable the fallback to forward_auth modules when auth_request or ext_authz fail.
|
||||||
|
TINYAUTH_EXPERIMENTAL_DISABLEAUTHMODULEFALLBACK=false
|
||||||
|
|
||||||
# tailscale config
|
# tailscale config
|
||||||
|
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # ratchet:pnpm/action-setup@v6
|
||||||
with:
|
with:
|
||||||
package_json_file: ./e2e/package.json
|
package_json_file: ./e2e/package.json
|
||||||
|
|
||||||
- name: Set up Docker
|
- name: Set up Docker
|
||||||
uses: docker/setup-docker-action@77e84dbf09b47d1e29270283c22f16145aa85ca1 # v5.4.0
|
uses: docker/setup-docker-action@6d7cfa65f60a9dda7b46e5513fa982536f3c9877 # ratchet:docker/setup-docker-action@v5
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm ci
|
run: pnpm ci
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
run: pnpm test
|
run: pnpm test
|
||||||
working-directory: e2e
|
working-directory: e2e
|
||||||
|
|
||||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # ratchet:actions/upload-artifact@v4
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report
|
name: playwright-report
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -233,7 +233,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -292,7 +292,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -351,7 +351,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -406,7 +406,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
@@ -445,7 +445,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -203,7 +203,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -260,7 +260,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -317,7 +317,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||||
@@ -373,7 +373,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
@@ -414,7 +414,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
|
|||||||
@@ -38,6 +38,6 @@ jobs:
|
|||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
|
||||||
- name: Upload to code-scanning
|
- name: Upload to code-scanning
|
||||||
uses: github/codeql-action/upload-sarif@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
|
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"packageManager": "pnpm@11.1.2",
|
"packageManager": "pnpm@11.1.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.9.0",
|
"@hookform/resolvers": "^5.7.1",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
||||||
"@radix-ui/react-label": "^2.1.15",
|
"@radix-ui/react-label": "^2.1.15",
|
||||||
"@radix-ui/react-select": "^2.3.7",
|
"@radix-ui/react-select": "^2.3.7",
|
||||||
@@ -49,12 +49,12 @@
|
|||||||
"@vitejs/plugin-react": "^6.0.5",
|
"@vitejs/plugin-react": "^6.0.5",
|
||||||
"eslint": "^10.8.1",
|
"eslint": "^10.8.1",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.4",
|
"eslint-plugin-react-refresh": "^0.5.3",
|
||||||
"globals": "^17.11.0",
|
"globals": "^17.9.0",
|
||||||
"rollup-plugin-visualizer": "^7.1.1",
|
"rollup-plugin-visualizer": "^7.0.1",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "~6.0.2",
|
"typescript": "~6.0.2",
|
||||||
"typescript-eslint": "^8.67.0",
|
"typescript-eslint": "^8.66.0",
|
||||||
"vite": "^8.2.1"
|
"vite": "^8.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+115
-124
@@ -9,8 +9,8 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hookform/resolvers':
|
'@hookform/resolvers':
|
||||||
specifier: ^5.9.0
|
specifier: ^5.7.1
|
||||||
version: 5.9.0(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)
|
version: 5.7.1(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)
|
||||||
'@radix-ui/react-dropdown-menu':
|
'@radix-ui/react-dropdown-menu':
|
||||||
specifier: ^2.1.24
|
specifier: ^2.1.24
|
||||||
version: 2.1.24(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
version: 2.1.24(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
|
||||||
@@ -115,14 +115,14 @@ importers:
|
|||||||
specifier: ^7.0.1
|
specifier: ^7.0.1
|
||||||
version: 7.1.1(eslint@10.8.1(jiti@2.7.0))
|
version: 7.1.1(eslint@10.8.1(jiti@2.7.0))
|
||||||
eslint-plugin-react-refresh:
|
eslint-plugin-react-refresh:
|
||||||
specifier: ^0.5.4
|
specifier: ^0.5.3
|
||||||
version: 0.5.4(eslint@10.8.1(jiti@2.7.0))
|
version: 0.5.3(eslint@10.8.1(jiti@2.7.0))
|
||||||
globals:
|
globals:
|
||||||
specifier: ^17.11.0
|
specifier: ^17.9.0
|
||||||
version: 17.11.0
|
version: 17.9.0
|
||||||
rollup-plugin-visualizer:
|
rollup-plugin-visualizer:
|
||||||
specifier: ^7.1.1
|
specifier: ^7.0.1
|
||||||
version: 7.1.1(rolldown@1.2.3)
|
version: 7.0.1(rolldown@1.2.3)
|
||||||
tw-animate-css:
|
tw-animate-css:
|
||||||
specifier: ^1.4.0
|
specifier: ^1.4.0
|
||||||
version: 1.4.0
|
version: 1.4.0
|
||||||
@@ -130,8 +130,8 @@ importers:
|
|||||||
specifier: ~6.0.2
|
specifier: ~6.0.2
|
||||||
version: 6.0.3
|
version: 6.0.3
|
||||||
typescript-eslint:
|
typescript-eslint:
|
||||||
specifier: ^8.67.0
|
specifier: ^8.66.0
|
||||||
version: 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
version: 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^8.2.1
|
specifier: ^8.2.1
|
||||||
version: 8.2.1(@types/node@26.2.0)(jiti@2.7.0)
|
version: 8.2.1(@types/node@26.2.0)(jiti@2.7.0)
|
||||||
@@ -267,8 +267,8 @@ packages:
|
|||||||
'@floating-ui/utils@0.2.12':
|
'@floating-ui/utils@0.2.12':
|
||||||
resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
|
resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
|
||||||
|
|
||||||
'@hookform/resolvers@5.9.0':
|
'@hookform/resolvers@5.7.1':
|
||||||
resolution: {integrity: sha512-8sNo1IklGaONrsKzXjwZJNsPbccAXLXGX//G+VFEcQOviMtbvR8/fM6HWyA0qrjgpOYauwoodda53CQIWOZ7Ag==}
|
resolution: {integrity: sha512-8wS/P4UDr5sQDe4nFaV51TVyfDPrWgNIXweqG0Bs9Z5LSuzKLb+RQNPvkN2oHM5SRrJyWrVH/F+LOUcFjUyvwQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@sinclair/typebox': '>=0.25.24'
|
'@sinclair/typebox': '>=0.25.24'
|
||||||
'@standard-schema/spec': ^1.0.0
|
'@standard-schema/spec': ^1.0.0
|
||||||
@@ -286,13 +286,13 @@ packages:
|
|||||||
fluentvalidation-ts: ^3.0.0
|
fluentvalidation-ts: ^3.0.0
|
||||||
fp-ts: ^2.7.0
|
fp-ts: ^2.7.0
|
||||||
io-ts: ^2.0.0
|
io-ts: ^2.0.0
|
||||||
joi: ^17.0.0 || ^18.0.0
|
joi: ^17.0.0
|
||||||
nope-validator: '>=0.12.0'
|
nope-validator: '>=0.12.0'
|
||||||
react-hook-form: ^7.55.0
|
react-hook-form: ^7.55.0
|
||||||
superstruct: '>=0.12.0'
|
superstruct: '>=0.12.0'
|
||||||
typanion: ^3.3.2
|
typanion: ^3.3.2
|
||||||
valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc'
|
valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc'
|
||||||
vest: '>=6.0.0'
|
vest: '>=3.0.0'
|
||||||
yup: ^1.0.0
|
yup: ^1.0.0
|
||||||
zod: ^3.25.0 || ^4.0.0
|
zod: ^3.25.0 || ^4.0.0
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
@@ -1322,16 +1322,16 @@ packages:
|
|||||||
'@types/unist@3.0.3':
|
'@types/unist@3.0.3':
|
||||||
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.67.0':
|
'@typescript-eslint/eslint-plugin@8.66.0':
|
||||||
resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==}
|
resolution: {integrity: sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@typescript-eslint/parser': ^8.67.0
|
'@typescript-eslint/parser': ^8.66.0
|
||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.67.0':
|
'@typescript-eslint/parser@8.66.0':
|
||||||
resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==}
|
resolution: {integrity: sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
@@ -1343,8 +1343,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/project-service@8.67.0':
|
'@typescript-eslint/project-service@8.66.0':
|
||||||
resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==}
|
resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
@@ -1353,8 +1353,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==}
|
resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.67.0':
|
'@typescript-eslint/scope-manager@8.66.0':
|
||||||
resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==}
|
resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.65.0':
|
'@typescript-eslint/tsconfig-utils@8.65.0':
|
||||||
@@ -1363,14 +1363,14 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.67.0':
|
'@typescript-eslint/tsconfig-utils@8.66.0':
|
||||||
resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==}
|
resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.67.0':
|
'@typescript-eslint/type-utils@8.66.0':
|
||||||
resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==}
|
resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
@@ -1380,8 +1380,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==}
|
resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/types@8.67.0':
|
'@typescript-eslint/types@8.66.0':
|
||||||
resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==}
|
resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.65.0':
|
'@typescript-eslint/typescript-estree@8.65.0':
|
||||||
@@ -1390,8 +1390,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.67.0':
|
'@typescript-eslint/typescript-estree@8.66.0':
|
||||||
resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==}
|
resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
@@ -1403,8 +1403,8 @@ packages:
|
|||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.67.0':
|
'@typescript-eslint/utils@8.66.0':
|
||||||
resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==}
|
resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
@@ -1414,8 +1414,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==}
|
resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.67.0':
|
'@typescript-eslint/visitor-keys@8.66.0':
|
||||||
resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==}
|
resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@ungap/structured-clone@1.3.1':
|
'@ungap/structured-clone@1.3.1':
|
||||||
@@ -1451,8 +1451,8 @@ packages:
|
|||||||
ajv@6.15.0:
|
ajv@6.15.0:
|
||||||
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
|
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
|
||||||
|
|
||||||
ansi-regex@6.3.0:
|
ansi-regex@6.2.2:
|
||||||
resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==}
|
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
ansi-styles@6.2.3:
|
ansi-styles@6.2.3:
|
||||||
@@ -1636,8 +1636,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0
|
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0
|
||||||
|
|
||||||
eslint-plugin-react-refresh@0.5.4:
|
eslint-plugin-react-refresh@0.5.3:
|
||||||
resolution: {integrity: sha512-7bqTKz7T0r+HKWFarNXByDE9/5+73wI2ru+M3zuqGbR7s/b/5/pQJXZoufWlrngqGqoZto73ZkGumCdLxk+4rw==}
|
resolution: {integrity: sha512-5EMmLCV98Pi4o/f/3DP/v/tNqLHMIc9I8LKClNDWhZ9JTho89/kQcitCXQBMG7sAfVRK0Ie3T2EDOzp1YXYiVA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^9 || ^10
|
eslint: ^9 || ^10
|
||||||
|
|
||||||
@@ -1771,8 +1771,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
globals@17.11.0:
|
globals@17.9.0:
|
||||||
resolution: {integrity: sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==}
|
resolution: {integrity: sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
gopd@1.2.0:
|
gopd@1.2.0:
|
||||||
@@ -2212,8 +2212,8 @@ packages:
|
|||||||
node-releases@2.0.44:
|
node-releases@2.0.44:
|
||||||
resolution: {integrity: sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==}
|
resolution: {integrity: sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==}
|
||||||
|
|
||||||
open@11.0.1:
|
open@11.0.0:
|
||||||
resolution: {integrity: sha512-NzwMUB6C1D0+Kd+9iMS/H4k+Ck3cTX6Ckyfr/gAGlmvSE1LUQZnEZvWBi4PYmMwH/S5SMeTXnE+9uAz8uF+pWw==}
|
resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
@@ -2242,6 +2242,10 @@ packages:
|
|||||||
picocolors@1.1.1:
|
picocolors@1.1.1:
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
|
picomatch@4.0.4:
|
||||||
|
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
picomatch@4.0.5:
|
picomatch@4.0.5:
|
||||||
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
|
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -2254,10 +2258,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
|
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
powershell-utils@0.2.0:
|
|
||||||
resolution: {integrity: sha512-ZlsFlG7MtSFCoc5xreOvBAozCJ6Pf06opgJjh9ONEv418xpZSAzNjstD36C6+JwOnfSqOW/9uDkqKjezTdxZhw==}
|
|
||||||
engines: {node: '>=20'}
|
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -2374,8 +2374,8 @@ packages:
|
|||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
rollup-plugin-visualizer@7.1.1:
|
rollup-plugin-visualizer@7.0.1:
|
||||||
resolution: {integrity: sha512-ThaGiHTU8XW02OkK80TrTHATraJmM9OAduU4otal+7gyXLpYEtmGBLfx5kW+EHvvLwn03YGW2NnwKUIqsYlJAA==}
|
resolution: {integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg==}
|
||||||
engines: {node: '>=22'}
|
engines: {node: '>=22'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2425,8 +2425,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
source-map@0.8.0:
|
source-map@0.7.6:
|
||||||
resolution: {integrity: sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==}
|
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
|
||||||
engines: {node: '>= 12'}
|
engines: {node: '>= 12'}
|
||||||
|
|
||||||
space-separated-tokens@2.0.2:
|
space-separated-tokens@2.0.2:
|
||||||
@@ -2436,10 +2436,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
string-width@8.2.2:
|
|
||||||
resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==}
|
|
||||||
engines: {node: '>=20'}
|
|
||||||
|
|
||||||
stringify-entities@4.0.4:
|
stringify-entities@4.0.4:
|
||||||
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
|
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
|
||||||
|
|
||||||
@@ -2489,8 +2485,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
typescript-eslint@8.67.0:
|
typescript-eslint@8.66.0:
|
||||||
resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==}
|
resolution: {integrity: sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
@@ -2618,8 +2614,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
|
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
wsl-utils@1.0.0:
|
wsl-utils@0.3.1:
|
||||||
resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==}
|
resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
y18n@5.0.8:
|
y18n@5.0.8:
|
||||||
@@ -2633,8 +2629,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
|
resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
|
||||||
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||||
|
|
||||||
yargs@18.1.0:
|
yargs@18.0.0:
|
||||||
resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==}
|
resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==}
|
||||||
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||||
|
|
||||||
yocto-queue@0.1.0:
|
yocto-queue@0.1.0:
|
||||||
@@ -2810,7 +2806,7 @@ snapshots:
|
|||||||
|
|
||||||
'@floating-ui/utils@0.2.12': {}
|
'@floating-ui/utils@0.2.12': {}
|
||||||
|
|
||||||
'@hookform/resolvers@5.9.0(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)':
|
'@hookform/resolvers@5.7.1(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@standard-schema/utils': 0.3.0
|
'@standard-schema/utils': 0.3.0
|
||||||
react-hook-form: 7.85.0(react@19.2.8)
|
react-hook-form: 7.85.0(react@19.2.8)
|
||||||
@@ -3771,14 +3767,14 @@ snapshots:
|
|||||||
|
|
||||||
'@types/unist@3.0.3': {}
|
'@types/unist@3.0.3': {}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
'@typescript-eslint/eslint-plugin@8.66.0(@typescript-eslint/parser@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.12.2
|
'@eslint-community/regexpp': 4.12.2
|
||||||
'@typescript-eslint/parser': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/parser': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
'@typescript-eslint/scope-manager': 8.67.0
|
'@typescript-eslint/scope-manager': 8.66.0
|
||||||
'@typescript-eslint/type-utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/type-utils': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
'@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/utils': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.67.0
|
'@typescript-eslint/visitor-keys': 8.66.0
|
||||||
eslint: 10.8.1(jiti@2.7.0)
|
eslint: 10.8.1(jiti@2.7.0)
|
||||||
ignore: 7.0.6
|
ignore: 7.0.6
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
@@ -3787,12 +3783,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
'@typescript-eslint/parser@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.67.0
|
'@typescript-eslint/scope-manager': 8.66.0
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.67.0
|
'@typescript-eslint/visitor-keys': 8.66.0
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
eslint: 10.8.1(jiti@2.7.0)
|
eslint: 10.8.1(jiti@2.7.0)
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
@@ -3808,10 +3804,10 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/project-service@8.67.0(typescript@6.0.3)':
|
'@typescript-eslint/project-service@8.66.0(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3)
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -3822,24 +3818,24 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.65.0
|
'@typescript-eslint/types': 8.65.0
|
||||||
'@typescript-eslint/visitor-keys': 8.65.0
|
'@typescript-eslint/visitor-keys': 8.65.0
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.67.0':
|
'@typescript-eslint/scope-manager@8.66.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
'@typescript-eslint/visitor-keys': 8.67.0
|
'@typescript-eslint/visitor-keys': 8.66.0
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.65.0(typescript@6.0.3)':
|
'@typescript-eslint/tsconfig-utils@8.65.0(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.67.0(typescript@6.0.3)':
|
'@typescript-eslint/tsconfig-utils@8.66.0(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
'@typescript-eslint/type-utils@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3)
|
||||||
'@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/utils': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
eslint: 10.8.1(jiti@2.7.0)
|
eslint: 10.8.1(jiti@2.7.0)
|
||||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||||
@@ -3849,7 +3845,7 @@ snapshots:
|
|||||||
|
|
||||||
'@typescript-eslint/types@8.65.0': {}
|
'@typescript-eslint/types@8.65.0': {}
|
||||||
|
|
||||||
'@typescript-eslint/types@8.67.0': {}
|
'@typescript-eslint/types@8.66.0': {}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.65.0(typescript@6.0.3)':
|
'@typescript-eslint/typescript-estree@8.65.0(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3866,12 +3862,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.67.0(typescript@6.0.3)':
|
'@typescript-eslint/typescript-estree@8.66.0(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/project-service': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/project-service': 8.66.0(typescript@6.0.3)
|
||||||
'@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3)
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
'@typescript-eslint/visitor-keys': 8.67.0
|
'@typescript-eslint/visitor-keys': 8.66.0
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
minimatch: 10.2.6
|
minimatch: 10.2.6
|
||||||
semver: 7.8.5
|
semver: 7.8.5
|
||||||
@@ -3892,12 +3888,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
'@typescript-eslint/utils@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0))
|
'@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0))
|
||||||
'@typescript-eslint/scope-manager': 8.67.0
|
'@typescript-eslint/scope-manager': 8.66.0
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3)
|
||||||
eslint: 10.8.1(jiti@2.7.0)
|
eslint: 10.8.1(jiti@2.7.0)
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -3908,9 +3904,9 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.65.0
|
'@typescript-eslint/types': 8.65.0
|
||||||
eslint-visitor-keys: 5.0.1
|
eslint-visitor-keys: 5.0.1
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.67.0':
|
'@typescript-eslint/visitor-keys@8.66.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.66.0
|
||||||
eslint-visitor-keys: 5.0.1
|
eslint-visitor-keys: 5.0.1
|
||||||
|
|
||||||
'@ungap/structured-clone@1.3.1': {}
|
'@ungap/structured-clone@1.3.1': {}
|
||||||
@@ -3939,7 +3935,7 @@ snapshots:
|
|||||||
json-schema-traverse: 0.4.1
|
json-schema-traverse: 0.4.1
|
||||||
uri-js: 4.4.1
|
uri-js: 4.4.1
|
||||||
|
|
||||||
ansi-regex@6.3.0: {}
|
ansi-regex@6.2.2: {}
|
||||||
|
|
||||||
ansi-styles@6.2.3: {}
|
ansi-styles@6.2.3: {}
|
||||||
|
|
||||||
@@ -4104,7 +4100,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-react-refresh@0.5.4(eslint@10.8.1(jiti@2.7.0)):
|
eslint-plugin-react-refresh@0.5.3(eslint@10.8.1(jiti@2.7.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 10.8.1(jiti@2.7.0)
|
eslint: 10.8.1(jiti@2.7.0)
|
||||||
|
|
||||||
@@ -4249,7 +4245,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
||||||
globals@17.11.0: {}
|
globals@17.9.0: {}
|
||||||
|
|
||||||
gopd@1.2.0: {}
|
gopd@1.2.0: {}
|
||||||
|
|
||||||
@@ -4745,14 +4741,14 @@ snapshots:
|
|||||||
|
|
||||||
node-releases@2.0.44: {}
|
node-releases@2.0.44: {}
|
||||||
|
|
||||||
open@11.0.1:
|
open@11.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
default-browser: 5.5.0
|
default-browser: 5.5.0
|
||||||
define-lazy-prop: 3.0.0
|
define-lazy-prop: 3.0.0
|
||||||
is-in-ssh: 1.0.0
|
is-in-ssh: 1.0.0
|
||||||
is-inside-container: 1.0.0
|
is-inside-container: 1.0.0
|
||||||
powershell-utils: 0.2.0
|
powershell-utils: 0.1.0
|
||||||
wsl-utils: 1.0.0
|
wsl-utils: 0.3.1
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4787,6 +4783,8 @@ snapshots:
|
|||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
|
picomatch@4.0.4: {}
|
||||||
|
|
||||||
picomatch@4.0.5: {}
|
picomatch@4.0.5: {}
|
||||||
|
|
||||||
postcss@8.5.26:
|
postcss@8.5.26:
|
||||||
@@ -4797,8 +4795,6 @@ snapshots:
|
|||||||
|
|
||||||
powershell-utils@0.1.0: {}
|
powershell-utils@0.1.0: {}
|
||||||
|
|
||||||
powershell-utils@0.2.0: {}
|
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
property-information@7.1.0: {}
|
property-information@7.1.0: {}
|
||||||
@@ -4981,12 +4977,12 @@ snapshots:
|
|||||||
'@rolldown/binding-win32-arm64-msvc': 1.2.3
|
'@rolldown/binding-win32-arm64-msvc': 1.2.3
|
||||||
'@rolldown/binding-win32-x64-msvc': 1.2.3
|
'@rolldown/binding-win32-x64-msvc': 1.2.3
|
||||||
|
|
||||||
rollup-plugin-visualizer@7.1.1(rolldown@1.2.3):
|
rollup-plugin-visualizer@7.0.1(rolldown@1.2.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
open: 11.0.1
|
open: 11.0.0
|
||||||
picomatch: 4.0.5
|
picomatch: 4.0.4
|
||||||
source-map: 0.8.0
|
source-map: 0.7.6
|
||||||
yargs: 18.1.0
|
yargs: 18.0.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
rolldown: 1.2.3
|
rolldown: 1.2.3
|
||||||
|
|
||||||
@@ -5013,7 +5009,7 @@ snapshots:
|
|||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
source-map@0.8.0: {}
|
source-map@0.7.6: {}
|
||||||
|
|
||||||
space-separated-tokens@2.0.2: {}
|
space-separated-tokens@2.0.2: {}
|
||||||
|
|
||||||
@@ -5023,11 +5019,6 @@ snapshots:
|
|||||||
get-east-asian-width: 1.6.0
|
get-east-asian-width: 1.6.0
|
||||||
strip-ansi: 7.2.0
|
strip-ansi: 7.2.0
|
||||||
|
|
||||||
string-width@8.2.2:
|
|
||||||
dependencies:
|
|
||||||
get-east-asian-width: 1.6.0
|
|
||||||
strip-ansi: 7.2.0
|
|
||||||
|
|
||||||
stringify-entities@4.0.4:
|
stringify-entities@4.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
character-entities-html4: 2.1.0
|
character-entities-html4: 2.1.0
|
||||||
@@ -5035,7 +5026,7 @@ snapshots:
|
|||||||
|
|
||||||
strip-ansi@7.2.0:
|
strip-ansi@7.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 6.3.0
|
ansi-regex: 6.2.2
|
||||||
|
|
||||||
style-to-js@1.1.21:
|
style-to-js@1.1.21:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5072,12 +5063,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prelude-ls: 1.2.1
|
prelude-ls: 1.2.1
|
||||||
|
|
||||||
typescript-eslint@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3):
|
typescript-eslint@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/eslint-plugin': 8.66.0(@typescript-eslint/parser@8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
'@typescript-eslint/parser': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/parser': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
|
'@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3)
|
||||||
'@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
'@typescript-eslint/utils': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||||
eslint: 10.8.1(jiti@2.7.0)
|
eslint: 10.8.1(jiti@2.7.0)
|
||||||
typescript: 6.0.3
|
typescript: 6.0.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -5183,7 +5174,7 @@ snapshots:
|
|||||||
string-width: 7.2.0
|
string-width: 7.2.0
|
||||||
strip-ansi: 7.2.0
|
strip-ansi: 7.2.0
|
||||||
|
|
||||||
wsl-utils@1.0.0:
|
wsl-utils@0.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-wsl: 3.1.1
|
is-wsl: 3.1.1
|
||||||
powershell-utils: 0.1.0
|
powershell-utils: 0.1.0
|
||||||
@@ -5194,12 +5185,12 @@ snapshots:
|
|||||||
|
|
||||||
yargs-parser@22.0.0: {}
|
yargs-parser@22.0.0: {}
|
||||||
|
|
||||||
yargs@18.1.0:
|
yargs@18.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
cliui: 9.0.1
|
cliui: 9.0.1
|
||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
get-caller-file: 2.0.5
|
get-caller-file: 2.0.5
|
||||||
string-width: 8.2.2
|
string-width: 7.2.0
|
||||||
y18n: 5.0.8
|
y18n: 5.0.8
|
||||||
yargs-parser: 22.0.0
|
yargs-parser: 22.0.0
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ go 1.26.4
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
charm.land/huh/v2 v2.0.3
|
charm.land/huh/v2 v2.0.3
|
||||||
charm.land/lipgloss/v2 v2.0.6
|
charm.land/lipgloss/v2 v2.0.5
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3
|
github.com/cenkalti/backoff/v5 v5.0.3
|
||||||
github.com/docker/docker v28.5.2+incompatible
|
github.com/docker/docker v28.5.2+incompatible
|
||||||
github.com/gin-gonic/gin v1.12.0
|
github.com/gin-gonic/gin v1.12.0
|
||||||
@@ -19,14 +19,14 @@ require (
|
|||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/rs/zerolog v1.35.1
|
github.com/rs/zerolog v1.35.1
|
||||||
github.com/steveiliop56/ding v0.2.0
|
github.com/steveiliop56/ding v0.2.0
|
||||||
github.com/stretchr/testify v1.12.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298
|
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298
|
||||||
github.com/weppos/publicsuffix-go v0.50.3
|
github.com/weppos/publicsuffix-go v0.50.3
|
||||||
go.uber.org/dig v1.19.0
|
go.uber.org/dig v1.19.0
|
||||||
golang.org/x/crypto v0.55.0
|
golang.org/x/crypto v0.54.0
|
||||||
golang.org/x/net v0.58.0
|
golang.org/x/net v0.57.0
|
||||||
golang.org/x/oauth2 v0.36.0
|
golang.org/x/oauth2 v0.36.0
|
||||||
golang.org/x/tools v0.49.0
|
golang.org/x/tools v0.48.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
k8s.io/apimachinery v0.36.3
|
k8s.io/apimachinery v0.36.3
|
||||||
k8s.io/client-go v0.36.3
|
k8s.io/client-go v0.36.3
|
||||||
@@ -51,8 +51,8 @@ require (
|
|||||||
github.com/catppuccin/go v0.3.0 // indirect
|
github.com/catppuccin/go v0.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||||
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 // indirect
|
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.11.8 // indirect
|
github.com/charmbracelet/x/ansi v0.11.7 // indirect
|
||||||
github.com/charmbracelet/x/exp/ordered v0.1.0 // indirect
|
github.com/charmbracelet/x/exp/ordered v0.1.0 // indirect
|
||||||
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
@@ -90,10 +90,10 @@ require (
|
|||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.4.1 // indirect
|
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.24 // indirect
|
github.com/mattn/go-isatty v0.0.24 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
github.com/mattn/go-runewidth v0.0.23 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.32 // indirect
|
github.com/mattn/go-sqlite3 v1.14.32 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
||||||
@@ -110,6 +110,7 @@ require (
|
|||||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/quic-go/qpack v0.6.0 // indirect
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
github.com/quic-go/quic-go v0.59.1 // indirect
|
github.com/quic-go/quic-go v0.59.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
@@ -132,14 +133,13 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
|
||||||
golang.org/x/arch v0.22.0 // indirect
|
golang.org/x/arch v0.22.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||||
golang.org/x/mod v0.39.0 // indirect
|
golang.org/x/mod v0.38.0 // indirect
|
||||||
golang.org/x/sync v0.22.0 // indirect
|
golang.org/x/sync v0.22.0 // indirect
|
||||||
golang.org/x/sys v0.47.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/term v0.45.0 // indirect
|
golang.org/x/term v0.45.0 // indirect
|
||||||
golang.org/x/text v0.41.0 // indirect
|
golang.org/x/text v0.40.0 // indirect
|
||||||
golang.org/x/time v0.14.0 // indirect
|
golang.org/x/time v0.14.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ charm.land/bubbletea/v2 v2.0.2 h1:4CRtRnuZOdFDTWSff9r8QFt/9+z6Emubz3aDMnf/dx0=
|
|||||||
charm.land/bubbletea/v2 v2.0.2/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ=
|
charm.land/bubbletea/v2 v2.0.2/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ=
|
||||||
charm.land/huh/v2 v2.0.3 h1:2cJsMqEPwSywGHvdlKsJyQKPtSJLVnFKyFbsYZTlLkU=
|
charm.land/huh/v2 v2.0.3 h1:2cJsMqEPwSywGHvdlKsJyQKPtSJLVnFKyFbsYZTlLkU=
|
||||||
charm.land/huh/v2 v2.0.3/go.mod h1:93eEveeeqn47MwiC3tf+2atZ2l7Is88rAtmZNZ8x9Wc=
|
charm.land/huh/v2 v2.0.3/go.mod h1:93eEveeeqn47MwiC3tf+2atZ2l7Is88rAtmZNZ8x9Wc=
|
||||||
charm.land/lipgloss/v2 v2.0.6 h1:EaGKeuA8FvF+v2BT5VmZd2LoYLaMZJXA5n34th8nCIQ=
|
charm.land/lipgloss/v2 v2.0.5 h1:kbNxgeeUOYv5J0YdpxFjfvf3dFvqH8Aci4zB6xqFtrY=
|
||||||
charm.land/lipgloss/v2 v2.0.6/go.mod h1:ipDDJNSGa1hlwDtSfW1s2/xR8Vdhbut4PXh2zEKZd0Q=
|
charm.land/lipgloss/v2 v2.0.5/go.mod h1:9oqhxt4yxIMe6q5A4kHr44DremZk7J9UNh74GlWa5nc=
|
||||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||||
@@ -47,10 +47,10 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||||
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 h1:rdnVWKgJpTVXKuKuJyxDJ+NFJdUaUqGvyGy61OcvlbA=
|
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA=
|
||||||
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro=
|
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98=
|
||||||
github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ=
|
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
||||||
github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0=
|
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
|
||||||
github.com/charmbracelet/x/conpty v0.1.1 h1:s1bUxjoi7EpqiXysVtC+a8RrvPPNcNvAjfi4jxsAuEs=
|
github.com/charmbracelet/x/conpty v0.1.1 h1:s1bUxjoi7EpqiXysVtC+a8RrvPPNcNvAjfi4jxsAuEs=
|
||||||
github.com/charmbracelet/x/conpty v0.1.1/go.mod h1:OmtR77VODEFbiTzGE9G1XiRJAga6011PIm4u5fTNZpk=
|
github.com/charmbracelet/x/conpty v0.1.1/go.mod h1:OmtR77VODEFbiTzGE9G1XiRJAga6011PIm4u5fTNZpk=
|
||||||
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA=
|
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA=
|
||||||
@@ -202,16 +202,16 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
|||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lucasb-eyer/go-colorful v1.4.1 h1:1EO+WB73+EH8EVbzlrG3KLAfEypQWVHIBqlTf+2hNss=
|
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
|
||||||
github.com/lucasb-eyer/go-colorful v1.4.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
||||||
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||||
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
|
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||||
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||||
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
||||||
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4=
|
github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4=
|
||||||
@@ -282,17 +282,16 @@ github.com/steveiliop56/ding v0.2.0/go.mod h1:bE2u2XH7CjhPzbb/0Ems+D8YZlf2Ae+eKh
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
|
|
||||||
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298 h1:EYSb5jv8ZL/0/NVFZtY7Ejplk0QG5+3lrdL3mSrjFZQ=
|
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298 h1:EYSb5jv8ZL/0/NVFZtY7Ejplk0QG5+3lrdL3mSrjFZQ=
|
||||||
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298/go.mod h1:TlUDoCF66hMqFZqoBym9bUdJ0bKAWYMir6hLJeYN5z0=
|
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298/go.mod h1:TlUDoCF66hMqFZqoBym9bUdJ0bKAWYMir6hLJeYN5z0=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
@@ -333,18 +332,18 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
|||||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||||
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||||
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
|
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||||
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
|
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||||
golang.org/x/mod v0.39.0 h1:UF5zwQdCRRUpHfyPwr7d4UrGiVeldIsogtzWVnczL74=
|
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||||
golang.org/x/mod v0.39.0/go.mod h1:bvIbwjQ0HUFFf5AKukeeYQG4ZBUG9yxQbR9aEweIwYY=
|
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||||
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||||
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||||
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
@@ -353,12 +352,12 @@ golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
|||||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||||
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||||
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||||
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||||
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
|
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
|
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||||
|
|||||||
@@ -294,7 +294,9 @@ func (controller *OAuthController) getCookieDomain() string {
|
|||||||
|
|
||||||
func (controller *OAuthController) isRedirectSafe(redirectURI string) bool {
|
func (controller *OAuthController) isRedirectSafe(redirectURI string) bool {
|
||||||
v := validators.NewDomainValidator(validators.DomainValidatorOptions{
|
v := validators.NewDomainValidator(validators.DomainValidatorOptions{
|
||||||
WithPort: true,
|
WithPort: true,
|
||||||
|
WithScheme: true,
|
||||||
|
AllowedSchemes: []string{"https", "http"},
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err := v.SafeHostname(controller.runtime.AppURL)
|
_, err := v.SafeHostname(controller.runtime.AppURL)
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ type ProxyContext struct {
|
|||||||
type ProxyController struct {
|
type ProxyController struct {
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
runtime *model.RuntimeConfig
|
runtime *model.RuntimeConfig
|
||||||
|
config *model.Config
|
||||||
acls *service.AccessControlsService
|
acls *service.AccessControlsService
|
||||||
auth *service.AuthService
|
auth *service.AuthService
|
||||||
policyEngine *service.PolicyEngine
|
policyEngine *service.PolicyEngine
|
||||||
@@ -67,6 +68,7 @@ type ProxyControllerInput struct {
|
|||||||
|
|
||||||
Log *logger.Logger
|
Log *logger.Logger
|
||||||
RuntimeConfig *model.RuntimeConfig
|
RuntimeConfig *model.RuntimeConfig
|
||||||
|
Config *model.Config
|
||||||
RouterGroup *gin.RouterGroup `name:"apiRouterGroup"`
|
RouterGroup *gin.RouterGroup `name:"apiRouterGroup"`
|
||||||
ACLsService *service.AccessControlsService
|
ACLsService *service.AccessControlsService
|
||||||
AuthService *service.AuthService
|
AuthService *service.AuthService
|
||||||
@@ -77,6 +79,7 @@ func NewProxyController(i ProxyControllerInput) *ProxyController {
|
|||||||
controller := &ProxyController{
|
controller := &ProxyController{
|
||||||
log: i.Log,
|
log: i.Log,
|
||||||
runtime: i.RuntimeConfig,
|
runtime: i.RuntimeConfig,
|
||||||
|
config: i.Config,
|
||||||
acls: i.ACLsService,
|
acls: i.ACLsService,
|
||||||
auth: i.AuthService,
|
auth: i.AuthService,
|
||||||
policyEngine: i.PolicyEngine,
|
policyEngine: i.PolicyEngine,
|
||||||
@@ -465,6 +468,10 @@ func (controller *ProxyController) getExtAuthzContext(c *gin.Context) (ProxyCont
|
|||||||
// We get the path from the query string
|
// We get the path from the query string
|
||||||
path := c.Query("path")
|
path := c.Query("path")
|
||||||
|
|
||||||
|
if strings.TrimSpace(path) == "" {
|
||||||
|
return ProxyContext{}, errors.New("path not found")
|
||||||
|
}
|
||||||
|
|
||||||
// For envoy we need to support every method
|
// For envoy we need to support every method
|
||||||
method := c.Request.Method
|
method := c.Request.Method
|
||||||
|
|
||||||
@@ -477,14 +484,22 @@ func (controller *ProxyController) getExtAuthzContext(c *gin.Context) (ProxyCont
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (controller *ProxyController) determineAuthModules(proxy ProxyType) []AuthModuleType {
|
func (controller *ProxyController) determineAuthModules(proxy ProxyType, fallbacks bool) []AuthModuleType {
|
||||||
switch proxy {
|
switch proxy {
|
||||||
case Traefik, Caddy:
|
case Traefik, Caddy:
|
||||||
return []AuthModuleType{ForwardAuth}
|
return []AuthModuleType{ForwardAuth}
|
||||||
case Envoy:
|
case Envoy:
|
||||||
return []AuthModuleType{ExtAuthz, ForwardAuth}
|
authModules := []AuthModuleType{ExtAuthz}
|
||||||
|
if fallbacks {
|
||||||
|
authModules = append(authModules, ForwardAuth)
|
||||||
|
}
|
||||||
|
return authModules
|
||||||
case Nginx:
|
case Nginx:
|
||||||
return []AuthModuleType{AuthRequest, ForwardAuth}
|
authModules := []AuthModuleType{AuthRequest}
|
||||||
|
if fallbacks {
|
||||||
|
authModules = append(authModules, ForwardAuth)
|
||||||
|
}
|
||||||
|
return authModules
|
||||||
default:
|
default:
|
||||||
return []AuthModuleType{}
|
return []AuthModuleType{}
|
||||||
}
|
}
|
||||||
@@ -514,6 +529,39 @@ func (controller *ProxyController) getContextFromAuthModule(c *gin.Context, modu
|
|||||||
return ProxyContext{}, fmt.Errorf("unsupported auth module: %v", module)
|
return ProxyContext{}, fmt.Errorf("unsupported auth module: %v", module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (controller *ProxyController) authModuleIdentifiersPresent(c *gin.Context, module AuthModuleType) bool {
|
||||||
|
switch module {
|
||||||
|
case ForwardAuth:
|
||||||
|
_, host := controller.getHeader(c, "x-forwarded-host")
|
||||||
|
_, uri := controller.getHeader(c, "x-forwarded-uri")
|
||||||
|
return host || uri
|
||||||
|
case AuthRequest:
|
||||||
|
_, ok := controller.getHeader(c, "x-original-url")
|
||||||
|
return ok
|
||||||
|
case ExtAuthz:
|
||||||
|
return strings.TrimSpace(c.Query("path")) != ""
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (controller *ProxyController) ensureNoMultipleAuthModules(c *gin.Context, authModules []AuthModuleType) error {
|
||||||
|
present := 0
|
||||||
|
|
||||||
|
for _, module := range authModules {
|
||||||
|
if controller.authModuleIdentifiersPresent(c, module) {
|
||||||
|
present++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if present > 1 {
|
||||||
|
controller.log.App.Warn().Msg("Request carries headers for multiple auth modules, possible spoofing attempt, denying")
|
||||||
|
return fmt.Errorf("conflicting auth module headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (controller *ProxyController) getProxyContext(c *gin.Context) (ProxyContext, error) {
|
func (controller *ProxyController) getProxyContext(c *gin.Context) (ProxyContext, error) {
|
||||||
var req Proxy
|
var req Proxy
|
||||||
|
|
||||||
@@ -530,28 +578,36 @@ func (controller *ProxyController) getProxyContext(c *gin.Context) (ProxyContext
|
|||||||
|
|
||||||
controller.log.App.Debug().Msgf("Determined proxy type: %v", proxy)
|
controller.log.App.Debug().Msgf("Determined proxy type: %v", proxy)
|
||||||
|
|
||||||
authModules := controller.determineAuthModules(proxy)
|
authModules := controller.determineAuthModules(proxy, !controller.config.Experimental.DisableAuthModuleFallback)
|
||||||
|
|
||||||
if len(authModules) == 0 {
|
if len(authModules) == 0 {
|
||||||
return ProxyContext{}, fmt.Errorf("no auth modules supported for proxy: %v", req.Proxy)
|
return ProxyContext{}, fmt.Errorf("no auth modules supported for proxy: %v", req.Proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctx ProxyContext
|
err = controller.ensureNoMultipleAuthModules(c, controller.determineAuthModules(proxy, true))
|
||||||
|
|
||||||
for _, module := range authModules {
|
|
||||||
controller.log.App.Debug().Msgf("Trying to get context from auth module %v", module)
|
|
||||||
ctx, err = controller.getContextFromAuthModule(c, module)
|
|
||||||
if err == nil {
|
|
||||||
controller.log.App.Debug().Msgf("Successfully got context from auth module %v", module)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
controller.log.App.Debug().Msgf("Failed to get context from auth module %v: %v", module, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ProxyContext{}, err
|
return ProxyContext{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ctx *ProxyContext
|
||||||
|
|
||||||
|
for _, module := range authModules {
|
||||||
|
controller.log.App.Debug().Msgf("Trying to get context from auth module %v", module)
|
||||||
|
authModuleCtx, err := controller.getContextFromAuthModule(c, module)
|
||||||
|
if err != nil {
|
||||||
|
controller.log.App.Debug().Msgf("Failed to get context from auth module %v: %v", module, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
controller.log.App.Debug().Msgf("Successfully got context from auth module %v", module)
|
||||||
|
ctx = &authModuleCtx
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx == nil {
|
||||||
|
return ProxyContext{}, fmt.Errorf("failed to get context from any auth module")
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the raw path to populate the cleaned path used for ACLs
|
// Parse the raw path to populate the cleaned path used for ACLs
|
||||||
upath, err := url.Parse(ctx.PathRaw)
|
upath, err := url.Parse(ctx.PathRaw)
|
||||||
|
|
||||||
@@ -577,5 +633,5 @@ func (controller *ProxyController) getProxyContext(c *gin.Context) (ProxyContext
|
|||||||
|
|
||||||
ctx.IsBrowser = isBrowser
|
ctx.IsBrowser = isBrowser
|
||||||
ctx.ProxyType = proxy
|
ctx.ProxyType = proxy
|
||||||
return ctx, nil
|
return *ctx, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
description: "Ensure forward auth fallback for envoy",
|
description: "Ensure forward auth fallback for envoy",
|
||||||
middlewares: []gin.HandlerFunc{},
|
middlewares: []gin.HandlerFunc{},
|
||||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||||
req := httptest.NewRequest("HEAD", "/api/auth/envoy?path=/hello", nil)
|
req := httptest.NewRequest("HEAD", "/api/auth/envoy", nil)
|
||||||
req.Host = ""
|
req.Host = ""
|
||||||
req.Header.Set("x-forwarded-host", "test.example.com")
|
req.Header.Set("x-forwarded-host", "test.example.com")
|
||||||
req.Header.Set("x-forwarded-proto", "https")
|
req.Header.Set("x-forwarded-proto", "https")
|
||||||
@@ -261,7 +261,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
description: "Ensure extauthz with envoy non browser returns json",
|
description: "Ensure extauthz with envoy non browser returns json",
|
||||||
middlewares: []gin.HandlerFunc{},
|
middlewares: []gin.HandlerFunc{},
|
||||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||||
req := httptest.NewRequest("HEAD", "/api/auth/envoy?path=/hello", nil)
|
req := httptest.NewRequest("HEAD", "/api/auth/envoy", nil)
|
||||||
req.Header.Set("x-forwarded-host", "test.example.com")
|
req.Header.Set("x-forwarded-host", "test.example.com")
|
||||||
req.Header.Set("x-forwarded-proto", "https")
|
req.Header.Set("x-forwarded-proto", "https")
|
||||||
req.Header.Set("x-forwarded-uri", "/hello")
|
req.Header.Set("x-forwarded-uri", "/hello")
|
||||||
@@ -877,6 +877,32 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, "bar", recorder.Header().Get("x-foo"))
|
assert.Equal(t, "bar", recorder.Header().Get("x-foo"))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "Forward auth and auth request headers should fail for nginx",
|
||||||
|
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||||
|
req := httptest.NewRequest("GET", "/api/auth/nginx", nil)
|
||||||
|
req.Header.Set("x-forwarded-host", "foo.example.com")
|
||||||
|
req.Header.Set("x-forwarded-proto", "https")
|
||||||
|
req.Header.Set("x-forwarded-uri", "/foo?bar=foo")
|
||||||
|
req.Header.Set("x-original-url", "https://foo.example.com/foo?bar=foo")
|
||||||
|
router.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusBadRequest, recorder.Code)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Forward auth and ext authz headers should fail for envoy",
|
||||||
|
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||||
|
req := httptest.NewRequest("HEAD", "/api/auth/envoy?path=/hello", nil)
|
||||||
|
req.Host = "foo.example.com"
|
||||||
|
req.Header.Set("x-forwarded-host", "foo.example.com")
|
||||||
|
req.Header.Set("x-forwarded-proto", "https")
|
||||||
|
req.Header.Set("x-forwarded-uri", "/foo?bar=foo")
|
||||||
|
router.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusBadRequest, recorder.Code)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
store := memory.New()
|
store := memory.New()
|
||||||
@@ -892,6 +918,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
aclsService := service.NewAccessControlsService(service.AccessControlServiceInput{
|
aclsService := service.NewAccessControlsService(service.AccessControlServiceInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
Config: &cfg,
|
Config: &cfg,
|
||||||
|
Runtime: &runtime,
|
||||||
LabelProvider: nil,
|
LabelProvider: nil,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -952,6 +979,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
NewProxyController(ProxyControllerInput{
|
NewProxyController(ProxyControllerInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
RuntimeConfig: &runtime,
|
RuntimeConfig: &runtime,
|
||||||
|
Config: &cfg,
|
||||||
RouterGroup: group,
|
RouterGroup: group,
|
||||||
ACLsService: aclsService,
|
ACLsService: aclsService,
|
||||||
AuthService: authService,
|
AuthService: authService,
|
||||||
|
|||||||
+14
-21
@@ -239,7 +239,8 @@ type LogStreamConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ExperimentalConfig struct {
|
type ExperimentalConfig struct {
|
||||||
OAuthBridgeEnabled bool `description:"Enable the OAuth bridge, uses a new way to format OAuth user information." yaml:"oauthBridgeEnabled,omitempty"`
|
OAuthBridgeEnabled bool `description:"Enable the OAuth bridge, uses a new way to format OAuth user information." yaml:"oauthBridgeEnabled,omitempty"`
|
||||||
|
DisableAuthModuleFallback bool `description:"Disable the fallback to forward_auth modules when auth_request or ext_authz fail." yaml:"disableAuthModuleFallback,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TailscaleConfig struct {
|
type TailscaleConfig struct {
|
||||||
@@ -253,26 +254,18 @@ type TailscaleConfig struct {
|
|||||||
// OAuth/OIDC config
|
// OAuth/OIDC config
|
||||||
|
|
||||||
type OAuthServiceConfig struct {
|
type OAuthServiceConfig struct {
|
||||||
ClientID string `description:"OAuth client ID." yaml:"clientId,omitempty"`
|
ClientID string `description:"OAuth client ID." yaml:"clientId,omitempty"`
|
||||||
ClientSecret string `description:"OAuth client secret." yaml:"clientSecret,omitempty"`
|
ClientSecret string `description:"OAuth client secret." yaml:"clientSecret,omitempty"`
|
||||||
ClientSecretFile string `description:"Path to the file containing the OAuth client secret." yaml:"clientSecretFile,omitempty"`
|
ClientSecretFile string `description:"Path to the file containing the OAuth client secret." yaml:"clientSecretFile,omitempty"`
|
||||||
Whitelist []string `description:"Comma-separated list of allowed OAuth domains for this provider." yaml:"whitelist,omitempty"`
|
Whitelist []string `description:"Comma-separated list of allowed OAuth domains for this provider." yaml:"whitelist,omitempty"`
|
||||||
WhitelistFile string `description:"Path to the OAuth whitelist file for this provider." yaml:"whitelistFile,omitempty"`
|
WhitelistFile string `description:"Path to the OAuth whitelist file for this provider." yaml:"whitelistFile,omitempty"`
|
||||||
Scopes []string `description:"OAuth scopes." yaml:"scopes,omitempty"`
|
Scopes []string `description:"OAuth scopes." yaml:"scopes,omitempty"`
|
||||||
RedirectURL string `description:"OAuth redirect URL." yaml:"redirectUrl,omitempty"`
|
RedirectURL string `description:"OAuth redirect URL." yaml:"redirectUrl,omitempty"`
|
||||||
AuthURL string `description:"OAuth authorization URL." yaml:"authUrl,omitempty"`
|
AuthURL string `description:"OAuth authorization URL." yaml:"authUrl,omitempty"`
|
||||||
TokenURL string `description:"OAuth token URL." yaml:"tokenUrl,omitempty"`
|
TokenURL string `description:"OAuth token URL." yaml:"tokenUrl,omitempty"`
|
||||||
UserinfoURL string `description:"OAuth userinfo URL." yaml:"userinfoUrl,omitempty"`
|
UserinfoURL string `description:"OAuth userinfo URL." yaml:"userinfoUrl,omitempty"`
|
||||||
Insecure bool `description:"Allow insecure OAuth connections." yaml:"insecure,omitempty"`
|
Insecure bool `description:"Allow insecure OAuth connections." yaml:"insecure,omitempty"`
|
||||||
Name string `description:"Provider name in UI." yaml:"name,omitempty"`
|
Name string `description:"Provider name in UI." yaml:"name,omitempty"`
|
||||||
Claims OAuthServiceClaimsMap `description:"Map of claims to extract from the userinfo response." yaml:"claims,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OAuthServiceClaimsMap struct {
|
|
||||||
Username string `description:"Username claim." yaml:"username,omitempty"`
|
|
||||||
Email string `description:"Email claim." yaml:"email,omitempty"`
|
|
||||||
Name string `description:"Name claim." yaml:"name,omitempty"`
|
|
||||||
Groups string `description:"Groups claim." yaml:"groups,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OIDCClientConfig struct {
|
type OIDCClientConfig struct {
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/tinyauthapp/tinyauth/internal/model"
|
"github.com/tinyauthapp/tinyauth/internal/model"
|
||||||
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
|
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
|
||||||
"github.com/tinyauthapp/tinyauth/pkg/validators"
|
|
||||||
"go.uber.org/dig"
|
"go.uber.org/dig"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ type LabelProvider interface {
|
|||||||
type AccessControlsService struct {
|
type AccessControlsService struct {
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
config *model.Config
|
config *model.Config
|
||||||
|
runtime *model.RuntimeConfig
|
||||||
labelProvider LabelProvider
|
labelProvider LabelProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +28,7 @@ type AccessControlServiceInput struct {
|
|||||||
|
|
||||||
Log *logger.Logger
|
Log *logger.Logger
|
||||||
Config *model.Config
|
Config *model.Config
|
||||||
|
Runtime *model.RuntimeConfig
|
||||||
LabelProvider LabelProvider `optional:"true"`
|
LabelProvider LabelProvider `optional:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,12 +37,38 @@ func NewAccessControlsService(i AccessControlServiceInput) *AccessControlsServic
|
|||||||
return &AccessControlsService{
|
return &AccessControlsService{
|
||||||
log: i.Log,
|
log: i.Log,
|
||||||
config: i.Config,
|
config: i.Config,
|
||||||
|
runtime: i.Runtime,
|
||||||
labelProvider: i.LabelProvider,
|
labelProvider: i.LabelProvider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (service *AccessControlsService) ensureAscii(str string) bool {
|
||||||
|
for i := 0; i < len(str); i++ {
|
||||||
|
if str[i] > unicode.MaxASCII {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *AccessControlsService) normalizeDomain(domain string) string {
|
||||||
|
if host, _, err := net.SplitHostPort(domain); err == nil {
|
||||||
|
domain = host
|
||||||
|
}
|
||||||
|
domain = strings.TrimRight(domain, ".")
|
||||||
|
return strings.ToLower(domain)
|
||||||
|
}
|
||||||
|
|
||||||
func (service *AccessControlsService) getACLs(domain string, lookup func(locator func(name string, app *model.App) bool) error) (*model.App, error) {
|
func (service *AccessControlsService) getACLs(domain string, lookup func(locator func(name string, app *model.App) bool) error) (*model.App, error) {
|
||||||
v := validators.NewDomainValidator(validators.DomainValidatorOptions{})
|
if !service.ensureAscii(domain) {
|
||||||
|
return nil, errors.New("domain contains non-ascii characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizedDomain := service.normalizeDomain(domain)
|
||||||
|
|
||||||
|
if !strings.HasSuffix(normalizedDomain, "."+service.runtime.CookieDomain) && normalizedDomain != service.runtime.CookieDomain {
|
||||||
|
return nil, fmt.Errorf("domain does not match cookie domain, expected %s (or a subdomain), got %s", service.runtime.CookieDomain, domain)
|
||||||
|
}
|
||||||
|
|
||||||
var domainMatch *model.App
|
var domainMatch *model.App
|
||||||
var nameMatch *model.App
|
var nameMatch *model.App
|
||||||
@@ -46,16 +76,18 @@ func (service *AccessControlsService) getACLs(domain string, lookup func(locator
|
|||||||
|
|
||||||
locatorFunc := func(name string, app *model.App) bool {
|
locatorFunc := func(name string, app *model.App) bool {
|
||||||
if app.Config.Domain != "" {
|
if app.Config.Domain != "" {
|
||||||
err := v.Validate(app.Config.Domain, domain)
|
if !service.ensureAscii(app.Config.Domain) {
|
||||||
if err == nil {
|
service.log.App.Warn().Str("name", name).Str("domain", app.Config.Domain).Msg("Domain contains non-ascii characters, skipping")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if normalizedDomain == service.normalizeDomain(app.Config.Domain) {
|
||||||
service.log.App.Debug().Str("name", name).Msg("Found matching container by domain")
|
service.log.App.Debug().Str("name", name).Msg("Found matching container by domain")
|
||||||
domainMatch = app
|
domainMatch = app
|
||||||
return true
|
return true
|
||||||
} else if !errors.Is(err, validators.ErrHostnameMismatch) {
|
|
||||||
service.log.App.Debug().Str("name", name).Err(err).Msg("Domain validation failed")
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(strings.ToLower(domain), strings.ToLower(name+".")) {
|
if strings.HasPrefix(normalizedDomain, strings.ToLower(name+".")) {
|
||||||
service.log.App.Debug().Str("name", name).Msg("Found matching container by app name")
|
service.log.App.Debug().Str("name", name).Msg("Found matching container by app name")
|
||||||
nameMatch = app
|
nameMatch = app
|
||||||
nameMatchedApps = append(nameMatchedApps, name)
|
nameMatchedApps = append(nameMatchedApps, name)
|
||||||
@@ -79,7 +111,7 @@ func (service *AccessControlsService) getACLs(domain string, lookup func(locator
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(nameMatchedApps) > 1 {
|
if len(nameMatchedApps) > 1 {
|
||||||
service.log.App.Warn().Str("domain", domain).Strs("apps", nameMatchedApps).Msg("Multiple apps matched domain by name, app names must be unique, using last match")
|
return nil, fmt.Errorf("domain matched multiple apps by name prefix, use explicit domain config")
|
||||||
}
|
}
|
||||||
|
|
||||||
service.log.App.Debug().Str("domain", domain).Msg("Found matching app by app name")
|
service.log.App.Debug().Str("domain", domain).Msg("Found matching app by app name")
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/tinyauthapp/tinyauth/internal/model"
|
"github.com/tinyauthapp/tinyauth/internal/model"
|
||||||
|
"github.com/tinyauthapp/tinyauth/internal/test"
|
||||||
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
|
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,14 +36,25 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
log := logger.NewLogger().WithTestConfig()
|
log := logger.NewLogger().WithTestConfig()
|
||||||
log.Init()
|
log.Init()
|
||||||
|
|
||||||
|
_, runtime := test.CreateTestConfigs(t)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
domain string
|
domain string
|
||||||
acls map[string]model.App
|
acls map[string]model.App
|
||||||
want *model.App
|
want *model.App
|
||||||
|
errorFunc func(t *testing.T, e error)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "returns ACLs for domain",
|
name: "returns ACLs for domain",
|
||||||
|
domain: "app.example.com",
|
||||||
|
acls: map[string]model.App{
|
||||||
|
"foo": {Config: model.AppConfig{Domain: "app.example.com"}},
|
||||||
|
},
|
||||||
|
want: &model.App{Config: model.AppConfig{Domain: "app.example.com"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "returns ACLs for root domain",
|
||||||
domain: "example.com",
|
domain: "example.com",
|
||||||
acls: map[string]model.App{
|
acls: map[string]model.App{
|
||||||
"foo": {Config: model.AppConfig{Domain: "example.com"}},
|
"foo": {Config: model.AppConfig{Domain: "example.com"}},
|
||||||
@@ -65,20 +78,11 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
want: &model.App{Config: model.AppConfig{Domain: "example.com"}},
|
want: &model.App{Config: model.AppConfig{Domain: "example.com"}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "returns ACLs for non-ascii domain",
|
name: "returns error for non-ascii domain",
|
||||||
domain: "bücher.example.com",
|
domain: "bücher.example.com",
|
||||||
acls: map[string]model.App{
|
errorFunc: func(t *testing.T, e error) {
|
||||||
"foo": {Config: model.AppConfig{Domain: "bücher.example.com"}},
|
assert.ErrorContains(t, e, "domain contains non-ascii characters")
|
||||||
},
|
},
|
||||||
want: &model.App{Config: model.AppConfig{Domain: "bücher.example.com"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "returns ACLs for punycode domain and non-ascii config",
|
|
||||||
domain: "bücher.example.com",
|
|
||||||
acls: map[string]model.App{
|
|
||||||
"foo": {Config: model.AppConfig{Domain: "xn--bcher-kva.example.com"}},
|
|
||||||
},
|
|
||||||
want: &model.App{Config: model.AppConfig{Domain: "xn--bcher-kva.example.com"}},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "returns ACLs with case-insensitive matching",
|
name: "returns ACLs with case-insensitive matching",
|
||||||
@@ -110,6 +114,33 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
acls: map[string]model.App{},
|
acls: map[string]model.App{},
|
||||||
want: nil,
|
want: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "App in domain not matching with the cookie domain should return nothing with name matching",
|
||||||
|
domain: "foo.bad_example.com",
|
||||||
|
acls: map[string]model.App{
|
||||||
|
"foo": {
|
||||||
|
Path: model.AppPath{Allow: "/foo"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
errorFunc: func(t *testing.T, e error) {
|
||||||
|
assert.ErrorContains(t, e, "domain does not match cookie domain")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "App in domain not matching with the cookie domain should return nothing with domain matching",
|
||||||
|
domain: "foo.bad_example.com",
|
||||||
|
acls: map[string]model.App{
|
||||||
|
"foo": {
|
||||||
|
Path: model.AppPath{Allow: "/foo"},
|
||||||
|
Config: model.AppConfig{Domain: "foo.bad_example.com"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
errorFunc: func(t *testing.T, e error) {
|
||||||
|
assert.ErrorContains(t, e, "domain does not match cookie domain")
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// run once for a mock provider
|
// run once for a mock provider
|
||||||
@@ -118,10 +149,15 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
mock := newMockProvider(test.acls, false)
|
mock := newMockProvider(test.acls, false)
|
||||||
acls := NewAccessControlsService(AccessControlServiceInput{
|
acls := NewAccessControlsService(AccessControlServiceInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
|
Runtime: &runtime,
|
||||||
Config: &model.Config{},
|
Config: &model.Config{},
|
||||||
LabelProvider: mock,
|
LabelProvider: mock,
|
||||||
})
|
})
|
||||||
app, err := acls.getACLs(test.domain, mock.Lookup)
|
app, err := acls.getACLs(test.domain, mock.Lookup)
|
||||||
|
if test.errorFunc != nil {
|
||||||
|
test.errorFunc(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, test.want, app)
|
require.Equal(t, test.want, app)
|
||||||
})
|
})
|
||||||
@@ -131,12 +167,17 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name+"(staticACLs)", func(t *testing.T) {
|
t.Run(test.name+"(staticACLs)", func(t *testing.T) {
|
||||||
acls := NewAccessControlsService(AccessControlServiceInput{
|
acls := NewAccessControlsService(AccessControlServiceInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
|
Runtime: &runtime,
|
||||||
Config: &model.Config{
|
Config: &model.Config{
|
||||||
Apps: test.acls,
|
Apps: test.acls,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
app, err := acls.lookupStaticACLs(test.domain)
|
app, err := acls.lookupStaticACLs(test.domain)
|
||||||
|
if test.errorFunc != nil {
|
||||||
|
test.errorFunc(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, test.want, app)
|
require.Equal(t, test.want, app)
|
||||||
})
|
})
|
||||||
@@ -145,16 +186,32 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
// get acls should return an error when the provider fails
|
// get acls should return an error when the provider fails
|
||||||
mock := newMockProvider(map[string]model.App{}, true)
|
mock := newMockProvider(map[string]model.App{}, true)
|
||||||
acls := NewAccessControlsService(AccessControlServiceInput{
|
acls := NewAccessControlsService(AccessControlServiceInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
Config: &model.Config{},
|
Runtime: &runtime,
|
||||||
|
Config: &model.Config{},
|
||||||
})
|
})
|
||||||
_, err := acls.getACLs("example.com", mock.Lookup)
|
_, err := acls.getACLs("example.com", mock.Lookup)
|
||||||
require.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
// get acls should return an error when multiple apps with the same domain exist
|
||||||
|
acls = NewAccessControlsService(AccessControlServiceInput{
|
||||||
|
Log: log,
|
||||||
|
Runtime: &runtime,
|
||||||
|
Config: &model.Config{
|
||||||
|
Apps: map[string]model.App{
|
||||||
|
"foo": {Path: model.AppPath{Allow: "/foo"}},
|
||||||
|
"foo.bar": {Path: model.AppPath{Allow: "/bar"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
_, err = acls.GetAccessControls("foo.bar.example.com")
|
||||||
|
assert.ErrorContains(t, err, "domain matched multiple apps by name prefix, use explicit domain config")
|
||||||
|
|
||||||
// get access controls should get acls from
|
// get access controls should get acls from
|
||||||
// static when static acls are configured
|
// static when static acls are configured
|
||||||
acls = NewAccessControlsService(AccessControlServiceInput{
|
acls = NewAccessControlsService(AccessControlServiceInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
|
Runtime: &runtime,
|
||||||
Config: &model.Config{
|
Config: &model.Config{
|
||||||
Apps: map[string]model.App{
|
Apps: map[string]model.App{
|
||||||
"foo": {Config: model.AppConfig{Domain: "foo.example.com"}},
|
"foo": {Config: model.AppConfig{Domain: "foo.example.com"}},
|
||||||
@@ -163,12 +220,12 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
})
|
})
|
||||||
app, err := acls.GetAccessControls("foo.example.com")
|
app, err := acls.GetAccessControls("foo.example.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &model.App{Config: model.AppConfig{Domain: "foo.example.com"}}, app)
|
assert.Equal(t, &model.App{Config: model.AppConfig{Domain: "foo.example.com"}}, app)
|
||||||
|
|
||||||
// should return nil for no apps
|
// should return nil for no apps
|
||||||
app, err = acls.GetAccessControls("bar.example.com")
|
app, err = acls.GetAccessControls("bar.example.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Nil(t, app)
|
assert.Nil(t, app)
|
||||||
|
|
||||||
// Should use label provider if available
|
// Should use label provider if available
|
||||||
mock = newMockProvider(map[string]model.App{
|
mock = newMockProvider(map[string]model.App{
|
||||||
@@ -178,10 +235,11 @@ func TestAccessControlsService(t *testing.T) {
|
|||||||
}, false)
|
}, false)
|
||||||
acls = NewAccessControlsService(AccessControlServiceInput{
|
acls = NewAccessControlsService(AccessControlServiceInput{
|
||||||
Log: log,
|
Log: log,
|
||||||
|
Runtime: &runtime,
|
||||||
Config: &model.Config{},
|
Config: &model.Config{},
|
||||||
LabelProvider: mock,
|
LabelProvider: mock,
|
||||||
})
|
})
|
||||||
app, err = acls.GetAccessControls("bar.example.com")
|
app, err = acls.GetAccessControls("bar.example.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &model.App{Config: model.AppConfig{Domain: "bar.example.com"}}, app)
|
assert.Equal(t, &model.App{Config: model.AppConfig{Domain: "bar.example.com"}}, app)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,11 @@ type GithubUserinfoResponse struct {
|
|||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultExtractor(client *http.Client, ctx context.Context, url string, mapClaims MapClaims) (*model.Claims, error) {
|
func defaultExtractor(client *http.Client, ctx context.Context, url string) (*model.Claims, error) {
|
||||||
claims, err := simpleReq[map[string]any](client, ctx, url, nil)
|
return simpleReq[model.Claims](client, ctx, url, nil)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return new(mapClaims(*claims)), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func githubExtractor(client *http.Client, ctx context.Context, _ string, _ MapClaims) (*model.Claims, error) {
|
func githubExtractor(client *http.Client, ctx context.Context, _ string) (*model.Claims, error) {
|
||||||
var user model.Claims
|
var user model.Claims
|
||||||
|
|
||||||
userInfo, err := simpleReq[GithubUserinfoResponse](client, ctx, "https://api.github.com/user", map[string]string{
|
userInfo, err := simpleReq[GithubUserinfoResponse](client, ctx, "https://api.github.com/user", map[string]string{
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MapClaims func(claims map[string]any) model.Claims
|
type OAuthUserinfoExtractor func(client *http.Client, ctx context.Context, url string) (*model.Claims, error)
|
||||||
type OAuthUserinfoExtractor func(client *http.Client, ctx context.Context, url string, mapClaims MapClaims) (*model.Claims, error)
|
|
||||||
|
|
||||||
type OAuthService struct {
|
type OAuthService struct {
|
||||||
serviceCfg model.OAuthServiceConfig
|
serviceCfg model.OAuthServiceConfig
|
||||||
@@ -82,7 +81,7 @@ func (s *OAuthService) GetToken(code string, verifier string) (*oauth2.Token, er
|
|||||||
|
|
||||||
func (s *OAuthService) GetUserinfo(token *oauth2.Token) (*model.Claims, error) {
|
func (s *OAuthService) GetUserinfo(token *oauth2.Token) (*model.Claims, error) {
|
||||||
client := oauth2.NewClient(s.ctx, oauth2.StaticTokenSource(token))
|
client := oauth2.NewClient(s.ctx, oauth2.StaticTokenSource(token))
|
||||||
return s.userinfoExtractor(client, s.ctx, s.serviceCfg.UserinfoURL, s.mapClaims)
|
return s.userinfoExtractor(client, s.ctx, s.serviceCfg.UserinfoURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OAuthService) GetConfig() model.OAuthServiceConfig {
|
func (s *OAuthService) GetConfig() model.OAuthServiceConfig {
|
||||||
@@ -98,26 +97,3 @@ func (s *OAuthService) UpdateConfig(config model.OAuthServiceConfig) {
|
|||||||
s.config.Endpoint.TokenURL = config.TokenURL
|
s.config.Endpoint.TokenURL = config.TokenURL
|
||||||
s.config.RedirectURL = config.RedirectURL
|
s.config.RedirectURL = config.RedirectURL
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OAuthService) mapClaims(claims map[string]any) model.Claims {
|
|
||||||
return model.Claims{
|
|
||||||
Sub: mapClaim[string]("sub", "", claims),
|
|
||||||
Name: mapClaim[string]("name", s.serviceCfg.Claims.Name, claims),
|
|
||||||
PreferredUsername: mapClaim[string]("preferred_username", s.serviceCfg.Claims.Username, claims),
|
|
||||||
Email: mapClaim[string]("email", s.serviceCfg.Claims.Email, claims),
|
|
||||||
Groups: mapClaim[any]("groups", s.serviceCfg.Claims.Groups, claims),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapClaim[T any](fallback, override string, kv map[string]any) T {
|
|
||||||
key := fallback
|
|
||||||
if override != "" {
|
|
||||||
key = override
|
|
||||||
}
|
|
||||||
v, ok := kv[key].(T)
|
|
||||||
if !ok {
|
|
||||||
var zero T
|
|
||||||
return zero
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -38,7 +38,16 @@ func SafeParseAppURL(str string) (string, error) {
|
|||||||
return "", fmt.Errorf("ip addresses not allowed")
|
return "", fmt.Errorf("ip addresses not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname, err = idna.Lookup.ToASCII(hostname)
|
i := idna.New(
|
||||||
|
idna.MapForLookup(),
|
||||||
|
idna.Transitional(false),
|
||||||
|
idna.BidiRule(),
|
||||||
|
idna.StrictDomainName(false),
|
||||||
|
idna.CheckHyphens(true),
|
||||||
|
idna.CheckJoiners(false),
|
||||||
|
)
|
||||||
|
|
||||||
|
hostname, err = i.ToASCII(hostname)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to convert hostname to ascii: %w", err)
|
return "", fmt.Errorf("failed to convert hostname to ascii: %w", err)
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ func TestSafeParseAPPURL(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expected, result)
|
assert.Equal(t, expected, result)
|
||||||
|
|
||||||
|
// Underscores
|
||||||
|
appURL = "http://sub_tinyauth.app"
|
||||||
|
expected = "http://sub_tinyauth.app"
|
||||||
|
result, err = utils.SafeParseAppURL(appURL)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, result)
|
||||||
|
|
||||||
// Lowercase
|
// Lowercase
|
||||||
appURL = "HTTP://SUb.tinyAUth.aPP"
|
appURL = "HTTP://SUb.tinyAUth.aPP"
|
||||||
expected = "http://sub.tinyauth.app"
|
expected = "http://sub.tinyauth.app"
|
||||||
@@ -66,7 +73,7 @@ func TestSafeParseAPPURL(t *testing.T) {
|
|||||||
assert.ErrorContains(t, err, "invalid url")
|
assert.ErrorContains(t, err, "invalid url")
|
||||||
|
|
||||||
// Invalid punycode
|
// Invalid punycode
|
||||||
appURL = "http://ab--cd.example.com"
|
appURL = "http://xn--h-kva.example.com"
|
||||||
_, err = utils.SafeParseAppURL(appURL)
|
_, err = utils.SafeParseAppURL(appURL)
|
||||||
assert.ErrorContains(t, err, "failed to convert hostname to ascii")
|
assert.ErrorContains(t, err, "failed to convert hostname to ascii")
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/net/idna"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
@@ -114,15 +112,11 @@ func (v *DomainValidator) getURL(i string) (*url.URL, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *DomainValidator) getHostname(hostname string) (string, error) {
|
func (v *DomainValidator) getHostname(hostname string) (string, error) {
|
||||||
hostname = strings.ToLower(hostname)
|
|
||||||
hostname = strings.TrimSuffix(hostname, ".")
|
|
||||||
if net.ParseIP(hostname) != nil {
|
if net.ParseIP(hostname) != nil {
|
||||||
return "", fmt.Errorf("ip addresses are not supported")
|
return "", fmt.Errorf("ip addresses are not supported")
|
||||||
}
|
}
|
||||||
hostname, err := idna.Lookup.ToASCII(hostname)
|
hostname = strings.ToLower(hostname)
|
||||||
if err != nil {
|
hostname = strings.TrimSuffix(hostname, ".")
|
||||||
return "", fmt.Errorf("failed to convert hostname to ascii: %w", err)
|
|
||||||
}
|
|
||||||
return hostname, nil
|
return hostname, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,18 +101,6 @@ func TestDomainValidator_SafeHostname(t *testing.T) {
|
|||||||
assert.ErrorContains(t, e, "ip addresses are not supported")
|
assert.ErrorContains(t, e, "ip addresses are not supported")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
description: "Domains with unicode characters should be allowed",
|
|
||||||
input: "bücher.example.com",
|
|
||||||
expected: "xn--bcher-kva.example.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Invalid IDNA domain should fail",
|
|
||||||
input: "ab--cd.example.com",
|
|
||||||
errorFunc: func(t *testing.T, e error) {
|
|
||||||
assert.ErrorContains(t, e, "invalid label")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
description: "With port enabled without any port should work",
|
description: "With port enabled without any port should work",
|
||||||
options: DomainValidatorOptions{WithPort: true},
|
options: DomainValidatorOptions{WithPort: true},
|
||||||
@@ -194,22 +182,6 @@ func TestDomainValidator_Validate(t *testing.T) {
|
|||||||
expected: "https://example.com:443",
|
expected: "https://example.com:443",
|
||||||
actual: "https://example.com:443",
|
actual: "https://example.com:443",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
description: "Failure to format expected domain should fail",
|
|
||||||
expected: "ab--cd.example.com",
|
|
||||||
actual: "example.com",
|
|
||||||
errorFunc: func(t *testing.T, e error) {
|
|
||||||
assert.ErrorContains(t, e, "idna: invalid label")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Failure to format check domain should fail",
|
|
||||||
expected: "example.com",
|
|
||||||
actual: "ab--cd.example.com",
|
|
||||||
errorFunc: func(t *testing.T, e error) {
|
|
||||||
assert.ErrorContains(t, e, "idna: invalid label")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
description: "Valid domains with matching schemes and ports should pass",
|
description: "Valid domains with matching schemes and ports should pass",
|
||||||
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}, WithPort: true},
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}, WithPort: true},
|
||||||
@@ -236,16 +208,6 @@ func TestDomainValidator_Validate(t *testing.T) {
|
|||||||
actual: "example.com",
|
actual: "example.com",
|
||||||
expected: "example.com",
|
expected: "example.com",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
description: "Unicode valid domains should pass",
|
|
||||||
expected: "xn--bcher-kva.example.com",
|
|
||||||
actual: "bücher.example.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Unicode valid domains should pass (reverse)",
|
|
||||||
expected: "bücher.example.com",
|
|
||||||
actual: "xn--bcher-kva.example.com",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
description: "Non matching hostnames should fail",
|
description: "Non matching hostnames should fail",
|
||||||
expected: "example.com",
|
expected: "example.com",
|
||||||
|
|||||||
Reference in New Issue
Block a user