mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-14 22:53:45 +02:00
Add verify middleware
This commit is contained in:
parent
e89ee4042a
commit
a8f944fc78
17 changed files with 1230 additions and 40 deletions
843
package-lock.json
generated
843
package-lock.json
generated
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lucia-auth/adapter-drizzle": "1.1.0",
|
"@lucia-auth/adapter-drizzle": "1.1.0",
|
||||||
"@node-rs/argon2": "1.8.3",
|
"@node-rs/argon2": "1.8.3",
|
||||||
|
"@node-rs/argon2-linux-x64-gnu": "1.8.3",
|
||||||
"@react-email/components": "0.0.25",
|
"@react-email/components": "0.0.25",
|
||||||
"@react-email/tailwind": "0.1.0",
|
"@react-email/tailwind": "0.1.0",
|
||||||
"axios": "1.7.7",
|
"axios": "1.7.7",
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
"http-errors": "2.0.0",
|
"http-errors": "2.0.0",
|
||||||
"lucia": "3.2.0",
|
"lucia": "3.2.0",
|
||||||
"next": "14.2.13",
|
"next": "14.2.13",
|
||||||
|
"node-fetch": "3.3.2",
|
||||||
"nodemailer": "6.9.15",
|
"nodemailer": "6.9.15",
|
||||||
"oslo": "1.2.1",
|
"oslo": "1.2.1",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
|
@ -2569,6 +2571,33 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/@emnapi/core": {
|
||||||
|
"version": "0.45.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-0.45.0.tgz",
|
||||||
|
"integrity": "sha512-DPWjcUDQkCeEM4VnljEOEcXdAD7pp8zSZsgOujk/LGIwCXWbXJngin+MO4zbH429lzeC3WbYLGjE2MaUOwzpyw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@emnapi/runtime": {
|
||||||
|
"version": "0.45.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz",
|
||||||
|
"integrity": "sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild-kit/core-utils": {
|
"node_modules/@esbuild-kit/core-utils": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -2853,6 +2882,27 @@
|
||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@expo/cli/node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@expo/cli/node_modules/picomatch": {
|
"node_modules/@expo/cli/node_modules/picomatch": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -3207,6 +3257,27 @@
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@expo/image-utils/node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@expo/image-utils/node_modules/resolve-from": {
|
"node_modules/@expo/image-utils/node_modules/resolve-from": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -3540,6 +3611,27 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@expo/rudder-sdk-node/node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@expo/sdk-runtime-versions": {
|
"node_modules/@expo/sdk-runtime-versions": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -3746,6 +3838,45 @@
|
||||||
"lucia": "3.x"
|
"lucia": "3.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.5.tgz",
|
||||||
|
"integrity": "sha512-kwUxR7J9WLutBbulqg1dfOrMTwhMdXLdcGUhcbCcGwnPLt3gz19uHVdwH1syKVDbE022ZS2vZxOWflFLS0YTjw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.1.0",
|
||||||
|
"@emnapi/runtime": "^1.1.0",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/wasm-runtime/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.1",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/wasm-runtime/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@napi-rs/wasm-runtime/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@next/env": {
|
"node_modules/@next/env": {
|
||||||
"version": "14.2.13",
|
"version": "14.2.13",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
@ -3831,6 +3962,36 @@
|
||||||
"@node-rs/argon2-win32-x64-msvc": "1.8.3"
|
"@node-rs/argon2-win32-x64-msvc": "1.8.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@node-rs/argon2-android-arm-eabi": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-android-arm-eabi/-/argon2-android-arm-eabi-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-udDqkr5P9E+wYX1SZwAVPdyfYvaF4ry9Tm+R9LkfSHbzWH0uhU6zjIwNRp7m+n4gx691rk+lqqDAIP8RLKwbhg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-android-arm64": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-android-arm64/-/argon2-android-arm64-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-s9j/G30xKUx8WU50WIhF0fIl1EdhBGq0RQ06lEhZ0Gi0ap8lhqbE2Bn5h3/G2D1k0Dx+yjeVVNmt/xOQIRG38A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@node-rs/argon2-darwin-arm64": {
|
"node_modules/@node-rs/argon2-darwin-arm64": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
|
@ -3845,6 +4006,353 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@node-rs/argon2-darwin-x64": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-darwin-x64/-/argon2-darwin-x64-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-5oi/pxqVhODW/pj1+3zElMTn/YukQeywPHHYDbcAW3KsojFjKySfhcJMd1DjKTc+CHQI+4lOxZzSUzK7mI14Hw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-freebsd-x64": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-freebsd-x64/-/argon2-freebsd-x64-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-Ify08683hA4QVXYoIm5SUWOY5DPIT/CMB0CQT+IdxQAg/F+qp342+lUkeAtD5bvStQuCx/dFO3bnnzoe2clMhA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-linux-arm-gnueabihf": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm-gnueabihf/-/argon2-linux-arm-gnueabihf-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-7DjDZ1h5AUHAtRNjD19RnQatbhL+uuxBASuuXIBu4/w6Dx8n7YPxwTP4MXfsvuRgKuMWiOb/Ub/HJ3kXVCXRkg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-linux-arm64-gnu": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm64-gnu/-/argon2-linux-arm64-gnu-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-nJDoMP4Y3YcqGswE4DvP080w6O24RmnFEDnL0emdI8Nou17kNYBzP2546Nasx9GCyLzRcYQwZOUjrtUuQ+od2g==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-linux-arm64-musl": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm64-musl/-/argon2-linux-arm64-musl-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-BKWS8iVconhE3jrb9mj6t1J9vwUqQPpzCbUKxfTGJfc+kNL58F1SXHBoe2cDYGnHrFEHTY0YochzXoAfm4Dm/A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-linux-x64-gnu": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-gnu/-/argon2-linux-x64-gnu-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-OBH+EFG7BGjFyldaao2H2gSCLmjtrrwf420B1L+lFn7JLW9UAjsIPFKAcWsYwPa/PwYzIge9Y7SGcpqlsSEX0w==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-linux-x64-musl": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-musl/-/argon2-linux-x64-musl-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-/o1efYCYIxjfuoRYyBTi2Iy+1iFfhqHCvvVsnjNSgO1xWiWrX0Rrt/xXW5Zsl7vS2Y+yu8PL8KFWRzZhaVxfKA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-wasm32-wasi": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-wasm32-wasi/-/argon2-wasm32-wasi-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-Evmk9VcxqnuwQftfAfYEr6YZYSPLzmKUsbFIMep5nTt9PT4XYRFAERj7wNYp+rOcBenF3X4xoB+LhwcOMTNE5w==",
|
||||||
|
"cpu": [
|
||||||
|
"wasm32"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^0.45.0",
|
||||||
|
"@emnapi/runtime": "^0.45.0",
|
||||||
|
"@tybys/wasm-util": "^0.8.1",
|
||||||
|
"memfs-browser": "^3.4.13000"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-win32-arm64-msvc": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-arm64-msvc/-/argon2-win32-arm64-msvc-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-qgsU7T004COWWpSA0tppDqDxbPLgg8FaU09krIJ7FBl71Sz8SFO40h7fDIjfbTT5w7u6mcaINMQ5bSHu75PCaA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-win32-ia32-msvc": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-ia32-msvc/-/argon2-win32-ia32-msvc-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-JGafwWYQ/HpZ3XSwP4adQ6W41pRvhcdXvpzIWtKvX+17+xEXAe2nmGWM6s27pVkg1iV2ZtoYLRDkOUoGqZkCcg==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2-win32-x64-msvc": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-x64-msvc/-/argon2-win32-x64-msvc-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-9oq4ShyFakw8AG3mRls0AoCpxBFcimYx7+jvXeAf2OqKNO+mSA6eZ9z7KQeVCi0+SOEUYxMGf5UiGiDb9R6+9Q==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-android-arm-eabi": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-android-arm-eabi/-/argon2-android-arm-eabi-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-JFZPlNM0A8Og+Tncb8UZsQrhEMlbHBXPsT3hRoKImzVmTmq28Os0ucFWow0AACp2coLHBSydXH3Dh0lZup3rWw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-android-arm64": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-android-arm64/-/argon2-android-arm64-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-zaf8P3T92caeW2xnMA7P1QvRA4pIt/04oilYP44XlTCtMye//vwXDMeK53sl7dvYiJKnzAWDRx41k8vZvpZazg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-darwin-x64": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-darwin-x64/-/argon2-darwin-x64-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-YMjmBGFZhLfYjfQ2gll9A+BZu/zAMV7lWZIbKxb7ZgEofILQwuGmExjDtY3Jplido/6leCEdpmlk2oIsME00LA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-freebsd-x64": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-freebsd-x64/-/argon2-freebsd-x64-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-Hq3Rj5Yb2RolTG/luRPnv+XiGCbi5nAK25Pc8ou/tVapwX+iktEm/NXbxc5zsMxraYVkCvfdwBjweC5O+KqCGw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-linux-arm-gnueabihf": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm-gnueabihf/-/argon2-linux-arm-gnueabihf-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-x49l8RgzKoG0/V0IXa5rrEl1TcJEc936ctlYFvqcunSOyowZ6kiWtrp1qrbOR8gbaNILl11KTF52vF6+h8UlEQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-linux-arm64-gnu": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm64-gnu/-/argon2-linux-arm64-gnu-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-gJesam/qA63reGkb9qJ2TjFSLBtY41zQh2oei7nfnYsmVQPuHHWItJxEa1Bm21SPW53gZex4jFJbDIgj0+PxIw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-linux-arm64-musl": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm64-musl/-/argon2-linux-arm64-musl-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-7O6kQdSKzB4Tjx/EBa8zKIxnmLkQE8VdJgPm6Ksrpn+ueo0mx2xf76fIDnbbTCtm3UbB+y+FkTo2wLA7tOqIKg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-linux-x64-musl": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-musl/-/argon2-linux-x64-musl-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-bDbMuyekIxZaN7NaX+gHVkOyABB8bcMEJYeRPW1vCXKHj3brJns1wiUFSxqeUXreupifNVJlQfPt1Y5B/vFXgQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-wasm32-wasi": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-wasm32-wasi/-/argon2-wasm32-wasi-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-NBf2cMCDbNKMzp13Pog8ZPmI0M9U4Ak5b95EUjkp17kdKZFds12dwW67EMnj7Zy+pRqby2QLECaWebDYfNENTg==",
|
||||||
|
"cpu": [
|
||||||
|
"wasm32"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@napi-rs/wasm-runtime": "^0.2.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-win32-arm64-msvc": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-arm64-msvc/-/argon2-win32-arm64-msvc-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-AHpPo7UbdW5WWjwreVpgFSY0o1RY4A7cUFaqDXZB2OqEuyrhMxBdZct9PX7PQKI18D85pLsODnR+gvVuTwJ6rQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-win32-ia32-msvc": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-ia32-msvc/-/argon2-win32-ia32-msvc-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-bqzn2rcQkEwCINefhm69ttBVVkgHJb/V03DdBKsPFtiX6H47axXKz62d1imi26zFXhOEYxhKbu3js03GobJOLw==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@node-rs/argon2/node_modules/@node-rs/argon2-win32-x64-msvc": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-x64-msvc/-/argon2-win32-x64-msvc-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-ILlrRThdbp5xNR5gwYM2ic1n/vG5rJ8dQZ+YMRqksl+lnTJ/6FDe5BOyIhiPtiDwlCiCtUA+1NxpDB9KlUCAIA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@node-rs/bcrypt": {
|
"node_modules/@node-rs/bcrypt": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -4346,6 +4854,27 @@
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native/dev-middleware/node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@react-native/dev-middleware/node_modules/open": {
|
"node_modules/@react-native/dev-middleware/node_modules/open": {
|
||||||
"version": "7.4.2",
|
"version": "7.4.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -4468,6 +4997,15 @@
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.8.3.tgz",
|
||||||
|
"integrity": "sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/better-sqlite3": {
|
"node_modules/@types/better-sqlite3": {
|
||||||
"version": "7.6.11",
|
"version": "7.6.11",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
|
@ -6203,6 +6741,27 @@
|
||||||
"node-fetch": "^2.6.12"
|
"node-fetch": "^2.6.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cross-fetch/node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -6260,6 +6819,14 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/data-view-buffer": {
|
"node_modules/data-view-buffer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
|
@ -8118,6 +8685,28 @@
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fetch-retry": {
|
"node_modules/fetch-retry": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -8319,6 +8908,17 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -8372,6 +8972,12 @@
|
||||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fs-monkey": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
|
@ -10046,6 +10652,21 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucia/node_modules/@node-rs/argon2-linux-x64-gnu": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-gnu/-/argon2-linux-x64-gnu-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-EmgqZOlf4Jurk/szW1iTsVISx25bKksVC5uttJDUloTgsAgIGReCpUUO1R24pBhu9ESJa47iv8NSf3yAfGv6jQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lucia/node_modules/oslo": {
|
"node_modules/lucia/node_modules/oslo": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -10150,6 +10771,27 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/memfs": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
|
||||||
|
"integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fs-monkey": "^1.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/memfs-browser": {
|
||||||
|
"version": "3.5.10302",
|
||||||
|
"resolved": "https://registry.npmjs.org/memfs-browser/-/memfs-browser-3.5.10302.tgz",
|
||||||
|
"integrity": "sha512-JJTc/nh3ig05O0gBBGZjTCPOyydaTxNF0uHYBrcc1gHNnO+KIHIvo0Y1FKCJsaei6FCl8C6xfQomXqu+cuzkIw==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"memfs": "3.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/memory-cache": {
|
"node_modules/memory-cache": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
|
@ -10546,24 +11188,39 @@
|
||||||
"node": ">= 0.10.5"
|
"node": ">= 0.10.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.7.0",
|
"version": "3.3.2",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
"optional": true,
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"whatwg-url": "^5.0.0"
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "4.x || >=6.0.0"
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"funding": {
|
||||||
"encoding": "^0.1.0"
|
"type": "opencollective",
|
||||||
},
|
"url": "https://opencollective.com/node-fetch"
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"encoding": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-forge": {
|
"node_modules/node-forge": {
|
||||||
|
@ -11046,6 +11703,21 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oslo/node_modules/@node-rs/argon2-linux-x64-gnu": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-gnu/-/argon2-linux-x64-gnu-1.7.0.tgz",
|
||||||
|
"integrity": "sha512-EmgqZOlf4Jurk/szW1iTsVISx25bKksVC5uttJDUloTgsAgIGReCpUUO1R24pBhu9ESJa47iv8NSf3yAfGv6jQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/p-finally": {
|
"node_modules/p-finally": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -12139,6 +12811,134 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-darwin-x64": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-linux-arm64-gnu": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-linux-arm64-musl": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-linux-x64-gnu": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-linux-x64-musl": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-win32-arm64-msvc": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-win32-ia32-msvc": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-email/node_modules/next/node_modules/@next/swc-win32-x64-msvc": {
|
||||||
|
"version": "14.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz",
|
||||||
|
"integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-email/node_modules/onetime": {
|
"node_modules/react-email/node_modules/onetime": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -13806,7 +14606,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/tr46": {
|
"node_modules/tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
@ -14342,15 +15143,25 @@
|
||||||
"defaults": "^1.0.3"
|
"defaults": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"license": "BSD-2-Clause",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/whatwg-url": {
|
"node_modules/whatwg-url": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -10,11 +10,12 @@
|
||||||
"db:studio": "drizzle-kit studio",
|
"db:studio": "drizzle-kit studio",
|
||||||
"build": "next build && tsc --project tsconfig.server.json && tsc-alias -p tsconfig.server.json",
|
"build": "next build && tsc --project tsconfig.server.json && tsc-alias -p tsconfig.server.json",
|
||||||
"start": "ENVIRONMENT=prod node dist/server/index.js",
|
"start": "ENVIRONMENT=prod node dist/server/index.js",
|
||||||
"email": "email dev --dir emailTemplates --port 3002"
|
"email": "email dev --dir server/emails/templates --port 3002"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lucia-auth/adapter-drizzle": "1.1.0",
|
"@lucia-auth/adapter-drizzle": "1.1.0",
|
||||||
"@node-rs/argon2": "1.8.3",
|
"@node-rs/argon2": "1.8.3",
|
||||||
|
"@node-rs/argon2-linux-x64-gnu": "1.8.3",
|
||||||
"@react-email/components": "0.0.25",
|
"@react-email/components": "0.0.25",
|
||||||
"@react-email/tailwind": "0.1.0",
|
"@react-email/tailwind": "0.1.0",
|
||||||
"axios": "1.7.7",
|
"axios": "1.7.7",
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
"http-errors": "2.0.0",
|
"http-errors": "2.0.0",
|
||||||
"lucia": "3.2.0",
|
"lucia": "3.2.0",
|
||||||
"next": "14.2.13",
|
"next": "14.2.13",
|
||||||
|
"node-fetch": "3.3.2",
|
||||||
"nodemailer": "6.9.15",
|
"nodemailer": "6.9.15",
|
||||||
"oslo": "1.2.1",
|
"oslo": "1.2.1",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
|
|
1
server/db/.gitignore
vendored
Normal file
1
server/db/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
names.json
|
|
@ -89,6 +89,16 @@ export const sessions = sqliteTable("session", {
|
||||||
expiresAt: integer("expiresAt").notNull(),
|
expiresAt: integer("expiresAt").notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const userOrgs = sqliteTable("userOrgs", {
|
||||||
|
userId: text("userId")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id),
|
||||||
|
orgId: integer("orgId")
|
||||||
|
.notNull()
|
||||||
|
.references(() => orgs.orgId),
|
||||||
|
role: text("role").notNull(), // e.g., 'admin', 'member', etc.
|
||||||
|
});
|
||||||
|
|
||||||
// Define the model types for type inference
|
// Define the model types for type inference
|
||||||
export type Org = InferSelectModel<typeof orgs>;
|
export type Org = InferSelectModel<typeof orgs>;
|
||||||
export type User = InferSelectModel<typeof users>;
|
export type User = InferSelectModel<typeof users>;
|
||||||
|
|
|
@ -73,6 +73,8 @@ declare global {
|
||||||
namespace Express {
|
namespace Express {
|
||||||
interface Request {
|
interface Request {
|
||||||
user?: User;
|
user?: User;
|
||||||
|
userOrgRole?: string;
|
||||||
|
userOrgs?: number[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
33
server/routers/auth/getUserOrgs.ts
Normal file
33
server/routers/auth/getUserOrgs.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { db } from '@server/db';
|
||||||
|
import { userOrgs, orgs } from '@server/db/schema';
|
||||||
|
import { eq } from 'drizzle-orm';
|
||||||
|
import createHttpError from 'http-errors';
|
||||||
|
import HttpCode from '@server/types/HttpCode';
|
||||||
|
|
||||||
|
export async function getUserOrgs(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const userId = req.user?.id; // Assuming you have user information in the request
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const userOrganizations = await db.select({
|
||||||
|
orgId: userOrgs.orgId,
|
||||||
|
role: userOrgs.role,
|
||||||
|
})
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(eq(userOrgs.userId, userId));
|
||||||
|
|
||||||
|
req.userOrgs = userOrganizations.map(org => org.orgId);
|
||||||
|
// req.userOrgRoles = userOrganizations.reduce((acc, org) => {
|
||||||
|
// acc[org.orgId] = org.role;
|
||||||
|
// return acc;
|
||||||
|
// }, {} as Record<number, string>);
|
||||||
|
|
||||||
|
next();
|
||||||
|
} catch (error) {
|
||||||
|
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error retrieving user organizations'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,3 +4,8 @@ export * from "./logout";
|
||||||
export * from "./verifyTotp";
|
export * from "./verifyTotp";
|
||||||
export * from "./requestTotpSecret";
|
export * from "./requestTotpSecret";
|
||||||
export * from "./disable2fa";
|
export * from "./disable2fa";
|
||||||
|
export * from "./verifyOrgAccess";
|
||||||
|
export * from "./getUserOrgs";
|
||||||
|
export * from "./verifySiteAccess";
|
||||||
|
export * from "./verifyResourceAccess";
|
||||||
|
export * from "./verifyTargetAccess";
|
36
server/routers/auth/verifyOrgAccess.ts
Normal file
36
server/routers/auth/verifyOrgAccess.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { db } from '@server/db';
|
||||||
|
import { userOrgs } from '@server/db/schema';
|
||||||
|
import { and, eq } from 'drizzle-orm';
|
||||||
|
import createHttpError from 'http-errors';
|
||||||
|
import HttpCode from '@server/types/HttpCode';
|
||||||
|
import { AuthenticatedRequest } from '@server/types/Auth';
|
||||||
|
|
||||||
|
export function verifyOrgAccess(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const userId = req.user.id; // Assuming you have user information in the request
|
||||||
|
const orgId = parseInt(req.params.orgId);
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(orgId)) {
|
||||||
|
return next(createHttpError(HttpCode.BAD_REQUEST, 'Invalid organization ID'));
|
||||||
|
}
|
||||||
|
|
||||||
|
db.select()
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId)))
|
||||||
|
.then((result) => {
|
||||||
|
if (result.length === 0) {
|
||||||
|
next(createHttpError(HttpCode.FORBIDDEN, 'User does not have access to this organization'));
|
||||||
|
} else {
|
||||||
|
// User has access, attach the user's role to the request for potential future use
|
||||||
|
req.userOrgRole = result[0].role;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying organization access'));
|
||||||
|
});
|
||||||
|
}
|
54
server/routers/auth/verifyResourceAccess.ts
Normal file
54
server/routers/auth/verifyResourceAccess.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { db } from '@server/db';
|
||||||
|
import { resources, userOrgs } from '@server/db/schema';
|
||||||
|
import { and, eq } from 'drizzle-orm';
|
||||||
|
import createHttpError from 'http-errors';
|
||||||
|
import HttpCode from '@server/types/HttpCode';
|
||||||
|
|
||||||
|
export async function verifyResourceAccess(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const userId = req.user!.id; // Assuming you have user information in the request
|
||||||
|
const resourceId = req.params.resourceId;
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const resource = await db.select()
|
||||||
|
.from(resources)
|
||||||
|
.where(eq(resources.resourceId, resourceId))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (resource.length === 0) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.NOT_FOUND,
|
||||||
|
`resource with ID ${resourceId} not found`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resource[0].orgId) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.INTERNAL_SERVER_ERROR,
|
||||||
|
`resource with ID ${resourceId} does not have an organization ID`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.select()
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, resource[0].orgId)))
|
||||||
|
.then((result) => {
|
||||||
|
if (result.length === 0) {
|
||||||
|
next(createHttpError(HttpCode.FORBIDDEN, 'User does not have access to this organization'));
|
||||||
|
} else {
|
||||||
|
// User has access, attach the user's role to the request for potential future use
|
||||||
|
req.userOrgRole = result[0].role;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying organization access'));
|
||||||
|
});
|
||||||
|
}
|
58
server/routers/auth/verifySiteAccess.ts
Normal file
58
server/routers/auth/verifySiteAccess.ts
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { db } from '@server/db';
|
||||||
|
import { sites, userOrgs } from '@server/db/schema';
|
||||||
|
import { and, eq } from 'drizzle-orm';
|
||||||
|
import createHttpError from 'http-errors';
|
||||||
|
import HttpCode from '@server/types/HttpCode';
|
||||||
|
|
||||||
|
export async function verifySiteAccess(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const userId = req.user!.id; // Assuming you have user information in the request
|
||||||
|
const siteId = parseInt(req.params.siteId);
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(siteId)) {
|
||||||
|
return next(createHttpError(HttpCode.BAD_REQUEST, 'Invalid organization ID'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const site = await db.select()
|
||||||
|
.from(sites)
|
||||||
|
.where(eq(sites.siteId, siteId))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (site.length === 0) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.NOT_FOUND,
|
||||||
|
`Site with ID ${siteId} not found`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!site[0].orgId) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.INTERNAL_SERVER_ERROR,
|
||||||
|
`Site with ID ${siteId} does not have an organization ID`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.select()
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, site[0].orgId)))
|
||||||
|
.then((result) => {
|
||||||
|
if (result.length === 0) {
|
||||||
|
next(createHttpError(HttpCode.FORBIDDEN, 'User does not have access to this organization'));
|
||||||
|
} else {
|
||||||
|
// User has access, attach the user's role to the request for potential future use
|
||||||
|
req.userOrgRole = result[0].role;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying organization access'));
|
||||||
|
});
|
||||||
|
}
|
83
server/routers/auth/verifyTargetAccess.ts
Normal file
83
server/routers/auth/verifyTargetAccess.ts
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { db } from '@server/db';
|
||||||
|
import { resources, targets, userOrgs } from '@server/db/schema';
|
||||||
|
import { and, eq } from 'drizzle-orm';
|
||||||
|
import createHttpError from 'http-errors';
|
||||||
|
import HttpCode from '@server/types/HttpCode';
|
||||||
|
|
||||||
|
export async function verifyTargetAccess(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const userId = req.user!.id; // Assuming you have user information in the request
|
||||||
|
const targetId = parseInt(req.params.targetId);
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(targetId)) {
|
||||||
|
return next(createHttpError(HttpCode.BAD_REQUEST, 'Invalid organization ID'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = await db.select()
|
||||||
|
.from(targets)
|
||||||
|
.where(eq(targets.targetId, targetId))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (target.length === 0) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.NOT_FOUND,
|
||||||
|
`target with ID ${targetId} not found`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourceId = target[0].resourceId;
|
||||||
|
|
||||||
|
if (resourceId) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.INTERNAL_SERVER_ERROR,
|
||||||
|
`target with ID ${targetId} does not have a resource ID`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resource = await db.select()
|
||||||
|
.from(resources)
|
||||||
|
.where(eq(resources.resourceId, resourceId!))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (resource.length === 0) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.NOT_FOUND,
|
||||||
|
`resource with ID ${resourceId} not found`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resource[0].orgId) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.INTERNAL_SERVER_ERROR,
|
||||||
|
`resource with ID ${resourceId} does not have an organization ID`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.select()
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, resource[0].orgId)))
|
||||||
|
.then((result) => {
|
||||||
|
if (result.length === 0) {
|
||||||
|
next(createHttpError(HttpCode.FORBIDDEN, 'User does not have access to this organization'));
|
||||||
|
} else {
|
||||||
|
// User has access, attach the user's role to the request for potential future use
|
||||||
|
req.userOrgRole = result[0].role;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying organization access'));
|
||||||
|
});
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import * as user from "./user";
|
||||||
import * as auth from "./auth";
|
import * as auth from "./auth";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
import { verifySessionMiddleware } from "@server/middlewares";
|
import { verifySessionMiddleware } from "@server/middlewares";
|
||||||
|
import { verifyOrgAccess, getUserOrgs, verifySiteAccess, verifyResourceAccess, verifyTargetAccess } from "./auth";
|
||||||
|
|
||||||
// Root routes
|
// Root routes
|
||||||
export const unauthenticated = Router();
|
export const unauthenticated = Router();
|
||||||
|
@ -19,30 +20,30 @@ unauthenticated.get("/", (_, res) => {
|
||||||
export const authenticated = Router();
|
export const authenticated = Router();
|
||||||
authenticated.use(verifySessionMiddleware);
|
authenticated.use(verifySessionMiddleware);
|
||||||
|
|
||||||
authenticated.put("/org", org.createOrg);
|
authenticated.put("/org", getUserOrgs, org.createOrg);
|
||||||
authenticated.get("/orgs", org.listOrgs);
|
authenticated.get("/orgs", getUserOrgs, org.listOrgs); // TODO we need to check the orgs here
|
||||||
authenticated.get("/org/:orgId", org.getOrg);
|
authenticated.get("/org/:orgId", verifyOrgAccess, org.getOrg);
|
||||||
authenticated.post("/org/:orgId", org.updateOrg);
|
authenticated.post("/org/:orgId", verifyOrgAccess, org.updateOrg);
|
||||||
authenticated.delete("/org/:orgId", org.deleteOrg);
|
authenticated.delete("/org/:orgId", verifyOrgAccess, org.deleteOrg);
|
||||||
|
|
||||||
authenticated.put("/org/:orgId/site", site.createSite);
|
authenticated.put("/org/:orgId/site", verifyOrgAccess, site.createSite);
|
||||||
authenticated.get("/org/:orgId/sites", site.listSites);
|
authenticated.get("/org/:orgId/sites", verifyOrgAccess, site.listSites);
|
||||||
authenticated.get("/site/:siteId", site.getSite);
|
authenticated.get("/site/:siteId", verifySiteAccess, site.getSite);
|
||||||
authenticated.post("/site/:siteId", site.updateSite);
|
authenticated.post("/site/:siteId", verifySiteAccess, site.updateSite);
|
||||||
authenticated.delete("/site/:siteId", site.deleteSite);
|
authenticated.delete("/site/:siteId", verifySiteAccess, site.deleteSite);
|
||||||
|
|
||||||
authenticated.put("/org/:orgId/site/:siteId/resource", resource.createResource);
|
authenticated.put("/org/:orgId/site/:siteId/resource", verifyOrgAccess, resource.createResource);
|
||||||
authenticated.get("/site/:siteId/resources", resource.listResources);
|
authenticated.get("/site/:siteId/resources", resource.listResources);
|
||||||
authenticated.get("/org/:orgId/resources", resource.listResources);
|
authenticated.get("/org/:orgId/resources", verifyOrgAccess, resource.listResources);
|
||||||
authenticated.get("/resource/:resourceId", resource.getResource);
|
authenticated.get("/resource/:resourceId", verifyResourceAccess, resource.getResource);
|
||||||
authenticated.post("/resource/:resourceId", resource.updateResource);
|
authenticated.post("/resource/:resourceId", verifyResourceAccess, resource.updateResource);
|
||||||
authenticated.delete("/resource/:resourceId", resource.deleteResource);
|
authenticated.delete("/resource/:resourceId", verifyResourceAccess, resource.deleteResource);
|
||||||
|
|
||||||
authenticated.put("/resource/:resourceId/target", target.createTarget);
|
authenticated.put("/resource/:resourceId/target", verifyResourceAccess, target.createTarget);
|
||||||
authenticated.get("/resource/:resourceId/targets", target.listTargets);
|
authenticated.get("/resource/:resourceId/targets", verifyResourceAccess, target.listTargets);
|
||||||
authenticated.get("/target/:targetId", target.getTarget);
|
authenticated.get("/target/:targetId", verifyTargetAccess, target.getTarget);
|
||||||
authenticated.post("/target/:targetId", target.updateTarget);
|
authenticated.post("/target/:targetId", verifyTargetAccess, target.updateTarget);
|
||||||
authenticated.delete("/target/:targetId", target.deleteTarget);
|
authenticated.delete("/target/:targetId", verifyTargetAccess, target.deleteTarget);
|
||||||
|
|
||||||
authenticated.get("/users", user.listUsers);
|
authenticated.get("/users", user.listUsers);
|
||||||
// authenticated.get("/org/:orgId/users", user.???); // TODO: Implement this
|
// authenticated.get("/org/:orgId/users", user.???); // TODO: Implement this
|
||||||
|
|
|
@ -11,6 +11,8 @@ const createOrgSchema = z.object({
|
||||||
domain: z.string().min(1).max(255),
|
domain: z.string().min(1).max(255),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const MAX_ORGS = 5;
|
||||||
|
|
||||||
export async function createOrg(req: Request, res: Response, next: NextFunction): Promise<any> {
|
export async function createOrg(req: Request, res: Response, next: NextFunction): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const parsedBody = createOrgSchema.safeParse(req.body);
|
const parsedBody = createOrgSchema.safeParse(req.body);
|
||||||
|
@ -23,6 +25,16 @@ export async function createOrg(req: Request, res: Response, next: NextFunction)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userOrgIds = req.userOrgs;
|
||||||
|
if (userOrgIds && userOrgIds.length > MAX_ORGS) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.FORBIDDEN,
|
||||||
|
`Maximum number of organizations reached.`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const { name, domain } = parsedBody.data;
|
const { name, domain } = parsedBody.data;
|
||||||
|
|
||||||
const newOrg = await db.insert(orgs).values({
|
const newOrg = await db.insert(orgs).values({
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { orgs } from '@server/db/schema';
|
||||||
import response from "@server/utils/response";
|
import response from "@server/utils/response";
|
||||||
import HttpCode from '@server/types/HttpCode';
|
import HttpCode from '@server/types/HttpCode';
|
||||||
import createHttpError from 'http-errors';
|
import createHttpError from 'http-errors';
|
||||||
import { sql } from 'drizzle-orm';
|
import { sql, inArray } from 'drizzle-orm';
|
||||||
|
|
||||||
const listOrgsSchema = z.object({
|
const listOrgsSchema = z.object({
|
||||||
limit: z.string().optional().transform(Number).pipe(z.number().int().positive().default(10)),
|
limit: z.string().optional().transform(Number).pipe(z.number().int().positive().default(10)),
|
||||||
|
@ -26,15 +26,45 @@ export async function listOrgs(req: Request, res: Response, next: NextFunction):
|
||||||
|
|
||||||
const { limit, offset } = parsedQuery.data;
|
const { limit, offset } = parsedQuery.data;
|
||||||
|
|
||||||
|
// Use the userOrgs passed from the middleware
|
||||||
|
const userOrgIds = req.userOrgs;
|
||||||
|
|
||||||
|
if (!userOrgIds || userOrgIds.length === 0) {
|
||||||
|
return res.status(HttpCode.OK).send(
|
||||||
|
response(res, {
|
||||||
|
data: {
|
||||||
|
organizations: [],
|
||||||
|
pagination: {
|
||||||
|
total: 0,
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
error: false,
|
||||||
|
message: "No organizations found for the user",
|
||||||
|
status: HttpCode.OK,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const organizations = await db.select()
|
const organizations = await db.select()
|
||||||
.from(orgs)
|
.from(orgs)
|
||||||
|
.where(inArray(orgs.orgId, userOrgIds))
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset);
|
.offset(offset);
|
||||||
|
|
||||||
const totalCountResult = await db.select({ count: sql<number>`cast(count(*) as integer)` })
|
const totalCountResult = await db.select({ count: sql<number>`cast(count(*) as integer)` })
|
||||||
.from(orgs);
|
.from(orgs)
|
||||||
|
.where(inArray(orgs.orgId, userOrgIds));
|
||||||
const totalCount = totalCountResult[0].count;
|
const totalCount = totalCountResult[0].count;
|
||||||
|
|
||||||
|
// // Add the user's role for each organization
|
||||||
|
// const organizationsWithRoles = organizations.map(org => ({
|
||||||
|
// ...org,
|
||||||
|
// userRole: req.userOrgRoles[org.orgId],
|
||||||
|
// }));
|
||||||
|
|
||||||
return res.status(HttpCode.OK).send(
|
return res.status(HttpCode.OK).send(
|
||||||
response(res, {
|
response(res, {
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -5,6 +5,9 @@ import { sites } from '@server/db/schema';
|
||||||
import response from "@server/utils/response";
|
import response from "@server/utils/response";
|
||||||
import HttpCode from '@server/types/HttpCode';
|
import HttpCode from '@server/types/HttpCode';
|
||||||
import createHttpError from 'http-errors';
|
import createHttpError from 'http-errors';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
|
const API_BASE_URL = "http://localhost:3000";
|
||||||
|
|
||||||
const createSiteParamsSchema = z.object({
|
const createSiteParamsSchema = z.object({
|
||||||
orgId: z.number().int().positive(),
|
orgId: z.number().int().positive(),
|
||||||
|
@ -68,3 +71,28 @@ export async function createSite(req: Request, res: Response, next: NextFunction
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function addPeer(peer: string) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/peer`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(peer),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data: any = await response.json();
|
||||||
|
console.log('Peer added successfully:', data.status);
|
||||||
|
return data;
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Error adding peer:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ import response from "@server/utils/response";
|
||||||
import HttpCode from '@server/types/HttpCode';
|
import HttpCode from '@server/types/HttpCode';
|
||||||
import createHttpError from 'http-errors';
|
import createHttpError from 'http-errors';
|
||||||
|
|
||||||
|
|
||||||
|
const API_BASE_URL = "http://localhost:3000";
|
||||||
|
|
||||||
// Define Zod schema for request parameters validation
|
// Define Zod schema for request parameters validation
|
||||||
const deleteSiteSchema = z.object({
|
const deleteSiteSchema = z.object({
|
||||||
siteId: z.string().transform(Number).pipe(z.number().int().positive())
|
siteId: z.string().transform(Number).pipe(z.number().int().positive())
|
||||||
|
@ -54,3 +57,23 @@ export async function deleteSite(req: Request, res: Response, next: NextFunction
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function removePeer(publicKey: string) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE_URL}/peer?public_key=${encodeURIComponent(publicKey)}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log('Peer removed successfully:', data.status);
|
||||||
|
return data;
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Error removing peer:', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,4 +5,5 @@ import { Session } from "lucia";
|
||||||
export interface AuthenticatedRequest extends Request {
|
export interface AuthenticatedRequest extends Request {
|
||||||
user: User;
|
user: User;
|
||||||
session: Session;
|
session: Session;
|
||||||
|
userOrgRole?: string;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue