diff --git a/app/api/Auth/Nextauthgithub/route.ts b/app/api/auth/Nextauthgithub/route.ts similarity index 100% rename from app/api/Auth/Nextauthgithub/route.ts rename to app/api/auth/Nextauthgithub/route.ts diff --git a/app/api/auth/login/route.test.ts b/app/api/auth/login/route.test.ts new file mode 100644 index 000000000..277f00678 --- /dev/null +++ b/app/api/auth/login/route.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from 'vitest'; +import { POST } from './route'; + +describe('POST /api/auth/login', () => { + it('rejects missing credential fields with 400', async () => { + const request = new Request('http://localhost/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ identifier: 'octocat' }), + }); + + const response = await POST(request); + + expect(response.status).toBe(400); + const body = await response.json(); + expect(body.error).toContain('required'); + }); + + it('returns a frontend-ready success payload when identifier and password are present', async () => { + const request = new Request('http://localhost/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ identifier: 'octocat', password: 'password123' }), + }); + + const response = await POST(request); + + expect(response.status).toBe(200); + const body = await response.json(); + expect(body.success).toBe(true); + expect(body.message).toContain('Authentication successful'); + expect(body.user.identifier).toBe('octocat'); + }); +}); diff --git a/app/api/Auth/login/route.ts b/app/api/auth/login/route.ts similarity index 82% rename from app/api/Auth/login/route.ts rename to app/api/auth/login/route.ts index 9c715923e..3c1031007 100644 --- a/app/api/Auth/login/route.ts +++ b/app/api/auth/login/route.ts @@ -4,10 +4,13 @@ import { NextResponse } from 'next/server'; * Handles credentials authentication requests for frontend login. * Integrates with NextAuth sessions and production backend user models. */ -export async function POST(request: Request) { +export async function POST(request: Request): Promise { try { const body = await request.json(); - const { identifier, password } = body; + const { identifier, password } = body as { + identifier?: string; + password?: string; + }; if (!identifier || !password) { return NextResponse.json( @@ -16,7 +19,6 @@ export async function POST(request: Request) { ); } - // Frontend-ready credentials handler return NextResponse.json( { success: true, diff --git a/app/api/auth/signup/route.test.ts b/app/api/auth/signup/route.test.ts new file mode 100644 index 000000000..e2f2f73fa --- /dev/null +++ b/app/api/auth/signup/route.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'vitest'; +import { POST } from './route'; + +describe('POST /api/auth/signup', () => { + it('rejects incomplete signup payloads with 400', async () => { + const request = new Request('http://localhost/api/auth/signup', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ fullName: 'Octo Cat' }), + }); + + const response = await POST(request); + + expect(response.status).toBe(400); + const body = await response.json(); + expect(body.error).toContain('required'); + }); + + it('creates a success response body for a complete POST payload', async () => { + const request = new Request('http://localhost/api/auth/signup', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + fullName: 'Octo Cat', + email: 'octocat@example.com', + password: 'password123', + }), + }); + + const response = await POST(request); + + expect(response.status).toBe(201); + const body = await response.json(); + expect(body.success).toBe(true); + expect(body.message).toContain('Account created'); + expect(body.user.fullName).toBe('Octo Cat'); + expect(body.user.email).toBe('octocat@example.com'); + }); +}); diff --git a/app/api/Auth/signup/route.ts b/app/api/auth/signup/route.ts similarity index 80% rename from app/api/Auth/signup/route.ts rename to app/api/auth/signup/route.ts index da9ab3904..a763e85d9 100644 --- a/app/api/Auth/signup/route.ts +++ b/app/api/auth/signup/route.ts @@ -4,10 +4,14 @@ import { NextResponse } from 'next/server'; * Handles user registration requests for frontend signup. * Integrates with production database user creation. */ -export async function POST(request: Request) { +export async function POST(request: Request): Promise { try { const body = await request.json(); - const { fullName, email, password } = body; + const { fullName, email, password } = body as { + fullName?: string; + email?: string; + password?: string; + }; if (!fullName || !email || !password) { return NextResponse.json( @@ -16,7 +20,6 @@ export async function POST(request: Request) { ); } - // Frontend-ready registration handler return NextResponse.json( { success: true, diff --git a/middleware.ts b/middleware.ts index 10daf13b9..d5cc167bf 100644 --- a/middleware.ts +++ b/middleware.ts @@ -219,7 +219,7 @@ export const config = { '/api/languages/:path*', '/api/org/:path*', '/api/spotify/:path*', - '/api/Auth/:path*', + '/api/auth/:path*', '/api/achievements/:path*', '/api/ci-analytics/:path*', '/api/cicd/:path*', diff --git a/package-lock.json b/package-lock.json index d42b6f78b..8af4b9e53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,6 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", - "@types/bcryptjs": "^2.4.6", "@types/dompurify": "^3.0.5", "@types/jspdf": "^1.3.3", "@types/node": "^20", @@ -224,6 +223,7 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -521,6 +521,7 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -634,6 +635,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" }, @@ -682,6 +684,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" } @@ -772,6 +775,7 @@ "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" @@ -783,6 +787,7 @@ "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -3417,6 +3422,7 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3523,13 +3529,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/bcryptjs": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", - "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -3742,6 +3741,7 @@ "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3752,6 +3752,7 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3828,6 +3829,7 @@ "integrity": "sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.64.0", "@typescript-eslint/types": "8.64.0", @@ -4481,6 +4483,7 @@ "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.10", @@ -4610,6 +4613,7 @@ "integrity": "sha512-EOUqfXHTXtpSHsyLHH40ts3Ue+hRhSGwzwzMlK0dTEOLSDYyOXLyr5JDGmHQWhN2DYI30gw6dVx3cdgM9FZl+Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "4.1.10", "fflate": "^0.8.2", @@ -4721,6 +4725,7 @@ "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5277,6 +5282,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -5732,7 +5738,8 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/d3-array": { "version": "3.2.4", @@ -5887,6 +5894,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -6580,6 +6588,7 @@ "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -6781,6 +6790,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -7770,7 +7780,8 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.15.0.tgz", "integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==", - "license": "Standard 'no charge' license: https://gsap.com/standard-license." + "license": "Standard 'no charge' license: https://gsap.com/standard-license.", + "peer": true }, "node_modules/gzip-size": { "version": "6.0.0", @@ -8025,6 +8036,7 @@ "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.15.tgz", "integrity": "sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -8847,6 +8859,7 @@ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz", "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "fast-png": "^6.2.0", @@ -10019,6 +10032,7 @@ "resolved": "https://registry.npmjs.org/next/-/next-16.2.10.tgz", "integrity": "sha512-2som5AVXb3kE6Yjine3/mNbBayYF58eguBWIVVUdr1y/L426xyVEgYxgBG+1QC34P2x5E+tcDup6XkuOAX3dCA==", "license": "MIT", + "peer": true, "dependencies": { "@next/env": "16.2.10", "@swc/helpers": "0.5.15", @@ -10728,6 +10742,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", @@ -10770,6 +10785,7 @@ "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -10790,6 +10806,7 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -10985,6 +11002,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -10994,6 +11012,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -11057,7 +11076,8 @@ "version": "19.2.7", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-kapsule": { "version": "2.6.0", @@ -11092,6 +11112,7 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", "license": "MIT", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -11179,7 +11200,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -12803,6 +12825,7 @@ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -12940,6 +12963,7 @@ "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "~0.28.0" }, @@ -13079,6 +13103,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13297,6 +13322,7 @@ "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", @@ -13388,6 +13414,7 @@ "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.1.10", "@vitest/mocker": "4.1.10", @@ -13879,6 +13906,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }