feat: integrate NextAuth for authentication, refactor login and registration processes, and enhance middleware for session management
This commit is contained in:
24
ENV.md
Normal file
24
ENV.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Variables d'environnement requises
|
||||||
|
|
||||||
|
## Production (.env)
|
||||||
|
```env
|
||||||
|
# MongoDB Configuration
|
||||||
|
MONGO_USER=admin
|
||||||
|
MONGO_PASSWORD=your-secure-password
|
||||||
|
MONGODB_URI=mongodb://admin:your-secure-password@mongodb:27017/stripstream?authSource=admin
|
||||||
|
|
||||||
|
# NextAuth Configuration
|
||||||
|
NEXTAUTH_SECRET=your-secret-key-here-generate-with-openssl-rand-base64-32
|
||||||
|
NEXTAUTH_URL=http://localhost:3020
|
||||||
|
|
||||||
|
# Node Environment
|
||||||
|
NODE_ENV=production
|
||||||
|
```
|
||||||
|
|
||||||
|
## Génération du secret NextAuth
|
||||||
|
```bash
|
||||||
|
openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
## Développement
|
||||||
|
Pour le développement, les variables sont définies directement dans `docker-compose.dev.yml`.
|
||||||
@@ -29,6 +29,8 @@ services:
|
|||||||
- MONGODB_URI=mongodb://admin:password123@mongodb:27017/stripstream?authSource=admin
|
- MONGODB_URI=mongodb://admin:password123@mongodb:27017/stripstream?authSource=admin
|
||||||
- PNPM_HOME=/app/.pnpm-store
|
- PNPM_HOME=/app/.pnpm-store
|
||||||
- WATCHPACK_POLLING=true
|
- WATCHPACK_POLLING=true
|
||||||
|
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||||
|
- NEXTAUTH_URL=${NEXTAUTH_URL}
|
||||||
command: sh -c "pnpm config set store-dir /app/.pnpm-store && pnpm install --frozen-lockfile && pnpm dev"
|
command: sh -c "pnpm config set store-dir /app/.pnpm-store && pnpm install --frozen-lockfile && pnpm dev"
|
||||||
|
|
||||||
mongodb:
|
mongodb:
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- MONGODB_URI=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@mongodb:27017/stripstream?authSource=admin
|
- MONGODB_URI=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@mongodb:27017/stripstream?authSource=admin
|
||||||
|
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||||
|
- NEXTAUTH_URL=${NEXTAUTH_URL}
|
||||||
depends_on:
|
depends_on:
|
||||||
- mongodb
|
- mongodb
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-slot": "1.0.2",
|
"@radix-ui/react-slot": "1.0.2",
|
||||||
"@radix-ui/react-toast": "1.1.5",
|
"@radix-ui/react-toast": "1.1.5",
|
||||||
"@types/bcrypt": "^5.0.2",
|
"@types/bcryptjs": "^3.0.0",
|
||||||
"@types/mongoose": "5.11.97",
|
"@types/mongoose": "5.11.97",
|
||||||
"bcrypt": "^5.1.1",
|
"bcryptjs": "^3.0.2",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^10.18.0",
|
"framer-motion": "^10.18.0",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"lucide-react": "^0.487.0",
|
"lucide-react": "^0.487.0",
|
||||||
"mongoose": "8.1.0",
|
"mongoose": "8.1.0",
|
||||||
"next": "15.2.0",
|
"next": "15.2.0",
|
||||||
"next-auth": "4.24.5",
|
"next-auth": "5.0.0-beta.29",
|
||||||
"next-themes": "0.2.1",
|
"next-themes": "0.2.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
|||||||
426
pnpm-lock.yaml
generated
426
pnpm-lock.yaml
generated
@@ -26,15 +26,15 @@ importers:
|
|||||||
'@radix-ui/react-toast':
|
'@radix-ui/react-toast':
|
||||||
specifier: 1.1.5
|
specifier: 1.1.5
|
||||||
version: 1.1.5(@types/react-dom@18.2.21)(@types/react@18.2.64)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 1.1.5(@types/react-dom@18.2.21)(@types/react@18.2.64)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
'@types/bcrypt':
|
'@types/bcryptjs':
|
||||||
specifier: ^5.0.2
|
specifier: ^3.0.0
|
||||||
version: 5.0.2
|
version: 3.0.0
|
||||||
'@types/mongoose':
|
'@types/mongoose':
|
||||||
specifier: 5.11.97
|
specifier: 5.11.97
|
||||||
version: 5.11.97
|
version: 5.11.97
|
||||||
bcrypt:
|
bcryptjs:
|
||||||
specifier: ^5.1.1
|
specifier: ^3.0.2
|
||||||
version: 5.1.1
|
version: 3.0.2
|
||||||
class-variance-authority:
|
class-variance-authority:
|
||||||
specifier: ^0.7.0
|
specifier: ^0.7.0
|
||||||
version: 0.7.1
|
version: 0.7.1
|
||||||
@@ -60,8 +60,8 @@ importers:
|
|||||||
specifier: 15.2.0
|
specifier: 15.2.0
|
||||||
version: 15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
next-auth:
|
next-auth:
|
||||||
specifier: 4.24.5
|
specifier: 5.0.0-beta.29
|
||||||
version: 4.24.5(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 5.0.0-beta.29(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)
|
||||||
next-themes:
|
next-themes:
|
||||||
specifier: 0.2.1
|
specifier: 0.2.1
|
||||||
version: 0.2.1(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 0.2.1(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
@@ -142,6 +142,20 @@ packages:
|
|||||||
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
'@auth/core@0.40.0':
|
||||||
|
resolution: {integrity: sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@simplewebauthn/browser': ^9.0.1
|
||||||
|
'@simplewebauthn/server': ^9.0.2
|
||||||
|
nodemailer: ^6.8.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@simplewebauthn/browser':
|
||||||
|
optional: true
|
||||||
|
'@simplewebauthn/server':
|
||||||
|
optional: true
|
||||||
|
nodemailer:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@babel/runtime@7.28.4':
|
'@babel/runtime@7.28.4':
|
||||||
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
|
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -445,10 +459,6 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.31':
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||||
|
|
||||||
'@mapbox/node-pre-gyp@1.0.11':
|
|
||||||
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
'@mongodb-js/saslprep@1.3.1':
|
'@mongodb-js/saslprep@1.3.1':
|
||||||
resolution: {integrity: sha512-6nZrq5kfAz0POWyhljnbWQQJQ5uT8oE2ddX303q1uY0tWsivWKgBDXBBvuFPwOqRRalXJuVO9EjOdVtuhLX0zg==}
|
resolution: {integrity: sha512-6nZrq5kfAz0POWyhljnbWQQJQ5uT8oE2ddX303q1uY0tWsivWKgBDXBBvuFPwOqRRalXJuVO9EjOdVtuhLX0zg==}
|
||||||
|
|
||||||
@@ -1065,8 +1075,9 @@ packages:
|
|||||||
'@tybys/wasm-util@0.10.1':
|
'@tybys/wasm-util@0.10.1':
|
||||||
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||||
|
|
||||||
'@types/bcrypt@5.0.2':
|
'@types/bcryptjs@3.0.0':
|
||||||
resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==}
|
resolution: {integrity: sha512-WRZOuCuaz8UcZZE4R5HXTco2goQSI2XxjGY3hbM/xDvwmqFWd4ivooImsMx65OKM6CtNKbnZ5YL+YwAwK7c1dg==}
|
||||||
|
deprecated: This is a stub types definition. bcryptjs provides its own type definitions, so you do not need this installed.
|
||||||
|
|
||||||
'@types/json-schema@7.0.15':
|
'@types/json-schema@7.0.15':
|
||||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
@@ -1316,9 +1327,6 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
abbrev@1.1.1:
|
|
||||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
|
||||||
|
|
||||||
acorn-jsx@5.3.2:
|
acorn-jsx@5.3.2:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1329,10 +1337,6 @@ packages:
|
|||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
agent-base@6.0.2:
|
|
||||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
|
||||||
engines: {node: '>= 6.0.0'}
|
|
||||||
|
|
||||||
ajv@6.12.6:
|
ajv@6.12.6:
|
||||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||||
|
|
||||||
@@ -1359,14 +1363,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
aproba@2.1.0:
|
|
||||||
resolution: {integrity: sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==}
|
|
||||||
|
|
||||||
are-we-there-yet@2.0.0:
|
|
||||||
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
deprecated: This package is no longer supported.
|
|
||||||
|
|
||||||
arg@5.0.2:
|
arg@5.0.2:
|
||||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||||
|
|
||||||
@@ -1450,9 +1446,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==}
|
resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
bcrypt@5.1.1:
|
bcryptjs@3.0.2:
|
||||||
resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==}
|
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
|
||||||
engines: {node: '>= 10.0.0'}
|
hasBin: true
|
||||||
|
|
||||||
binary-extensions@2.3.0:
|
binary-extensions@2.3.0:
|
||||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||||
@@ -1512,10 +1508,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||||
engines: {node: '>= 8.10.0'}
|
engines: {node: '>= 8.10.0'}
|
||||||
|
|
||||||
chownr@2.0.0:
|
|
||||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
class-variance-authority@0.7.1:
|
class-variance-authority@0.7.1:
|
||||||
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
|
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
|
||||||
|
|
||||||
@@ -1536,10 +1528,6 @@ packages:
|
|||||||
color-string@1.9.1:
|
color-string@1.9.1:
|
||||||
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
|
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
|
||||||
|
|
||||||
color-support@1.1.3:
|
|
||||||
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
color@4.2.3:
|
color@4.2.3:
|
||||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||||
engines: {node: '>=12.5.0'}
|
engines: {node: '>=12.5.0'}
|
||||||
@@ -1551,13 +1539,6 @@ packages:
|
|||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
|
|
||||||
console-control-strings@1.1.0:
|
|
||||||
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
|
||||||
|
|
||||||
cookie@0.5.0:
|
|
||||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -1613,9 +1594,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
delegates@1.0.0:
|
|
||||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
|
||||||
|
|
||||||
detect-libc@2.1.2:
|
detect-libc@2.1.2:
|
||||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1910,10 +1888,6 @@ packages:
|
|||||||
react-dom:
|
react-dom:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
fs-minipass@2.1.0:
|
|
||||||
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
|
|
||||||
fs.realpath@1.0.0:
|
fs.realpath@1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
|
|
||||||
@@ -1932,11 +1906,6 @@ packages:
|
|||||||
functions-have-names@1.2.3:
|
functions-have-names@1.2.3:
|
||||||
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
||||||
|
|
||||||
gauge@3.0.2:
|
|
||||||
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
deprecated: This package is no longer supported.
|
|
||||||
|
|
||||||
generator-function@2.0.1:
|
generator-function@2.0.1:
|
||||||
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
|
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2018,9 +1987,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
|
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
has-unicode@2.0.1:
|
|
||||||
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
|
||||||
|
|
||||||
hasown@2.0.2:
|
hasown@2.0.2:
|
||||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2028,10 +1994,6 @@ packages:
|
|||||||
html-parse-stringify@3.0.1:
|
html-parse-stringify@3.0.1:
|
||||||
resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
|
resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
|
||||||
|
|
||||||
https-proxy-agent@5.0.1:
|
|
||||||
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
|
|
||||||
i18next-browser-languagedetector@8.2.0:
|
i18next-browser-languagedetector@8.2.0:
|
||||||
resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==}
|
resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==}
|
||||||
|
|
||||||
@@ -2205,8 +2167,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
|
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
jose@4.15.9:
|
jose@6.1.0:
|
||||||
resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==}
|
resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==}
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
@@ -2278,19 +2240,11 @@ packages:
|
|||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
|
|
||||||
lru-cache@6.0.0:
|
|
||||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
lucide-react@0.487.0:
|
lucide-react@0.487.0:
|
||||||
resolution: {integrity: sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==}
|
resolution: {integrity: sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
make-dir@3.1.0:
|
|
||||||
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
math-intrinsics@1.1.0:
|
math-intrinsics@1.1.0:
|
||||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2320,27 +2274,10 @@ packages:
|
|||||||
minimist@1.2.8:
|
minimist@1.2.8:
|
||||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||||
|
|
||||||
minipass@3.3.6:
|
|
||||||
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
minipass@5.0.0:
|
|
||||||
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
minipass@7.1.2:
|
minipass@7.1.2:
|
||||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
|
|
||||||
minizlib@2.1.2:
|
|
||||||
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
|
|
||||||
mkdirp@1.0.4:
|
|
||||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
mongodb-connection-string-url@3.0.2:
|
mongodb-connection-string-url@3.0.2:
|
||||||
resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==}
|
resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==}
|
||||||
|
|
||||||
@@ -2405,14 +2342,19 @@ packages:
|
|||||||
natural-compare@1.4.0:
|
natural-compare@1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
next-auth@4.24.5:
|
next-auth@5.0.0-beta.29:
|
||||||
resolution: {integrity: sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og==}
|
resolution: {integrity: sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: ^12.2.5 || ^13 || ^14
|
'@simplewebauthn/browser': ^9.0.1
|
||||||
|
'@simplewebauthn/server': ^9.0.2
|
||||||
|
next: ^14.0.0-0 || ^15.0.0-0
|
||||||
nodemailer: ^6.6.5
|
nodemailer: ^6.6.5
|
||||||
react: ^17.0.2 || ^18
|
react: ^18.2.0 || ^19.0.0-0
|
||||||
react-dom: ^17.0.2 || ^18
|
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
|
'@simplewebauthn/browser':
|
||||||
|
optional: true
|
||||||
|
'@simplewebauthn/server':
|
||||||
|
optional: true
|
||||||
nodemailer:
|
nodemailer:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -2444,26 +2386,9 @@ packages:
|
|||||||
sass:
|
sass:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
node-addon-api@5.1.0:
|
|
||||||
resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
|
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
|
||||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
|
||||||
engines: {node: 4.x || >=6.0.0}
|
|
||||||
peerDependencies:
|
|
||||||
encoding: ^0.1.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
encoding:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
node-releases@2.0.23:
|
node-releases@2.0.23:
|
||||||
resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==}
|
resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==}
|
||||||
|
|
||||||
nopt@5.0.0:
|
|
||||||
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
normalize-path@3.0.0:
|
normalize-path@3.0.0:
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -2472,21 +2397,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
|
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
npmlog@5.0.1:
|
oauth4webapi@3.8.2:
|
||||||
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
|
resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==}
|
||||||
deprecated: This package is no longer supported.
|
|
||||||
|
|
||||||
oauth@0.9.15:
|
|
||||||
resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==}
|
|
||||||
|
|
||||||
object-assign@4.1.1:
|
object-assign@4.1.1:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
object-hash@2.2.0:
|
|
||||||
resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
|
|
||||||
object-hash@3.0.0:
|
object-hash@3.0.0:
|
||||||
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
|
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@@ -2519,16 +2436,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
oidc-token-hash@5.1.1:
|
|
||||||
resolution: {integrity: sha512-D7EmwxJV6DsEB6vOFLrBM2OzsVgQzgPWyHlV2OOAVj772n+WTXpudC9e9u5BVKQnYwaD30Ivhi9b+4UeBcGu9g==}
|
|
||||||
engines: {node: ^10.13.0 || >=12.0.0}
|
|
||||||
|
|
||||||
once@1.4.0:
|
once@1.4.0:
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
|
|
||||||
openid-client@5.7.1:
|
|
||||||
resolution: {integrity: sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==}
|
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -2643,21 +2553,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==}
|
resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
preact-render-to-string@5.2.6:
|
preact-render-to-string@6.5.11:
|
||||||
resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
|
resolution: {integrity: sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
preact: '>=10'
|
preact: '>=10'
|
||||||
|
|
||||||
preact@10.27.2:
|
preact@10.24.3:
|
||||||
resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==}
|
resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==}
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
pretty-format@3.8.0:
|
|
||||||
resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
|
|
||||||
|
|
||||||
prop-types@15.8.1:
|
prop-types@15.8.1:
|
||||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
||||||
|
|
||||||
@@ -2746,10 +2653,6 @@ packages:
|
|||||||
read-cache@1.0.0:
|
read-cache@1.0.0:
|
||||||
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
||||||
|
|
||||||
readable-stream@3.6.2:
|
|
||||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
|
|
||||||
readdirp@3.6.0:
|
readdirp@3.6.0:
|
||||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||||
engines: {node: '>=8.10.0'}
|
engines: {node: '>=8.10.0'}
|
||||||
@@ -2794,9 +2697,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
|
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
|
||||||
engines: {node: '>=0.4'}
|
engines: {node: '>=0.4'}
|
||||||
|
|
||||||
safe-buffer@5.2.1:
|
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
|
||||||
|
|
||||||
safe-push-apply@1.0.0:
|
safe-push-apply@1.0.0:
|
||||||
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
|
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2817,9 +2717,6 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
set-blocking@2.0.0:
|
|
||||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2867,9 +2764,6 @@ packages:
|
|||||||
sift@16.0.1:
|
sift@16.0.1:
|
||||||
resolution: {integrity: sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==}
|
resolution: {integrity: sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==}
|
||||||
|
|
||||||
signal-exit@3.0.7:
|
|
||||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
|
||||||
|
|
||||||
signal-exit@4.1.0:
|
signal-exit@4.1.0:
|
||||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -2930,9 +2824,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
|
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
string_decoder@1.3.0:
|
|
||||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
|
||||||
|
|
||||||
strip-ansi@6.0.1:
|
strip-ansi@6.0.1:
|
||||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -2988,10 +2879,6 @@ packages:
|
|||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
tar@6.2.1:
|
|
||||||
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
text-table@0.2.0:
|
text-table@0.2.0:
|
||||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||||
|
|
||||||
@@ -3010,9 +2897,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
engines: {node: '>=8.0'}
|
engines: {node: '>=8.0'}
|
||||||
|
|
||||||
tr46@0.0.3:
|
|
||||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
|
||||||
|
|
||||||
tr46@5.1.1:
|
tr46@5.1.1:
|
||||||
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
|
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -3122,17 +3006,10 @@ packages:
|
|||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
uuid@8.3.2:
|
|
||||||
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
void-elements@3.1.0:
|
void-elements@3.1.0:
|
||||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
webidl-conversions@3.0.1:
|
|
||||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
|
||||||
|
|
||||||
webidl-conversions@7.0.0:
|
webidl-conversions@7.0.0:
|
||||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -3141,9 +3018,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
|
resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
whatwg-url@5.0.0:
|
|
||||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
|
||||||
|
|
||||||
which-boxed-primitive@1.1.1:
|
which-boxed-primitive@1.1.1:
|
||||||
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
|
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3165,9 +3039,6 @@ packages:
|
|||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
wide-align@1.1.5:
|
|
||||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
|
||||||
|
|
||||||
word-wrap@1.2.5:
|
word-wrap@1.2.5:
|
||||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -3183,9 +3054,6 @@ packages:
|
|||||||
wrappy@1.0.2:
|
wrappy@1.0.2:
|
||||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||||
|
|
||||||
yallist@4.0.0:
|
|
||||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
|
||||||
|
|
||||||
yaml@2.8.1:
|
yaml@2.8.1:
|
||||||
resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
|
resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
|
||||||
engines: {node: '>= 14.6'}
|
engines: {node: '>= 14.6'}
|
||||||
@@ -3202,6 +3070,14 @@ snapshots:
|
|||||||
|
|
||||||
'@alloc/quick-lru@5.2.0': {}
|
'@alloc/quick-lru@5.2.0': {}
|
||||||
|
|
||||||
|
'@auth/core@0.40.0':
|
||||||
|
dependencies:
|
||||||
|
'@panva/hkdf': 1.2.1
|
||||||
|
jose: 6.1.0
|
||||||
|
oauth4webapi: 3.8.2
|
||||||
|
preact: 10.24.3
|
||||||
|
preact-render-to-string: 6.5.11(preact@10.24.3)
|
||||||
|
|
||||||
'@babel/runtime@7.28.4': {}
|
'@babel/runtime@7.28.4': {}
|
||||||
|
|
||||||
'@emnapi/core@1.5.0':
|
'@emnapi/core@1.5.0':
|
||||||
@@ -3458,21 +3334,6 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
'@mapbox/node-pre-gyp@1.0.11':
|
|
||||||
dependencies:
|
|
||||||
detect-libc: 2.1.2
|
|
||||||
https-proxy-agent: 5.0.1
|
|
||||||
make-dir: 3.1.0
|
|
||||||
node-fetch: 2.7.0
|
|
||||||
nopt: 5.0.0
|
|
||||||
npmlog: 5.0.1
|
|
||||||
rimraf: 3.0.2
|
|
||||||
semver: 7.7.3
|
|
||||||
tar: 6.2.1
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
'@mongodb-js/saslprep@1.3.1':
|
'@mongodb-js/saslprep@1.3.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
sparse-bitfield: 3.0.3
|
sparse-bitfield: 3.0.3
|
||||||
@@ -4039,9 +3900,9 @@ snapshots:
|
|||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@types/bcrypt@5.0.2':
|
'@types/bcryptjs@3.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 24.7.2
|
bcryptjs: 3.0.2
|
||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
|
||||||
@@ -4317,20 +4178,12 @@ snapshots:
|
|||||||
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
|
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
abbrev@1.1.1: {}
|
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.15.0
|
acorn: 8.15.0
|
||||||
|
|
||||||
acorn@8.15.0: {}
|
acorn@8.15.0: {}
|
||||||
|
|
||||||
agent-base@6.0.2:
|
|
||||||
dependencies:
|
|
||||||
debug: 4.4.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
ajv@6.12.6:
|
ajv@6.12.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal: 3.1.3
|
fast-deep-equal: 3.1.3
|
||||||
@@ -4355,13 +4208,6 @@ snapshots:
|
|||||||
normalize-path: 3.0.0
|
normalize-path: 3.0.0
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
|
|
||||||
aproba@2.1.0: {}
|
|
||||||
|
|
||||||
are-we-there-yet@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
delegates: 1.0.0
|
|
||||||
readable-stream: 3.6.2
|
|
||||||
|
|
||||||
arg@5.0.2: {}
|
arg@5.0.2: {}
|
||||||
|
|
||||||
argparse@2.0.1: {}
|
argparse@2.0.1: {}
|
||||||
@@ -4467,13 +4313,7 @@ snapshots:
|
|||||||
|
|
||||||
baseline-browser-mapping@2.8.16: {}
|
baseline-browser-mapping@2.8.16: {}
|
||||||
|
|
||||||
bcrypt@5.1.1:
|
bcryptjs@3.0.2: {}
|
||||||
dependencies:
|
|
||||||
'@mapbox/node-pre-gyp': 1.0.11
|
|
||||||
node-addon-api: 5.1.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
binary-extensions@2.3.0: {}
|
binary-extensions@2.3.0: {}
|
||||||
|
|
||||||
@@ -4544,8 +4384,6 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
chownr@2.0.0: {}
|
|
||||||
|
|
||||||
class-variance-authority@0.7.1:
|
class-variance-authority@0.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
clsx: 2.1.1
|
clsx: 2.1.1
|
||||||
@@ -4565,8 +4403,6 @@ snapshots:
|
|||||||
color-name: 1.1.4
|
color-name: 1.1.4
|
||||||
simple-swizzle: 0.2.4
|
simple-swizzle: 0.2.4
|
||||||
|
|
||||||
color-support@1.1.3: {}
|
|
||||||
|
|
||||||
color@4.2.3:
|
color@4.2.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert: 2.0.1
|
color-convert: 2.0.1
|
||||||
@@ -4576,10 +4412,6 @@ snapshots:
|
|||||||
|
|
||||||
concat-map@0.0.1: {}
|
concat-map@0.0.1: {}
|
||||||
|
|
||||||
console-control-strings@1.1.0: {}
|
|
||||||
|
|
||||||
cookie@0.5.0: {}
|
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key: 3.1.1
|
path-key: 3.1.1
|
||||||
@@ -4632,8 +4464,6 @@ snapshots:
|
|||||||
has-property-descriptors: 1.0.2
|
has-property-descriptors: 1.0.2
|
||||||
object-keys: 1.1.1
|
object-keys: 1.1.1
|
||||||
|
|
||||||
delegates@1.0.0: {}
|
|
||||||
|
|
||||||
detect-libc@2.1.2: {}
|
detect-libc@2.1.2: {}
|
||||||
|
|
||||||
detect-node-es@1.1.0: {}
|
detect-node-es@1.1.0: {}
|
||||||
@@ -5069,10 +4899,6 @@ snapshots:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
||||||
fs-minipass@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
minipass: 3.3.6
|
|
||||||
|
|
||||||
fs.realpath@1.0.0: {}
|
fs.realpath@1.0.0: {}
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
@@ -5091,18 +4917,6 @@ snapshots:
|
|||||||
|
|
||||||
functions-have-names@1.2.3: {}
|
functions-have-names@1.2.3: {}
|
||||||
|
|
||||||
gauge@3.0.2:
|
|
||||||
dependencies:
|
|
||||||
aproba: 2.1.0
|
|
||||||
color-support: 1.1.3
|
|
||||||
console-control-strings: 1.1.0
|
|
||||||
has-unicode: 2.0.1
|
|
||||||
object-assign: 4.1.1
|
|
||||||
signal-exit: 3.0.7
|
|
||||||
string-width: 4.2.3
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
wide-align: 1.1.5
|
|
||||||
|
|
||||||
generator-function@2.0.1: {}
|
generator-function@2.0.1: {}
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
@@ -5201,8 +5015,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-symbols: 1.1.0
|
has-symbols: 1.1.0
|
||||||
|
|
||||||
has-unicode@2.0.1: {}
|
|
||||||
|
|
||||||
hasown@2.0.2:
|
hasown@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
function-bind: 1.1.2
|
function-bind: 1.1.2
|
||||||
@@ -5211,13 +5023,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
void-elements: 3.1.0
|
void-elements: 3.1.0
|
||||||
|
|
||||||
https-proxy-agent@5.0.1:
|
|
||||||
dependencies:
|
|
||||||
agent-base: 6.0.2
|
|
||||||
debug: 4.4.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
i18next-browser-languagedetector@8.2.0:
|
i18next-browser-languagedetector@8.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.4
|
'@babel/runtime': 7.28.4
|
||||||
@@ -5395,7 +5200,7 @@ snapshots:
|
|||||||
|
|
||||||
jiti@1.21.7: {}
|
jiti@1.21.7: {}
|
||||||
|
|
||||||
jose@4.15.9: {}
|
jose@6.1.0: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
@@ -5457,18 +5262,10 @@ snapshots:
|
|||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
lru-cache@6.0.0:
|
|
||||||
dependencies:
|
|
||||||
yallist: 4.0.0
|
|
||||||
|
|
||||||
lucide-react@0.487.0(react@18.2.0):
|
lucide-react@0.487.0(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
|
|
||||||
make-dir@3.1.0:
|
|
||||||
dependencies:
|
|
||||||
semver: 6.3.1
|
|
||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
|
|
||||||
memory-pager@1.5.0: {}
|
memory-pager@1.5.0: {}
|
||||||
@@ -5494,21 +5291,8 @@ snapshots:
|
|||||||
|
|
||||||
minimist@1.2.8: {}
|
minimist@1.2.8: {}
|
||||||
|
|
||||||
minipass@3.3.6:
|
|
||||||
dependencies:
|
|
||||||
yallist: 4.0.0
|
|
||||||
|
|
||||||
minipass@5.0.0: {}
|
|
||||||
|
|
||||||
minipass@7.1.2: {}
|
minipass@7.1.2: {}
|
||||||
|
|
||||||
minizlib@2.1.2:
|
|
||||||
dependencies:
|
|
||||||
minipass: 3.3.6
|
|
||||||
yallist: 4.0.0
|
|
||||||
|
|
||||||
mkdirp@1.0.4: {}
|
|
||||||
|
|
||||||
mongodb-connection-string-url@3.0.2:
|
mongodb-connection-string-url@3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/whatwg-url': 11.0.5
|
'@types/whatwg-url': 11.0.5
|
||||||
@@ -5563,20 +5347,11 @@ snapshots:
|
|||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
next-auth@4.24.5(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
next-auth@5.0.0-beta.29(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.4
|
'@auth/core': 0.40.0
|
||||||
'@panva/hkdf': 1.2.1
|
|
||||||
cookie: 0.5.0
|
|
||||||
jose: 4.15.9
|
|
||||||
next: 15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
next: 15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
oauth: 0.9.15
|
|
||||||
openid-client: 5.7.1
|
|
||||||
preact: 10.27.2
|
|
||||||
preact-render-to-string: 5.2.6(preact@10.27.2)
|
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
uuid: 8.3.2
|
|
||||||
|
|
||||||
next-themes@0.2.1(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
next-themes@0.2.1(next@15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5609,35 +5384,16 @@ snapshots:
|
|||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
|
|
||||||
node-addon-api@5.1.0: {}
|
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
|
||||||
dependencies:
|
|
||||||
whatwg-url: 5.0.0
|
|
||||||
|
|
||||||
node-releases@2.0.23: {}
|
node-releases@2.0.23: {}
|
||||||
|
|
||||||
nopt@5.0.0:
|
|
||||||
dependencies:
|
|
||||||
abbrev: 1.1.1
|
|
||||||
|
|
||||||
normalize-path@3.0.0: {}
|
normalize-path@3.0.0: {}
|
||||||
|
|
||||||
normalize-range@0.1.2: {}
|
normalize-range@0.1.2: {}
|
||||||
|
|
||||||
npmlog@5.0.1:
|
oauth4webapi@3.8.2: {}
|
||||||
dependencies:
|
|
||||||
are-we-there-yet: 2.0.0
|
|
||||||
console-control-strings: 1.1.0
|
|
||||||
gauge: 3.0.2
|
|
||||||
set-blocking: 2.0.0
|
|
||||||
|
|
||||||
oauth@0.9.15: {}
|
|
||||||
|
|
||||||
object-assign@4.1.1: {}
|
object-assign@4.1.1: {}
|
||||||
|
|
||||||
object-hash@2.2.0: {}
|
|
||||||
|
|
||||||
object-hash@3.0.0: {}
|
object-hash@3.0.0: {}
|
||||||
|
|
||||||
object-inspect@1.13.4: {}
|
object-inspect@1.13.4: {}
|
||||||
@@ -5680,19 +5436,10 @@ snapshots:
|
|||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-object-atoms: 1.1.1
|
es-object-atoms: 1.1.1
|
||||||
|
|
||||||
oidc-token-hash@5.1.1: {}
|
|
||||||
|
|
||||||
once@1.4.0:
|
once@1.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
wrappy: 1.0.2
|
wrappy: 1.0.2
|
||||||
|
|
||||||
openid-client@5.7.1:
|
|
||||||
dependencies:
|
|
||||||
jose: 4.15.9
|
|
||||||
lru-cache: 6.0.0
|
|
||||||
object-hash: 2.2.0
|
|
||||||
oidc-token-hash: 5.1.1
|
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
@@ -5792,17 +5539,14 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
preact-render-to-string@5.2.6(preact@10.27.2):
|
preact-render-to-string@6.5.11(preact@10.24.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
preact: 10.27.2
|
preact: 10.24.3
|
||||||
pretty-format: 3.8.0
|
|
||||||
|
|
||||||
preact@10.27.2: {}
|
preact@10.24.3: {}
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
pretty-format@3.8.0: {}
|
|
||||||
|
|
||||||
prop-types@15.8.1:
|
prop-types@15.8.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
@@ -5882,12 +5626,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pify: 2.3.0
|
pify: 2.3.0
|
||||||
|
|
||||||
readable-stream@3.6.2:
|
|
||||||
dependencies:
|
|
||||||
inherits: 2.0.4
|
|
||||||
string_decoder: 1.3.0
|
|
||||||
util-deprecate: 1.0.2
|
|
||||||
|
|
||||||
readdirp@3.6.0:
|
readdirp@3.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
@@ -5946,8 +5684,6 @@ snapshots:
|
|||||||
has-symbols: 1.1.0
|
has-symbols: 1.1.0
|
||||||
isarray: 2.0.5
|
isarray: 2.0.5
|
||||||
|
|
||||||
safe-buffer@5.2.1: {}
|
|
||||||
|
|
||||||
safe-push-apply@1.0.0:
|
safe-push-apply@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@@ -5967,8 +5703,6 @@ snapshots:
|
|||||||
|
|
||||||
semver@7.7.3: {}
|
semver@7.7.3: {}
|
||||||
|
|
||||||
set-blocking@2.0.0: {}
|
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
define-data-property: 1.1.4
|
define-data-property: 1.1.4
|
||||||
@@ -6080,8 +5814,6 @@ snapshots:
|
|||||||
|
|
||||||
sift@16.0.1: {}
|
sift@16.0.1: {}
|
||||||
|
|
||||||
signal-exit@3.0.7: {}
|
|
||||||
|
|
||||||
signal-exit@4.1.0: {}
|
signal-exit@4.1.0: {}
|
||||||
|
|
||||||
simple-swizzle@0.2.4:
|
simple-swizzle@0.2.4:
|
||||||
@@ -6167,10 +5899,6 @@ snapshots:
|
|||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-object-atoms: 1.1.1
|
es-object-atoms: 1.1.1
|
||||||
|
|
||||||
string_decoder@1.3.0:
|
|
||||||
dependencies:
|
|
||||||
safe-buffer: 5.2.1
|
|
||||||
|
|
||||||
strip-ansi@6.0.1:
|
strip-ansi@6.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 5.0.1
|
ansi-regex: 5.0.1
|
||||||
@@ -6237,15 +5965,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- ts-node
|
- ts-node
|
||||||
|
|
||||||
tar@6.2.1:
|
|
||||||
dependencies:
|
|
||||||
chownr: 2.0.0
|
|
||||||
fs-minipass: 2.1.0
|
|
||||||
minipass: 5.0.0
|
|
||||||
minizlib: 2.1.2
|
|
||||||
mkdirp: 1.0.4
|
|
||||||
yallist: 4.0.0
|
|
||||||
|
|
||||||
text-table@0.2.0: {}
|
text-table@0.2.0: {}
|
||||||
|
|
||||||
thenify-all@1.6.0:
|
thenify-all@1.6.0:
|
||||||
@@ -6265,8 +5984,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
|
|
||||||
tr46@0.0.3: {}
|
|
||||||
|
|
||||||
tr46@5.1.1:
|
tr46@5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
@@ -6400,12 +6117,8 @@ snapshots:
|
|||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
uuid@8.3.2: {}
|
|
||||||
|
|
||||||
void-elements@3.1.0: {}
|
void-elements@3.1.0: {}
|
||||||
|
|
||||||
webidl-conversions@3.0.1: {}
|
|
||||||
|
|
||||||
webidl-conversions@7.0.0: {}
|
webidl-conversions@7.0.0: {}
|
||||||
|
|
||||||
whatwg-url@14.2.0:
|
whatwg-url@14.2.0:
|
||||||
@@ -6413,11 +6126,6 @@ snapshots:
|
|||||||
tr46: 5.1.1
|
tr46: 5.1.1
|
||||||
webidl-conversions: 7.0.0
|
webidl-conversions: 7.0.0
|
||||||
|
|
||||||
whatwg-url@5.0.0:
|
|
||||||
dependencies:
|
|
||||||
tr46: 0.0.3
|
|
||||||
webidl-conversions: 3.0.1
|
|
||||||
|
|
||||||
which-boxed-primitive@1.1.1:
|
which-boxed-primitive@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-bigint: 1.1.0
|
is-bigint: 1.1.0
|
||||||
@@ -6463,10 +6171,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|
||||||
wide-align@1.1.5:
|
|
||||||
dependencies:
|
|
||||||
string-width: 4.2.3
|
|
||||||
|
|
||||||
word-wrap@1.2.5: {}
|
word-wrap@1.2.5: {}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
@@ -6483,8 +6187,6 @@ snapshots:
|
|||||||
|
|
||||||
wrappy@1.0.2: {}
|
wrappy@1.0.2: {}
|
||||||
|
|
||||||
yallist@4.0.0: {}
|
|
||||||
|
|
||||||
yaml@2.8.1: {}
|
yaml@2.8.1: {}
|
||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
|||||||
3
src/app/api/auth/[...nextauth]/route.ts
Normal file
3
src/app/api/auth/[...nextauth]/route.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { handlers } from "@/lib/auth";
|
||||||
|
|
||||||
|
export const { GET, POST } = handlers;
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import { NextResponse } from "next/server";
|
|
||||||
import { AuthServerService } from "@/lib/services/auth-server.service";
|
|
||||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
|
||||||
import { AppError } from "@/utils/errors";
|
|
||||||
import type { UserData } from "@/lib/services/auth-server.service";
|
|
||||||
import { getErrorMessage } from "@/utils/errors";
|
|
||||||
import type { NextRequest } from "next/server";
|
|
||||||
export async function POST(request: NextRequest) {
|
|
||||||
try {
|
|
||||||
const { email, password, remember } = await request.json();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const userData: UserData = await AuthServerService.loginUser(email, password);
|
|
||||||
await AuthServerService.setUserCookie(userData, remember);
|
|
||||||
|
|
||||||
return NextResponse.json({
|
|
||||||
message: "✅ Connexion réussie",
|
|
||||||
user: userData,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof AppError) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
{ status: 401 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Erreur lors de la connexion:", error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error: {
|
|
||||||
code: ERROR_CODES.AUTH.INVALID_CREDENTIALS,
|
|
||||||
name: "Invalid credentials",
|
|
||||||
message: getErrorMessage(ERROR_CODES.AUTH.INVALID_CREDENTIALS),
|
|
||||||
} as AppError,
|
|
||||||
},
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { NextResponse } from "next/server";
|
|
||||||
import { cookies } from "next/headers";
|
|
||||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
|
||||||
import { getErrorMessage } from "@/utils/errors";
|
|
||||||
import type { AppErrorType } from "@/types/global";
|
|
||||||
|
|
||||||
export async function POST() {
|
|
||||||
try {
|
|
||||||
// Supprimer le cookie
|
|
||||||
const cookieStore = await cookies();
|
|
||||||
cookieStore.delete("stripUser");
|
|
||||||
|
|
||||||
return NextResponse.json({ message: "👋 Déconnexion réussie" });
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Erreur lors de la déconnexion:", error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error: {
|
|
||||||
code: ERROR_CODES.AUTH.LOGOUT_ERROR,
|
|
||||||
name: "Logout error",
|
|
||||||
message: getErrorMessage(ERROR_CODES.AUTH.LOGOUT_ERROR),
|
|
||||||
} as AppErrorType,
|
|
||||||
},
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +1,52 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import type { UserData } from "@/lib/services/auth-server.service";
|
|
||||||
import { AuthServerService } from "@/lib/services/auth-server.service";
|
import { AuthServerService } from "@/lib/services/auth-server.service";
|
||||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
import { ERROR_CODES } from "@/constants/errorCodes";
|
||||||
|
import { ERROR_MESSAGES } from "@/constants/errorMessages";
|
||||||
import { AppError } from "@/utils/errors";
|
import { AppError } from "@/utils/errors";
|
||||||
import { getErrorMessage } from "@/utils/errors";
|
|
||||||
import type { NextRequest } from "next/server";
|
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const { email, password } = await request.json();
|
const { email, password } = await request.json();
|
||||||
|
|
||||||
try {
|
if (!email || !password) {
|
||||||
const userData: UserData = await AuthServerService.createUser(email, password);
|
return NextResponse.json(
|
||||||
await AuthServerService.setUserCookie(userData);
|
{
|
||||||
|
error: {
|
||||||
return NextResponse.json({
|
code: ERROR_CODES.AUTH.INVALID_USER_DATA,
|
||||||
message: "✅ Inscription réussie",
|
name: "Invalid user data",
|
||||||
user: userData,
|
message: ERROR_MESSAGES[ERROR_CODES.AUTH.INVALID_USER_DATA],
|
||||||
});
|
} as AppError,
|
||||||
} catch (error) {
|
},
|
||||||
if (error instanceof AppError) {
|
{ status: 400 }
|
||||||
const status =
|
);
|
||||||
error.code === ERROR_CODES.AUTH.EMAIL_EXISTS ||
|
|
||||||
error.code === ERROR_CODES.AUTH.PASSWORD_NOT_STRONG
|
|
||||||
? 400
|
|
||||||
: 500;
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
{ status }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userData = await AuthServerService.registerUser(email, password);
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, user: userData });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur lors de l'inscription:", error);
|
console.error("Registration error:", error);
|
||||||
|
|
||||||
|
if (error instanceof AppError) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: {
|
||||||
|
code: error.code,
|
||||||
|
name: error.name,
|
||||||
|
message: error.message,
|
||||||
|
} as AppError,
|
||||||
|
},
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
error: {
|
error: {
|
||||||
code: ERROR_CODES.AUTH.INVALID_USER_DATA,
|
code: ERROR_CODES.AUTH.REGISTRATION_FAILED,
|
||||||
name: "Invalid user data",
|
name: "Registration failed",
|
||||||
message: getErrorMessage(ERROR_CODES.AUTH.INVALID_USER_DATA),
|
message: ERROR_MESSAGES[ERROR_CODES.AUTH.REGISTRATION_FAILED],
|
||||||
},
|
} as AppError,
|
||||||
},
|
},
|
||||||
{ status: 500 }
|
{ status: 500 }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import ClientLayout from "@/components/layout/ClientLayout";
|
|||||||
import { PreferencesService } from "@/lib/services/preferences.service";
|
import { PreferencesService } from "@/lib/services/preferences.service";
|
||||||
import { PreferencesProvider } from "@/contexts/PreferencesContext";
|
import { PreferencesProvider } from "@/contexts/PreferencesContext";
|
||||||
import { I18nProvider } from "@/components/providers/I18nProvider";
|
import { I18nProvider } from "@/components/providers/I18nProvider";
|
||||||
|
import { AuthProvider } from "@/components/providers/AuthProvider";
|
||||||
import "@/i18n/i18n"; // Import i18next configuration
|
import "@/i18n/i18n"; // Import i18next configuration
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { defaultPreferences } from "@/types/preferences";
|
import { defaultPreferences } from "@/types/preferences";
|
||||||
@@ -158,13 +159,15 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
|||||||
<body
|
<body
|
||||||
className={cn("min-h-screen bg-background font-sans antialiased h-full", inter.className)}
|
className={cn("min-h-screen bg-background font-sans antialiased h-full", inter.className)}
|
||||||
>
|
>
|
||||||
<I18nProvider locale={locale}>
|
<AuthProvider>
|
||||||
<PreferencesProvider initialPreferences={preferences}>
|
<I18nProvider locale={locale}>
|
||||||
<ClientLayout initialLibraries={libraries} initialFavorites={favorites}>
|
<PreferencesProvider initialPreferences={preferences}>
|
||||||
{children}
|
<ClientLayout initialLibraries={libraries} initialFavorites={favorites}>
|
||||||
</ClientLayout>
|
{children}
|
||||||
</PreferencesProvider>
|
</ClientLayout>
|
||||||
</I18nProvider>
|
</PreferencesProvider>
|
||||||
|
</I18nProvider>
|
||||||
|
</AuthProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { authService } from "@/lib/services/auth.service";
|
import { signIn } from "next-auth/react";
|
||||||
import type { AppErrorType } from "@/types/global";
|
|
||||||
import { ErrorMessage } from "@/components/ui/ErrorMessage";
|
|
||||||
import { useTranslate } from "@/hooks/useTranslate";
|
import { useTranslate } from "@/hooks/useTranslate";
|
||||||
|
|
||||||
interface LoginFormProps {
|
interface LoginFormProps {
|
||||||
@@ -14,7 +12,7 @@ interface LoginFormProps {
|
|||||||
export function LoginForm({ from }: LoginFormProps) {
|
export function LoginForm({ from }: LoginFormProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [error, setError] = useState<AppErrorType | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const { t } = useTranslate();
|
const { t } = useTranslate();
|
||||||
|
|
||||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
@@ -28,11 +26,21 @@ export function LoginForm({ from }: LoginFormProps) {
|
|||||||
const remember = formData.get("remember") === "on";
|
const remember = formData.get("remember") === "on";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authService.login(email, password, remember);
|
const result = await signIn("credentials", {
|
||||||
router.push(from || "/");
|
email,
|
||||||
router.refresh();
|
password,
|
||||||
} catch (error) {
|
remember,
|
||||||
setError(error as AppErrorType);
|
redirect: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result?.error) {
|
||||||
|
setError("Email ou mot de passe incorrect");
|
||||||
|
} else {
|
||||||
|
router.push(from || "/");
|
||||||
|
router.refresh();
|
||||||
|
}
|
||||||
|
} catch (_error) {
|
||||||
|
setError("Une erreur est survenue lors de la connexion : " + _error);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@@ -89,7 +97,11 @@ export function LoginForm({ from }: LoginFormProps) {
|
|||||||
{t("login.form.remember")}
|
{t("login.form.remember")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{error && <ErrorMessage errorCode={error.code} variant="form" />}
|
{error && (
|
||||||
|
<div className="text-red-600 text-sm">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
|
|||||||
@@ -2,18 +2,16 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { authService } from "@/lib/services/auth.service";
|
import { signIn } from "next-auth/react";
|
||||||
import type { AppErrorType } from "@/types/global";
|
|
||||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
|
||||||
import { ErrorMessage } from "@/components/ui/ErrorMessage";
|
import { ErrorMessage } from "@/components/ui/ErrorMessage";
|
||||||
import { useTranslate } from "@/hooks/useTranslate";
|
import { useTranslate } from "@/hooks/useTranslate";
|
||||||
import { getErrorMessage } from "@/utils/errors";
|
import type { AppErrorType } from "@/types/global";
|
||||||
|
|
||||||
interface RegisterFormProps {
|
interface RegisterFormProps {
|
||||||
from?: string;
|
from?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RegisterForm({ from }: RegisterFormProps) {
|
export function RegisterForm({ from: _from }: RegisterFormProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [error, setError] = useState<AppErrorType | null>(null);
|
const [error, setError] = useState<AppErrorType | null>(null);
|
||||||
@@ -31,20 +29,57 @@ export function RegisterForm({ from }: RegisterFormProps) {
|
|||||||
|
|
||||||
if (password !== confirmPassword) {
|
if (password !== confirmPassword) {
|
||||||
setError({
|
setError({
|
||||||
code: ERROR_CODES.AUTH.PASSWORD_MISMATCH,
|
code: "AUTH_PASSWORD_MISMATCH",
|
||||||
name: "Password mismatch",
|
name: "Password mismatch",
|
||||||
message: getErrorMessage(ERROR_CODES.AUTH.PASSWORD_MISMATCH),
|
message: "Les mots de passe ne correspondent pas",
|
||||||
});
|
});
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authService.register(email, password);
|
// Étape 1: Inscription via l'API
|
||||||
router.push(from || "/");
|
const response = await fetch("/api/auth/register", {
|
||||||
router.refresh();
|
method: "POST",
|
||||||
} catch (error) {
|
headers: {
|
||||||
setError(error as AppErrorType);
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ email, password }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
setError(data.error || {
|
||||||
|
code: "AUTH_REGISTRATION_FAILED",
|
||||||
|
name: "Registration failed",
|
||||||
|
message: "Erreur lors de l'inscription",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Étape 2: Connexion automatique via NextAuth
|
||||||
|
const signInResult = await signIn("credentials", {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
redirect: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (signInResult?.error) {
|
||||||
|
setError({
|
||||||
|
code: "AUTH_INVALID_CREDENTIALS",
|
||||||
|
name: "Login failed",
|
||||||
|
message: "Inscription réussie mais erreur lors de la connexion automatique",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
router.push("/");
|
||||||
|
router.refresh();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setError({
|
||||||
|
code: "AUTH_REGISTRATION_FAILED",
|
||||||
|
name: "Registration failed",
|
||||||
|
message: "Une erreur est survenue lors de l'inscription",
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { Home, Library, Settings, LogOut, RefreshCw, Star, Download } from "lucide-react";
|
import { Home, Library, Settings, LogOut, RefreshCw, Star, Download } from "lucide-react";
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { authService } from "@/lib/services/auth.service";
|
import { signOut } from "next-auth/react";
|
||||||
import { useEffect, useState, useCallback } from "react";
|
import { useEffect, useState, useCallback } from "react";
|
||||||
import type { KomgaLibrary, KomgaSeries } from "@/types/komga";
|
import type { KomgaLibrary, KomgaSeries } from "@/types/komga";
|
||||||
import { usePreferences } from "@/contexts/PreferencesContext";
|
import { usePreferences } from "@/contexts/PreferencesContext";
|
||||||
@@ -118,19 +118,15 @@ export function Sidebar({ isOpen, onClose, initialLibraries, initialFavorites }:
|
|||||||
|
|
||||||
const handleLogout = async () => {
|
const handleLogout = async () => {
|
||||||
try {
|
try {
|
||||||
await authService.logout();
|
await signOut({ callbackUrl: "/login" });
|
||||||
setLibraries([]);
|
setLibraries([]);
|
||||||
setFavorites([]);
|
setFavorites([]);
|
||||||
onClose();
|
onClose();
|
||||||
router.push("/login");
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur lors de la déconnexion:", error);
|
console.error("Erreur lors de la déconnexion:", error);
|
||||||
toast({
|
toast({
|
||||||
title: "Erreur",
|
title: "Erreur",
|
||||||
description:
|
description: "Une erreur est survenue lors de la déconnexion",
|
||||||
error instanceof AppError
|
|
||||||
? error.message
|
|
||||||
: getErrorMessage(ERROR_CODES.AUTH.LOGOUT_ERROR),
|
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { SeriesGrid } from "./SeriesGrid";
|
import { SeriesGrid } from "./SeriesGrid";
|
||||||
import { Pagination } from "@/components/ui/Pagination";
|
import { Pagination } from "@/components/ui/Pagination";
|
||||||
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import type { KomgaSeries } from "@/types/komga";
|
import type { KomgaSeries } from "@/types/komga";
|
||||||
@@ -27,7 +27,7 @@ export function PaginatedSeriesGrid({
|
|||||||
series,
|
series,
|
||||||
currentPage,
|
currentPage,
|
||||||
totalPages,
|
totalPages,
|
||||||
totalElements,
|
totalElements: _totalElements,
|
||||||
defaultShowOnlyUnread,
|
defaultShowOnlyUnread,
|
||||||
showOnlyUnread: initialShowOnlyUnread,
|
showOnlyUnread: initialShowOnlyUnread,
|
||||||
}: PaginatedSeriesGridProps) {
|
}: PaginatedSeriesGridProps) {
|
||||||
@@ -36,10 +36,10 @@ export function PaginatedSeriesGrid({
|
|||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [isChangingPage, setIsChangingPage] = useState(false);
|
const [isChangingPage, setIsChangingPage] = useState(false);
|
||||||
const [showOnlyUnread, setShowOnlyUnread] = useState(initialShowOnlyUnread);
|
const [showOnlyUnread, setShowOnlyUnread] = useState(initialShowOnlyUnread);
|
||||||
const { isCompact, itemsPerPage } = useDisplayPreferences();
|
const { isCompact, itemsPerPage: _itemsPerPage } = useDisplayPreferences();
|
||||||
const { t } = useTranslate();
|
const { t } = useTranslate();
|
||||||
|
|
||||||
const updateUrlParams = async (
|
const updateUrlParams = useCallback(async (
|
||||||
updates: Record<string, string | null>,
|
updates: Record<string, string | null>,
|
||||||
replace: boolean = false
|
replace: boolean = false
|
||||||
) => {
|
) => {
|
||||||
@@ -59,7 +59,7 @@ export function PaginatedSeriesGrid({
|
|||||||
} else {
|
} else {
|
||||||
await router.push(`${pathname}?${params.toString()}`);
|
await router.push(`${pathname}?${params.toString()}`);
|
||||||
}
|
}
|
||||||
};
|
}, [router, pathname, searchParams]);
|
||||||
|
|
||||||
// Reset loading state when series change
|
// Reset loading state when series change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -76,7 +76,7 @@ export function PaginatedSeriesGrid({
|
|||||||
if (defaultShowOnlyUnread && !searchParams.has("unread")) {
|
if (defaultShowOnlyUnread && !searchParams.has("unread")) {
|
||||||
updateUrlParams({ page: "1", unread: "true" }, true);
|
updateUrlParams({ page: "1", unread: "true" }, true);
|
||||||
}
|
}
|
||||||
}, [defaultShowOnlyUnread, pathname, router, searchParams]);
|
}, [defaultShowOnlyUnread, pathname, router, searchParams, updateUrlParams]);
|
||||||
|
|
||||||
const handlePageChange = async (page: number) => {
|
const handlePageChange = async (page: number) => {
|
||||||
await updateUrlParams({ page: page.toString() });
|
await updateUrlParams({ page: page.toString() });
|
||||||
|
|||||||
12
src/components/providers/AuthProvider.tsx
Normal file
12
src/components/providers/AuthProvider.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { SessionProvider } from "next-auth/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface AuthProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AuthProvider({ children }: AuthProviderProps) {
|
||||||
|
return <SessionProvider>{children}</SessionProvider>;
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
interface ZoomablePageProps {
|
interface ZoomablePageProps {
|
||||||
pageUrl: string | null;
|
pageUrl: string | null;
|
||||||
@@ -23,10 +22,7 @@ export const ZoomablePage = ({
|
|||||||
order = "first",
|
order = "first",
|
||||||
onZoomChange,
|
onZoomChange,
|
||||||
}: ZoomablePageProps) => {
|
}: ZoomablePageProps) => {
|
||||||
const [currentScale, setCurrentScale] = useState(1);
|
|
||||||
|
|
||||||
const handleTransform = (ref: any, state: { scale: number; positionX: number; positionY: number }) => {
|
const handleTransform = (ref: any, state: { scale: number; positionX: number; positionY: number }) => {
|
||||||
setCurrentScale(state.scale);
|
|
||||||
onZoomChange?.(state.scale > 1.1);
|
onZoomChange?.(state.scale > 1.1);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { BookGrid } from "./BookGrid";
|
import { BookGrid } from "./BookGrid";
|
||||||
import { Pagination } from "@/components/ui/Pagination";
|
import { Pagination } from "@/components/ui/Pagination";
|
||||||
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import type { KomgaBook } from "@/types/komga";
|
import type { KomgaBook } from "@/types/komga";
|
||||||
@@ -38,7 +38,7 @@ export function PaginatedBookGrid({
|
|||||||
const { isCompact, itemsPerPage } = useDisplayPreferences();
|
const { isCompact, itemsPerPage } = useDisplayPreferences();
|
||||||
const { t } = useTranslate();
|
const { t } = useTranslate();
|
||||||
|
|
||||||
const updateUrlParams = async (
|
const updateUrlParams = useCallback(async (
|
||||||
updates: Record<string, string | null>,
|
updates: Record<string, string | null>,
|
||||||
replace: boolean = false
|
replace: boolean = false
|
||||||
) => {
|
) => {
|
||||||
@@ -58,7 +58,7 @@ export function PaginatedBookGrid({
|
|||||||
} else {
|
} else {
|
||||||
await router.push(`${pathname}?${params.toString()}`);
|
await router.push(`${pathname}?${params.toString()}`);
|
||||||
}
|
}
|
||||||
};
|
}, [router, pathname, searchParams]);
|
||||||
|
|
||||||
// Reset loading state when books change
|
// Reset loading state when books change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -75,7 +75,7 @@ export function PaginatedBookGrid({
|
|||||||
if (defaultShowOnlyUnread && !searchParams.has("unread")) {
|
if (defaultShowOnlyUnread && !searchParams.has("unread")) {
|
||||||
updateUrlParams({ page: "1", unread: "true" }, true);
|
updateUrlParams({ page: "1", unread: "true" }, true);
|
||||||
}
|
}
|
||||||
}, [defaultShowOnlyUnread, pathname, router, searchParams]);
|
}, [defaultShowOnlyUnread, pathname, router, searchParams, updateUrlParams]);
|
||||||
|
|
||||||
const handlePageChange = async (page: number) => {
|
const handlePageChange = async (page: number) => {
|
||||||
await updateUrlParams({ page: page.toString() });
|
await updateUrlParams({ page: page.toString() });
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const ERROR_CODES = {
|
|||||||
EMAIL_EXISTS: "AUTH_EMAIL_EXISTS",
|
EMAIL_EXISTS: "AUTH_EMAIL_EXISTS",
|
||||||
INVALID_USER_DATA: "AUTH_INVALID_USER_DATA",
|
INVALID_USER_DATA: "AUTH_INVALID_USER_DATA",
|
||||||
LOGOUT_ERROR: "AUTH_LOGOUT_ERROR",
|
LOGOUT_ERROR: "AUTH_LOGOUT_ERROR",
|
||||||
|
REGISTRATION_FAILED: "AUTH_REGISTRATION_FAILED",
|
||||||
},
|
},
|
||||||
KOMGA: {
|
KOMGA: {
|
||||||
MISSING_CONFIG: "KOMGA_MISSING_CONFIG",
|
MISSING_CONFIG: "KOMGA_MISSING_CONFIG",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export const ERROR_MESSAGES: Record<string, string> = {
|
|||||||
[ERROR_CODES.AUTH.EMAIL_EXISTS]: "📧 This email is already in use",
|
[ERROR_CODES.AUTH.EMAIL_EXISTS]: "📧 This email is already in use",
|
||||||
[ERROR_CODES.AUTH.INVALID_USER_DATA]: "👤 Invalid user data",
|
[ERROR_CODES.AUTH.INVALID_USER_DATA]: "👤 Invalid user data",
|
||||||
[ERROR_CODES.AUTH.LOGOUT_ERROR]: "🚪 Error during logout",
|
[ERROR_CODES.AUTH.LOGOUT_ERROR]: "🚪 Error during logout",
|
||||||
|
[ERROR_CODES.AUTH.REGISTRATION_FAILED]: "❌ Registration failed",
|
||||||
|
|
||||||
// Komga
|
// Komga
|
||||||
[ERROR_CODES.KOMGA.MISSING_CONFIG]: "⚙️ Komga configuration not found",
|
[ERROR_CODES.KOMGA.MISSING_CONFIG]: "⚙️ Komga configuration not found",
|
||||||
|
|||||||
17
src/lib/auth-utils.ts
Normal file
17
src/lib/auth-utils.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { auth } from "@/lib/auth";
|
||||||
|
import type { UserData } from "@/lib/services/auth-server.service";
|
||||||
|
|
||||||
|
export async function getCurrentUser(): Promise<UserData | null> {
|
||||||
|
const session = await auth();
|
||||||
|
|
||||||
|
if (!session?.user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: session.user.id,
|
||||||
|
email: session.user.email,
|
||||||
|
roles: session.user.roles,
|
||||||
|
authenticated: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
61
src/lib/auth.ts
Normal file
61
src/lib/auth.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import NextAuth from "next-auth";
|
||||||
|
import Credentials from "next-auth/providers/credentials";
|
||||||
|
import { AuthServerService } from "@/lib/services/auth-server.service";
|
||||||
|
|
||||||
|
export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||||
|
providers: [
|
||||||
|
Credentials({
|
||||||
|
name: "credentials",
|
||||||
|
credentials: {
|
||||||
|
email: { label: "Email", type: "email" },
|
||||||
|
password: { label: "Password", type: "password" },
|
||||||
|
remember: { label: "Remember me", type: "checkbox" },
|
||||||
|
},
|
||||||
|
async authorize(credentials) {
|
||||||
|
if (!credentials?.email || !credentials?.password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const userData = await AuthServerService.loginUser(
|
||||||
|
credentials.email as string,
|
||||||
|
credentials.password as string
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: userData.id,
|
||||||
|
email: userData.email,
|
||||||
|
roles: userData.roles,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Auth error:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
callbacks: {
|
||||||
|
async jwt({ token, user }) {
|
||||||
|
if (user) {
|
||||||
|
// Convertir le tableau en string pour éviter les problèmes de clonage
|
||||||
|
token.roles = JSON.stringify(user.roles);
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
},
|
||||||
|
async session({ session, token }) {
|
||||||
|
if (token) {
|
||||||
|
session.user.id = token.sub!;
|
||||||
|
// Reconvertir la string en tableau
|
||||||
|
session.user.roles = JSON.parse(token.roles as string);
|
||||||
|
}
|
||||||
|
return session;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pages: {
|
||||||
|
signIn: "/login",
|
||||||
|
},
|
||||||
|
session: {
|
||||||
|
strategy: "jwt",
|
||||||
|
},
|
||||||
|
secret: process.env.NEXTAUTH_SECRET,
|
||||||
|
});
|
||||||
@@ -10,7 +10,14 @@ export function withPageTiming(pageName: string, Component: PageComponent) {
|
|||||||
|
|
||||||
// Ensure params is awaited before using it
|
// Ensure params is awaited before using it
|
||||||
const params = props.params ? await Promise.resolve(props.params) : {};
|
const params = props.params ? await Promise.resolve(props.params) : {};
|
||||||
await DebugService.logPageRender(pageName + JSON.stringify(params), duration);
|
|
||||||
|
// Only log if debug is enabled and user is authenticated
|
||||||
|
try {
|
||||||
|
await DebugService.logPageRender(pageName + JSON.stringify(params), duration);
|
||||||
|
} catch {
|
||||||
|
// Silently fail if user is not authenticated or debug is disabled
|
||||||
|
// This prevents errors on public pages like /login
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|||||||
26
src/lib/middleware-auth.ts
Normal file
26
src/lib/middleware-auth.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { NextRequest } from "next/server";
|
||||||
|
import { getToken } from "next-auth/jwt";
|
||||||
|
|
||||||
|
export async function getAuthSession(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = await getToken({
|
||||||
|
req: request,
|
||||||
|
secret: process.env.NEXTAUTH_SECRET
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: {
|
||||||
|
id: token.sub!,
|
||||||
|
email: token.email!,
|
||||||
|
roles: JSON.parse(token.roles as string),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Auth error in middleware:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { cookies } from "next/headers";
|
|
||||||
import connectDB from "@/lib/mongodb";
|
import connectDB from "@/lib/mongodb";
|
||||||
import { UserModel } from "@/lib/models/user.model";
|
import { UserModel } from "@/lib/models/user.model";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcryptjs";
|
||||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||||
import { AppError } from "../../utils/errors";
|
import { AppError } from "../../utils/errors";
|
||||||
|
|
||||||
@@ -15,7 +14,7 @@ export interface UserData {
|
|||||||
export class AuthServerService {
|
export class AuthServerService {
|
||||||
private static readonly SALT_ROUNDS = 10;
|
private static readonly SALT_ROUNDS = 10;
|
||||||
|
|
||||||
static async createUser(email: string, password: string): Promise<UserData> {
|
static async registerUser(email: string, password: string): Promise<UserData> {
|
||||||
await connectDB();
|
await connectDB();
|
||||||
|
|
||||||
//check if password is strong
|
//check if password is strong
|
||||||
@@ -67,37 +66,6 @@ export class AuthServerService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setUserCookie(userData: UserData, remember: boolean = false): Promise<void> {
|
|
||||||
// Encode user data in base64
|
|
||||||
const encodedUserData = Buffer.from(JSON.stringify(userData)).toString("base64");
|
|
||||||
|
|
||||||
// Set cookie with user data
|
|
||||||
const cookieStore = await cookies();
|
|
||||||
cookieStore.set("stripUser", encodedUserData, {
|
|
||||||
httpOnly: true,
|
|
||||||
secure: process.env.NODE_ENV === "production",
|
|
||||||
sameSite: "lax",
|
|
||||||
path: "/",
|
|
||||||
maxAge: remember ? 30 * 24 * 60 * 60 : 24 * 60 * 60, // 30 days if remember, 24 hours otherwise
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getCurrentUser(): Promise<UserData | null> {
|
|
||||||
const cookieStore = await cookies();
|
|
||||||
const userCookie = cookieStore.get("stripUser");
|
|
||||||
|
|
||||||
if (!userCookie) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return JSON.parse(atob(userCookie.value));
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error while getting user from cookie:", error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async loginUser(email: string, password: string): Promise<UserData> {
|
static async loginUser(email: string, password: string): Promise<UserData> {
|
||||||
await connectDB();
|
await connectDB();
|
||||||
|
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import type { AppErrorType } from "@/types/global";
|
|
||||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
|
||||||
|
|
||||||
class AuthService {
|
|
||||||
private static instance: AuthService;
|
|
||||||
|
|
||||||
// Constructeur privé pour le pattern Singleton
|
|
||||||
private constructor() {
|
|
||||||
// Pas d'initialisation nécessaire
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getInstance(): AuthService {
|
|
||||||
if (!AuthService.instance) {
|
|
||||||
AuthService.instance = new AuthService();
|
|
||||||
}
|
|
||||||
return AuthService.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authentifie un utilisateur
|
|
||||||
*/
|
|
||||||
async login(email: string, password: string, remember: boolean = false): Promise<void> {
|
|
||||||
try {
|
|
||||||
const response = await fetch("/api/auth/login", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ email, password, remember }),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
throw data.error;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if ((error as AppErrorType).code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
throw {
|
|
||||||
code: ERROR_CODES.AUTH.INVALID_CREDENTIALS,
|
|
||||||
name: "Invalid credentials",
|
|
||||||
message: "The email or password is incorrect",
|
|
||||||
} as AppErrorType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crée un nouvel utilisateur
|
|
||||||
*/
|
|
||||||
async register(email: string, password: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
const response = await fetch("/api/auth/register", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ email, password }),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
throw data.error;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if ((error as AppErrorType).code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
throw {
|
|
||||||
code: ERROR_CODES.AUTH.INVALID_USER_DATA,
|
|
||||||
name: "Invalid user data",
|
|
||||||
message: "The email or password is incorrect",
|
|
||||||
} as AppErrorType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Déconnecte l'utilisateur
|
|
||||||
*/
|
|
||||||
async logout(): Promise<void> {
|
|
||||||
try {
|
|
||||||
const response = await fetch("/api/auth/logout", {
|
|
||||||
method: "POST",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
throw data.error;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if ((error as AppErrorType).code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
throw {
|
|
||||||
code: ERROR_CODES.AUTH.LOGOUT_ERROR,
|
|
||||||
name: "Logout error",
|
|
||||||
message: "The logout failed",
|
|
||||||
} as AppErrorType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const authService = AuthService.getInstance();
|
|
||||||
@@ -2,14 +2,14 @@ import connectDB from "@/lib/mongodb";
|
|||||||
import { KomgaConfig as KomgaConfigModel } from "@/lib/models/config.model";
|
import { KomgaConfig as KomgaConfigModel } from "@/lib/models/config.model";
|
||||||
import { TTLConfig as TTLConfigModel } from "@/lib/models/ttl-config.model";
|
import { TTLConfig as TTLConfigModel } from "@/lib/models/ttl-config.model";
|
||||||
import { DebugService } from "./debug.service";
|
import { DebugService } from "./debug.service";
|
||||||
import { AuthServerService } from "./auth-server.service";
|
import { getCurrentUser } from "../auth-utils";
|
||||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||||
import { AppError } from "../../utils/errors";
|
import { AppError } from "../../utils/errors";
|
||||||
import type { User, KomgaConfigData, TTLConfigData, KomgaConfig, TTLConfig } from "@/types/komga";
|
import type { User, KomgaConfigData, TTLConfigData, KomgaConfig, TTLConfig } from "@/types/komga";
|
||||||
|
|
||||||
export class ConfigDBService {
|
export class ConfigDBService {
|
||||||
private static async getCurrentUser(): Promise<User> {
|
private static async getCurrentUser(): Promise<User> {
|
||||||
const user: User | null = await AuthServerService.getCurrentUser();
|
const user: User | null = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import type { CacheType } from "./base-api.service";
|
import type { CacheType } from "./base-api.service";
|
||||||
import { AuthServerService } from "./auth-server.service";
|
|
||||||
import { PreferencesService } from "./preferences.service";
|
import { PreferencesService } from "./preferences.service";
|
||||||
|
import { getCurrentUser } from "../auth-utils";
|
||||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||||
import { AppError } from "../../utils/errors";
|
import { AppError } from "../../utils/errors";
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ export class DebugService {
|
|||||||
private static writeQueues = new Map<string, Promise<void>>();
|
private static writeQueues = new Map<string, Promise<void>>();
|
||||||
|
|
||||||
private static async getCurrentUserId(): Promise<string> {
|
private static async getCurrentUserId(): Promise<string> {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ export class DebugService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static async isDebugEnabled(): Promise<boolean> {
|
private static async isDebugEnabled(): Promise<boolean> {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import connectDB from "@/lib/mongodb";
|
import connectDB from "@/lib/mongodb";
|
||||||
import { FavoriteModel } from "@/lib/models/favorite.model";
|
import { FavoriteModel } from "@/lib/models/favorite.model";
|
||||||
import { DebugService } from "./debug.service";
|
import { DebugService } from "./debug.service";
|
||||||
import { AuthServerService } from "./auth-server.service";
|
import { getCurrentUser } from "../auth-utils";
|
||||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||||
import { AppError } from "../../utils/errors";
|
import { AppError } from "../../utils/errors";
|
||||||
import type { User } from "@/types/komga";
|
import type { User } from "@/types/komga";
|
||||||
@@ -17,7 +17,7 @@ export class FavoriteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static async getCurrentUser(): Promise<User> {
|
private static async getCurrentUser(): Promise<User> {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { PreferencesModel } from "@/lib/models/preferences.model";
|
import { PreferencesModel } from "@/lib/models/preferences.model";
|
||||||
import { AuthServerService } from "./auth-server.service";
|
import { getCurrentUser } from "../auth-utils";
|
||||||
import { ERROR_CODES } from "../../constants/errorCodes";
|
import { ERROR_CODES } from "../../constants/errorCodes";
|
||||||
import { AppError } from "../../utils/errors";
|
import { AppError } from "../../utils/errors";
|
||||||
import type { UserPreferences } from "@/types/preferences";
|
import type { UserPreferences } from "@/types/preferences";
|
||||||
@@ -9,7 +9,7 @@ import connectDB from "@/lib/mongodb";
|
|||||||
|
|
||||||
export class PreferencesService {
|
export class PreferencesService {
|
||||||
static async getCurrentUser(): Promise<User> {
|
static async getCurrentUser(): Promise<User> {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class RequestMonitor {
|
|||||||
} else if (count >= this.thresholds.high) {
|
} else if (count >= this.thresholds.high) {
|
||||||
console.warn(`[REQUEST-MONITOR] ⚠️ HIGH concurrency: ${count} active requests`);
|
console.warn(`[REQUEST-MONITOR] ⚠️ HIGH concurrency: ${count} active requests`);
|
||||||
} else if (count >= this.thresholds.warning) {
|
} else if (count >= this.thresholds.warning) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(`[REQUEST-MONITOR] ⚡ Warning concurrency: ${count} active requests`);
|
console.log(`[REQUEST-MONITOR] ⚡ Warning concurrency: ${count} active requests`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import fs from "fs";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { PreferencesService } from "./preferences.service";
|
import { PreferencesService } from "./preferences.service";
|
||||||
import { DebugService } from "./debug.service";
|
import { DebugService } from "./debug.service";
|
||||||
import { AuthServerService } from "./auth-server.service";
|
import { getCurrentUser } from "../auth-utils";
|
||||||
|
|
||||||
export type CacheMode = "file" | "memory";
|
export type CacheMode = "file" | "memory";
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class ServerCacheService {
|
|||||||
|
|
||||||
private async initializeCacheMode(): Promise<void> {
|
private async initializeCacheMode(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
this.setCacheMode("memory");
|
this.setCacheMode("memory");
|
||||||
return;
|
return;
|
||||||
@@ -293,7 +293,7 @@ class ServerCacheService {
|
|||||||
* Supprime une entrée du cache
|
* Supprime une entrée du cache
|
||||||
*/
|
*/
|
||||||
async delete(key: string): Promise<void> {
|
async delete(key: string): Promise<void> {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error("Utilisateur non authentifié");
|
throw new Error("Utilisateur non authentifié");
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ class ServerCacheService {
|
|||||||
* Supprime toutes les entrées du cache qui commencent par un préfixe
|
* Supprime toutes les entrées du cache qui commencent par un préfixe
|
||||||
*/
|
*/
|
||||||
async deleteAll(prefix: string): Promise<void> {
|
async deleteAll(prefix: string): Promise<void> {
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error("Utilisateur non authentifié");
|
throw new Error("Utilisateur non authentifié");
|
||||||
}
|
}
|
||||||
@@ -390,7 +390,7 @@ class ServerCacheService {
|
|||||||
type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT"
|
type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT"
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const startTime = performance.now();
|
const startTime = performance.now();
|
||||||
const user = await AuthServerService.getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error("Utilisateur non authentifié");
|
throw new Error("Utilisateur non authentifié");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,32 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse, NextRequest } from "next/server";
|
||||||
import type { NextRequest } from "next/server";
|
import { getAuthSession } from "@/lib/middleware-auth";
|
||||||
import { ERROR_CODES } from "./constants/errorCodes";
|
|
||||||
import type { UserData } from "./lib/services/auth-server.service";
|
|
||||||
import { getErrorMessage } from "./utils/errors";
|
|
||||||
|
|
||||||
// Routes qui ne nécessitent pas d'authentification
|
// Routes qui ne nécessitent pas d'authentification
|
||||||
const publicRoutes = ["/login", "/register", "/images"];
|
const publicRoutes = ["/login", "/register", "/images"];
|
||||||
|
|
||||||
// Routes d'API qui ne nécessitent pas d'authentification
|
// Routes d'API qui ne nécessitent pas d'authentification
|
||||||
const publicApiRoutes = ["/api/auth/login", "/api/auth/register", "/api/komga/test"];
|
const publicApiRoutes = ["/api/auth/register", "/api/komga/test"];
|
||||||
|
|
||||||
// Langues supportées
|
// Langues supportées
|
||||||
const locales = ["fr", "en"];
|
const locales = ["fr", "en"];
|
||||||
const defaultLocale = "fr";
|
const defaultLocale = "fr";
|
||||||
|
|
||||||
export function middleware(request: NextRequest) {
|
export default async function middleware(request: NextRequest) {
|
||||||
const { pathname } = request.nextUrl;
|
const { pathname } = request.nextUrl;
|
||||||
|
|
||||||
// Gestion de la langue
|
// Gestion de la langue
|
||||||
let locale = request.cookies.get("NEXT_LOCALE")?.value;
|
let locale = request.headers.get("cookie")?.match(/NEXT_LOCALE=([^;]+)/)?.[1];
|
||||||
|
|
||||||
// Si pas de cookie de langue ou langue non supportée, on utilise la langue par défaut
|
// Si pas de cookie de langue ou langue non supportée, on utilise la langue par défaut
|
||||||
if (!locale || !locales.includes(locale)) {
|
if (!locale || !locales.includes(locale)) {
|
||||||
locale = defaultLocale;
|
locale = defaultLocale;
|
||||||
|
|
||||||
// On s'assure que la réponse est bien une redirection si nécessaire
|
|
||||||
const response =
|
|
||||||
pathname === "/login"
|
|
||||||
? NextResponse.next()
|
|
||||||
: NextResponse.redirect(new URL("/login", request.url));
|
|
||||||
|
|
||||||
response.cookies.set("NEXT_LOCALE", locale, {
|
|
||||||
path: "/",
|
|
||||||
maxAge: 365 * 24 * 60 * 60, // 1 an
|
|
||||||
secure: true, // Ajout de secure pour HTTPS
|
|
||||||
sameSite: "lax", // Protection CSRF
|
|
||||||
});
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestion de l'authentification
|
|
||||||
const user = request.cookies.get("stripUser");
|
|
||||||
|
|
||||||
// Vérifier si c'est une route publique avant de gérer l'authentification
|
// Vérifier si c'est une route publique avant de gérer l'authentification
|
||||||
if (
|
if (
|
||||||
publicRoutes.includes(pathname) ||
|
publicRoutes.includes(pathname) ||
|
||||||
publicApiRoutes.includes(pathname) ||
|
publicApiRoutes.includes(pathname) ||
|
||||||
|
pathname.startsWith("/api/auth/") ||
|
||||||
pathname.startsWith("/images/") ||
|
pathname.startsWith("/images/") ||
|
||||||
pathname.startsWith("/_next/") ||
|
pathname.startsWith("/_next/") ||
|
||||||
pathname.startsWith("/fonts/")
|
pathname.startsWith("/fonts/")
|
||||||
@@ -54,14 +34,16 @@ export function middleware(request: NextRequest) {
|
|||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pour toutes les routes protégées, vérifier la présence de l'utilisateur
|
// Vérifier l'authentification avec NextAuth v5
|
||||||
if (!user?.value) {
|
const session = await getAuthSession(request);
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
if (pathname.startsWith("/api/")) {
|
if (pathname.startsWith("/api/")) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
error: {
|
error: {
|
||||||
code: ERROR_CODES.MIDDLEWARE.UNAUTHORIZED,
|
code: "UNAUTHORIZED",
|
||||||
message: getErrorMessage(ERROR_CODES.MIDDLEWARE.UNAUTHORIZED),
|
message: "Unauthorized access",
|
||||||
name: "Unauthorized",
|
name: "Unauthorized",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -70,35 +52,21 @@ export function middleware(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loginUrl = new URL("/login", request.url);
|
const loginUrl = new URL("/login", request.url);
|
||||||
// loginUrl.searchParams.set("from", encodeURIComponent(pathname));
|
|
||||||
return NextResponse.redirect(loginUrl);
|
return NextResponse.redirect(loginUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Définir le cookie de langue si nécessaire
|
||||||
const userData: UserData = JSON.parse(atob(user.value));
|
const response = NextResponse.next();
|
||||||
if (!userData || !userData.authenticated || !userData.id || !userData.email) {
|
if (!request.headers.get("cookie")?.includes("NEXT_LOCALE") && locale) {
|
||||||
throw new Error(getErrorMessage(ERROR_CODES.MIDDLEWARE.INVALID_SESSION));
|
response.cookies.set("NEXT_LOCALE", locale, {
|
||||||
}
|
path: "/",
|
||||||
} catch (error) {
|
maxAge: 365 * 24 * 60 * 60, // 1 an
|
||||||
console.error("Erreur de validation du cookie:", error);
|
secure: true, // Ajout de secure pour HTTPS
|
||||||
if (pathname.startsWith("/api/")) {
|
sameSite: "lax", // Protection CSRF
|
||||||
return NextResponse.json(
|
});
|
||||||
{
|
|
||||||
error: {
|
|
||||||
code: ERROR_CODES.MIDDLEWARE.INVALID_TOKEN,
|
|
||||||
message: getErrorMessage(ERROR_CODES.MIDDLEWARE.INVALID_TOKEN),
|
|
||||||
name: "Invalid token",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ status: 401 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const loginUrl = new URL("/login", request.url);
|
|
||||||
// loginUrl.searchParams.set("from", pathname);
|
|
||||||
return NextResponse.redirect(loginUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.next();
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration des routes à protéger
|
// Configuration des routes à protéger
|
||||||
@@ -106,12 +74,12 @@ export const config = {
|
|||||||
matcher: [
|
matcher: [
|
||||||
/*
|
/*
|
||||||
* Match all request paths except:
|
* Match all request paths except:
|
||||||
* 1. /api/auth/* (authentication routes)
|
* 1. /api/auth/* (NextAuth routes)
|
||||||
* 2. /_next/* (Next.js internals)
|
* 2. /_next/* (Next.js internals)
|
||||||
* 3. /fonts/* (inside public directory)
|
* 3. /fonts/* (inside public directory)
|
||||||
* 4. /images/* (inside public directory)
|
* 4. /images/* (inside public directory)
|
||||||
* 5. Static files (manifest.json, favicon.ico, etc.)
|
* 5. Static files (manifest.json, favicon.ico, etc.)
|
||||||
*/
|
*/
|
||||||
"/((?!api/auth/*|_next/static|_next/image|fonts|images|manifest.json|favicon.ico|sitemap.xml|sw.js|offline.html).*)",
|
"/((?!api/auth|_next/static|_next/image|fonts|images|manifest.json|favicon.ico|sitemap.xml|sw.js|offline.html).*)",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
23
src/types/next-auth.d.ts
vendored
Normal file
23
src/types/next-auth.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import type { DefaultSession } from "next-auth";
|
||||||
|
|
||||||
|
declare module "next-auth" {
|
||||||
|
interface Session {
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
roles: string[];
|
||||||
|
} & DefaultSession["user"];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
roles: string[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "next-auth/jwt" {
|
||||||
|
interface JWT {
|
||||||
|
roles: string; // Stocké comme string JSON
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user