diff --git a/package-lock.json b/package-lock.json index eefe19c..e7b4651 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "date-fns": "^4.1.0", "leaflet": "^1.9.4", "next": "15.1.8", - "next-auth": "^4.24.11", + "next-auth": "^5.0.0-beta.29", "proj4": "^2.19.3", "proj4leaflet": "^1.0.2", "react": "^19.0.0", @@ -71,6 +71,35 @@ "node": ">=6.0.0" } }, + "node_modules/@auth/core": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.40.0.tgz", + "integrity": "sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==", + "license": "ISC", + "dependencies": { + "@panva/hkdf": "^1.2.1", + "jose": "^6.0.6", + "oauth4webapi": "^3.3.0", + "preact": "10.24.3", + "preact-render-to-string": "6.5.11" + }, + "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 + } + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -1919,6 +1948,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -3930,14 +3960,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -7204,9 +7226,10 @@ } }, "node_modules/jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.0.11.tgz", + "integrity": "sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -7756,29 +7779,25 @@ } }, "node_modules/next-auth": { - "version": "4.24.11", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz", - "integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==", + "version": "5.0.0-beta.29", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.29.tgz", + "integrity": "sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A==", + "license": "ISC", "dependencies": { - "@babel/runtime": "^7.20.13", - "@panva/hkdf": "^1.0.2", - "cookie": "^0.7.0", - "jose": "^4.15.5", - "oauth": "^0.9.15", - "openid-client": "^5.4.0", - "preact": "^10.6.3", - "preact-render-to-string": "^5.1.19", - "uuid": "^8.3.2" + "@auth/core": "0.40.0" }, "peerDependencies": { - "@auth/core": "0.34.2", - "next": "^12.2.5 || ^13 || ^14 || ^15", + "@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 || ^19", - "react-dom": "^17.0.2 || ^18 || ^19" + "react": "^18.2.0 || ^19.0.0-0" }, "peerDependenciesMeta": { - "@auth/core": { + "@simplewebauthn/browser": { + "optional": true + }, + "@simplewebauthn/server": { "optional": true }, "nodemailer": { @@ -7867,10 +7886,14 @@ "dev": true, "license": "MIT" }, - "node_modules/oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + "node_modules/oauth4webapi": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.5.3.tgz", + "integrity": "sha512-2bnHosmBLAQpXNBLOvaJMyMkr4Yya5ohE5Q9jqyxiN+aa7GFCzvDN1RRRMrp0NkfqRR2MTaQNkcSUCCjILD9oQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } }, "node_modules/object-assign": { "version": "4.1.1", @@ -7995,14 +8018,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oidc-token-hash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz", - "integrity": "sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==", - "engines": { - "node": "^10.13.0 || >=12.0.0" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8027,44 +8042,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openid-client": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", - "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", - "dependencies": { - "jose": "^4.15.9", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/openid-client/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/openid-client/node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/openid-client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -8522,30 +8499,24 @@ "dev": true }, "node_modules/preact": { - "version": "10.26.9", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.9.tgz", - "integrity": "sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==", + "version": "10.24.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", + "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" } }, "node_modules/preact-render-to-string": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", - "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", - "dependencies": { - "pretty-format": "^3.8.0" - }, + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz", + "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==", + "license": "MIT", "peerDependencies": { "preact": ">=10" } }, - "node_modules/preact-render-to-string/node_modules/pretty-format": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", - "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" - }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -10465,14 +10436,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -11015,6 +10978,18 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "@auth/core": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.40.0.tgz", + "integrity": "sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==", + "requires": { + "@panva/hkdf": "^1.2.1", + "jose": "^6.0.6", + "oauth4webapi": "^3.3.0", + "preact": "10.24.3", + "preact-render-to-string": "6.5.11" + } + }, "@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -13596,11 +13571,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - }, "create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -15912,9 +15882,9 @@ "dev": true }, "jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==" + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.0.11.tgz", + "integrity": "sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==" }, "js-tokens": { "version": "4.0.0", @@ -16307,19 +16277,11 @@ } }, "next-auth": { - "version": "4.24.11", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz", - "integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==", + "version": "5.0.0-beta.29", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.29.tgz", + "integrity": "sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A==", "requires": { - "@babel/runtime": "^7.20.13", - "@panva/hkdf": "^1.0.2", - "cookie": "^0.7.0", - "jose": "^4.15.5", - "oauth": "^0.9.15", - "openid-client": "^5.4.0", - "preact": "^10.6.3", - "preact-render-to-string": "^5.1.19", - "uuid": "^8.3.2" + "@auth/core": "0.40.0" } }, "node-abi": { @@ -16363,10 +16325,10 @@ "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", "dev": true }, - "oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + "oauth4webapi": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.5.3.tgz", + "integrity": "sha512-2bnHosmBLAQpXNBLOvaJMyMkr4Yya5ohE5Q9jqyxiN+aa7GFCzvDN1RRRMrp0NkfqRR2MTaQNkcSUCCjILD9oQ==" }, "object-assign": { "version": "4.1.1", @@ -16452,11 +16414,6 @@ "es-object-atoms": "^1.0.0" } }, - "oidc-token-hash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz", - "integrity": "sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==" - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -16474,37 +16431,6 @@ "mimic-fn": "^2.1.0" } }, - "openid-client": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", - "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", - "requires": { - "jose": "^4.15.9", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, "optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -16795,24 +16721,15 @@ "dev": true }, "preact": { - "version": "10.26.9", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.9.tgz", - "integrity": "sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==" + "version": "10.24.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", + "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==" }, "preact-render-to-string": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", - "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", - "requires": { - "pretty-format": "^3.8.0" - }, - "dependencies": { - "pretty-format": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", - "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" - } - } + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz", + "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==", + "requires": {} }, "prebuild-install": { "version": "7.1.3", @@ -18136,11 +18053,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, "v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", diff --git a/package.json b/package.json index c998b7e..16cf266 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "date-fns": "^4.1.0", "leaflet": "^1.9.4", "next": "15.1.8", - "next-auth": "^4.24.11", + "next-auth": "^5.0.0-beta.29", "proj4": "^2.19.3", "proj4leaflet": "^1.0.2", "react": "^19.0.0", diff --git a/scripts/create-admin.js b/scripts/create-admin.js index 3f487f4..5da9828 100644 --- a/scripts/create-admin.js +++ b/scripts/create-admin.js @@ -10,13 +10,13 @@ async function createInitialAdmin() { const adminUser = await createUser({ name: "Administrator", - email: "admin@localhost", + email: "admin@localhost.com", password: "admin123456", // Change this in production! role: "admin" }) console.log("ā Initial admin user created successfully!") - console.log("š§ Email: admin@localhost") + console.log("š§ Email: admin@localhost.com") console.log("š Password: admin123456") console.log("ā ļø Please change the password after first login!") console.log("š¤ User ID:", adminUser.id) diff --git a/src/app/api/all-project-tasks/route.js b/src/app/api/all-project-tasks/route.js index 0ed991d..5d645b1 100644 --- a/src/app/api/all-project-tasks/route.js +++ b/src/app/api/all-project-tasks/route.js @@ -1,8 +1,9 @@ import { getAllProjectTasks } from "@/lib/queries/tasks"; import { NextResponse } from "next/server"; +import { withReadAuth } from "@/lib/middleware/auth"; // GET: Get all project tasks across all projects -export async function GET() { +async function getAllProjectTasksHandler() { try { const tasks = getAllProjectTasks(); return NextResponse.json(tasks); @@ -13,3 +14,6 @@ export async function GET() { ); } } + +// Protected routes - require authentication +export const GET = withReadAuth(getAllProjectTasksHandler); diff --git a/src/app/api/auth/[...nextauth]/route.js b/src/app/api/auth/[...nextauth]/route.js index 59a8046..866b2be 100644 --- a/src/app/api/auth/[...nextauth]/route.js +++ b/src/app/api/auth/[...nextauth]/route.js @@ -1,4 +1,3 @@ -import NextAuth from "@/lib/auth" +import { handlers } from "@/lib/auth" -export const GET = NextAuth -export const POST = NextAuth +export const { GET, POST } = handlers diff --git a/src/app/api/contracts/[id]/route.js b/src/app/api/contracts/[id]/route.js index eae30af..0dd9410 100644 --- a/src/app/api/contracts/[id]/route.js +++ b/src/app/api/contracts/[id]/route.js @@ -1,7 +1,8 @@ import db from "@/lib/db"; import { NextResponse } from "next/server"; +import { withReadAuth, withUserAuth } from "@/lib/middleware/auth"; -export async function GET(req, { params }) { +async function getContractHandler(req, { params }) { const { id } = await params; const contract = db @@ -20,7 +21,7 @@ export async function GET(req, { params }) { return NextResponse.json(contract); } -export async function DELETE(req, { params }) { +async function deleteContractHandler(req, { params }) { const { id } = params; try { @@ -57,3 +58,7 @@ export async function DELETE(req, { params }) { ); } } + +// Protected routes - require authentication +export const GET = withReadAuth(getContractHandler); +export const DELETE = withUserAuth(deleteContractHandler); diff --git a/src/app/api/contracts/route.js b/src/app/api/contracts/route.js index 4867ccb..796ac4e 100644 --- a/src/app/api/contracts/route.js +++ b/src/app/api/contracts/route.js @@ -1,7 +1,8 @@ import db from "@/lib/db"; import { NextResponse } from "next/server"; +import { withReadAuth, withUserAuth } from "@/lib/middleware/auth"; -export async function GET() { +async function getContractsHandler() { const contracts = db .prepare( ` @@ -21,7 +22,7 @@ export async function GET() { return NextResponse.json(contracts); } -export async function POST(req) { +async function createContractHandler(req) { const data = await req.json(); db.prepare( ` @@ -46,3 +47,7 @@ export async function POST(req) { ); return NextResponse.json({ success: true }); } + +// Protected routes - require authentication +export const GET = withReadAuth(getContractsHandler); +export const POST = withUserAuth(createContractHandler); diff --git a/src/app/api/notes/route.js b/src/app/api/notes/route.js index d728731..7724c35 100644 --- a/src/app/api/notes/route.js +++ b/src/app/api/notes/route.js @@ -1,7 +1,8 @@ import db from "@/lib/db"; import { NextResponse } from "next/server"; +import { withUserAuth } from "@/lib/middleware/auth"; -export async function POST(req) { +async function createNoteHandler(req) { const { project_id, task_id, note } = await req.json(); if (!note || (!project_id && !task_id)) { @@ -18,7 +19,7 @@ export async function POST(req) { return NextResponse.json({ success: true }); } -export async function DELETE(_, { params }) { +async function deleteNoteHandler(_, { params }) { const { id } = params; db.prepare("DELETE FROM notes WHERE note_id = ?").run(id); @@ -26,7 +27,7 @@ export async function DELETE(_, { params }) { return NextResponse.json({ success: true }); } -export async function PUT(req, { params }) { +async function updateNoteHandler(req, { params }) { const noteId = params.id; const { note } = await req.json(); @@ -42,3 +43,8 @@ export async function PUT(req, { params }) { return NextResponse.json({ success: true }); } + +// Protected routes - require authentication +export const POST = withUserAuth(createNoteHandler); +export const DELETE = withUserAuth(deleteNoteHandler); +export const PUT = withUserAuth(updateNoteHandler); diff --git a/src/app/api/project-tasks/[id]/route.js b/src/app/api/project-tasks/[id]/route.js index a9d7665..a45116a 100644 --- a/src/app/api/project-tasks/[id]/route.js +++ b/src/app/api/project-tasks/[id]/route.js @@ -3,9 +3,10 @@ import { deleteProjectTask, } from "@/lib/queries/tasks"; import { NextResponse } from "next/server"; +import { withUserAuth } from "@/lib/middleware/auth"; // PATCH: Update project task status -export async function PATCH(req, { params }) { +async function updateProjectTaskHandler(req, { params }) { try { const { status } = await req.json(); @@ -27,7 +28,7 @@ export async function PATCH(req, { params }) { } // DELETE: Delete a project task -export async function DELETE(req, { params }) { +async function deleteProjectTaskHandler(req, { params }) { try { deleteProjectTask(params.id); return NextResponse.json({ success: true }); @@ -38,3 +39,7 @@ export async function DELETE(req, { params }) { ); } } + +// Protected routes - require authentication +export const PATCH = withUserAuth(updateProjectTaskHandler); +export const DELETE = withUserAuth(deleteProjectTaskHandler); diff --git a/src/app/api/project-tasks/route.js b/src/app/api/project-tasks/route.js index fd3c93b..7f2e1b6 100644 --- a/src/app/api/project-tasks/route.js +++ b/src/app/api/project-tasks/route.js @@ -5,9 +5,10 @@ import { } from "@/lib/queries/tasks"; import { NextResponse } from "next/server"; import db from "@/lib/db"; +import { withReadAuth, withUserAuth } from "@/lib/middleware/auth"; // GET: Get all project tasks or task templates based on query params -export async function GET(req) { +async function getProjectTasksHandler(req) { const { searchParams } = new URL(req.url); const projectId = searchParams.get("project_id"); @@ -23,7 +24,7 @@ export async function GET(req) { } // POST: Create a new project task -export async function POST(req) { +async function createProjectTaskHandler(req) { try { const data = await req.json(); @@ -113,3 +114,7 @@ export async function PATCH(req) { ); } } + +// Protected routes - require authentication +export const GET = withReadAuth(getProjectTasksHandler); +export const POST = withUserAuth(createProjectTaskHandler); diff --git a/src/app/api/projects/[id]/route.js b/src/app/api/projects/[id]/route.js index 40803f5..f8ec179 100644 --- a/src/app/api/projects/[id]/route.js +++ b/src/app/api/projects/[id]/route.js @@ -4,19 +4,25 @@ import { deleteProject, } from "@/lib/queries/projects"; import { NextResponse } from "next/server"; +import { withReadAuth, withUserAuth } from "@/lib/middleware/auth"; -export async function GET(_, { params }) { +async function getProjectHandler(_, { params }) { const project = getProjectById(params.id); return NextResponse.json(project); } -export async function PUT(req, { params }) { +async function updateProjectHandler(req, { params }) { const data = await req.json(); updateProject(params.id, data); return NextResponse.json({ success: true }); } -export async function DELETE(_, { params }) { +async function deleteProjectHandler(_, { params }) { deleteProject(params.id); return NextResponse.json({ success: true }); } + +// Protected routes - require authentication +export const GET = withReadAuth(getProjectHandler); +export const PUT = withUserAuth(updateProjectHandler); +export const DELETE = withUserAuth(deleteProjectHandler); diff --git a/src/app/api/task-notes/route.js b/src/app/api/task-notes/route.js index 28652ac..9381ac5 100644 --- a/src/app/api/task-notes/route.js +++ b/src/app/api/task-notes/route.js @@ -4,9 +4,10 @@ import { deleteNote, } from "@/lib/queries/notes"; import { NextResponse } from "next/server"; +import { withReadAuth, withUserAuth } from "@/lib/middleware/auth"; // GET: Get notes for a specific task -export async function GET(req) { +async function getTaskNotesHandler(req) { const { searchParams } = new URL(req.url); const taskId = searchParams.get("task_id"); @@ -26,7 +27,7 @@ export async function GET(req) { } // POST: Add a note to a task -export async function POST(req) { +async function addTaskNoteHandler(req) { try { const { task_id, note, is_system } = await req.json(); @@ -49,7 +50,7 @@ export async function POST(req) { } // DELETE: Delete a note -export async function DELETE(req) { +async function deleteTaskNoteHandler(req) { try { const { searchParams } = new URL(req.url); const noteId = searchParams.get("note_id"); @@ -71,3 +72,8 @@ export async function DELETE(req) { ); } } + +// Protected routes - require authentication +export const GET = withReadAuth(getTaskNotesHandler); +export const POST = withUserAuth(addTaskNoteHandler); +export const DELETE = withUserAuth(deleteTaskNoteHandler); diff --git a/src/app/api/tasks/[id]/route.js b/src/app/api/tasks/[id]/route.js index fd14899..5e792af 100644 --- a/src/app/api/tasks/[id]/route.js +++ b/src/app/api/tasks/[id]/route.js @@ -1,8 +1,9 @@ import db from "@/lib/db"; import { NextResponse } from "next/server"; +import { withReadAuth, withUserAuth } from "@/lib/middleware/auth"; // GET: Get a specific task template -export async function GET(req, { params }) { +async function getTaskHandler(req, { params }) { try { const template = db .prepare("SELECT * FROM tasks WHERE task_id = ? AND is_standard = 1") @@ -25,7 +26,7 @@ export async function GET(req, { params }) { } // PUT: Update a task template -export async function PUT(req, { params }) { +async function updateTaskHandler(req, { params }) { try { const { name, max_wait_days, description } = await req.json(); @@ -58,7 +59,7 @@ export async function PUT(req, { params }) { } // DELETE: Delete a task template -export async function DELETE(req, { params }) { +async function deleteTaskHandler(req, { params }) { try { const result = db .prepare("DELETE FROM tasks WHERE task_id = ? AND is_standard = 1") @@ -79,3 +80,8 @@ export async function DELETE(req, { params }) { ); } } + +// Protected routes - require authentication +export const GET = withReadAuth(getTaskHandler); +export const PUT = withUserAuth(updateTaskHandler); +export const DELETE = withUserAuth(deleteTaskHandler); diff --git a/src/app/api/tasks/route.js b/src/app/api/tasks/route.js index ce0cd22..7dc61a0 100644 --- a/src/app/api/tasks/route.js +++ b/src/app/api/tasks/route.js @@ -1,8 +1,9 @@ import db from "@/lib/db"; import { NextResponse } from "next/server"; +import { withUserAuth } from "@/lib/middleware/auth"; // POST: create new template -export async function POST(req) { +async function createTaskHandler(req) { const { name, max_wait_days, description } = await req.json(); if (!name) { @@ -18,3 +19,6 @@ export async function POST(req) { return NextResponse.json({ success: true }); } + +// Protected routes - require authentication +export const POST = withUserAuth(createTaskHandler); diff --git a/src/app/api/tasks/templates/route.js b/src/app/api/tasks/templates/route.js index 7c7387e..0f6b7ca 100644 --- a/src/app/api/tasks/templates/route.js +++ b/src/app/api/tasks/templates/route.js @@ -1,8 +1,12 @@ import { getAllTaskTemplates } from "@/lib/queries/tasks"; import { NextResponse } from "next/server"; +import { withReadAuth } from "@/lib/middleware/auth"; // GET: Get all task templates -export async function GET() { +async function getTaskTemplatesHandler() { const templates = getAllTaskTemplates(); return NextResponse.json(templates); } + +// Protected routes - require authentication +export const GET = withReadAuth(getTaskTemplatesHandler); diff --git a/src/app/auth/error/page.js b/src/app/auth/error/page.js index db8b24b..5b2d3e3 100644 --- a/src/app/auth/error/page.js +++ b/src/app/auth/error/page.js @@ -1,4 +1,24 @@ +'use client' + +import { useSearchParams } from 'next/navigation' + export default function AuthError() { + const searchParams = useSearchParams() + const error = searchParams.get('error') + + const getErrorMessage = (error) => { + switch (error) { + case 'CredentialsSignin': + return 'Invalid email or password. Please check your credentials and try again.' + case 'AccessDenied': + return 'Access denied. You do not have permission to sign in.' + case 'Verification': + return 'The verification token has expired or has already been used.' + default: + return 'An unexpected error occurred during authentication. Please try again.' + } + } + return (