mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-25 08:41:55 +00:00
Compare commits
38 Commits
1.19.2
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abfab56082 | ||
|
|
963e9da7dd | ||
|
|
2cbc88fa05 | ||
|
|
7ae29612d4 | ||
|
|
1bff7bbc2f | ||
|
|
50db5695fc | ||
|
|
cfb63f9742 | ||
|
|
c76b4555e1 | ||
|
|
c25bfbad27 | ||
|
|
44782f8963 | ||
|
|
e6f7cd6da9 | ||
|
|
62c7e0a13e | ||
|
|
753358a17d | ||
|
|
c859393418 | ||
|
|
d747b45f0b | ||
|
|
a24091257a | ||
|
|
1c60041390 | ||
|
|
95c3f74a33 | ||
|
|
16c0f4eef4 | ||
|
|
a08c6d70fe | ||
|
|
a6568692b7 | ||
|
|
a1196d3da6 | ||
|
|
70bc4c0b30 | ||
|
|
a0fef89031 | ||
|
|
ea1badf4e0 | ||
|
|
f15654ed11 | ||
|
|
4435a669a6 | ||
|
|
0b41fe3d49 | ||
|
|
90eceb457a | ||
|
|
f39cbc9bf4 | ||
|
|
50da863bb7 | ||
|
|
c6ddd5c402 | ||
|
|
0fb5ace9c7 | ||
|
|
cedccd8cdb | ||
|
|
b136bd2246 | ||
|
|
92d611df9a | ||
|
|
89f3f3c8cd | ||
|
|
44c16d69af |
48
.github/dependabot.yml
vendored
48
.github/dependabot.yml
vendored
@@ -1,52 +1,42 @@
|
|||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 1
|
||||||
groups:
|
groups:
|
||||||
dev-patch-updates:
|
npm-dependencies:
|
||||||
dependency-type: "development"
|
patterns:
|
||||||
update-types:
|
- "*"
|
||||||
- "patch"
|
|
||||||
dev-minor-updates:
|
|
||||||
dependency-type: "development"
|
|
||||||
update-types:
|
|
||||||
- "minor"
|
|
||||||
prod-patch-updates:
|
|
||||||
dependency-type: "production"
|
|
||||||
update-types:
|
|
||||||
- "patch"
|
|
||||||
prod-minor-updates:
|
|
||||||
dependency-type: "production"
|
|
||||||
update-types:
|
|
||||||
- "minor"
|
|
||||||
|
|
||||||
- package-ecosystem: "docker"
|
- package-ecosystem: "docker"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 1
|
||||||
groups:
|
groups:
|
||||||
patch-updates:
|
docker-dependencies:
|
||||||
update-types:
|
patterns:
|
||||||
- "patch"
|
- "*"
|
||||||
minor-updates:
|
|
||||||
update-types:
|
|
||||||
- "minor"
|
|
||||||
|
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
|
open-pull-requests-limit: 1
|
||||||
|
groups:
|
||||||
|
github-actions-dependencies:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|
||||||
- package-ecosystem: "gomod"
|
- package-ecosystem: "gomod"
|
||||||
directory: "/install"
|
directory: "/install"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 1
|
||||||
groups:
|
groups:
|
||||||
patch-updates:
|
go-install-dependencies:
|
||||||
update-types:
|
patterns:
|
||||||
- "patch"
|
- "*"
|
||||||
minor-updates:
|
|
||||||
update-types:
|
|
||||||
- "minor"
|
|
||||||
|
|||||||
8
.github/workflows/cicd.yml
vendored
8
.github/workflows/cicd.yml
vendored
@@ -62,7 +62,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Monitor storage space
|
- name: Monitor storage space
|
||||||
run: |
|
run: |
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Monitor storage space
|
- name: Monitor storage space
|
||||||
run: |
|
run: |
|
||||||
@@ -201,7 +201,7 @@ jobs:
|
|||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||||
@@ -256,7 +256,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Extract tag name
|
- name: Extract tag name
|
||||||
id: get-tag
|
id: get-tag
|
||||||
|
|||||||
2
.github/workflows/linting.yml
vendored
2
.github/workflows/linting.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
|
|||||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Build Docker image sqlite
|
- name: Build Docker image sqlite
|
||||||
run: make dev-build-sqlite
|
run: make dev-build-sqlite
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Build Docker image pg
|
- name: Build Docker image pg
|
||||||
run: make dev-build-pg
|
run: make dev-build-pg
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:24-alpine
|
FROM node:26-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ go 1.25.0
|
|||||||
require (
|
require (
|
||||||
github.com/charmbracelet/huh v1.0.0
|
github.com/charmbracelet/huh v1.0.0
|
||||||
github.com/charmbracelet/lipgloss v1.1.0
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
golang.org/x/term v0.43.0
|
golang.org/x/term v0.44.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,6 +33,6 @@ require (
|
|||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
golang.org/x/sync v0.15.0 // indirect
|
golang.org/x/sync v0.15.0 // indirect
|
||||||
golang.org/x/sys v0.44.0 // indirect
|
golang.org/x/sys v0.46.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -69,10 +69,10 @@ golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
|||||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
|
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||||
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
|
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
|||||||
438
package-lock.json
generated
438
package-lock.json
generated
@@ -70,7 +70,7 @@
|
|||||||
"input-otp": "1.4.2",
|
"input-otp": "1.4.2",
|
||||||
"ioredis": "5.11.0",
|
"ioredis": "5.11.0",
|
||||||
"jmespath": "0.16.0",
|
"jmespath": "0.16.0",
|
||||||
"js-yaml": "4.1.1",
|
"js-yaml": "4.2.0",
|
||||||
"jsonwebtoken": "9.0.3",
|
"jsonwebtoken": "9.0.3",
|
||||||
"lucide-react": "1.17.0",
|
"lucide-react": "1.17.0",
|
||||||
"maxmind": "5.0.6",
|
"maxmind": "5.0.6",
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
"next-themes": "0.4.6",
|
"next-themes": "0.4.6",
|
||||||
"nextjs-toploader": "3.9.17",
|
"nextjs-toploader": "3.9.17",
|
||||||
"node-cache": "5.1.2",
|
"node-cache": "5.1.2",
|
||||||
"nodemailer": "8.0.9",
|
"nodemailer": "9.0.1",
|
||||||
"oslo": "1.2.1",
|
"oslo": "1.2.1",
|
||||||
"pg": "8.21.0",
|
"pg": "8.21.0",
|
||||||
"posthog-node": "5.35.6",
|
"posthog-node": "5.35.6",
|
||||||
@@ -142,7 +142,7 @@
|
|||||||
"@types/yargs": "17.0.35",
|
"@types/yargs": "17.0.35",
|
||||||
"babel-plugin-react-compiler": "1.0.0",
|
"babel-plugin-react-compiler": "1.0.0",
|
||||||
"drizzle-kit": "0.31.10",
|
"drizzle-kit": "0.31.10",
|
||||||
"esbuild": "0.28.0",
|
"esbuild": "0.28.1",
|
||||||
"esbuild-node-externals": "1.22.0",
|
"esbuild-node-externals": "1.22.0",
|
||||||
"eslint": "10.4.0",
|
"eslint": "10.4.0",
|
||||||
"eslint-config-next": "16.2.6",
|
"eslint-config-next": "16.2.6",
|
||||||
@@ -1248,9 +1248,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
|
||||||
"integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
|
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1265,9 +1265,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm": {
|
"node_modules/@esbuild/android-arm": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
|
||||||
"integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
|
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1282,9 +1282,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm64": {
|
"node_modules/@esbuild/android-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
|
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1299,9 +1299,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-x64": {
|
"node_modules/@esbuild/android-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
|
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1316,9 +1316,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-arm64": {
|
"node_modules/@esbuild/darwin-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
|
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1333,9 +1333,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-x64": {
|
"node_modules/@esbuild/darwin-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
|
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1350,9 +1350,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-arm64": {
|
"node_modules/@esbuild/freebsd-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
|
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1367,9 +1367,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-x64": {
|
"node_modules/@esbuild/freebsd-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
|
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1384,9 +1384,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm": {
|
"node_modules/@esbuild/linux-arm": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
|
||||||
"integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
|
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1401,9 +1401,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm64": {
|
"node_modules/@esbuild/linux-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
|
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1418,9 +1418,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ia32": {
|
"node_modules/@esbuild/linux-ia32": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
|
||||||
"integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
|
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -1435,9 +1435,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-loong64": {
|
"node_modules/@esbuild/linux-loong64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
|
||||||
"integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
|
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -1452,9 +1452,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-mips64el": {
|
"node_modules/@esbuild/linux-mips64el": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
|
||||||
"integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
|
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
@@ -1469,9 +1469,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ppc64": {
|
"node_modules/@esbuild/linux-ppc64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
|
||||||
"integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
|
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1486,9 +1486,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-riscv64": {
|
"node_modules/@esbuild/linux-riscv64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
|
||||||
"integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
|
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -1503,9 +1503,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-s390x": {
|
"node_modules/@esbuild/linux-s390x": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
|
||||||
"integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
|
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -1520,9 +1520,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-x64": {
|
"node_modules/@esbuild/linux-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
|
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1537,9 +1537,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-arm64": {
|
"node_modules/@esbuild/netbsd-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
|
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1554,9 +1554,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-x64": {
|
"node_modules/@esbuild/netbsd-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
|
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1571,9 +1571,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-arm64": {
|
"node_modules/@esbuild/openbsd-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
|
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1588,9 +1588,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-x64": {
|
"node_modules/@esbuild/openbsd-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
|
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1605,9 +1605,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openharmony-arm64": {
|
"node_modules/@esbuild/openharmony-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
|
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1622,9 +1622,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/sunos-x64": {
|
"node_modules/@esbuild/sunos-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
|
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1639,9 +1639,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-arm64": {
|
"node_modules/@esbuild/win32-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
|
||||||
"integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
|
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1656,9 +1656,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-ia32": {
|
"node_modules/@esbuild/win32-ia32": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
|
||||||
"integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
|
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -1673,9 +1673,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-x64": {
|
"node_modules/@esbuild/win32-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
|
||||||
"integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
|
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2076,9 +2076,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2095,9 +2092,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2114,9 +2108,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2133,9 +2124,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2152,9 +2140,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2187,9 +2172,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2222,9 +2204,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2247,9 +2226,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2272,9 +2248,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2297,9 +2270,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2322,9 +2292,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2369,9 +2336,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2664,9 +2628,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2683,9 +2644,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2941,9 +2899,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2960,9 +2915,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3200,9 +3152,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3219,9 +3168,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3582,9 +3528,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3605,9 +3548,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3628,9 +3568,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3651,9 +3588,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -6873,9 +6807,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -6892,9 +6823,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -6911,9 +6839,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -6930,9 +6855,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0 AND MIT",
|
"license": "Apache-2.0 AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7200,9 +7122,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7220,9 +7139,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7296,6 +7212,72 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.2.1",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@tybys/wasm-util": "^0.10.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emnapi/core": "^1.7.1",
|
||||||
|
"@emnapi/runtime": "^1.7.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.10.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz",
|
||||||
@@ -8448,9 +8430,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8465,9 +8444,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8482,9 +8458,6 @@
|
|||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8499,9 +8472,6 @@
|
|||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8516,9 +8486,6 @@
|
|||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8533,9 +8500,6 @@
|
|||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -11261,9 +11225,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.28.0",
|
"version": "0.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||||
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
|
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -11274,32 +11238,32 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@esbuild/aix-ppc64": "0.28.0",
|
"@esbuild/aix-ppc64": "0.28.1",
|
||||||
"@esbuild/android-arm": "0.28.0",
|
"@esbuild/android-arm": "0.28.1",
|
||||||
"@esbuild/android-arm64": "0.28.0",
|
"@esbuild/android-arm64": "0.28.1",
|
||||||
"@esbuild/android-x64": "0.28.0",
|
"@esbuild/android-x64": "0.28.1",
|
||||||
"@esbuild/darwin-arm64": "0.28.0",
|
"@esbuild/darwin-arm64": "0.28.1",
|
||||||
"@esbuild/darwin-x64": "0.28.0",
|
"@esbuild/darwin-x64": "0.28.1",
|
||||||
"@esbuild/freebsd-arm64": "0.28.0",
|
"@esbuild/freebsd-arm64": "0.28.1",
|
||||||
"@esbuild/freebsd-x64": "0.28.0",
|
"@esbuild/freebsd-x64": "0.28.1",
|
||||||
"@esbuild/linux-arm": "0.28.0",
|
"@esbuild/linux-arm": "0.28.1",
|
||||||
"@esbuild/linux-arm64": "0.28.0",
|
"@esbuild/linux-arm64": "0.28.1",
|
||||||
"@esbuild/linux-ia32": "0.28.0",
|
"@esbuild/linux-ia32": "0.28.1",
|
||||||
"@esbuild/linux-loong64": "0.28.0",
|
"@esbuild/linux-loong64": "0.28.1",
|
||||||
"@esbuild/linux-mips64el": "0.28.0",
|
"@esbuild/linux-mips64el": "0.28.1",
|
||||||
"@esbuild/linux-ppc64": "0.28.0",
|
"@esbuild/linux-ppc64": "0.28.1",
|
||||||
"@esbuild/linux-riscv64": "0.28.0",
|
"@esbuild/linux-riscv64": "0.28.1",
|
||||||
"@esbuild/linux-s390x": "0.28.0",
|
"@esbuild/linux-s390x": "0.28.1",
|
||||||
"@esbuild/linux-x64": "0.28.0",
|
"@esbuild/linux-x64": "0.28.1",
|
||||||
"@esbuild/netbsd-arm64": "0.28.0",
|
"@esbuild/netbsd-arm64": "0.28.1",
|
||||||
"@esbuild/netbsd-x64": "0.28.0",
|
"@esbuild/netbsd-x64": "0.28.1",
|
||||||
"@esbuild/openbsd-arm64": "0.28.0",
|
"@esbuild/openbsd-arm64": "0.28.1",
|
||||||
"@esbuild/openbsd-x64": "0.28.0",
|
"@esbuild/openbsd-x64": "0.28.1",
|
||||||
"@esbuild/openharmony-arm64": "0.28.0",
|
"@esbuild/openharmony-arm64": "0.28.1",
|
||||||
"@esbuild/sunos-x64": "0.28.0",
|
"@esbuild/sunos-x64": "0.28.1",
|
||||||
"@esbuild/win32-arm64": "0.28.0",
|
"@esbuild/win32-arm64": "0.28.1",
|
||||||
"@esbuild/win32-ia32": "0.28.0",
|
"@esbuild/win32-ia32": "0.28.1",
|
||||||
"@esbuild/win32-x64": "0.28.0"
|
"@esbuild/win32-x64": "0.28.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/esbuild-node-externals": {
|
"node_modules/esbuild-node-externals": {
|
||||||
@@ -12191,16 +12155,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
|
||||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
"hasown": "^2.0.2",
|
"hasown": "^2.0.4",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.35"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
@@ -12629,9 +12593,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||||
"integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
|
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"function-bind": "^1.1.2"
|
"function-bind": "^1.1.2"
|
||||||
@@ -13425,9 +13389,19 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.1",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz",
|
||||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
"integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/puzrin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/nodeca"
|
||||||
|
}
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
@@ -13767,9 +13741,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -13791,9 +13762,6 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -14574,9 +14542,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/nodemailer": {
|
"node_modules/nodemailer": {
|
||||||
"version": "8.0.9",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.1.tgz",
|
||||||
"integrity": "sha512-5ofa7BUN8+C+Hckh5V2GjeeOGRQBx0CJQA6KxrvuZfC8iU4/q7sLn8XrtEEhJkjV6HdyIiQs7Bba6bTao8JhkA==",
|
"integrity": "sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw==",
|
||||||
"license": "MIT-0",
|
"license": "MIT-0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
@@ -15001,9 +14969,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"glibc"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -15020,9 +14985,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"libc": [
|
|
||||||
"musl"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
"input-otp": "1.4.2",
|
"input-otp": "1.4.2",
|
||||||
"ioredis": "5.11.0",
|
"ioredis": "5.11.0",
|
||||||
"jmespath": "0.16.0",
|
"jmespath": "0.16.0",
|
||||||
"js-yaml": "4.1.1",
|
"js-yaml": "4.2.0",
|
||||||
"jsonwebtoken": "9.0.3",
|
"jsonwebtoken": "9.0.3",
|
||||||
"lucide-react": "1.17.0",
|
"lucide-react": "1.17.0",
|
||||||
"maxmind": "5.0.6",
|
"maxmind": "5.0.6",
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
"next-themes": "0.4.6",
|
"next-themes": "0.4.6",
|
||||||
"nextjs-toploader": "3.9.17",
|
"nextjs-toploader": "3.9.17",
|
||||||
"node-cache": "5.1.2",
|
"node-cache": "5.1.2",
|
||||||
"nodemailer": "8.0.9",
|
"nodemailer": "9.0.1",
|
||||||
"oslo": "1.2.1",
|
"oslo": "1.2.1",
|
||||||
"pg": "8.21.0",
|
"pg": "8.21.0",
|
||||||
"posthog-node": "5.35.6",
|
"posthog-node": "5.35.6",
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
"@types/yargs": "17.0.35",
|
"@types/yargs": "17.0.35",
|
||||||
"babel-plugin-react-compiler": "1.0.0",
|
"babel-plugin-react-compiler": "1.0.0",
|
||||||
"drizzle-kit": "0.31.10",
|
"drizzle-kit": "0.31.10",
|
||||||
"esbuild": "0.28.0",
|
"esbuild": "0.28.1",
|
||||||
"esbuild-node-externals": "1.22.0",
|
"esbuild-node-externals": "1.22.0",
|
||||||
"eslint": "10.4.0",
|
"eslint": "10.4.0",
|
||||||
"eslint-config-next": "16.2.6",
|
"eslint-config-next": "16.2.6",
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
"typescript-eslint": "8.60.0"
|
"typescript-eslint": "8.60.0"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"esbuild": "0.28.0",
|
"esbuild": "0.28.1",
|
||||||
"dompurify": "3.4.0",
|
"dompurify": "3.4.0",
|
||||||
"postcss": "8.5.15"
|
"postcss": "8.5.15"
|
||||||
}
|
}
|
||||||
|
|||||||
74
server/lib/pathMatch.ts
Normal file
74
server/lib/pathMatch.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
const MAX_RECURSION_DEPTH = 100;
|
||||||
|
|
||||||
|
const segmentRegexCache = new Map<string, RegExp>();
|
||||||
|
|
||||||
|
function getSegmentRegex(patternPart: string): RegExp {
|
||||||
|
let regex = segmentRegexCache.get(patternPart);
|
||||||
|
if (!regex) {
|
||||||
|
const regexPattern = patternPart
|
||||||
|
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
||||||
|
.replace(/\*/g, ".*")
|
||||||
|
.replace(/\?/g, ".");
|
||||||
|
regex = new RegExp(`^${regexPattern}$`);
|
||||||
|
segmentRegexCache.set(patternPart, regex);
|
||||||
|
}
|
||||||
|
return regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPathAllowed(pattern: string, path: string): boolean {
|
||||||
|
const normalize = (p: string) => p.split("/").filter(Boolean);
|
||||||
|
const patternParts = normalize(pattern);
|
||||||
|
const pathParts = normalize(path);
|
||||||
|
|
||||||
|
function matchSegments(
|
||||||
|
patternIndex: number,
|
||||||
|
pathIndex: number,
|
||||||
|
depth: number = 0
|
||||||
|
): boolean {
|
||||||
|
if (depth > MAX_RECURSION_DEPTH) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentPatternPart = patternParts[patternIndex];
|
||||||
|
const currentPathPart = pathParts[pathIndex];
|
||||||
|
|
||||||
|
if (patternIndex >= patternParts.length) {
|
||||||
|
return pathIndex >= pathParts.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathIndex >= pathParts.length) {
|
||||||
|
return patternParts.slice(patternIndex).every((p) => p === "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPatternPart === "*") {
|
||||||
|
if (matchSegments(patternIndex + 1, pathIndex, depth + 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (matchSegments(patternIndex, pathIndex + 1, depth + 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPatternPart.includes("*")) {
|
||||||
|
const regex = getSegmentRegex(currentPatternPart);
|
||||||
|
|
||||||
|
if (regex.test(currentPathPart)) {
|
||||||
|
return matchSegments(
|
||||||
|
patternIndex + 1,
|
||||||
|
pathIndex + 1,
|
||||||
|
depth + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPatternPart !== currentPathPart) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchSegments(patternIndex + 1, pathIndex + 1, depth + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchSegments(0, 0, 0);
|
||||||
|
}
|
||||||
@@ -511,6 +511,12 @@ export class TraefikConfigManager {
|
|||||||
let traefikConfig;
|
let traefikConfig;
|
||||||
try {
|
try {
|
||||||
const currentExitNode = await getCurrentExitNodeId();
|
const currentExitNode = await getCurrentExitNodeId();
|
||||||
|
|
||||||
|
const maintenancePort = config.getRawConfig().server.next_port;
|
||||||
|
const maintenanceHost =
|
||||||
|
config.getRawConfig().server.internal_hostname;
|
||||||
|
const pangolinUIUrl = `http://${maintenanceHost}:${maintenancePort}`;
|
||||||
|
|
||||||
// logger.debug(`Fetching traefik config for exit node: ${currentExitNode}`);
|
// logger.debug(`Fetching traefik config for exit node: ${currentExitNode}`);
|
||||||
traefikConfig = await getTraefikConfig(
|
traefikConfig = await getTraefikConfig(
|
||||||
// this is called by the local exit node to get its own config
|
// this is called by the local exit node to get its own config
|
||||||
@@ -521,7 +527,8 @@ export class TraefikConfigManager {
|
|||||||
build == "saas"
|
build == "saas"
|
||||||
? false
|
? false
|
||||||
: config.getRawConfig().traefik.allow_raw_resources, // dont allow raw resources on saas otherwise use config
|
: config.getRawConfig().traefik.allow_raw_resources, // dont allow raw resources on saas otherwise use config
|
||||||
build != "oss" // generate browser gateway targets on cloud and enterprise
|
pangolinUIUrl, // generate maintenance pages on cloud and hybrid
|
||||||
|
pangolinUIUrl // generate browser gateway targets on cloud and hybrid
|
||||||
);
|
);
|
||||||
|
|
||||||
const domains = new Set<string>();
|
const domains = new Set<string>();
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ export async function getTraefikConfig(
|
|||||||
filterOutNamespaceDomains = false, // UNUSED BUT USED IN PRIVATE
|
filterOutNamespaceDomains = false, // UNUSED BUT USED IN PRIVATE
|
||||||
generateLoginPageRouters = false, // UNUSED BUT USED IN PRIVATE
|
generateLoginPageRouters = false, // UNUSED BUT USED IN PRIVATE
|
||||||
allowRawResources = true,
|
allowRawResources = true,
|
||||||
allowMaintenancePage = true, // UNUSED BUT USED IN PRIVATE
|
maintenancePageUiUrl: string | null = null, // UNUSED BUT USED IN PRIVATE
|
||||||
allowBrowserGatewayResources = true
|
browserGatewayUiUrl: string | null = null // UNUSED BUT USED IN PRIVATE
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
// Get resources with their targets and sites in a single optimized query
|
// Get resources with their targets and sites in a single optimized query
|
||||||
// Start from sites on this exit node, then join to targets and resources
|
// Start from sites on this exit node, then join to targets and resources
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ export async function getTraefikConfig(
|
|||||||
filterOutNamespaceDomains = false,
|
filterOutNamespaceDomains = false,
|
||||||
generateLoginPageRouters = false,
|
generateLoginPageRouters = false,
|
||||||
allowRawResources = true,
|
allowRawResources = true,
|
||||||
allowMaintenancePage = true,
|
maintenancePageUiUrl: string | null = null,
|
||||||
allowBrowserGatewayResources = true
|
browserGatewayUiUrl: string | null = null
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
// Get resources with their targets and sites in a single optimized query
|
// Get resources with their targets and sites in a single optimized query
|
||||||
// Start from sites on this exit node, then join to targets and resources
|
// Start from sites on this exit node, then join to targets and resources
|
||||||
@@ -317,7 +317,7 @@ export async function getTraefikConfig(
|
|||||||
BrowserGatewayResourceEntry
|
BrowserGatewayResourceEntry
|
||||||
>();
|
>();
|
||||||
|
|
||||||
if (allowBrowserGatewayResources) {
|
if (browserGatewayUiUrl) {
|
||||||
for (const row of resourcesWithTargetsAndSites) {
|
for (const row of resourcesWithTargetsAndSites) {
|
||||||
if (!["ssh", "vnc", "rdp"].includes(row.mode)) {
|
if (!["ssh", "vnc", "rdp"].includes(row.mode)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -630,10 +630,11 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showMaintenancePage && allowMaintenancePage) {
|
if (showMaintenancePage && maintenancePageUiUrl) {
|
||||||
const maintenanceServiceName = `${key}-maintenance-service`;
|
const maintenanceServiceName = `${key}-maintenance-service`;
|
||||||
const maintenanceRouterName = `${key}-maintenance-router`;
|
const maintenanceRouterName = `${key}-maintenance-router`;
|
||||||
const rewriteMiddlewareName = `${key}-maintenance-rewrite`;
|
const rewriteMiddlewareName = `${key}-maintenance-rewrite`;
|
||||||
|
const maintenanceHeadersMiddlewareName = `${key}-maintenance-headers`;
|
||||||
|
|
||||||
const entrypointHttp =
|
const entrypointHttp =
|
||||||
config.getRawConfig().traefik.http_entrypoint;
|
config.getRawConfig().traefik.http_entrypoint;
|
||||||
@@ -646,15 +647,11 @@ export async function getTraefikConfig(
|
|||||||
? `*.${domainParts.slice(1).join(".")}`
|
? `*.${domainParts.slice(1).join(".")}`
|
||||||
: fullDomain;
|
: fullDomain;
|
||||||
|
|
||||||
const maintenancePort = config.getRawConfig().server.next_port;
|
|
||||||
const maintenanceHost =
|
|
||||||
config.getRawConfig().server.internal_hostname;
|
|
||||||
|
|
||||||
config_output.http.services[maintenanceServiceName] = {
|
config_output.http.services[maintenanceServiceName] = {
|
||||||
loadBalancer: {
|
loadBalancer: {
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: `http://${maintenanceHost}:${maintenancePort}`
|
url: maintenancePageUiUrl
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
@@ -673,12 +670,26 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config_output.http.middlewares[
|
||||||
|
maintenanceHeadersMiddlewareName
|
||||||
|
] = {
|
||||||
|
headers: {
|
||||||
|
customRequestHeaders: {
|
||||||
|
Host: "app.pangolin.net", // if we are sending to the cloud the host needs to be this but we will pull the p-host to find the resource
|
||||||
|
"p-host": fullDomain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
config_output.http.routers[maintenanceRouterName] = {
|
config_output.http.routers[maintenanceRouterName] = {
|
||||||
entryPoints: [
|
entryPoints: [
|
||||||
resource.ssl ? entrypointHttps : entrypointHttp
|
resource.ssl ? entrypointHttps : entrypointHttp
|
||||||
],
|
],
|
||||||
service: maintenanceServiceName,
|
service: maintenanceServiceName,
|
||||||
middlewares: [rewriteMiddlewareName],
|
middlewares: [
|
||||||
|
rewriteMiddlewareName,
|
||||||
|
maintenanceHeadersMiddlewareName
|
||||||
|
],
|
||||||
rule: rule,
|
rule: rule,
|
||||||
priority: 2000,
|
priority: 2000,
|
||||||
...(resource.ssl ? { tls } : {})
|
...(resource.ssl ? { tls } : {})
|
||||||
@@ -691,6 +702,7 @@ export async function getTraefikConfig(
|
|||||||
resource.ssl ? entrypointHttps : entrypointHttp
|
resource.ssl ? entrypointHttps : entrypointHttp
|
||||||
],
|
],
|
||||||
service: maintenanceServiceName,
|
service: maintenanceServiceName,
|
||||||
|
middlewares: [maintenanceHeadersMiddlewareName],
|
||||||
rule: `${rule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`)) `,
|
rule: `${rule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`)) `,
|
||||||
priority: 2001,
|
priority: 2001,
|
||||||
...(resource.ssl ? { tls } : {})
|
...(resource.ssl ? { tls } : {})
|
||||||
@@ -1027,7 +1039,7 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowBrowserGatewayResources) {
|
if (browserGatewayUiUrl) {
|
||||||
// Generate Traefik config for browser gateway resources
|
// Generate Traefik config for browser gateway resources
|
||||||
const browserGatewayPort = 39999;
|
const browserGatewayPort = 39999;
|
||||||
for (const [, bgResource] of browserGatewayResourcesMap.entries()) {
|
for (const [, bgResource] of browserGatewayResourcesMap.entries()) {
|
||||||
@@ -1119,20 +1131,17 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showBgMaintenancePage && allowMaintenancePage) {
|
if (showBgMaintenancePage && maintenancePageUiUrl) {
|
||||||
const bgMaintenanceServiceName = `bg-r${bgResource.resourceId}-maintenance-service`;
|
const bgMaintenanceServiceName = `bg-r${bgResource.resourceId}-maintenance-service`;
|
||||||
const bgMaintenanceRouterName = `bg-r${bgResource.resourceId}-maintenance-router`;
|
const bgMaintenanceRouterName = `bg-r${bgResource.resourceId}-maintenance-router`;
|
||||||
const bgRewriteMiddlewareName = `bg-r${bgResource.resourceId}-maintenance-rewrite`;
|
const bgRewriteMiddlewareName = `bg-r${bgResource.resourceId}-maintenance-rewrite`;
|
||||||
|
const bgMaintenanceHeadersMiddlewareName = `bg-r${bgResource.resourceId}-maintenance-headers`;
|
||||||
|
|
||||||
const entrypointHttp =
|
const entrypointHttp =
|
||||||
config.getRawConfig().traefik.http_entrypoint;
|
config.getRawConfig().traefik.http_entrypoint;
|
||||||
const entrypointHttps =
|
const entrypointHttps =
|
||||||
config.getRawConfig().traefik.https_entrypoint;
|
config.getRawConfig().traefik.https_entrypoint;
|
||||||
|
|
||||||
const maintenancePort = config.getRawConfig().server.next_port;
|
|
||||||
const maintenanceHost =
|
|
||||||
config.getRawConfig().server.internal_hostname;
|
|
||||||
|
|
||||||
if (!config_output.http.services)
|
if (!config_output.http.services)
|
||||||
config_output.http.services = {};
|
config_output.http.services = {};
|
||||||
if (!config_output.http.middlewares)
|
if (!config_output.http.middlewares)
|
||||||
@@ -1144,7 +1153,7 @@ export async function getTraefikConfig(
|
|||||||
loadBalancer: {
|
loadBalancer: {
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: `http://${maintenanceHost}:${maintenancePort}`
|
url: maintenancePageUiUrl
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
@@ -1158,12 +1167,26 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config_output.http.middlewares![
|
||||||
|
bgMaintenanceHeadersMiddlewareName
|
||||||
|
] = {
|
||||||
|
headers: {
|
||||||
|
customRequestHeaders: {
|
||||||
|
Host: "app.pangolin.net", // if we are sending to the cloud the host needs to be this but we will pull the p-host to find the resource
|
||||||
|
"p-host": fullDomain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
config_output.http.routers![bgMaintenanceRouterName] = {
|
config_output.http.routers![bgMaintenanceRouterName] = {
|
||||||
entryPoints: [
|
entryPoints: [
|
||||||
bgResource.ssl ? entrypointHttps : entrypointHttp
|
bgResource.ssl ? entrypointHttps : entrypointHttp
|
||||||
],
|
],
|
||||||
service: bgMaintenanceServiceName,
|
service: bgMaintenanceServiceName,
|
||||||
middlewares: [bgRewriteMiddlewareName],
|
middlewares: [
|
||||||
|
bgRewriteMiddlewareName,
|
||||||
|
bgMaintenanceHeadersMiddlewareName
|
||||||
|
],
|
||||||
rule: hostRule,
|
rule: hostRule,
|
||||||
priority: 2000,
|
priority: 2000,
|
||||||
...(bgResource.ssl ? { tls } : {})
|
...(bgResource.ssl ? { tls } : {})
|
||||||
@@ -1176,6 +1199,7 @@ export async function getTraefikConfig(
|
|||||||
bgResource.ssl ? entrypointHttps : entrypointHttp
|
bgResource.ssl ? entrypointHttps : entrypointHttp
|
||||||
],
|
],
|
||||||
service: bgMaintenanceServiceName,
|
service: bgMaintenanceServiceName,
|
||||||
|
middlewares: [bgMaintenanceHeadersMiddlewareName],
|
||||||
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
|
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
|
||||||
priority: 2001,
|
priority: 2001,
|
||||||
...(bgResource.ssl ? { tls } : {})
|
...(bgResource.ssl ? { tls } : {})
|
||||||
@@ -1234,9 +1258,8 @@ export async function getTraefikConfig(
|
|||||||
// The primary type is used for the path rewrite (e.g. /rdp), mirroring
|
// The primary type is used for the path rewrite (e.g. /rdp), mirroring
|
||||||
// how the maintenance page rewrites everything to /maintenance-screen.
|
// how the maintenance page rewrites everything to /maintenance-screen.
|
||||||
const primaryType = typeMap.keys().next().value as string;
|
const primaryType = typeMap.keys().next().value as string;
|
||||||
const internalHost = config.getRawConfig().server.internal_hostname;
|
|
||||||
const internalPort = config.getRawConfig().server.next_port;
|
|
||||||
const uiRewriteMiddlewareName = `bg-r${bgResource.resourceId}-ui-rewrite`;
|
const uiRewriteMiddlewareName = `bg-r${bgResource.resourceId}-ui-rewrite`;
|
||||||
|
const uiHeadersMiddlewareName = `bg-r${bgResource.resourceId}-ui-headers`;
|
||||||
const entrypoint = bgResource.ssl
|
const entrypoint = bgResource.ssl
|
||||||
? config.getRawConfig().traefik.https_entrypoint
|
? config.getRawConfig().traefik.https_entrypoint
|
||||||
: config.getRawConfig().traefik.http_entrypoint;
|
: config.getRawConfig().traefik.http_entrypoint;
|
||||||
@@ -1252,22 +1275,33 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config_output.http.middlewares![uiHeadersMiddlewareName] = {
|
||||||
|
headers: {
|
||||||
|
customRequestHeaders: {
|
||||||
|
Host: "app.pangolin.net", // if we are sending to the cloud the host needs to be this but we will pull the p-host to find the resource
|
||||||
|
"p-host": fullDomain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
config_output.http.services![bgUiServiceName] = {
|
config_output.http.services![bgUiServiceName] = {
|
||||||
loadBalancer: {
|
loadBalancer: {
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: `http://${internalHost}:${internalPort}`
|
url: browserGatewayUiUrl
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assets router at higher priority so /_next files load without rewrite
|
// Assets router at higher priority so /_next files load without rewrite.
|
||||||
|
// Do NOT apply the path-rewrite middleware here — static assets must
|
||||||
|
// keep their original path; only the host headers are needed.
|
||||||
config_output.http.routers![
|
config_output.http.routers![
|
||||||
`bg-r${bgResource.resourceId}-assets-router`
|
`bg-r${bgResource.resourceId}-assets-router`
|
||||||
] = {
|
] = {
|
||||||
entryPoints: [entrypoint],
|
entryPoints: [entrypoint],
|
||||||
middlewares: routerMiddlewares,
|
middlewares: [...routerMiddlewares, uiHeadersMiddlewareName],
|
||||||
service: bgUiServiceName,
|
service: bgUiServiceName,
|
||||||
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
|
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
|
||||||
priority: 101,
|
priority: 101,
|
||||||
@@ -1279,7 +1313,11 @@ export async function getTraefikConfig(
|
|||||||
`bg-r${bgResource.resourceId}-ui-router`
|
`bg-r${bgResource.resourceId}-ui-router`
|
||||||
] = {
|
] = {
|
||||||
entryPoints: [entrypoint],
|
entryPoints: [entrypoint],
|
||||||
middlewares: [...routerMiddlewares, uiRewriteMiddlewareName],
|
middlewares: [
|
||||||
|
...routerMiddlewares,
|
||||||
|
uiRewriteMiddlewareName,
|
||||||
|
uiHeadersMiddlewareName
|
||||||
|
],
|
||||||
service: bgUiServiceName,
|
service: bgUiServiceName,
|
||||||
rule: hostRule,
|
rule: hostRule,
|
||||||
priority: 100,
|
priority: 100,
|
||||||
@@ -1312,10 +1350,6 @@ export async function getTraefikConfig(
|
|||||||
const siteResourceRouterName = `${srKey}-router`;
|
const siteResourceRouterName = `${srKey}-router`;
|
||||||
const siteResourceRewriteMiddlewareName = `${srKey}-rewrite`;
|
const siteResourceRewriteMiddlewareName = `${srKey}-rewrite`;
|
||||||
|
|
||||||
const maintenancePort = config.getRawConfig().server.next_port;
|
|
||||||
const maintenanceHost =
|
|
||||||
config.getRawConfig().server.internal_hostname;
|
|
||||||
|
|
||||||
if (!config_output.http.routers) {
|
if (!config_output.http.routers) {
|
||||||
config_output.http.routers = {};
|
config_output.http.routers = {};
|
||||||
}
|
}
|
||||||
@@ -1331,7 +1365,7 @@ export async function getTraefikConfig(
|
|||||||
loadBalancer: {
|
loadBalancer: {
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: `http://${maintenanceHost}:${maintenancePort}`
|
url: maintenancePageUiUrl
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
|
|||||||
@@ -277,6 +277,8 @@ hybridRouter.get(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pangolinUIUrl = config.getRawConfig().app.dashboard_url; // points to the dashboard to serve from there
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const traefikConfig = await getTraefikConfig(
|
const traefikConfig = await getTraefikConfig(
|
||||||
remoteExitNode.exitNodeId,
|
remoteExitNode.exitNodeId,
|
||||||
@@ -284,8 +286,8 @@ hybridRouter.get(
|
|||||||
true, // But don't allow domain namespace resources
|
true, // But don't allow domain namespace resources
|
||||||
false, // Dont include login pages,
|
false, // Dont include login pages,
|
||||||
true, // allow raw resources
|
true, // allow raw resources
|
||||||
false, // dont generate maintenance page
|
pangolinUIUrl, // dont generate maintenance page
|
||||||
false // dont generate browser gateway targets
|
pangolinUIUrl // generate browser gateway targets
|
||||||
);
|
);
|
||||||
|
|
||||||
return response(res, {
|
return response(res, {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { assertEquals } from "@test/assert";
|
import { assertEquals } from "@test/assert";
|
||||||
import { REGIONS } from "@server/db/regions";
|
import { REGIONS } from "@server/db/regions";
|
||||||
|
import { isPathAllowed } from "@server/lib/pathMatch";
|
||||||
|
|
||||||
function isIpInRegion(
|
function isIpInRegion(
|
||||||
ipCountryCode: string | undefined,
|
ipCountryCode: string | undefined,
|
||||||
@@ -33,76 +34,6 @@ function isIpInRegion(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPathAllowed(pattern: string, path: string): boolean {
|
|
||||||
// Normalize and split paths into segments
|
|
||||||
const normalize = (p: string) => p.split("/").filter(Boolean);
|
|
||||||
const patternParts = normalize(pattern);
|
|
||||||
const pathParts = normalize(path);
|
|
||||||
|
|
||||||
// Recursive function to try different wildcard matches
|
|
||||||
function matchSegments(patternIndex: number, pathIndex: number): boolean {
|
|
||||||
const indent = " ".repeat(pathIndex); // Indent based on recursion depth
|
|
||||||
const currentPatternPart = patternParts[patternIndex];
|
|
||||||
const currentPathPart = pathParts[pathIndex];
|
|
||||||
|
|
||||||
// If we've consumed all pattern parts, we should have consumed all path parts
|
|
||||||
if (patternIndex >= patternParts.length) {
|
|
||||||
const result = pathIndex >= pathParts.length;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we've consumed all path parts but still have pattern parts
|
|
||||||
if (pathIndex >= pathParts.length) {
|
|
||||||
// The only way this can match is if all remaining pattern parts are wildcards
|
|
||||||
const remainingPattern = patternParts.slice(patternIndex);
|
|
||||||
const result = remainingPattern.every((p) => p === "*");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For full segment wildcards, try consuming different numbers of path segments
|
|
||||||
if (currentPatternPart === "*") {
|
|
||||||
// Try consuming 0 segments (skip the wildcard)
|
|
||||||
if (matchSegments(patternIndex + 1, pathIndex)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try consuming current segment and recursively try rest
|
|
||||||
if (matchSegments(patternIndex, pathIndex + 1)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for in-segment wildcard (e.g., "prefix*" or "prefix*suffix")
|
|
||||||
if (currentPatternPart.includes("*")) {
|
|
||||||
// Convert the pattern segment to a regex pattern
|
|
||||||
const regexPattern = currentPatternPart
|
|
||||||
.replace(/\*/g, ".*") // Replace * with .* for regex wildcard
|
|
||||||
.replace(/\?/g, "."); // Replace ? with . for single character wildcard if needed
|
|
||||||
|
|
||||||
const regex = new RegExp(`^${regexPattern}$`);
|
|
||||||
|
|
||||||
if (regex.test(currentPathPart)) {
|
|
||||||
return matchSegments(patternIndex + 1, pathIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For regular segments, they must match exactly
|
|
||||||
if (currentPatternPart !== currentPathPart) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to next segments in both pattern and path
|
|
||||||
return matchSegments(patternIndex + 1, pathIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = matchSegments(0, 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
console.log("Running path matching tests...");
|
console.log("Running path matching tests...");
|
||||||
|
|
||||||
@@ -308,6 +239,121 @@ function runTests() {
|
|||||||
console.log("All path matching tests passed!");
|
console.log("All path matching tests passed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runSpecialCharacterTests() {
|
||||||
|
console.log("\nRunning special character tests...");
|
||||||
|
|
||||||
|
let threw = false;
|
||||||
|
try {
|
||||||
|
isPathAllowed("(api*", "anything");
|
||||||
|
isPathAllowed("a(b*", "a(bc");
|
||||||
|
isPathAllowed("c[d*", "c[de");
|
||||||
|
isPathAllowed("x{2}*", "x{2}y");
|
||||||
|
isPathAllowed("a|b*", "a|bc");
|
||||||
|
isPathAllowed("back\\slash*", "back\\slashed");
|
||||||
|
} catch (e) {
|
||||||
|
threw = true;
|
||||||
|
console.error(
|
||||||
|
"Patterns accepted by isValidUrlGlobPattern crashed the matcher:",
|
||||||
|
e instanceof Error ? e.message : e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assertEquals(
|
||||||
|
threw,
|
||||||
|
false,
|
||||||
|
"Patterns with regex metacharacters must not throw"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("(api*", "(api-v1"),
|
||||||
|
true,
|
||||||
|
"Parenthesis should be treated as a literal character"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("(api*", "xapi-v1"),
|
||||||
|
false,
|
||||||
|
"Parenthesis should not match other characters"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("a(b)*", "a(b)c"),
|
||||||
|
true,
|
||||||
|
"Parentheses pair should be treated as literal characters"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("*.png", "image.png"),
|
||||||
|
true,
|
||||||
|
"Dot should match a literal dot"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("*.png", "imageXpng"),
|
||||||
|
false,
|
||||||
|
"Dot should not act as a regex wildcard"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("v1.0*", "v1.0.1"),
|
||||||
|
true,
|
||||||
|
"Version-like literal should match itself"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("v1.0*", "v1x0-beta"),
|
||||||
|
false,
|
||||||
|
"Version-like literal should not match arbitrary characters"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("a+b*", "a+bc"),
|
||||||
|
true,
|
||||||
|
"Plus should be treated as a literal character"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("a+b*", "aaabc"),
|
||||||
|
false,
|
||||||
|
"Plus should not act as a regex quantifier"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("$ref*", "$refs"),
|
||||||
|
true,
|
||||||
|
"Dollar sign should be treated as a literal character"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("price$*", "price$100"),
|
||||||
|
true,
|
||||||
|
"Dollar sign mid-pattern should be treated as a literal character"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("^start*", "^started"),
|
||||||
|
true,
|
||||||
|
"Caret should be treated as a literal character"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("a|b*", "a|bc"),
|
||||||
|
true,
|
||||||
|
"Pipe should be treated as a literal character"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("a|b*", "a"),
|
||||||
|
false,
|
||||||
|
"Pipe should not act as regex alternation"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("file?*", "fileX"),
|
||||||
|
true,
|
||||||
|
"Question mark should still act as a single-character wildcard"
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
isPathAllowed("api/*", "api/" + "x/".repeat(50)),
|
||||||
|
true,
|
||||||
|
"Deeply nested paths should still match"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("All special character tests passed!");
|
||||||
|
}
|
||||||
|
|
||||||
function runRegionTests() {
|
function runRegionTests() {
|
||||||
console.log("\nRunning isIpInRegion tests...");
|
console.log("\nRunning isIpInRegion tests...");
|
||||||
|
|
||||||
@@ -367,6 +413,7 @@ function runRegionTests() {
|
|||||||
// Run all tests
|
// Run all tests
|
||||||
try {
|
try {
|
||||||
runTests();
|
runTests();
|
||||||
|
runSpecialCharacterTests();
|
||||||
runRegionTests();
|
runRegionTests();
|
||||||
console.log("\n✅ All tests passed!");
|
console.log("\n✅ All tests passed!");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import config from "@server/lib/config";
|
import config from "@server/lib/config";
|
||||||
import { isIpInCidr, stripPortFromHost } from "@server/lib/ip";
|
import { isIpInCidr, stripPortFromHost } from "@server/lib/ip";
|
||||||
|
import { isPathAllowed } from "@server/lib/pathMatch";
|
||||||
import { response } from "@server/lib/response";
|
import { response } from "@server/lib/response";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
@@ -1090,143 +1091,7 @@ async function checkRules(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPathAllowed(pattern: string, path: string): boolean {
|
export { isPathAllowed };
|
||||||
logger.debug(`\nMatching path "${path}" against pattern "${pattern}"`);
|
|
||||||
|
|
||||||
// Normalize and split paths into segments
|
|
||||||
const normalize = (p: string) => p.split("/").filter(Boolean);
|
|
||||||
const patternParts = normalize(pattern);
|
|
||||||
const pathParts = normalize(path);
|
|
||||||
|
|
||||||
logger.debug(`Normalized pattern parts: [${patternParts.join(", ")}]`);
|
|
||||||
logger.debug(`Normalized path parts: [${pathParts.join(", ")}]`);
|
|
||||||
|
|
||||||
// Maximum recursion depth to prevent stack overflow and memory issues
|
|
||||||
const MAX_RECURSION_DEPTH = 100;
|
|
||||||
|
|
||||||
// Recursive function to try different wildcard matches
|
|
||||||
function matchSegments(
|
|
||||||
patternIndex: number,
|
|
||||||
pathIndex: number,
|
|
||||||
depth: number = 0
|
|
||||||
): boolean {
|
|
||||||
// Check recursion depth limit
|
|
||||||
if (depth > MAX_RECURSION_DEPTH) {
|
|
||||||
logger.warn(
|
|
||||||
`Path matching exceeded maximum recursion depth (${MAX_RECURSION_DEPTH}) for pattern "${pattern}" and path "${path}"`
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const indent = " ".repeat(depth); // Indent based on recursion depth
|
|
||||||
const currentPatternPart = patternParts[patternIndex];
|
|
||||||
const currentPathPart = pathParts[pathIndex];
|
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Checking patternIndex=${patternIndex} (${currentPatternPart || "END"}) vs pathIndex=${pathIndex} (${currentPathPart || "END"}) [depth=${depth}]`
|
|
||||||
);
|
|
||||||
|
|
||||||
// If we've consumed all pattern parts, we should have consumed all path parts
|
|
||||||
if (patternIndex >= patternParts.length) {
|
|
||||||
const result = pathIndex >= pathParts.length;
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Reached end of pattern, remaining path: ${pathParts.slice(pathIndex).join("/")} -> ${result}`
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we've consumed all path parts but still have pattern parts
|
|
||||||
if (pathIndex >= pathParts.length) {
|
|
||||||
// The only way this can match is if all remaining pattern parts are wildcards
|
|
||||||
const remainingPattern = patternParts.slice(patternIndex);
|
|
||||||
const result = remainingPattern.every((p) => p === "*");
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Reached end of path, remaining pattern: ${remainingPattern.join("/")} -> ${result}`
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For full segment wildcards, try consuming different numbers of path segments
|
|
||||||
if (currentPatternPart === "*") {
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Found wildcard at pattern index ${patternIndex}`
|
|
||||||
);
|
|
||||||
|
|
||||||
// Try consuming 0 segments (skip the wildcard)
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Trying to skip wildcard (consume 0 segments)`
|
|
||||||
);
|
|
||||||
if (matchSegments(patternIndex + 1, pathIndex, depth + 1)) {
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Successfully matched by skipping wildcard`
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try consuming current segment and recursively try rest
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Trying to consume segment "${currentPathPart}" for wildcard`
|
|
||||||
);
|
|
||||||
if (matchSegments(patternIndex, pathIndex + 1, depth + 1)) {
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Successfully matched by consuming segment for wildcard`
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(`${indent}Failed to match wildcard`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for in-segment wildcard (e.g., "prefix*" or "prefix*suffix")
|
|
||||||
if (currentPatternPart.includes("*")) {
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Found in-segment wildcard in "${currentPatternPart}"`
|
|
||||||
);
|
|
||||||
|
|
||||||
// Convert the pattern segment to a regex pattern
|
|
||||||
const regexPattern = currentPatternPart
|
|
||||||
.replace(/\*/g, ".*") // Replace * with .* for regex wildcard
|
|
||||||
.replace(/\?/g, "."); // Replace ? with . for single character wildcard if needed
|
|
||||||
|
|
||||||
const regex = new RegExp(`^${regexPattern}$`);
|
|
||||||
|
|
||||||
if (regex.test(currentPathPart)) {
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Segment with wildcard matches: "${currentPatternPart}" matches "${currentPathPart}"`
|
|
||||||
);
|
|
||||||
return matchSegments(
|
|
||||||
patternIndex + 1,
|
|
||||||
pathIndex + 1,
|
|
||||||
depth + 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Segment with wildcard mismatch: "${currentPatternPart}" doesn't match "${currentPathPart}"`
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For regular segments, they must match exactly
|
|
||||||
if (currentPatternPart !== currentPathPart) {
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Segment mismatch: "${currentPatternPart}" != "${currentPathPart}"`
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
`${indent}Segments match: "${currentPatternPart}" = "${currentPathPart}"`
|
|
||||||
);
|
|
||||||
// Move to next segments in both pattern and path
|
|
||||||
return matchSegments(patternIndex + 1, pathIndex + 1, depth + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = matchSegments(0, 0, 0);
|
|
||||||
logger.debug(`Final result: ${result}`);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function isIpInGeoIP(
|
async function isIpInGeoIP(
|
||||||
ipCountryCode: string | undefined,
|
ipCountryCode: string | undefined,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
verifyApiKey,
|
verifyApiKey,
|
||||||
verifyApiKeyOrgAccess,
|
verifyApiKeyOrgAccess,
|
||||||
verifyApiKeyHasAction,
|
verifyApiKeyHasAction,
|
||||||
verifyApiKeyCanSetUserOrgRoles,
|
|
||||||
verifyApiKeySiteAccess,
|
verifyApiKeySiteAccess,
|
||||||
verifyApiKeyResourceAccess,
|
verifyApiKeyResourceAccess,
|
||||||
verifyApiKeyTargetAccess,
|
verifyApiKeyTargetAccess,
|
||||||
@@ -974,6 +973,13 @@ authenticated.get(
|
|||||||
idp.getIdp
|
idp.getIdp
|
||||||
);
|
);
|
||||||
|
|
||||||
|
authenticated.delete(
|
||||||
|
"/idp/:idpId",
|
||||||
|
verifyApiKeyIsRoot,
|
||||||
|
verifyApiKeyHasAction(ActionsEnum.deleteIdp),
|
||||||
|
idp.deleteIdp
|
||||||
|
);
|
||||||
|
|
||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/idp/:idpId/org/:orgId",
|
"/idp/:idpId/org/:orgId",
|
||||||
verifyApiKeyIsRoot,
|
verifyApiKeyIsRoot,
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const handleNewtGetConfigMessage: MessageHandler = async (context) => {
|
|||||||
// TODO: somehow we should make sure a recent hole punch has happened if this occurs (hole punch could be from the last restart if done quickly)
|
// TODO: somehow we should make sure a recent hole punch has happened if this occurs (hole punch could be from the last restart if done quickly)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingSite.lastHolePunch && now - existingSite.lastHolePunch > 5) {
|
if (existingSite.lastHolePunch && now - existingSite.lastHolePunch > 12) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`Site last hole punch is too old; skipping this register. The site is failing to hole punch and identify its network address with the server. Can the site reach the server on UDP port ${config.getRawConfig().gerbil.clients_start_port}?`
|
`Site last hole punch is too old; skipping this register. The site is failing to hole punch and identify its network address with the server. Can the site reach the server on UDP port ${config.getRawConfig().gerbil.clients_start_port}?`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
|
|||||||
// this prevents us from accepting a register from an olm that has not hole punched yet.
|
// this prevents us from accepting a register from an olm that has not hole punched yet.
|
||||||
// the olm will pump the register so we can keep checking
|
// the olm will pump the register so we can keep checking
|
||||||
// TODO: I still think there is a better way to do this rather than locking it out here but ???
|
// TODO: I still think there is a better way to do this rather than locking it out here but ???
|
||||||
if (now - (client.lastHolePunch || 0) > 5 && sitesCount > 0) {
|
if (now - (client.lastHolePunch || 0) > 12 && sitesCount > 0) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`[handleOlmRegisterMessage] Client last hole punch is too old and we have sites to send; skipping this register. The client is failing to hole punch and identify its network address with the server. Can the client reach the server on UDP port ${config.getRawConfig().gerbil.clients_start_port}?`,
|
`[handleOlmRegisterMessage] Client last hole punch is too old and we have sites to send; skipping this register. The client is failing to hole punch and identify its network address with the server. Can the client reach the server on UDP port ${config.getRawConfig().gerbil.clients_start_port}?`,
|
||||||
{ orgId: client.orgId, clientId: client.clientId }
|
{ orgId: client.orgId, clientId: client.clientId }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { NextFunction, Request, Response } from "express";
|
|||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { fromError } from "zod-validation-error";
|
import { fromError } from "zod-validation-error";
|
||||||
|
import { applyInlinePolicyFields } from "./inlinePolicyFields";
|
||||||
|
|
||||||
const getResourceSchema = z.strictObject({
|
const getResourceSchema = z.strictObject({
|
||||||
resourceId: z
|
resourceId: z
|
||||||
@@ -151,13 +152,7 @@ export async function getResource(
|
|||||||
const policy = await queryInlinePolicy(
|
const policy = await queryInlinePolicy(
|
||||||
resource.defaultResourcePolicyId!
|
resource.defaultResourcePolicyId!
|
||||||
);
|
);
|
||||||
returnData = {
|
returnData = applyInlinePolicyFields(returnData, policy);
|
||||||
...returnData,
|
|
||||||
sso: policy?.sso || null,
|
|
||||||
emailWhitelistEnabled: policy?.emailWhitelistEnabled || null,
|
|
||||||
applyRules: policy?.applyRules || null,
|
|
||||||
skipToIdpId: policy?.idpId || null
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response<GetResourceResponse>(res, {
|
return response<GetResourceResponse>(res, {
|
||||||
|
|||||||
74
server/routers/resource/inlinePolicyFields.test.ts
Normal file
74
server/routers/resource/inlinePolicyFields.test.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { assertEquals } from "../../../test/assert";
|
||||||
|
import { applyInlinePolicyFields } from "./inlinePolicyFields";
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
const resource = {
|
||||||
|
resourceId: 1,
|
||||||
|
name: "dashboard",
|
||||||
|
sso: null,
|
||||||
|
emailWhitelistEnabled: null,
|
||||||
|
applyRules: null,
|
||||||
|
skipToIdpId: null
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
const enabledPolicy = {
|
||||||
|
sso: true,
|
||||||
|
emailWhitelistEnabled: true,
|
||||||
|
applyRules: true,
|
||||||
|
idpId: 42
|
||||||
|
};
|
||||||
|
|
||||||
|
const enabledResult = applyInlinePolicyFields(resource, enabledPolicy);
|
||||||
|
assertEquals(enabledResult.sso, true, "sso should mirror policy true");
|
||||||
|
assertEquals(
|
||||||
|
enabledResult.emailWhitelistEnabled,
|
||||||
|
true,
|
||||||
|
"email whitelist should mirror policy true"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
enabledResult.applyRules,
|
||||||
|
true,
|
||||||
|
"applyRules should mirror policy true"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
enabledResult.skipToIdpId,
|
||||||
|
42,
|
||||||
|
"skipToIdpId should use policy idpId"
|
||||||
|
);
|
||||||
|
|
||||||
|
const disabledPolicy = {
|
||||||
|
sso: false,
|
||||||
|
emailWhitelistEnabled: false,
|
||||||
|
applyRules: false,
|
||||||
|
idpId: null
|
||||||
|
};
|
||||||
|
|
||||||
|
const disabledResult = applyInlinePolicyFields(resource, disabledPolicy);
|
||||||
|
assertEquals(disabledResult.sso, false, "sso false must not become null");
|
||||||
|
assertEquals(
|
||||||
|
disabledResult.emailWhitelistEnabled,
|
||||||
|
false,
|
||||||
|
"email whitelist false must not become null"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
disabledResult.applyRules,
|
||||||
|
false,
|
||||||
|
"applyRules false must not become null"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
disabledResult.skipToIdpId,
|
||||||
|
null,
|
||||||
|
"missing idp should stay null"
|
||||||
|
);
|
||||||
|
|
||||||
|
const missingPolicyResult = applyInlinePolicyFields(resource, null);
|
||||||
|
assertEquals(
|
||||||
|
missingPolicyResult.sso,
|
||||||
|
null,
|
||||||
|
"missing policy should return nullable resource fields"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("PASS: inline policy fields mirror policy values");
|
||||||
|
}
|
||||||
|
|
||||||
|
runTests();
|
||||||
19
server/routers/resource/inlinePolicyFields.ts
Normal file
19
server/routers/resource/inlinePolicyFields.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import type { Resource, ResourcePolicy } from "@server/db";
|
||||||
|
|
||||||
|
type InlinePolicyFields = Pick<
|
||||||
|
ResourcePolicy,
|
||||||
|
"sso" | "emailWhitelistEnabled" | "applyRules" | "idpId"
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function applyInlinePolicyFields<T extends Resource>(
|
||||||
|
resource: T,
|
||||||
|
policy: InlinePolicyFields | null | undefined
|
||||||
|
): T {
|
||||||
|
return {
|
||||||
|
...resource,
|
||||||
|
sso: policy?.sso ?? null,
|
||||||
|
emailWhitelistEnabled: policy?.emailWhitelistEnabled ?? null,
|
||||||
|
applyRules: policy?.applyRules ?? null,
|
||||||
|
skipToIdpId: policy?.idpId ?? null
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ import { build } from "@server/build";
|
|||||||
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||||
|
import { applyInlinePolicyFields } from "./inlinePolicyFields";
|
||||||
|
|
||||||
const updateResourceParamsSchema = z.strictObject({
|
const updateResourceParamsSchema = z.strictObject({
|
||||||
resourceId: z.coerce.number().int().positive()
|
resourceId: z.coerce.number().int().positive()
|
||||||
@@ -682,6 +683,12 @@ async function updateHttpResource(
|
|||||||
.where(eq(resourcePolicies.resourcePolicyId, policyId));
|
.where(eq(resourcePolicies.resourcePolicyId, policyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [inlinePolicy] = await db
|
||||||
|
.select()
|
||||||
|
.from(resourcePolicies)
|
||||||
|
.where(eq(resourcePolicies.resourcePolicyId, policyId))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
const updatedResource = await db
|
const updatedResource = await db
|
||||||
.update(resources)
|
.update(resources)
|
||||||
.set({ ...resourceOnlyData, headers })
|
.set({ ...resourceOnlyData, headers })
|
||||||
@@ -698,7 +705,7 @@ async function updateHttpResource(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response(res, {
|
return response(res, {
|
||||||
data: updatedResource[0],
|
data: applyInlinePolicyFields(updatedResource[0], inlinePolicy),
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
message: "HTTP resource updated successfully",
|
message: "HTTP resource updated successfully",
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import HttpCode from "@server/types/HttpCode";
|
|||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { response as sendResponse } from "@server/lib/response";
|
import { response as sendResponse } from "@server/lib/response";
|
||||||
import config from "@server/lib/config";
|
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { APP_VERSION } from "@server/lib/consts";
|
import { APP_VERSION } from "@server/lib/consts";
|
||||||
import license from "#dynamic/license/license";
|
import license from "#dynamic/license/license";
|
||||||
@@ -22,9 +21,6 @@ export async function getServerInfo(
|
|||||||
next: NextFunction
|
next: NextFunction
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const supporterData = config.getSupporterData();
|
|
||||||
const supporterStatusValid = supporterData?.valid || false;
|
|
||||||
|
|
||||||
let enterpriseLicenseValid = false;
|
let enterpriseLicenseValid = false;
|
||||||
let enterpriseLicenseType: string | null = null;
|
let enterpriseLicenseType: string | null = null;
|
||||||
|
|
||||||
@@ -41,7 +37,7 @@ export async function getServerInfo(
|
|||||||
return sendResponse<GetServerInfoResponse>(res, {
|
return sendResponse<GetServerInfoResponse>(res, {
|
||||||
data: {
|
data: {
|
||||||
version: APP_VERSION,
|
version: APP_VERSION,
|
||||||
supporterStatusValid,
|
supporterStatusValid: true,
|
||||||
build,
|
build,
|
||||||
enterpriseLicenseValid,
|
enterpriseLicenseValid,
|
||||||
enterpriseLicenseType
|
enterpriseLicenseType
|
||||||
|
|||||||
@@ -17,13 +17,18 @@ export async function traefikConfigProvider(
|
|||||||
// Get the current exit node name from config
|
// Get the current exit node name from config
|
||||||
const currentExitNodeId = await getCurrentExitNodeId();
|
const currentExitNodeId = await getCurrentExitNodeId();
|
||||||
|
|
||||||
|
const maintenancePort = config.getRawConfig().server.next_port;
|
||||||
|
const maintenanceHost = config.getRawConfig().server.internal_hostname;
|
||||||
|
const pangolinUIUrl = `http://${maintenanceHost}:${maintenancePort}`;
|
||||||
|
|
||||||
const traefikConfig = await getTraefikConfig(
|
const traefikConfig = await getTraefikConfig(
|
||||||
currentExitNodeId,
|
currentExitNodeId,
|
||||||
config.getRawConfig().traefik.site_types,
|
config.getRawConfig().traefik.site_types,
|
||||||
build == "oss", // filter out the namespace domains in open source
|
build == "oss", // filter out the namespace domains in open source
|
||||||
build != "oss", // generate the login pages on the cloud and and enterprise,
|
build != "oss", // generate the login pages on the cloud and and enterprise,
|
||||||
config.getRawConfig().traefik.allow_raw_resources,
|
config.getRawConfig().traefik.allow_raw_resources,
|
||||||
build != "oss" // generate browser gateway resources on cloud and enterprise
|
pangolinUIUrl,
|
||||||
|
pangolinUIUrl
|
||||||
);
|
);
|
||||||
|
|
||||||
if (traefikConfig?.http?.middlewares) {
|
if (traefikConfig?.http?.middlewares) {
|
||||||
|
|||||||
@@ -42,7 +42,14 @@ import {
|
|||||||
SettingsSectionFooter
|
SettingsSectionFooter
|
||||||
} from "@app/components/Settings";
|
} from "@app/components/Settings";
|
||||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||||
import { ArrowRight, Check, ExternalLink, Heart, InfoIcon, TicketCheck } from "lucide-react";
|
import {
|
||||||
|
ArrowRight,
|
||||||
|
Check,
|
||||||
|
ExternalLink,
|
||||||
|
Heart,
|
||||||
|
InfoIcon,
|
||||||
|
TicketCheck
|
||||||
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import DismissableBanner from "@app/components/DismissableBanner";
|
import DismissableBanner from "@app/components/DismissableBanner";
|
||||||
import CopyTextBox from "@app/components/CopyTextBox";
|
import CopyTextBox from "@app/components/CopyTextBox";
|
||||||
@@ -50,7 +57,7 @@ import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
|
|||||||
import { SitePriceCalculator } from "@app/components/SitePriceCalculator";
|
import { SitePriceCalculator } from "@app/components/SitePriceCalculator";
|
||||||
import { Checkbox } from "@app/components/ui/checkbox";
|
import { Checkbox } from "@app/components/ui/checkbox";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
||||||
import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
// import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const ENTERPRISE_DOCS_URL =
|
const ENTERPRISE_DOCS_URL =
|
||||||
@@ -82,7 +89,7 @@ export default function LicensePage() {
|
|||||||
const [isActivatingLicense, setIsActivatingLicense] = useState(false);
|
const [isActivatingLicense, setIsActivatingLicense] = useState(false);
|
||||||
const [isDeletingLicense, setIsDeletingLicense] = useState(false);
|
const [isDeletingLicense, setIsDeletingLicense] = useState(false);
|
||||||
const [isRecheckingLicense, setIsRecheckingLicense] = useState(false);
|
const [isRecheckingLicense, setIsRecheckingLicense] = useState(false);
|
||||||
const { supporterStatus } = useSupporterStatusContext();
|
// const { supporterStatus } = useSupporterStatusContext();
|
||||||
|
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
@@ -347,9 +354,7 @@ export default function LicensePage() {
|
|||||||
storageKey="license-banner-dismissed"
|
storageKey="license-banner-dismissed"
|
||||||
version={1}
|
version={1}
|
||||||
title={t("licenseBannerTitle")}
|
title={t("licenseBannerTitle")}
|
||||||
titleIcon={
|
titleIcon={<TicketCheck className="w-5 h-5 text-primary" />}
|
||||||
<TicketCheck className="w-5 h-5 text-primary" />
|
|
||||||
}
|
|
||||||
description={t("licenseBannerDescription")}
|
description={t("licenseBannerDescription")}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -68,15 +68,15 @@ export default async function RootLayout({
|
|||||||
const env = pullEnv();
|
const env = pullEnv();
|
||||||
const locale = await getLocale();
|
const locale = await getLocale();
|
||||||
|
|
||||||
const supporterData = {
|
// const supporterData = {
|
||||||
visible: true
|
// visible: true
|
||||||
} as any;
|
// } as any;
|
||||||
|
|
||||||
const res = await priv.get<AxiosResponse<IsSupporterKeyVisibleResponse>>(
|
// const res = await priv.get<AxiosResponse<IsSupporterKeyVisibleResponse>>(
|
||||||
"supporter-key/visible"
|
// "supporter-key/visible"
|
||||||
);
|
// );
|
||||||
supporterData.visible = res.data.data.visible;
|
// supporterData.visible = res.data.data.visible;
|
||||||
supporterData.tier = res.data.data.tier;
|
// supporterData.tier = res.data.data.tier;
|
||||||
|
|
||||||
let licenseStatus: GetLicenseStatusResponse;
|
let licenseStatus: GetLicenseStatusResponse;
|
||||||
if (build === "enterprise") {
|
if (build === "enterprise") {
|
||||||
@@ -127,20 +127,20 @@ export default async function RootLayout({
|
|||||||
<LicenseStatusProvider
|
<LicenseStatusProvider
|
||||||
licenseStatus={licenseStatus}
|
licenseStatus={licenseStatus}
|
||||||
>
|
>
|
||||||
<SupportStatusProvider
|
{/* <SupportStatusProvider
|
||||||
supporterStatus={supporterData}
|
supporterStatus={supporterData}
|
||||||
>
|
> */}
|
||||||
{/* Main content */}
|
{/* Main content */}
|
||||||
<div className="h-full flex flex-col">
|
<div className="h-full flex flex-col">
|
||||||
<div className="flex-1 overflow-auto">
|
<div className="flex-1 overflow-auto">
|
||||||
<SplashImage>
|
<SplashImage>
|
||||||
<LicenseViolation />
|
|
||||||
{children}
|
|
||||||
</SplashImage>
|
|
||||||
<LicenseViolation />
|
<LicenseViolation />
|
||||||
</div>
|
{children}
|
||||||
|
</SplashImage>
|
||||||
|
<LicenseViolation />
|
||||||
</div>
|
</div>
|
||||||
</SupportStatusProvider>
|
</div>
|
||||||
|
{/* </SupportStatusProvider> */}
|
||||||
</LicenseStatusProvider>
|
</LicenseStatusProvider>
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</TanstackQueryProvider>
|
</TanstackQueryProvider>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default async function MaintenanceScreen() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
const host = headersList.get("host") || "";
|
const host = headersList.get("p-host") || headersList.get("host") || "";
|
||||||
const hostname = host.split(":")[0];
|
const hostname = host.split(":")[0];
|
||||||
|
|
||||||
const res = await priv.get<AxiosResponse<GetMaintenanceInfoResponse>>(
|
const res = await priv.get<AxiosResponse<GetMaintenanceInfoResponse>>(
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
// import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||||
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";
|
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
|
|
||||||
export default function AuthPageFooterNotices() {
|
export default function AuthPageFooterNotices() {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const { supporterStatus } = useSupporterStatusContext();
|
// const { supporterStatus } = useSupporterStatusContext();
|
||||||
const { isUnlocked, licenseStatus } = useLicenseStatusContext();
|
const { isUnlocked, licenseStatus } = useLicenseStatusContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{supporterStatus?.visible && (
|
{/* {supporterStatus?.visible && (
|
||||||
<div className="text-center mt-2">
|
<div className="text-center mt-2">
|
||||||
<span className="text-sm text-muted-foreground opacity-50">
|
<span className="text-sm text-muted-foreground opacity-50">
|
||||||
{t("noSupportKey")}
|
{t("noSupportKey")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
{build === "enterprise" && !isUnlocked() ? (
|
{build === "enterprise" && !isUnlocked() ? (
|
||||||
<div className="text-center mt-2">
|
<div className="text-center mt-2">
|
||||||
<span className="text-sm font-medium text-muted-foreground">
|
<span className="text-sm font-medium text-muted-foreground">
|
||||||
|
|||||||
@@ -9,33 +9,34 @@ export default function SupporterMessage({ tier }: { tier: string }) {
|
|||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex items-center space-x-2 whitespace-nowrap group">
|
<></>
|
||||||
<span
|
// <div className="relative flex items-center space-x-2 whitespace-nowrap group">
|
||||||
className="cursor-pointer"
|
// <span
|
||||||
onClick={(e) => {
|
// className="cursor-pointer"
|
||||||
// Get the bounding box of the element
|
// onClick={(e) => {
|
||||||
const rect = (
|
// // Get the bounding box of the element
|
||||||
e.target as HTMLElement
|
// const rect = (
|
||||||
).getBoundingClientRect();
|
// e.target as HTMLElement
|
||||||
|
// ).getBoundingClientRect();
|
||||||
|
|
||||||
// Trigger confetti centered on the word "Pangolin"
|
// // Trigger confetti centered on the word "Pangolin"
|
||||||
confetti({
|
// confetti({
|
||||||
particleCount: 100,
|
// particleCount: 100,
|
||||||
spread: 70,
|
// spread: 70,
|
||||||
origin: {
|
// origin: {
|
||||||
x: (rect.left + rect.width / 2) / window.innerWidth,
|
// x: (rect.left + rect.width / 2) / window.innerWidth,
|
||||||
y: rect.top / window.innerHeight
|
// y: rect.top / window.innerHeight
|
||||||
},
|
// },
|
||||||
colors: ["#FFA500", "#FF4500", "#FFD700"]
|
// colors: ["#FFA500", "#FF4500", "#FFD700"]
|
||||||
});
|
// });
|
||||||
}}
|
// }}
|
||||||
>
|
// >
|
||||||
Pangolin
|
// Pangolin
|
||||||
</span>
|
// </span>
|
||||||
<Star className="w-3 h-3" />
|
// <Star className="w-3 h-3" />
|
||||||
<div className="absolute left-1/2 transform -translate-x-1/2 -top-10 hidden group-hover:block text-primary text-sm rounded-md border shadow-md px-4 py-2 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
|
// <div className="absolute left-1/2 transform -translate-x-1/2 -top-10 hidden group-hover:block text-primary text-sm rounded-md border shadow-md px-4 py-2 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
{t("componentsSupporterMessage", { tier: tier })}
|
// {t("componentsSupporterMessage", { tier: tier })}
|
||||||
</div>
|
// </div>
|
||||||
</div>
|
// </div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// THIS IS DEPRECATED AND IS NO LONGER SHOWED TO THE USER WITH THE DISCONTINUATION
|
// THIS IS DEPRECATED AND IS NO LONGER SHOWED TO THE USER WITH THE DISCONTINUATION
|
||||||
// OF THE SUPPORTER PROGRAM. IT MAY BE REMOVED IN A FUTURE UPDATE.
|
// OF THE SUPPORTER PROGRAM. IT MAY BE REMOVED IN A FUTURE UPDATE.
|
||||||
|
|
||||||
import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
// import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||||
import { useState, useTransition } from "react";
|
import { useState, useTransition } from "react";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@@ -58,134 +58,134 @@ interface SupporterStatusProps {
|
|||||||
export default function SupporterStatus({
|
export default function SupporterStatus({
|
||||||
isCollapsed = false
|
isCollapsed = false
|
||||||
}: SupporterStatusProps) {
|
}: SupporterStatusProps) {
|
||||||
const { supporterStatus, updateSupporterStatus } =
|
// const { supporterStatus, updateSupporterStatus } =
|
||||||
useSupporterStatusContext();
|
// useSupporterStatusContext();
|
||||||
const [supportOpen, setSupportOpen] = useState(false);
|
// const [supportOpen, setSupportOpen] = useState(false);
|
||||||
const [keyOpen, setKeyOpen] = useState(false);
|
// const [keyOpen, setKeyOpen] = useState(false);
|
||||||
const [purchaseOptionsOpen, setPurchaseOptionsOpen] = useState(false);
|
// const [purchaseOptionsOpen, setPurchaseOptionsOpen] = useState(false);
|
||||||
|
|
||||||
const { env } = useEnvContext();
|
// const { env } = useEnvContext();
|
||||||
const api = createApiClient({ env });
|
// const api = createApiClient({ env });
|
||||||
const t = useTranslations();
|
// const t = useTranslations();
|
||||||
|
|
||||||
const formSchema = z.object({
|
// const formSchema = z.object({
|
||||||
githubUsername: z.string().nonempty({
|
// githubUsername: z.string().nonempty({
|
||||||
error: "GitHub username is required"
|
// error: "GitHub username is required"
|
||||||
}),
|
// }),
|
||||||
key: z.string().nonempty({
|
// key: z.string().nonempty({
|
||||||
error: "Supporter key is required"
|
// error: "Supporter key is required"
|
||||||
})
|
// })
|
||||||
});
|
// });
|
||||||
|
|
||||||
const form = useForm({
|
// const form = useForm({
|
||||||
resolver: zodResolver(formSchema),
|
// resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
// defaultValues: {
|
||||||
githubUsername: "",
|
// githubUsername: "",
|
||||||
key: ""
|
// key: ""
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
async function hide() {
|
// async function hide() {
|
||||||
await api.post("/supporter-key/hide");
|
// await api.post("/supporter-key/hide");
|
||||||
|
|
||||||
updateSupporterStatus({
|
// updateSupporterStatus({
|
||||||
visible: false
|
// visible: false
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
async function onSubmit(values: z.infer<typeof formSchema>) {
|
// async function onSubmit(values: z.infer<typeof formSchema>) {
|
||||||
try {
|
// try {
|
||||||
const res = await api.post<
|
// const res = await api.post<
|
||||||
AxiosResponse<ValidateSupporterKeyResponse>
|
// AxiosResponse<ValidateSupporterKeyResponse>
|
||||||
>("/supporter-key/validate", {
|
// >("/supporter-key/validate", {
|
||||||
githubUsername: values.githubUsername,
|
// githubUsername: values.githubUsername,
|
||||||
key: values.key
|
// key: values.key
|
||||||
});
|
// });
|
||||||
|
|
||||||
const data = res.data.data;
|
// const data = res.data.data;
|
||||||
|
|
||||||
if (!data || !data.valid) {
|
// if (!data || !data.valid) {
|
||||||
toast({
|
// toast({
|
||||||
variant: "destructive",
|
// variant: "destructive",
|
||||||
title: t("supportKeyInvalid"),
|
// title: t("supportKeyInvalid"),
|
||||||
description: t("supportKeyInvalidDescription")
|
// description: t("supportKeyInvalidDescription")
|
||||||
});
|
// });
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Trigger the toast
|
// // Trigger the toast
|
||||||
toast({
|
// toast({
|
||||||
variant: "default",
|
// variant: "default",
|
||||||
title: t("supportKeyValid"),
|
// title: t("supportKeyValid"),
|
||||||
description: t("supportKeyValidDescription")
|
// description: t("supportKeyValidDescription")
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Fireworks-style confetti
|
// // Fireworks-style confetti
|
||||||
const duration = 5 * 1000; // 5 seconds
|
// const duration = 5 * 1000; // 5 seconds
|
||||||
const animationEnd = Date.now() + duration;
|
// const animationEnd = Date.now() + duration;
|
||||||
const defaults = {
|
// const defaults = {
|
||||||
startVelocity: 30,
|
// startVelocity: 30,
|
||||||
spread: 360,
|
// spread: 360,
|
||||||
ticks: 60,
|
// ticks: 60,
|
||||||
zIndex: 0,
|
// zIndex: 0,
|
||||||
colors: ["#FFA500", "#FF4500", "#FFD700"] // Orange hues
|
// colors: ["#FFA500", "#FF4500", "#FFD700"] // Orange hues
|
||||||
};
|
// };
|
||||||
|
|
||||||
function randomInRange(min: number, max: number) {
|
// function randomInRange(min: number, max: number) {
|
||||||
return Math.random() * (max - min) + min;
|
// return Math.random() * (max - min) + min;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
// const interval = setInterval(() => {
|
||||||
const timeLeft = animationEnd - Date.now();
|
// const timeLeft = animationEnd - Date.now();
|
||||||
|
|
||||||
if (timeLeft <= 0) {
|
// if (timeLeft <= 0) {
|
||||||
clearInterval(interval);
|
// clearInterval(interval);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const particleCount = 50 * (timeLeft / duration);
|
// const particleCount = 50 * (timeLeft / duration);
|
||||||
|
|
||||||
// Launch confetti from two random horizontal positions
|
// // Launch confetti from two random horizontal positions
|
||||||
confetti({
|
// confetti({
|
||||||
...defaults,
|
// ...defaults,
|
||||||
particleCount,
|
// particleCount,
|
||||||
origin: {
|
// origin: {
|
||||||
x: randomInRange(0.1, 0.3),
|
// x: randomInRange(0.1, 0.3),
|
||||||
y: Math.random() - 0.2
|
// y: Math.random() - 0.2
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
confetti({
|
// confetti({
|
||||||
...defaults,
|
// ...defaults,
|
||||||
particleCount,
|
// particleCount,
|
||||||
origin: {
|
// origin: {
|
||||||
x: randomInRange(0.7, 0.9),
|
// x: randomInRange(0.7, 0.9),
|
||||||
y: Math.random() - 0.2
|
// y: Math.random() - 0.2
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}, 250);
|
// }, 250);
|
||||||
|
|
||||||
setPurchaseOptionsOpen(false);
|
// setPurchaseOptionsOpen(false);
|
||||||
setKeyOpen(false);
|
// setKeyOpen(false);
|
||||||
|
|
||||||
updateSupporterStatus({
|
// updateSupporterStatus({
|
||||||
visible: false
|
// visible: false
|
||||||
});
|
// });
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
toast({
|
// toast({
|
||||||
variant: "destructive",
|
// variant: "destructive",
|
||||||
title: t("error"),
|
// title: t("error"),
|
||||||
description: formatAxiosError(
|
// description: formatAxiosError(
|
||||||
error,
|
// error,
|
||||||
t("supportKeyErrorValidationDescription")
|
// t("supportKeyErrorValidationDescription")
|
||||||
)
|
// )
|
||||||
});
|
// });
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Credenza
|
{/* <Credenza
|
||||||
open={purchaseOptionsOpen}
|
open={purchaseOptionsOpen}
|
||||||
onOpenChange={(val) => {
|
onOpenChange={(val) => {
|
||||||
setPurchaseOptionsOpen(val);
|
setPurchaseOptionsOpen(val);
|
||||||
@@ -469,7 +469,7 @@ export default function SupporterStatus({
|
|||||||
{t("supportKeyBuy")}
|
{t("supportKeyBuy")}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
) : null}
|
) : null} */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { cache } from "react";
|
|||||||
|
|
||||||
export const getBrowserTargetForRequest = cache(async () => {
|
export const getBrowserTargetForRequest = cache(async () => {
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
const host = headersList.get("host") || "";
|
const host = headersList.get("p-host") || headersList.get("host") || "";
|
||||||
const hostname = host.split(":")[0];
|
const hostname = host.split(":")[0];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user