From 7426bfb33c83444c65ae2bd56aa61eb0e9083833 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Thu, 16 Oct 2025 15:50:37 +0200 Subject: [PATCH] feat: integrate NextAuth for authentication, refactor login and registration processes, and enhance middleware for session management --- ENV.md | 24 + docker-compose.dev.yml | 2 + docker-compose.yml | 2 + package.json | 6 +- pnpm-lock.yaml | 426 +++--------------- src/app/api/auth/[...nextauth]/route.ts | 3 + src/app/api/auth/login/route.ts | 44 -- src/app/api/auth/logout/route.ts | 27 -- src/app/api/auth/register/route.ts | 68 +-- src/app/layout.tsx | 17 +- src/components/auth/LoginForm.tsx | 32 +- src/components/auth/RegisterForm.tsx | 59 ++- src/components/layout/Sidebar.tsx | 10 +- .../library/PaginatedSeriesGrid.tsx | 12 +- src/components/providers/AuthProvider.tsx | 12 + .../reader/components/ZoomablePage.tsx | 4 - src/components/series/PaginatedBookGrid.tsx | 8 +- src/constants/errorCodes.ts | 1 + src/constants/errorMessages.ts | 1 + src/lib/auth-utils.ts | 17 + src/lib/auth.ts | 61 +++ src/lib/hoc/withPageTiming.tsx | 9 +- src/lib/middleware-auth.ts | 26 ++ src/lib/services/auth-server.service.ts | 36 +- src/lib/services/auth.service.ts | 105 ----- src/lib/services/config-db.service.ts | 4 +- src/lib/services/debug.service.ts | 6 +- src/lib/services/favorite.service.ts | 4 +- src/lib/services/preferences.service.ts | 4 +- src/lib/services/request-monitor.service.ts | 1 + src/lib/services/server-cache.service.ts | 10 +- src/middleware.ts | 82 +--- src/types/next-auth.d.ts | 23 + 33 files changed, 417 insertions(+), 729 deletions(-) create mode 100644 ENV.md create mode 100644 src/app/api/auth/[...nextauth]/route.ts delete mode 100644 src/app/api/auth/login/route.ts delete mode 100644 src/app/api/auth/logout/route.ts create mode 100644 src/components/providers/AuthProvider.tsx create mode 100644 src/lib/auth-utils.ts create mode 100644 src/lib/auth.ts create mode 100644 src/lib/middleware-auth.ts delete mode 100644 src/lib/services/auth.service.ts create mode 100644 src/types/next-auth.d.ts diff --git a/ENV.md b/ENV.md new file mode 100644 index 0000000..58f1e2d --- /dev/null +++ b/ENV.md @@ -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`. diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 7436fd5..7492333 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -29,6 +29,8 @@ services: - MONGODB_URI=mongodb://admin:password123@mongodb:27017/stripstream?authSource=admin - PNPM_HOME=/app/.pnpm-store - 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" mongodb: diff --git a/docker-compose.yml b/docker-compose.yml index a80c9f5..11a25f9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,8 @@ services: environment: - NODE_ENV=production - MONGODB_URI=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@mongodb:27017/stripstream?authSource=admin + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} + - NEXTAUTH_URL=${NEXTAUTH_URL} depends_on: - mongodb networks: diff --git a/package.json b/package.json index 785a8f1..cae38da 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,9 @@ "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-slot": "1.0.2", "@radix-ui/react-toast": "1.1.5", - "@types/bcrypt": "^5.0.2", + "@types/bcryptjs": "^3.0.0", "@types/mongoose": "5.11.97", - "bcrypt": "^5.1.1", + "bcryptjs": "^3.0.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "framer-motion": "^10.18.0", @@ -28,7 +28,7 @@ "lucide-react": "^0.487.0", "mongoose": "8.1.0", "next": "15.2.0", - "next-auth": "4.24.5", + "next-auth": "5.0.0-beta.29", "next-themes": "0.2.1", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e749ab9..1f12c6c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,15 +26,15 @@ importers: '@radix-ui/react-toast': 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) - '@types/bcrypt': - specifier: ^5.0.2 - version: 5.0.2 + '@types/bcryptjs': + specifier: ^3.0.0 + version: 3.0.0 '@types/mongoose': specifier: 5.11.97 version: 5.11.97 - bcrypt: - specifier: ^5.1.1 - version: 5.1.1 + bcryptjs: + specifier: ^3.0.2 + version: 3.0.2 class-variance-authority: specifier: ^0.7.0 version: 0.7.1 @@ -60,8 +60,8 @@ importers: specifier: 15.2.0 version: 15.2.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) next-auth: - specifier: 4.24.5 - 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) + specifier: 5.0.0-beta.29 + 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: 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) @@ -142,6 +142,20 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 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': resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} @@ -445,10 +459,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': 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': resolution: {integrity: sha512-6nZrq5kfAz0POWyhljnbWQQJQ5uT8oE2ddX303q1uY0tWsivWKgBDXBBvuFPwOqRRalXJuVO9EjOdVtuhLX0zg==} @@ -1065,8 +1075,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@types/bcrypt@5.0.2': - resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==} + '@types/bcryptjs@3.0.0': + 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': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1316,9 +1327,6 @@ packages: cpu: [x64] os: [win32] - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1329,10 +1337,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1359,14 +1363,6 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 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: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1450,9 +1446,9 @@ packages: resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==} hasBin: true - bcrypt@5.1.1: - resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} - engines: {node: '>= 10.0.0'} + bcryptjs@3.0.2: + resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==} + hasBin: true binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} @@ -1512,10 +1508,6 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -1536,10 +1528,6 @@ packages: color-string@1.9.1: 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: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -1551,13 +1539,6 @@ packages: concat-map@0.0.1: 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: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1613,9 +1594,6 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -1910,10 +1888,6 @@ packages: react-dom: optional: true - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1932,11 +1906,6 @@ packages: functions-have-names@1.2.3: 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: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} @@ -2018,9 +1987,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -2028,10 +1994,6 @@ packages: html-parse-stringify@3.0.1: 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: resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==} @@ -2205,8 +2167,8 @@ packages: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true - jose@4.15.9: - resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + jose@6.1.0: + resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2278,19 +2240,11 @@ packages: lru-cache@10.4.3: 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: resolution: {integrity: sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==} peerDependencies: 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: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -2320,27 +2274,10 @@ packages: minimist@1.2.8: 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: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 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: resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==} @@ -2405,14 +2342,19 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - next-auth@4.24.5: - resolution: {integrity: sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og==} + next-auth@5.0.0-beta.29: + resolution: {integrity: sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A==} 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 - react: ^17.0.2 || ^18 - react-dom: ^17.0.2 || ^18 + react: ^18.2.0 || ^19.0.0-0 peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true nodemailer: optional: true @@ -2444,26 +2386,9 @@ packages: sass: 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: 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: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2472,21 +2397,13 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} - npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - deprecated: This package is no longer supported. - - oauth@0.9.15: - resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + oauth4webapi@3.8.2: + resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-hash@2.2.0: - resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} - engines: {node: '>= 6'} - object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -2519,16 +2436,9 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} 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: 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: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2643,21 +2553,18 @@ packages: resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} engines: {node: ^10 || ^12 || >=14} - preact-render-to-string@5.2.6: - resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} + preact-render-to-string@6.5.11: + resolution: {integrity: sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==} peerDependencies: preact: '>=10' - preact@10.27.2: - resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} + preact@10.24.3: + resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - pretty-format@3.8.0: - resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} - prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -2746,10 +2653,6 @@ packages: read-cache@1.0.0: 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: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2794,9 +2697,6 @@ packages: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -2817,9 +2717,6 @@ packages: engines: {node: '>=10'} hasBin: true - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2867,9 +2764,6 @@ packages: sift@16.0.1: 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: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2930,9 +2824,6 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2988,10 +2879,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -3010,9 +2897,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} @@ -3122,17 +3006,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - void-elements@3.1.0: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} engines: {node: '>=0.10.0'} - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -3141,9 +3018,6 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -3165,9 +3039,6 @@ packages: engines: {node: '>= 8'} hasBin: true - wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -3183,9 +3054,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@2.8.1: resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} engines: {node: '>= 14.6'} @@ -3202,6 +3070,14 @@ snapshots: '@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': {} '@emnapi/core@1.5.0': @@ -3458,21 +3334,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@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': dependencies: sparse-bitfield: 3.0.3 @@ -4039,9 +3900,9 @@ snapshots: tslib: 2.8.1 optional: true - '@types/bcrypt@5.0.2': + '@types/bcryptjs@3.0.0': dependencies: - '@types/node': 24.7.2 + bcryptjs: 3.0.2 '@types/json-schema@7.0.15': {} @@ -4317,20 +4178,12 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - abbrev@1.1.1: {} - acorn-jsx@5.3.2(acorn@8.15.0): dependencies: 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: dependencies: fast-deep-equal: 3.1.3 @@ -4355,13 +4208,6 @@ snapshots: normalize-path: 3.0.0 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: {} argparse@2.0.1: {} @@ -4467,13 +4313,7 @@ snapshots: baseline-browser-mapping@2.8.16: {} - bcrypt@5.1.1: - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - node-addon-api: 5.1.0 - transitivePeerDependencies: - - encoding - - supports-color + bcryptjs@3.0.2: {} binary-extensions@2.3.0: {} @@ -4544,8 +4384,6 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chownr@2.0.0: {} - class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -4565,8 +4403,6 @@ snapshots: color-name: 1.1.4 simple-swizzle: 0.2.4 - color-support@1.1.3: {} - color@4.2.3: dependencies: color-convert: 2.0.1 @@ -4576,10 +4412,6 @@ snapshots: concat-map@0.0.1: {} - console-control-strings@1.1.0: {} - - cookie@0.5.0: {} - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4632,8 +4464,6 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - delegates@1.0.0: {} - detect-libc@2.1.2: {} detect-node-es@1.1.0: {} @@ -5069,10 +4899,6 @@ snapshots: 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: {} fsevents@2.3.3: @@ -5091,18 +4917,6 @@ snapshots: 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: {} get-intrinsic@1.3.0: @@ -5201,8 +5015,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - has-unicode@2.0.1: {} - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -5211,13 +5023,6 @@ snapshots: dependencies: 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: dependencies: '@babel/runtime': 7.28.4 @@ -5395,7 +5200,7 @@ snapshots: jiti@1.21.7: {} - jose@4.15.9: {} + jose@6.1.0: {} js-tokens@4.0.0: {} @@ -5457,18 +5262,10 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - lucide-react@0.487.0(react@18.2.0): dependencies: react: 18.2.0 - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - math-intrinsics@1.1.0: {} memory-pager@1.5.0: {} @@ -5494,21 +5291,8 @@ snapshots: minimist@1.2.8: {} - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - - minipass@5.0.0: {} - 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: dependencies: '@types/whatwg-url': 11.0.5 @@ -5563,20 +5347,11 @@ snapshots: 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: - '@babel/runtime': 7.28.4 - '@panva/hkdf': 1.2.1 - cookie: 0.5.0 - jose: 4.15.9 + '@auth/core': 0.40.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-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): dependencies: @@ -5609,35 +5384,16 @@ snapshots: - '@babel/core' - 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: {} - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - normalize-path@3.0.0: {} normalize-range@0.1.2: {} - npmlog@5.0.1: - 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: {} + oauth4webapi@3.8.2: {} object-assign@4.1.1: {} - object-hash@2.2.0: {} - object-hash@3.0.0: {} object-inspect@1.13.4: {} @@ -5680,19 +5436,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - oidc-token-hash@5.1.1: {} - once@1.4.0: dependencies: 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: dependencies: deep-is: 0.1.4 @@ -5792,17 +5539,14 @@ snapshots: picocolors: 1.1.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: - preact: 10.27.2 - pretty-format: 3.8.0 + preact: 10.24.3 - preact@10.27.2: {} + preact@10.24.3: {} prelude-ls@1.2.1: {} - pretty-format@3.8.0: {} - prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -5882,12 +5626,6 @@ snapshots: dependencies: 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: dependencies: picomatch: 2.3.1 @@ -5946,8 +5684,6 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 - safe-buffer@5.2.1: {} - safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -5967,8 +5703,6 @@ snapshots: semver@7.7.3: {} - set-blocking@2.0.0: {} - set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -6080,8 +5814,6 @@ snapshots: sift@16.0.1: {} - signal-exit@3.0.7: {} - signal-exit@4.1.0: {} simple-swizzle@0.2.4: @@ -6167,10 +5899,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -6237,15 +5965,6 @@ snapshots: transitivePeerDependencies: - 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: {} thenify-all@1.6.0: @@ -6265,8 +5984,6 @@ snapshots: dependencies: is-number: 7.0.0 - tr46@0.0.3: {} - tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -6400,12 +6117,8 @@ snapshots: util-deprecate@1.0.2: {} - uuid@8.3.2: {} - void-elements@3.1.0: {} - webidl-conversions@3.0.1: {} - webidl-conversions@7.0.0: {} whatwg-url@14.2.0: @@ -6413,11 +6126,6 @@ snapshots: tr46: 5.1.1 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: dependencies: is-bigint: 1.1.0 @@ -6463,10 +6171,6 @@ snapshots: dependencies: isexe: 2.0.0 - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - word-wrap@1.2.5: {} wrap-ansi@7.0.0: @@ -6483,8 +6187,6 @@ snapshots: wrappy@1.0.2: {} - yallist@4.0.0: {} - yaml@2.8.1: {} yocto-queue@0.1.0: {} diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..879310b --- /dev/null +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,3 @@ +import { handlers } from "@/lib/auth"; + +export const { GET, POST } = handlers; \ No newline at end of file diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts deleted file mode 100644 index ed41ade..0000000 --- a/src/app/api/auth/login/route.ts +++ /dev/null @@ -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 } - ); - } -} diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts deleted file mode 100644 index 9cceaa3..0000000 --- a/src/app/api/auth/logout/route.ts +++ /dev/null @@ -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 } - ); - } -} diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 12baf9f..524b9a2 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -1,48 +1,52 @@ -import { NextResponse } from "next/server"; -import type { UserData } from "@/lib/services/auth-server.service"; +import { NextRequest, NextResponse } from "next/server"; import { AuthServerService } from "@/lib/services/auth-server.service"; import { ERROR_CODES } from "@/constants/errorCodes"; +import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { AppError } from "@/utils/errors"; -import { getErrorMessage } from "@/utils/errors"; -import type { NextRequest } from "next/server"; export async function POST(request: NextRequest) { try { const { email, password } = await request.json(); - try { - const userData: UserData = await AuthServerService.createUser(email, password); - await AuthServerService.setUserCookie(userData); - - return NextResponse.json({ - message: "✅ Inscription réussie", - user: userData, - }); - } catch (error) { - if (error instanceof AppError) { - 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; + if (!email || !password) { + return NextResponse.json( + { + error: { + code: ERROR_CODES.AUTH.INVALID_USER_DATA, + name: "Invalid user data", + message: ERROR_MESSAGES[ERROR_CODES.AUTH.INVALID_USER_DATA], + } as AppError, + }, + { status: 400 } + ); } + + const userData = await AuthServerService.registerUser(email, password); + + return NextResponse.json({ success: true, user: userData }); } 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( { error: { - code: ERROR_CODES.AUTH.INVALID_USER_DATA, - name: "Invalid user data", - message: getErrorMessage(ERROR_CODES.AUTH.INVALID_USER_DATA), - }, + code: ERROR_CODES.AUTH.REGISTRATION_FAILED, + name: "Registration failed", + message: ERROR_MESSAGES[ERROR_CODES.AUTH.REGISTRATION_FAILED], + } as AppError, }, { status: 500 } ); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index d416478..4a79765 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,6 +6,7 @@ import ClientLayout from "@/components/layout/ClientLayout"; import { PreferencesService } from "@/lib/services/preferences.service"; import { PreferencesProvider } from "@/contexts/PreferencesContext"; import { I18nProvider } from "@/components/providers/I18nProvider"; +import { AuthProvider } from "@/components/providers/AuthProvider"; import "@/i18n/i18n"; // Import i18next configuration import { cookies } from "next/headers"; import { defaultPreferences } from "@/types/preferences"; @@ -158,13 +159,15 @@ export default async function RootLayout({ children }: { children: React.ReactNo - - - - {children} - - - + + + + + {children} + + + + ); diff --git a/src/components/auth/LoginForm.tsx b/src/components/auth/LoginForm.tsx index 88edc92..2825d1f 100644 --- a/src/components/auth/LoginForm.tsx +++ b/src/components/auth/LoginForm.tsx @@ -2,9 +2,7 @@ import { useState } from "react"; import { useRouter } from "next/navigation"; -import { authService } from "@/lib/services/auth.service"; -import type { AppErrorType } from "@/types/global"; -import { ErrorMessage } from "@/components/ui/ErrorMessage"; +import { signIn } from "next-auth/react"; import { useTranslate } from "@/hooks/useTranslate"; interface LoginFormProps { @@ -14,7 +12,7 @@ interface LoginFormProps { export function LoginForm({ from }: LoginFormProps) { const router = useRouter(); const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); + const [error, setError] = useState(null); const { t } = useTranslate(); const handleSubmit = async (event: React.FormEvent) => { @@ -28,11 +26,21 @@ export function LoginForm({ from }: LoginFormProps) { const remember = formData.get("remember") === "on"; try { - await authService.login(email, password, remember); - router.push(from || "/"); - router.refresh(); - } catch (error) { - setError(error as AppErrorType); + const result = await signIn("credentials", { + email, + password, + remember, + 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 { setIsLoading(false); } @@ -89,7 +97,11 @@ export function LoginForm({ from }: LoginFormProps) { {t("login.form.remember")} - {error && } + {error && ( +
+ {error} +
+ )}