mirror of
https://github.com/tinyauthapp/tinyauth.git
synced 2026-09-12 02:43:30 +08:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbd53437e1 |
@@ -171,14 +171,6 @@ TINYAUTH_OAUTH_PROVIDERS_name_USERINFOURL=
|
||||
TINYAUTH_OAUTH_PROVIDERS_name_INSECURE=false
|
||||
# Provider name in UI.
|
||||
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
|
||||
|
||||
|
||||
@@ -11,17 +11,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # ratchet:actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
||||
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # ratchet:pnpm/action-setup@v6
|
||||
with:
|
||||
package_json_file: ./e2e/package.json
|
||||
|
||||
- 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
|
||||
run: pnpm ci
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
run: pnpm test
|
||||
working-directory: e2e
|
||||
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # ratchet:actions/upload-artifact@v4
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: playwright-report
|
||||
|
||||
@@ -174,7 +174,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -233,7 +233,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -292,7 +292,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -351,7 +351,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -406,7 +406,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
@@ -445,7 +445,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -260,7 +260,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -317,7 +317,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
|
||||
@@ -373,7 +373,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
@@ -414,7 +414,7 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
|
||||
@@ -38,6 +38,6 @@ jobs:
|
||||
retention-days: 5
|
||||
|
||||
- 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:
|
||||
sarif_file: results.sarif
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ COPY ./frontend/vite.config.ts ./
|
||||
RUN pnpm run build
|
||||
|
||||
# Builder
|
||||
FROM golang:1.27-alpine3.23 AS builder
|
||||
FROM golang:1.26-alpine3.23 AS builder
|
||||
|
||||
ARG VERSION
|
||||
ARG COMMIT_HASH
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.27-alpine3.23
|
||||
FROM golang:1.26-alpine3.23
|
||||
|
||||
WORKDIR /tinyauth
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ COPY ./frontend/vite.config.ts ./
|
||||
RUN pnpm run build
|
||||
|
||||
# Builder
|
||||
FROM golang:1.27-alpine3.23 AS builder
|
||||
FROM golang:1.26-alpine3.23 AS builder
|
||||
|
||||
ARG VERSION
|
||||
ARG COMMIT_HASH
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"packageManager": "pnpm@11.1.2",
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^5.9.0",
|
||||
"@hookform/resolvers": "^5.7.1",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
||||
"@radix-ui/react-label": "^2.1.15",
|
||||
"@radix-ui/react-select": "^2.3.7",
|
||||
@@ -49,12 +49,12 @@
|
||||
"@vitejs/plugin-react": "^6.0.5",
|
||||
"eslint": "^10.8.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.4",
|
||||
"globals": "^17.11.0",
|
||||
"rollup-plugin-visualizer": "^7.1.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.3",
|
||||
"globals": "^17.9.0",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "~6.0.2",
|
||||
"typescript-eslint": "^8.67.0",
|
||||
"typescript-eslint": "^8.66.0",
|
||||
"vite": "^8.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+115
-124
@@ -9,8 +9,8 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.9.0
|
||||
version: 5.9.0(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)
|
||||
specifier: ^5.7.1
|
||||
version: 5.7.1(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)
|
||||
'@radix-ui/react-dropdown-menu':
|
||||
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)
|
||||
@@ -115,14 +115,14 @@ importers:
|
||||
specifier: ^7.0.1
|
||||
version: 7.1.1(eslint@10.8.1(jiti@2.7.0))
|
||||
eslint-plugin-react-refresh:
|
||||
specifier: ^0.5.4
|
||||
version: 0.5.4(eslint@10.8.1(jiti@2.7.0))
|
||||
specifier: ^0.5.3
|
||||
version: 0.5.3(eslint@10.8.1(jiti@2.7.0))
|
||||
globals:
|
||||
specifier: ^17.11.0
|
||||
version: 17.11.0
|
||||
specifier: ^17.9.0
|
||||
version: 17.9.0
|
||||
rollup-plugin-visualizer:
|
||||
specifier: ^7.1.1
|
||||
version: 7.1.1(rolldown@1.2.3)
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1(rolldown@1.2.3)
|
||||
tw-animate-css:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
@@ -130,8 +130,8 @@ importers:
|
||||
specifier: ~6.0.2
|
||||
version: 6.0.3
|
||||
typescript-eslint:
|
||||
specifier: ^8.67.0
|
||||
version: 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||
specifier: ^8.66.0
|
||||
version: 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||
vite:
|
||||
specifier: ^8.2.1
|
||||
version: 8.2.1(@types/node@26.2.0)(jiti@2.7.0)
|
||||
@@ -267,8 +267,8 @@ packages:
|
||||
'@floating-ui/utils@0.2.12':
|
||||
resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
|
||||
|
||||
'@hookform/resolvers@5.9.0':
|
||||
resolution: {integrity: sha512-8sNo1IklGaONrsKzXjwZJNsPbccAXLXGX//G+VFEcQOviMtbvR8/fM6HWyA0qrjgpOYauwoodda53CQIWOZ7Ag==}
|
||||
'@hookform/resolvers@5.7.1':
|
||||
resolution: {integrity: sha512-8wS/P4UDr5sQDe4nFaV51TVyfDPrWgNIXweqG0Bs9Z5LSuzKLb+RQNPvkN2oHM5SRrJyWrVH/F+LOUcFjUyvwQ==}
|
||||
peerDependencies:
|
||||
'@sinclair/typebox': '>=0.25.24'
|
||||
'@standard-schema/spec': ^1.0.0
|
||||
@@ -286,13 +286,13 @@ packages:
|
||||
fluentvalidation-ts: ^3.0.0
|
||||
fp-ts: ^2.7.0
|
||||
io-ts: ^2.0.0
|
||||
joi: ^17.0.0 || ^18.0.0
|
||||
joi: ^17.0.0
|
||||
nope-validator: '>=0.12.0'
|
||||
react-hook-form: ^7.55.0
|
||||
superstruct: '>=0.12.0'
|
||||
typanion: ^3.3.2
|
||||
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
|
||||
zod: ^3.25.0 || ^4.0.0
|
||||
peerDependenciesMeta:
|
||||
@@ -1322,16 +1322,16 @@ packages:
|
||||
'@types/unist@3.0.3':
|
||||
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.67.0':
|
||||
resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==}
|
||||
'@typescript-eslint/eslint-plugin@8.66.0':
|
||||
resolution: {integrity: sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^8.67.0
|
||||
'@typescript-eslint/parser': ^8.66.0
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/parser@8.67.0':
|
||||
resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==}
|
||||
'@typescript-eslint/parser@8.66.0':
|
||||
resolution: {integrity: sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
@@ -1343,8 +1343,8 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/project-service@8.67.0':
|
||||
resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==}
|
||||
'@typescript-eslint/project-service@8.66.0':
|
||||
resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
@@ -1353,8 +1353,8 @@ packages:
|
||||
resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/scope-manager@8.67.0':
|
||||
resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==}
|
||||
'@typescript-eslint/scope-manager@8.66.0':
|
||||
resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.65.0':
|
||||
@@ -1363,14 +1363,14 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.67.0':
|
||||
resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==}
|
||||
'@typescript-eslint/tsconfig-utils@8.66.0':
|
||||
resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/type-utils@8.67.0':
|
||||
resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==}
|
||||
'@typescript-eslint/type-utils@8.66.0':
|
||||
resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
@@ -1380,8 +1380,8 @@ packages:
|
||||
resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/types@8.67.0':
|
||||
resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==}
|
||||
'@typescript-eslint/types@8.66.0':
|
||||
resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.65.0':
|
||||
@@ -1390,8 +1390,8 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.67.0':
|
||||
resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==}
|
||||
'@typescript-eslint/typescript-estree@8.66.0':
|
||||
resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
@@ -1403,8 +1403,8 @@ packages:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/utils@8.67.0':
|
||||
resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==}
|
||||
'@typescript-eslint/utils@8.66.0':
|
||||
resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
@@ -1414,8 +1414,8 @@ packages:
|
||||
resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.67.0':
|
||||
resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==}
|
||||
'@typescript-eslint/visitor-keys@8.66.0':
|
||||
resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@ungap/structured-clone@1.3.1':
|
||||
@@ -1451,8 +1451,8 @@ packages:
|
||||
ajv@6.15.0:
|
||||
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
|
||||
|
||||
ansi-regex@6.3.0:
|
||||
resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==}
|
||||
ansi-regex@6.2.2:
|
||||
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ansi-styles@6.2.3:
|
||||
@@ -1636,8 +1636,8 @@ packages:
|
||||
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-plugin-react-refresh@0.5.4:
|
||||
resolution: {integrity: sha512-7bqTKz7T0r+HKWFarNXByDE9/5+73wI2ru+M3zuqGbR7s/b/5/pQJXZoufWlrngqGqoZto73ZkGumCdLxk+4rw==}
|
||||
eslint-plugin-react-refresh@0.5.3:
|
||||
resolution: {integrity: sha512-5EMmLCV98Pi4o/f/3DP/v/tNqLHMIc9I8LKClNDWhZ9JTho89/kQcitCXQBMG7sAfVRK0Ie3T2EDOzp1YXYiVA==}
|
||||
peerDependencies:
|
||||
eslint: ^9 || ^10
|
||||
|
||||
@@ -1771,8 +1771,8 @@ packages:
|
||||
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
globals@17.11.0:
|
||||
resolution: {integrity: sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==}
|
||||
globals@17.9.0:
|
||||
resolution: {integrity: sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
gopd@1.2.0:
|
||||
@@ -2212,8 +2212,8 @@ packages:
|
||||
node-releases@2.0.44:
|
||||
resolution: {integrity: sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==}
|
||||
|
||||
open@11.0.1:
|
||||
resolution: {integrity: sha512-NzwMUB6C1D0+Kd+9iMS/H4k+Ck3cTX6Ckyfr/gAGlmvSE1LUQZnEZvWBi4PYmMwH/S5SMeTXnE+9uAz8uF+pWw==}
|
||||
open@11.0.0:
|
||||
resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
optionator@0.9.4:
|
||||
@@ -2242,6 +2242,10 @@ packages:
|
||||
picocolors@1.1.1:
|
||||
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:
|
||||
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2254,10 +2258,6 @@ packages:
|
||||
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
powershell-utils@0.2.0:
|
||||
resolution: {integrity: sha512-ZlsFlG7MtSFCoc5xreOvBAozCJ6Pf06opgJjh9ONEv418xpZSAzNjstD36C6+JwOnfSqOW/9uDkqKjezTdxZhw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
prelude-ls@1.2.1:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -2374,8 +2374,8 @@ packages:
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
|
||||
rollup-plugin-visualizer@7.1.1:
|
||||
resolution: {integrity: sha512-ThaGiHTU8XW02OkK80TrTHATraJmM9OAduU4otal+7gyXLpYEtmGBLfx5kW+EHvvLwn03YGW2NnwKUIqsYlJAA==}
|
||||
rollup-plugin-visualizer@7.0.1:
|
||||
resolution: {integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg==}
|
||||
engines: {node: '>=22'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -2425,8 +2425,8 @@ packages:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
source-map@0.8.0:
|
||||
resolution: {integrity: sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==}
|
||||
source-map@0.7.6:
|
||||
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
space-separated-tokens@2.0.2:
|
||||
@@ -2436,10 +2436,6 @@ packages:
|
||||
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
string-width@8.2.2:
|
||||
resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
stringify-entities@4.0.4:
|
||||
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
|
||||
|
||||
@@ -2489,8 +2485,8 @@ packages:
|
||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
typescript-eslint@8.67.0:
|
||||
resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==}
|
||||
typescript-eslint@8.66.0:
|
||||
resolution: {integrity: sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
@@ -2618,8 +2614,8 @@ packages:
|
||||
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
wsl-utils@1.0.0:
|
||||
resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==}
|
||||
wsl-utils@0.3.1:
|
||||
resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
y18n@5.0.8:
|
||||
@@ -2633,8 +2629,8 @@ packages:
|
||||
resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
|
||||
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||
|
||||
yargs@18.1.0:
|
||||
resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==}
|
||||
yargs@18.0.0:
|
||||
resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==}
|
||||
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||
|
||||
yocto-queue@0.1.0:
|
||||
@@ -2810,7 +2806,7 @@ snapshots:
|
||||
|
||||
'@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:
|
||||
'@standard-schema/utils': 0.3.0
|
||||
react-hook-form: 7.85.0(react@19.2.8)
|
||||
@@ -3771,14 +3767,14 @@ snapshots:
|
||||
|
||||
'@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:
|
||||
'@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/scope-manager': 8.67.0
|
||||
'@typescript-eslint/type-utils': 8.67.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/visitor-keys': 8.67.0
|
||||
'@typescript-eslint/parser': 8.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.66.0
|
||||
'@typescript-eslint/type-utils': 8.66.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.66.0
|
||||
eslint: 10.8.1(jiti@2.7.0)
|
||||
ignore: 7.0.6
|
||||
natural-compare: 1.4.0
|
||||
@@ -3787,12 +3783,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
'@typescript-eslint/scope-manager': 8.67.0
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.67.0
|
||||
'@typescript-eslint/scope-manager': 8.66.0
|
||||
'@typescript-eslint/types': 8.66.0
|
||||
'@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.66.0
|
||||
debug: 4.4.3
|
||||
eslint: 10.8.1(jiti@2.7.0)
|
||||
typescript: 6.0.3
|
||||
@@ -3808,10 +3804,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
'@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.66.0
|
||||
debug: 4.4.3
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -3822,24 +3818,24 @@ snapshots:
|
||||
'@typescript-eslint/types': 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:
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/visitor-keys': 8.67.0
|
||||
'@typescript-eslint/types': 8.66.0
|
||||
'@typescript-eslint/visitor-keys': 8.66.0
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.65.0(typescript@6.0.3)':
|
||||
dependencies:
|
||||
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:
|
||||
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:
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/typescript-estree': 8.67.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/types': 8.66.0
|
||||
'@typescript-eslint/typescript-estree': 8.66.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
|
||||
eslint: 10.8.1(jiti@2.7.0)
|
||||
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.67.0': {}
|
||||
'@typescript-eslint/types@8.66.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.65.0(typescript@6.0.3)':
|
||||
dependencies:
|
||||
@@ -3866,12 +3862,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
'@typescript-eslint/project-service': 8.67.0(typescript@6.0.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/visitor-keys': 8.67.0
|
||||
'@typescript-eslint/project-service': 8.66.0(typescript@6.0.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.66.0
|
||||
'@typescript-eslint/visitor-keys': 8.66.0
|
||||
debug: 4.4.3
|
||||
minimatch: 10.2.6
|
||||
semver: 7.8.5
|
||||
@@ -3892,12 +3888,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0))
|
||||
'@typescript-eslint/scope-manager': 8.67.0
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.66.0
|
||||
'@typescript-eslint/types': 8.66.0
|
||||
'@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3)
|
||||
eslint: 10.8.1(jiti@2.7.0)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -3908,9 +3904,9 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.65.0
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.67.0':
|
||||
'@typescript-eslint/visitor-keys@8.66.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.67.0
|
||||
'@typescript-eslint/types': 8.66.0
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
'@ungap/structured-clone@1.3.1': {}
|
||||
@@ -3939,7 +3935,7 @@ snapshots:
|
||||
json-schema-traverse: 0.4.1
|
||||
uri-js: 4.4.1
|
||||
|
||||
ansi-regex@6.3.0: {}
|
||||
ansi-regex@6.2.2: {}
|
||||
|
||||
ansi-styles@6.2.3: {}
|
||||
|
||||
@@ -4104,7 +4100,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- 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:
|
||||
eslint: 10.8.1(jiti@2.7.0)
|
||||
|
||||
@@ -4249,7 +4245,7 @@ snapshots:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
|
||||
globals@17.11.0: {}
|
||||
globals@17.9.0: {}
|
||||
|
||||
gopd@1.2.0: {}
|
||||
|
||||
@@ -4745,14 +4741,14 @@ snapshots:
|
||||
|
||||
node-releases@2.0.44: {}
|
||||
|
||||
open@11.0.1:
|
||||
open@11.0.0:
|
||||
dependencies:
|
||||
default-browser: 5.5.0
|
||||
define-lazy-prop: 3.0.0
|
||||
is-in-ssh: 1.0.0
|
||||
is-inside-container: 1.0.0
|
||||
powershell-utils: 0.2.0
|
||||
wsl-utils: 1.0.0
|
||||
powershell-utils: 0.1.0
|
||||
wsl-utils: 0.3.1
|
||||
|
||||
optionator@0.9.4:
|
||||
dependencies:
|
||||
@@ -4787,6 +4783,8 @@ snapshots:
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@4.0.4: {}
|
||||
|
||||
picomatch@4.0.5: {}
|
||||
|
||||
postcss@8.5.26:
|
||||
@@ -4797,8 +4795,6 @@ snapshots:
|
||||
|
||||
powershell-utils@0.1.0: {}
|
||||
|
||||
powershell-utils@0.2.0: {}
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
property-information@7.1.0: {}
|
||||
@@ -4981,12 +4977,12 @@ snapshots:
|
||||
'@rolldown/binding-win32-arm64-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:
|
||||
open: 11.0.1
|
||||
picomatch: 4.0.5
|
||||
source-map: 0.8.0
|
||||
yargs: 18.1.0
|
||||
open: 11.0.0
|
||||
picomatch: 4.0.4
|
||||
source-map: 0.7.6
|
||||
yargs: 18.0.0
|
||||
optionalDependencies:
|
||||
rolldown: 1.2.3
|
||||
|
||||
@@ -5013,7 +5009,7 @@ snapshots:
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
source-map@0.8.0: {}
|
||||
source-map@0.7.6: {}
|
||||
|
||||
space-separated-tokens@2.0.2: {}
|
||||
|
||||
@@ -5023,11 +5019,6 @@ snapshots:
|
||||
get-east-asian-width: 1.6.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:
|
||||
dependencies:
|
||||
character-entities-html4: 2.1.0
|
||||
@@ -5035,7 +5026,7 @@ snapshots:
|
||||
|
||||
strip-ansi@7.2.0:
|
||||
dependencies:
|
||||
ansi-regex: 6.3.0
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
style-to-js@1.1.21:
|
||||
dependencies:
|
||||
@@ -5072,12 +5063,12 @@ snapshots:
|
||||
dependencies:
|
||||
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:
|
||||
'@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/parser': 8.67.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/utils': 8.67.0(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.66.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)
|
||||
'@typescript-eslint/typescript-estree': 8.66.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)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -5183,7 +5174,7 @@ snapshots:
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.2.0
|
||||
|
||||
wsl-utils@1.0.0:
|
||||
wsl-utils@0.3.1:
|
||||
dependencies:
|
||||
is-wsl: 3.1.1
|
||||
powershell-utils: 0.1.0
|
||||
@@ -5194,12 +5185,12 @@ snapshots:
|
||||
|
||||
yargs-parser@22.0.0: {}
|
||||
|
||||
yargs@18.1.0:
|
||||
yargs@18.0.0:
|
||||
dependencies:
|
||||
cliui: 9.0.1
|
||||
escalade: 3.2.0
|
||||
get-caller-file: 2.0.5
|
||||
string-width: 8.2.2
|
||||
string-width: 7.2.0
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 22.0.0
|
||||
|
||||
|
||||
@@ -190,7 +190,8 @@ export const AuthorizePage = () => {
|
||||
<CardFooter className="flex flex-col items-stretch gap-3">
|
||||
<Button
|
||||
onClick={() => authorizeMutate()}
|
||||
loading={authorizePending || shouldAutoAuthorize}
|
||||
loading={authorizePending}
|
||||
disabled={shouldAutoAuthorize}
|
||||
>
|
||||
{t("authorizeTitle")}
|
||||
</Button>
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.26.4
|
||||
|
||||
require (
|
||||
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/docker/docker v28.5.2+incompatible
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
@@ -19,14 +19,14 @@ require (
|
||||
github.com/pquerna/otp v1.5.0
|
||||
github.com/rs/zerolog v1.35.1
|
||||
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/weppos/publicsuffix-go v0.50.3
|
||||
go.uber.org/dig v1.19.0
|
||||
golang.org/x/crypto v0.55.0
|
||||
golang.org/x/net v0.58.0
|
||||
golang.org/x/crypto v0.54.0
|
||||
golang.org/x/net v0.57.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
|
||||
k8s.io/apimachinery 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/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.8 // indirect
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // 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/strings v0.0.0-20240722160745-212f7b056ed0 // 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/klauspost/cpuid/v2 v2.3.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-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/mitchellh/copystructure v1.2.0 // 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/pelletier/go-toml/v2 v2.2.4 // 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/quic-go v0.59.1 // 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/trace v1.43.0 // 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/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/sys v0.47.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
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // 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/huh/v2 v2.0.3 h1:2cJsMqEPwSywGHvdlKsJyQKPtSJLVnFKyFbsYZTlLkU=
|
||||
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.6/go.mod h1:ipDDJNSGa1hlwDtSfW1s2/xR8Vdhbut4PXh2zEKZd0Q=
|
||||
charm.land/lipgloss/v2 v2.0.5 h1:kbNxgeeUOYv5J0YdpxFjfvf3dFvqH8Aci4zB6xqFtrY=
|
||||
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/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
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/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/ultraviolet v0.0.0-20260811164956-006e29f97886 h1:rdnVWKgJpTVXKuKuJyxDJ+NFJdUaUqGvyGy61OcvlbA=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro=
|
||||
github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ=
|
||||
github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98=
|
||||
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
||||
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/go.mod h1:OmtR77VODEFbiTzGE9G1XiRJAga6011PIm4u5fTNZpk=
|
||||
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/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
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.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
|
||||
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/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
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-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
||||
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.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||
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/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
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.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.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.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.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.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.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
||||
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
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/go.mod h1:TlUDoCF66hMqFZqoBym9bUdJ0bKAWYMir6hLJeYN5z0=
|
||||
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.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/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
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/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
|
||||
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
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/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||
golang.org/x/mod v0.39.0 h1:UF5zwQdCRRUpHfyPwr7d4UrGiVeldIsogtzWVnczL74=
|
||||
golang.org/x/mod v0.39.0/go.mod h1:bvIbwjQ0HUFFf5AKukeeYQG4ZBUG9yxQbR9aEweIwYY=
|
||||
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
||||
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||
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/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
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/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||
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.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||
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/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
|
||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
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/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=
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
DROP TABLE IF EXISTS "oidc_consents";
|
||||
@@ -1,7 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS "oidc_consents" (
|
||||
"username" TEXT NOT NULL,
|
||||
"client_id" TEXT NOT NULL,
|
||||
"scope" TEXT NOT NULL,
|
||||
"created_at" BIGINT NOT NULL,
|
||||
PRIMARY KEY ("username", "client_id")
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
DROP TABLE IF EXISTS "oidc_consents";
|
||||
@@ -1,7 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS "oidc_consents" (
|
||||
"username" TEXT NOT NULL,
|
||||
"client_id" TEXT NOT NULL,
|
||||
"scope" TEXT NOT NULL,
|
||||
"created_at" INTEGER NOT NULL,
|
||||
PRIMARY KEY ("username", "client_id")
|
||||
);
|
||||
@@ -179,6 +179,8 @@ func (app *BootstrapApp) Setup() error {
|
||||
cookieId := strings.Split(app.runtime.UUID, "-")[0] // first 8 characters of the uuid should be good enough
|
||||
|
||||
app.runtime.SessionCookieName = fmt.Sprintf("%s-%s", model.SessionCookieName, cookieId)
|
||||
app.runtime.CSRFCookieName = fmt.Sprintf("%s-%s", model.CSRFCookieName, cookieId)
|
||||
app.runtime.RedirectCookieName = fmt.Sprintf("%s-%s", model.RedirectCookieName, cookieId)
|
||||
app.runtime.OAuthSessionCookieName = fmt.Sprintf("%s-%s", model.OAuthSessionCookieName, cookieId)
|
||||
|
||||
// database
|
||||
|
||||
@@ -242,16 +242,6 @@ func (controller *OIDCController) authorize(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
if userContext != nil && userContext.Authenticated && values.OIDCPrompt != service.OIDCPromptLogin {
|
||||
consent, err := controller.oidc.GetOIDCConsent(c, userContext.GetUsername(), req.ClientID)
|
||||
|
||||
if err != nil {
|
||||
controller.log.App.Warn().Err(err).Msg("Failed to get OIDC consent")
|
||||
} else if consent != nil && scopesGranted(consent.Scope, req.Scope) {
|
||||
values.OIDCPrompt = service.OIDCPromptNone
|
||||
}
|
||||
}
|
||||
|
||||
queries, err := query.Values(values)
|
||||
|
||||
if err != nil {
|
||||
@@ -330,19 +320,6 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get the client
|
||||
client, ok := controller.oidc.GetClient(authorizeReq.ClientID)
|
||||
|
||||
if !ok {
|
||||
controller.authorizeError(c, authorizeErrorParams{
|
||||
err: errors.New("client not found"),
|
||||
reason: "Client not found",
|
||||
reasonPublic: "The client is not configured",
|
||||
json: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// We no longer need the ticket
|
||||
controller.oidc.DeleteAuthorizeRequestTicket(req.Ticket)
|
||||
|
||||
@@ -379,11 +356,6 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Store the consent granted by the user for this client
|
||||
if _, err := controller.oidc.UpsertOIDCConsent(c, userContext.GetUsername(), authorizeReq.Scope, client.ClientID); err != nil {
|
||||
controller.log.App.Warn().Err(err).Msg("Failed to store OIDC consent")
|
||||
}
|
||||
|
||||
q := cu.Query()
|
||||
|
||||
q.Set("code", code)
|
||||
@@ -784,20 +756,3 @@ func (controller *OIDCController) resolveNormalParams(c *gin.Context) (*service.
|
||||
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
// scopesGranted reports whether every scope in requested is present in the
|
||||
// space-separated granted scope string.
|
||||
func scopesGranted(granted, requested string) bool {
|
||||
grantedScopes := strings.Split(granted, " ")
|
||||
|
||||
for _, scope := range strings.Split(requested, " ") {
|
||||
if scope == "" {
|
||||
continue
|
||||
}
|
||||
if !slices.Contains(grantedScopes, scope) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -170,102 +170,6 @@ func TestOIDCController(t *testing.T) {
|
||||
assert.Contains(t, location, "oidc_name="+url.QueryEscape("Test Client"))
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Authorize skips the consent screen when all requested scopes were already granted",
|
||||
middlewares: []gin.HandlerFunc{authedUser},
|
||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||
_, err := store.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "testuser", ClientID: "some-client-id",
|
||||
Scope: "openid profile", CreatedAt: time.Now().Unix(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
q := url.Values{}
|
||||
q.Set("scope", "openid profile")
|
||||
q.Set("response_type", "code")
|
||||
q.Set("client_id", "some-client-id")
|
||||
q.Set("redirect_uri", "https://test.example.com/callback")
|
||||
|
||||
req := httptest.NewRequest("GET", "/authorize?"+q.Encode(), nil)
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
assert.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
assert.True(t, strings.HasPrefix(location, oidcService.GetIssuer()+"/oidc/authorize?"))
|
||||
assert.Contains(t, location, "oidc_prompt=none")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Authorize shows the consent screen when a new scope is requested",
|
||||
middlewares: []gin.HandlerFunc{authedUser},
|
||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||
_, err := store.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "testuser", ClientID: "some-client-id",
|
||||
Scope: "openid", CreatedAt: time.Now().Unix(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
q := url.Values{}
|
||||
q.Set("scope", "openid profile")
|
||||
q.Set("response_type", "code")
|
||||
q.Set("client_id", "some-client-id")
|
||||
q.Set("redirect_uri", "https://test.example.com/callback")
|
||||
|
||||
req := httptest.NewRequest("GET", "/authorize?"+q.Encode(), nil)
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
assert.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
assert.True(t, strings.HasPrefix(location, oidcService.GetIssuer()+"/oidc/authorize?"))
|
||||
assert.NotContains(t, location, "oidc_prompt=none")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Authorize skips the consent screen for a subset of already granted scopes",
|
||||
middlewares: []gin.HandlerFunc{authedUser},
|
||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||
_, err := store.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "testuser", ClientID: "some-client-id",
|
||||
Scope: "openid profile email", CreatedAt: time.Now().Unix(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
q := url.Values{}
|
||||
q.Set("scope", "openid profile")
|
||||
q.Set("response_type", "code")
|
||||
q.Set("client_id", "some-client-id")
|
||||
q.Set("redirect_uri", "https://test.example.com/callback")
|
||||
|
||||
req := httptest.NewRequest("GET", "/authorize?"+q.Encode(), nil)
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
assert.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
assert.True(t, strings.HasPrefix(location, oidcService.GetIssuer()+"/oidc/authorize?"))
|
||||
assert.Contains(t, location, "oidc_prompt=none")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Authorize shows the consent screen when no consent was granted yet",
|
||||
middlewares: []gin.HandlerFunc{authedUser},
|
||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||
require.NoError(t, store.DeleteOIDCConsentByClientID(ctx, "some-client-id"))
|
||||
|
||||
q := url.Values{}
|
||||
q.Set("scope", "openid profile")
|
||||
q.Set("response_type", "code")
|
||||
q.Set("client_id", "some-client-id")
|
||||
q.Set("redirect_uri", "https://test.example.com/callback")
|
||||
|
||||
req := httptest.NewRequest("GET", "/authorize?"+q.Encode(), nil)
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
assert.Equal(t, http.StatusFound, recorder.Code)
|
||||
location := recorder.Header().Get("Location")
|
||||
assert.True(t, strings.HasPrefix(location, oidcService.GetIssuer()+"/oidc/authorize?"))
|
||||
assert.NotContains(t, location, "oidc_prompt=none")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Authorize redirects to error screen when the request object is invalid",
|
||||
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
|
||||
|
||||
+12
-20
@@ -253,26 +253,18 @@ type TailscaleConfig struct {
|
||||
// OAuth/OIDC config
|
||||
|
||||
type OAuthServiceConfig struct {
|
||||
ClientID string `description:"OAuth client ID." yaml:"clientId,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"`
|
||||
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"`
|
||||
Scopes []string `description:"OAuth scopes." yaml:"scopes,omitempty"`
|
||||
RedirectURL string `description:"OAuth redirect URL." yaml:"redirectUrl,omitempty"`
|
||||
AuthURL string `description:"OAuth authorization URL." yaml:"authUrl,omitempty"`
|
||||
TokenURL string `description:"OAuth token URL." yaml:"tokenUrl,omitempty"`
|
||||
UserinfoURL string `description:"OAuth userinfo URL." yaml:"userinfoUrl,omitempty"`
|
||||
Insecure bool `description:"Allow insecure OAuth connections." yaml:"insecure,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"`
|
||||
ClientID string `description:"OAuth client ID." yaml:"clientId,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"`
|
||||
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"`
|
||||
Scopes []string `description:"OAuth scopes." yaml:"scopes,omitempty"`
|
||||
RedirectURL string `description:"OAuth redirect URL." yaml:"redirectUrl,omitempty"`
|
||||
AuthURL string `description:"OAuth authorization URL." yaml:"authUrl,omitempty"`
|
||||
TokenURL string `description:"OAuth token URL." yaml:"tokenUrl,omitempty"`
|
||||
UserinfoURL string `description:"OAuth userinfo URL." yaml:"userinfoUrl,omitempty"`
|
||||
Insecure bool `description:"Allow insecure OAuth connections." yaml:"insecure,omitempty"`
|
||||
Name string `description:"Provider name in UI." yaml:"name,omitempty"`
|
||||
}
|
||||
|
||||
type OIDCClientConfig struct {
|
||||
|
||||
@@ -20,6 +20,8 @@ var OverrideProviders = map[string]string{
|
||||
var ReservedProviderNames = []string{"local", "ldap", "tailscale"}
|
||||
|
||||
const SessionCookieName = "tinyauth-session"
|
||||
const CSRFCookieName = "tinyauth-csrf"
|
||||
const RedirectCookieName = "tinyauth-redirect"
|
||||
const OAuthSessionCookieName = "tinyauth-oauth"
|
||||
|
||||
const GracefulShutdownTimeout = 5 // seconds
|
||||
|
||||
@@ -5,6 +5,8 @@ type RuntimeConfig struct {
|
||||
UUID string
|
||||
CookieDomain string
|
||||
SessionCookieName string
|
||||
CSRFCookieName string
|
||||
RedirectCookieName string
|
||||
OAuthSessionCookieName string
|
||||
LocalUsers []LocalUser
|
||||
OAuthProviders map[string]OAuthServiceConfig
|
||||
|
||||
@@ -277,80 +277,6 @@ func TestMemoryStore(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Upsert creates a consent for each user+client pair",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "alice", ClientID: "client-a", Scope: "openid profile", CreatedAt: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = s.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "alice", ClientID: "client-b", Scope: "openid email", CreatedAt: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
consents, err := s.ListOIDCConsents(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, consents, 2)
|
||||
|
||||
gotA, err := s.GetOIDCConsentByUsernameAndClientID(ctx, repository.GetOIDCConsentByUsernameAndClientIDParams{Username: "alice", ClientID: "client-a"})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "openid profile", gotA.Scope)
|
||||
|
||||
gotB, err := s.GetOIDCConsentByUsernameAndClientID(ctx, repository.GetOIDCConsentByUsernameAndClientIDParams{Username: "alice", ClientID: "client-b"})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "openid email", gotB.Scope)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Upsert overwrites the same consent row",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "alice", ClientID: "client-a", Scope: "openid", CreatedAt: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "alice", ClientID: "client-a", Scope: "openid email", CreatedAt: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
consents, err := s.ListOIDCConsents(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, consents, 1)
|
||||
|
||||
got, err := s.GetOIDCConsentByUsernameAndClientID(ctx, repository.GetOIDCConsentByUsernameAndClientIDParams{Username: "alice", ClientID: "client-a"})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "openid email", got.Scope)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get consent by username and client not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOIDCConsentByUsernameAndClientID(ctx, repository.GetOIDCConsentByUsernameAndClientIDParams{Username: "alice", ClientID: "client-a"})
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete consent by client id",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "alice", ClientID: "client-a", Scope: "openid", CreatedAt: 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = s.UpsertOIDCConsent(ctx, repository.UpsertOIDCConsentParams{
|
||||
Username: "alice", ClientID: "client-b", Scope: "openid", CreatedAt: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOIDCConsentByClientID(ctx, "client-a"))
|
||||
|
||||
consents, err := s.ListOIDCConsents(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, consents, 1)
|
||||
assert.Equal(t, "client-b", consents[0].ClientID)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@@ -94,46 +94,3 @@ func (s *Store) DeleteExpiredOIDCSessions(_ context.Context, arg repository.Dele
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func consentKey(username, clientID string) string {
|
||||
return username + "\x00" + clientID
|
||||
}
|
||||
|
||||
func (s *Store) UpsertOIDCConsent(_ context.Context, arg repository.UpsertOIDCConsentParams) (repository.OidcConsent, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
oc := repository.OidcConsent(arg)
|
||||
s.oidcConsents[consentKey(arg.Username, arg.ClientID)] = oc
|
||||
return oc, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOIDCConsentByUsernameAndClientID(_ context.Context, arg repository.GetOIDCConsentByUsernameAndClientIDParams) (repository.OidcConsent, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
oc, ok := s.oidcConsents[consentKey(arg.Username, arg.ClientID)]
|
||||
if !ok {
|
||||
return repository.OidcConsent{}, repository.ErrNotFound
|
||||
}
|
||||
return oc, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOIDCConsentByClientID(_ context.Context, clientID string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for key, oc := range s.oidcConsents {
|
||||
if oc.ClientID == clientID {
|
||||
delete(s.oidcConsents, key)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) ListOIDCConsents(_ context.Context) ([]repository.OidcConsent, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
out := make([]repository.OidcConsent, 0, len(s.oidcConsents))
|
||||
for _, oc := range s.oidcConsents {
|
||||
out = append(out, oc)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ type Store struct {
|
||||
mu sync.RWMutex
|
||||
sessions map[string]repository.Session
|
||||
oidcSessions map[string]repository.OidcSession
|
||||
oidcConsents map[string]repository.OidcConsent
|
||||
}
|
||||
|
||||
// New returns a new empty in-memory Store.
|
||||
@@ -20,6 +19,5 @@ func New() repository.Store {
|
||||
return &Store{
|
||||
sessions: make(map[string]repository.Session),
|
||||
oidcSessions: make(map[string]repository.OidcSession),
|
||||
oidcConsents: make(map[string]repository.OidcConsent),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,22 +84,3 @@ type DeleteExpiredOIDCSessionsParams struct {
|
||||
TokenExpiresAt int64
|
||||
RefreshTokenExpiresAt int64
|
||||
}
|
||||
|
||||
type OidcConsent struct {
|
||||
Username string
|
||||
ClientID string
|
||||
Scope string
|
||||
CreatedAt int64
|
||||
}
|
||||
|
||||
type UpsertOIDCConsentParams struct {
|
||||
Username string
|
||||
ClientID string
|
||||
Scope string
|
||||
CreatedAt int64
|
||||
}
|
||||
|
||||
type GetOIDCConsentByUsernameAndClientIDParams struct {
|
||||
Username string
|
||||
ClientID string
|
||||
}
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
|
||||
package postgres
|
||||
|
||||
type OidcConsent struct {
|
||||
Username string
|
||||
ClientID string
|
||||
Scope string
|
||||
CreatedAt int64
|
||||
}
|
||||
|
||||
type OidcSession struct {
|
||||
Sub string
|
||||
AccessTokenHash string
|
||||
|
||||
@@ -80,16 +80,6 @@ func (q *Queries) DeleteExpiredOIDCSessions(ctx context.Context, arg DeleteExpir
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteOIDCConsentByClientID = `-- name: DeleteOIDCConsentByClientID :exec
|
||||
DELETE FROM "oidc_consents"
|
||||
WHERE "client_id" = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteOIDCConsentByClientID(ctx context.Context, clientID string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteOIDCConsentByClientID, clientID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteOIDCSessionBySub = `-- name: DeleteOIDCSessionBySub :exec
|
||||
DELETE FROM "oidc_sessions"
|
||||
WHERE "sub" = $1
|
||||
@@ -100,28 +90,6 @@ func (q *Queries) DeleteOIDCSessionBySub(ctx context.Context, sub string) error
|
||||
return err
|
||||
}
|
||||
|
||||
const getOIDCConsentByUsernameAndClientID = `-- name: GetOIDCConsentByUsernameAndClientID :one
|
||||
SELECT username, client_id, scope, created_at FROM "oidc_consents"
|
||||
WHERE "username" = $1 AND "client_id" = $2
|
||||
`
|
||||
|
||||
type GetOIDCConsentByUsernameAndClientIDParams struct {
|
||||
Username string
|
||||
ClientID string
|
||||
}
|
||||
|
||||
func (q *Queries) GetOIDCConsentByUsernameAndClientID(ctx context.Context, arg GetOIDCConsentByUsernameAndClientIDParams) (OidcConsent, error) {
|
||||
row := q.db.QueryRowContext(ctx, getOIDCConsentByUsernameAndClientID, arg.Username, arg.ClientID)
|
||||
var i OidcConsent
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.ClientID,
|
||||
&i.Scope,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getOIDCSessionByAccessTokenHash = `-- name: GetOIDCSessionByAccessTokenHash :one
|
||||
SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce, userinfo_json FROM "oidc_sessions"
|
||||
WHERE "access_token_hash" = $1
|
||||
@@ -188,38 +156,6 @@ func (q *Queries) GetOIDCSessionBySub(ctx context.Context, sub string) (OidcSess
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listOIDCConsents = `-- name: ListOIDCConsents :many
|
||||
SELECT username, client_id, scope, created_at FROM "oidc_consents"
|
||||
`
|
||||
|
||||
func (q *Queries) ListOIDCConsents(ctx context.Context) ([]OidcConsent, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listOIDCConsents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []OidcConsent
|
||||
for rows.Next() {
|
||||
var i OidcConsent
|
||||
if err := rows.Scan(
|
||||
&i.Username,
|
||||
&i.ClientID,
|
||||
&i.Scope,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateOIDCSession = `-- name: UpdateOIDCSession :one
|
||||
UPDATE "oidc_sessions" SET
|
||||
"access_token_hash" = $1,
|
||||
@@ -272,43 +208,3 @@ func (q *Queries) UpdateOIDCSession(ctx context.Context, arg UpdateOIDCSessionPa
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertOIDCConsent = `-- name: UpsertOIDCConsent :one
|
||||
INSERT INTO "oidc_consents" (
|
||||
"username",
|
||||
"client_id",
|
||||
"scope",
|
||||
"created_at"
|
||||
) VALUES (
|
||||
$1, $2, $3, $4
|
||||
)
|
||||
ON CONFLICT ("username", "client_id")
|
||||
DO UPDATE SET
|
||||
"scope" = excluded.scope,
|
||||
"created_at" = excluded.created_at
|
||||
RETURNING username, client_id, scope, created_at
|
||||
`
|
||||
|
||||
type UpsertOIDCConsentParams struct {
|
||||
Username string
|
||||
ClientID string
|
||||
Scope string
|
||||
CreatedAt int64
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertOIDCConsent(ctx context.Context, arg UpsertOIDCConsentParams) (OidcConsent, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertOIDCConsent,
|
||||
arg.Username,
|
||||
arg.ClientID,
|
||||
arg.Scope,
|
||||
arg.CreatedAt,
|
||||
)
|
||||
var i OidcConsent
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.ClientID,
|
||||
&i.Scope,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -56,10 +56,6 @@ func (s *Store) DeleteExpiredSessions(ctx context.Context, expiry int64) error {
|
||||
return mapErr(s.q.DeleteExpiredSessions(ctx, expiry))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOIDCConsentByClientID(ctx context.Context, clientID string) error {
|
||||
return mapErr(s.q.DeleteOIDCConsentByClientID(ctx, clientID))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOIDCSessionBySub(ctx context.Context, sub string) error {
|
||||
return mapErr(s.q.DeleteOIDCSessionBySub(ctx, sub))
|
||||
}
|
||||
@@ -68,14 +64,6 @@ func (s *Store) DeleteSession(ctx context.Context, uuid string) error {
|
||||
return mapErr(s.q.DeleteSession(ctx, uuid))
|
||||
}
|
||||
|
||||
func (s *Store) GetOIDCConsentByUsernameAndClientID(ctx context.Context, arg repository.GetOIDCConsentByUsernameAndClientIDParams) (repository.OidcConsent, error) {
|
||||
r, err := s.q.GetOIDCConsentByUsernameAndClientID(ctx, GetOIDCConsentByUsernameAndClientIDParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcConsent{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcConsent(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOIDCSessionByAccessTokenHash(ctx context.Context, accessTokenHash string) (repository.OidcSession, error) {
|
||||
r, err := s.q.GetOIDCSessionByAccessTokenHash(ctx, accessTokenHash)
|
||||
if err != nil {
|
||||
@@ -108,18 +96,6 @@ func (s *Store) GetSession(ctx context.Context, uuid string) (repository.Session
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) ListOIDCConsents(ctx context.Context) ([]repository.OidcConsent, error) {
|
||||
rows, err := s.q.ListOIDCConsents(ctx)
|
||||
if err != nil {
|
||||
return nil, mapErr(err)
|
||||
}
|
||||
out := make([]repository.OidcConsent, len(rows))
|
||||
for i, row := range rows {
|
||||
out[i] = repository.OidcConsent(row)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateOIDCSession(ctx context.Context, arg repository.UpdateOIDCSessionParams) (repository.OidcSession, error) {
|
||||
r, err := s.q.UpdateOIDCSession(ctx, UpdateOIDCSessionParams(arg))
|
||||
if err != nil {
|
||||
@@ -135,11 +111,3 @@ func (s *Store) UpdateSession(ctx context.Context, arg repository.UpdateSessionP
|
||||
}
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) UpsertOIDCConsent(ctx context.Context, arg repository.UpsertOIDCConsentParams) (repository.OidcConsent, error) {
|
||||
r, err := s.q.UpsertOIDCConsent(ctx, UpsertOIDCConsentParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcConsent{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcConsent(r), nil
|
||||
}
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
|
||||
package sqlite
|
||||
|
||||
type OidcConsent struct {
|
||||
Username string
|
||||
ClientID string
|
||||
Scope string
|
||||
CreatedAt int64
|
||||
}
|
||||
|
||||
type OidcSession struct {
|
||||
Sub string
|
||||
AccessTokenHash string
|
||||
|
||||
@@ -80,16 +80,6 @@ func (q *Queries) DeleteExpiredOIDCSessions(ctx context.Context, arg DeleteExpir
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteOIDCConsentByClientID = `-- name: DeleteOIDCConsentByClientID :exec
|
||||
DELETE FROM "oidc_consents"
|
||||
WHERE "client_id" = ?
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteOIDCConsentByClientID(ctx context.Context, clientID string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteOIDCConsentByClientID, clientID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteOIDCSessionBySub = `-- name: DeleteOIDCSessionBySub :exec
|
||||
DELETE FROM "oidc_sessions"
|
||||
WHERE "sub" = ?
|
||||
@@ -100,28 +90,6 @@ func (q *Queries) DeleteOIDCSessionBySub(ctx context.Context, sub string) error
|
||||
return err
|
||||
}
|
||||
|
||||
const getOIDCConsentByUsernameAndClientID = `-- name: GetOIDCConsentByUsernameAndClientID :one
|
||||
SELECT username, client_id, scope, created_at FROM "oidc_consents"
|
||||
WHERE "username" = ? AND "client_id" = ?
|
||||
`
|
||||
|
||||
type GetOIDCConsentByUsernameAndClientIDParams struct {
|
||||
Username string
|
||||
ClientID string
|
||||
}
|
||||
|
||||
func (q *Queries) GetOIDCConsentByUsernameAndClientID(ctx context.Context, arg GetOIDCConsentByUsernameAndClientIDParams) (OidcConsent, error) {
|
||||
row := q.db.QueryRowContext(ctx, getOIDCConsentByUsernameAndClientID, arg.Username, arg.ClientID)
|
||||
var i OidcConsent
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.ClientID,
|
||||
&i.Scope,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getOIDCSessionByAccessTokenHash = `-- name: GetOIDCSessionByAccessTokenHash :one
|
||||
SELECT sub, access_token_hash, refresh_token_hash, scope, client_id, token_expires_at, refresh_token_expires_at, nonce, userinfo_json FROM "oidc_sessions"
|
||||
WHERE "access_token_hash" = ?
|
||||
@@ -188,38 +156,6 @@ func (q *Queries) GetOIDCSessionBySub(ctx context.Context, sub string) (OidcSess
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listOIDCConsents = `-- name: ListOIDCConsents :many
|
||||
SELECT username, client_id, scope, created_at FROM "oidc_consents"
|
||||
`
|
||||
|
||||
func (q *Queries) ListOIDCConsents(ctx context.Context) ([]OidcConsent, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listOIDCConsents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []OidcConsent
|
||||
for rows.Next() {
|
||||
var i OidcConsent
|
||||
if err := rows.Scan(
|
||||
&i.Username,
|
||||
&i.ClientID,
|
||||
&i.Scope,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateOIDCSession = `-- name: UpdateOIDCSession :one
|
||||
UPDATE "oidc_sessions" SET
|
||||
"access_token_hash" = ?,
|
||||
@@ -272,43 +208,3 @@ func (q *Queries) UpdateOIDCSession(ctx context.Context, arg UpdateOIDCSessionPa
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertOIDCConsent = `-- name: UpsertOIDCConsent :one
|
||||
INSERT INTO "oidc_consents" (
|
||||
"username",
|
||||
"client_id",
|
||||
"scope",
|
||||
"created_at"
|
||||
) VALUES (
|
||||
?, ?, ?, ?
|
||||
)
|
||||
ON CONFLICT ("username", "client_id")
|
||||
DO UPDATE SET
|
||||
"scope" = excluded.scope,
|
||||
"created_at" = excluded.created_at
|
||||
RETURNING username, client_id, scope, created_at
|
||||
`
|
||||
|
||||
type UpsertOIDCConsentParams struct {
|
||||
Username string
|
||||
ClientID string
|
||||
Scope string
|
||||
CreatedAt int64
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertOIDCConsent(ctx context.Context, arg UpsertOIDCConsentParams) (OidcConsent, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertOIDCConsent,
|
||||
arg.Username,
|
||||
arg.ClientID,
|
||||
arg.Scope,
|
||||
arg.CreatedAt,
|
||||
)
|
||||
var i OidcConsent
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.ClientID,
|
||||
&i.Scope,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -56,10 +56,6 @@ func (s *Store) DeleteExpiredSessions(ctx context.Context, expiry int64) error {
|
||||
return mapErr(s.q.DeleteExpiredSessions(ctx, expiry))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOIDCConsentByClientID(ctx context.Context, clientID string) error {
|
||||
return mapErr(s.q.DeleteOIDCConsentByClientID(ctx, clientID))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOIDCSessionBySub(ctx context.Context, sub string) error {
|
||||
return mapErr(s.q.DeleteOIDCSessionBySub(ctx, sub))
|
||||
}
|
||||
@@ -68,14 +64,6 @@ func (s *Store) DeleteSession(ctx context.Context, uuid string) error {
|
||||
return mapErr(s.q.DeleteSession(ctx, uuid))
|
||||
}
|
||||
|
||||
func (s *Store) GetOIDCConsentByUsernameAndClientID(ctx context.Context, arg repository.GetOIDCConsentByUsernameAndClientIDParams) (repository.OidcConsent, error) {
|
||||
r, err := s.q.GetOIDCConsentByUsernameAndClientID(ctx, GetOIDCConsentByUsernameAndClientIDParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcConsent{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcConsent(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOIDCSessionByAccessTokenHash(ctx context.Context, accessTokenHash string) (repository.OidcSession, error) {
|
||||
r, err := s.q.GetOIDCSessionByAccessTokenHash(ctx, accessTokenHash)
|
||||
if err != nil {
|
||||
@@ -108,18 +96,6 @@ func (s *Store) GetSession(ctx context.Context, uuid string) (repository.Session
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) ListOIDCConsents(ctx context.Context) ([]repository.OidcConsent, error) {
|
||||
rows, err := s.q.ListOIDCConsents(ctx)
|
||||
if err != nil {
|
||||
return nil, mapErr(err)
|
||||
}
|
||||
out := make([]repository.OidcConsent, len(rows))
|
||||
for i, row := range rows {
|
||||
out[i] = repository.OidcConsent(row)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateOIDCSession(ctx context.Context, arg repository.UpdateOIDCSessionParams) (repository.OidcSession, error) {
|
||||
r, err := s.q.UpdateOIDCSession(ctx, UpdateOIDCSessionParams(arg))
|
||||
if err != nil {
|
||||
@@ -135,11 +111,3 @@ func (s *Store) UpdateSession(ctx context.Context, arg repository.UpdateSessionP
|
||||
}
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) UpsertOIDCConsent(ctx context.Context, arg repository.UpsertOIDCConsentParams) (repository.OidcConsent, error) {
|
||||
r, err := s.q.UpsertOIDCConsent(ctx, UpsertOIDCConsentParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcConsent{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcConsent(r), nil
|
||||
}
|
||||
|
||||
@@ -27,10 +27,4 @@ type Store interface {
|
||||
GetOIDCSessionByRefreshTokenHash(ctx context.Context, refreshTokenHash string) (OidcSession, error)
|
||||
GetOIDCSessionBySub(ctx context.Context, sub string) (OidcSession, error)
|
||||
UpdateOIDCSession(ctx context.Context, arg UpdateOIDCSessionParams) (OidcSession, error)
|
||||
|
||||
// OIDC Consents
|
||||
UpsertOIDCConsent(ctx context.Context, arg UpsertOIDCConsentParams) (OidcConsent, error)
|
||||
GetOIDCConsentByUsernameAndClientID(ctx context.Context, arg GetOIDCConsentByUsernameAndClientIDParams) (OidcConsent, error)
|
||||
DeleteOIDCConsentByClientID(ctx context.Context, clientID string) error
|
||||
ListOIDCConsents(ctx context.Context) ([]OidcConsent, error)
|
||||
}
|
||||
|
||||
@@ -21,15 +21,11 @@ type GithubUserinfoResponse struct {
|
||||
ID int `json:"id"`
|
||||
}
|
||||
|
||||
func defaultExtractor(client *http.Client, ctx context.Context, url string, mapClaims MapClaims) (*model.Claims, error) {
|
||||
claims, err := simpleReq[map[string]any](client, ctx, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return new(mapClaims(*claims)), nil
|
||||
func defaultExtractor(client *http.Client, ctx context.Context, url string) (*model.Claims, error) {
|
||||
return simpleReq[model.Claims](client, ctx, url, 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
|
||||
|
||||
userInfo, err := simpleReq[GithubUserinfoResponse](client, ctx, "https://api.github.com/user", map[string]string{
|
||||
|
||||
@@ -10,8 +10,7 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
type MapClaims func(claims map[string]any) model.Claims
|
||||
type OAuthUserinfoExtractor func(client *http.Client, ctx context.Context, url string, mapClaims MapClaims) (*model.Claims, error)
|
||||
type OAuthUserinfoExtractor func(client *http.Client, ctx context.Context, url string) (*model.Claims, error)
|
||||
|
||||
type OAuthService struct {
|
||||
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) {
|
||||
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 {
|
||||
@@ -98,26 +97,3 @@ func (s *OAuthService) UpdateConfig(config model.OAuthServiceConfig) {
|
||||
s.config.Endpoint.TokenURL = config.TokenURL
|
||||
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
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"slices"
|
||||
@@ -164,10 +163,6 @@ type OIDCService struct {
|
||||
usedCode *cache.CacheStore[UsedCodeEntry]
|
||||
authorize *cache.CacheStore[AuthorizeRequest]
|
||||
}
|
||||
|
||||
mus struct {
|
||||
consent sync.RWMutex
|
||||
}
|
||||
}
|
||||
|
||||
type OIDCServiceInput struct {
|
||||
@@ -341,11 +336,6 @@ func NewOIDCService(i OIDCServiceInput) (*OIDCService, error) {
|
||||
issuer: issuer,
|
||||
}
|
||||
|
||||
// Remove consents for clients that are no longer configured
|
||||
if err := service.reconcileOIDCConsents(context.Background()); err != nil {
|
||||
i.Log.App.Warn().Err(err).Msg("Failed to reconcile OIDC consents")
|
||||
}
|
||||
|
||||
// Start cleanup routine
|
||||
i.Ding.Go(service.cleanupRoutine, ding.RingMinor)
|
||||
|
||||
@@ -930,7 +920,7 @@ func (service *OIDCService) DeleteAuthorizeRequestTicket(ticket string) {
|
||||
service.caches.authorize.Delete(ticket)
|
||||
}
|
||||
|
||||
// DecodeAuthorizeJWT TODO: support signed request objects in the future
|
||||
// TODO: support signed request objects in the future
|
||||
func (service *OIDCService) DecodeAuthorizeJWT(tokenString string) (*AuthorizeRequest, error) {
|
||||
var claims jwt.MapClaims
|
||||
|
||||
@@ -980,114 +970,3 @@ func (service *OIDCService) GetPrompt(prompt string) []OIDCPrompt {
|
||||
|
||||
return parsedPromps
|
||||
}
|
||||
|
||||
func (service *OIDCService) getOIDCConsentUnsafe(ctx context.Context, username, clientId string) (*repository.OidcConsent, error) {
|
||||
entry, err := service.queries.GetOIDCConsentByUsernameAndClientID(ctx, repository.GetOIDCConsentByUsernameAndClientIDParams{
|
||||
Username: username,
|
||||
ClientID: clientId,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, repository.ErrNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get oidc consent: %w", err)
|
||||
}
|
||||
|
||||
return &entry, nil
|
||||
}
|
||||
|
||||
func (service *OIDCService) GetOIDCConsent(ctx context.Context, username, clientId string) (*repository.OidcConsent, error) {
|
||||
service.mus.consent.RLock()
|
||||
defer service.mus.consent.RUnlock()
|
||||
return service.getOIDCConsentUnsafe(ctx, username, clientId)
|
||||
}
|
||||
|
||||
func (service *OIDCService) UpsertOIDCConsent(ctx context.Context, username, scope, clientId string) (repository.OidcConsent, error) {
|
||||
service.mus.consent.Lock()
|
||||
defer service.mus.consent.Unlock()
|
||||
|
||||
existing, err := service.getOIDCConsentUnsafe(ctx, username, clientId)
|
||||
|
||||
if err != nil {
|
||||
return repository.OidcConsent{}, err
|
||||
}
|
||||
|
||||
merged := scope
|
||||
|
||||
if existing != nil {
|
||||
merged = mergeScopes(existing.Scope, scope)
|
||||
}
|
||||
|
||||
entry := repository.UpsertOIDCConsentParams{
|
||||
Username: username,
|
||||
Scope: merged,
|
||||
ClientID: clientId,
|
||||
CreatedAt: time.Now().Unix(),
|
||||
}
|
||||
|
||||
consent, err := service.queries.UpsertOIDCConsent(ctx, entry)
|
||||
|
||||
if err != nil {
|
||||
service.log.App.Error().Err(err).Msg("Failed to upsert OIDC consent")
|
||||
return repository.OidcConsent{}, err
|
||||
}
|
||||
|
||||
return consent, nil
|
||||
}
|
||||
|
||||
func (service *OIDCService) reconcileOIDCConsents(ctx context.Context) error {
|
||||
consents, err := service.queries.ListOIDCConsents(ctx)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list oidc consents: %w", err)
|
||||
}
|
||||
|
||||
cleaned := make(map[string]struct{})
|
||||
|
||||
for _, consent := range consents {
|
||||
if _, ok := cleaned[consent.ClientID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
cleaned[consent.ClientID] = struct{}{}
|
||||
|
||||
if _, ok := service.clients[consent.ClientID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
service.log.App.Info().Str("clientId", consent.ClientID).Msg("Removed OIDC client no longer in configuration, deleting its consents")
|
||||
|
||||
if err := service.queries.DeleteOIDCConsentByClientID(ctx, consent.ClientID); err != nil {
|
||||
service.log.App.Warn().Err(err).Str("clientId", consent.ClientID).Msg("Failed to delete OIDC consents for removed client")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergeScopes(existing, requested string) string {
|
||||
set := make(map[string]struct{})
|
||||
|
||||
for _, scope := range strings.Split(existing, " ") {
|
||||
if scope != "" {
|
||||
set[scope] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for _, scope := range strings.Split(requested, " ") {
|
||||
if scope != "" {
|
||||
set[scope] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
scopes := make([]string, 0, len(set))
|
||||
|
||||
for scope := range set {
|
||||
scopes = append(scopes, scope)
|
||||
}
|
||||
|
||||
slices.Sort(scopes)
|
||||
|
||||
return strings.Join(scopes, " ")
|
||||
}
|
||||
|
||||
@@ -46,29 +46,3 @@ UPDATE "oidc_sessions" SET
|
||||
"userinfo_json" = $8
|
||||
WHERE "sub" = $9
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpsertOIDCConsent :one
|
||||
INSERT INTO "oidc_consents" (
|
||||
"username",
|
||||
"client_id",
|
||||
"scope",
|
||||
"created_at"
|
||||
) VALUES (
|
||||
$1, $2, $3, $4
|
||||
)
|
||||
ON CONFLICT ("username", "client_id")
|
||||
DO UPDATE SET
|
||||
"scope" = excluded.scope,
|
||||
"created_at" = excluded.created_at
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetOIDCConsentByUsernameAndClientID :one
|
||||
SELECT * FROM "oidc_consents"
|
||||
WHERE "username" = $1 AND "client_id" = $2;
|
||||
|
||||
-- name: DeleteOIDCConsentByClientID :exec
|
||||
DELETE FROM "oidc_consents"
|
||||
WHERE "client_id" = $1;
|
||||
|
||||
-- name: ListOIDCConsents :many
|
||||
SELECT * FROM "oidc_consents";
|
||||
|
||||
@@ -9,12 +9,3 @@ CREATE TABLE IF NOT EXISTS "oidc_sessions" (
|
||||
"nonce" TEXT NOT NULL DEFAULT '',
|
||||
"userinfo_json" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "oidc_consents" (
|
||||
"username" TEXT NOT NULL,
|
||||
"client_id" TEXT NOT NULL,
|
||||
"scope" TEXT NOT NULL,
|
||||
"created_at" BIGINT NOT NULL,
|
||||
PRIMARY KEY ("username", "client_id")
|
||||
);
|
||||
|
||||
|
||||
@@ -46,29 +46,3 @@ UPDATE "oidc_sessions" SET
|
||||
"userinfo_json" = ?
|
||||
WHERE "sub" = ?
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpsertOIDCConsent :one
|
||||
INSERT INTO "oidc_consents" (
|
||||
"username",
|
||||
"client_id",
|
||||
"scope",
|
||||
"created_at"
|
||||
) VALUES (
|
||||
?, ?, ?, ?
|
||||
)
|
||||
ON CONFLICT ("username", "client_id")
|
||||
DO UPDATE SET
|
||||
"scope" = excluded.scope,
|
||||
"created_at" = excluded.created_at
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetOIDCConsentByUsernameAndClientID :one
|
||||
SELECT * FROM "oidc_consents"
|
||||
WHERE "username" = ? AND "client_id" = ?;
|
||||
|
||||
-- name: DeleteOIDCConsentByClientID :exec
|
||||
DELETE FROM "oidc_consents"
|
||||
WHERE "client_id" = ?;
|
||||
|
||||
-- name: ListOIDCConsents :many
|
||||
SELECT * FROM "oidc_consents";
|
||||
|
||||
@@ -9,11 +9,3 @@ CREATE TABLE IF NOT EXISTS "oidc_sessions" (
|
||||
"nonce" TEXT NOT NULL DEFAULT "",
|
||||
"userinfo_json" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "oidc_consents" (
|
||||
"username" TEXT NOT NULL,
|
||||
"client_id" TEXT NOT NULL,
|
||||
"scope" TEXT NOT NULL,
|
||||
"created_at" INTEGER NOT NULL,
|
||||
PRIMARY KEY ("username", "client_id")
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user