route.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // app/api/auth/login/route.js
  2. import bcrypt from "bcryptjs";
  3. import User from "@/models/user";
  4. import { getDb } from "@/lib/db";
  5. import { createSession } from "@/lib/auth/session";
  6. /**
  7. * POST /api/auth/login
  8. *
  9. * Body (JSON):
  10. * {
  11. * "username": "example.user",
  12. * "password": "plain-text-password"
  13. * }
  14. */
  15. export async function POST(request) {
  16. try {
  17. let body;
  18. try {
  19. body = await request.json();
  20. } catch {
  21. return jsonResponse({ error: "Invalid request body" }, 400);
  22. }
  23. if (!body || typeof body !== "object") {
  24. return jsonResponse({ error: "Invalid request body" }, 400);
  25. }
  26. const { username, password } = body;
  27. if (
  28. typeof username !== "string" ||
  29. typeof password !== "string" ||
  30. !username.trim() ||
  31. !password.trim()
  32. ) {
  33. return jsonResponse({ error: "Missing username or password" }, 400);
  34. }
  35. const normalizedUsername = username.trim().toLowerCase();
  36. // Ensure DB (Mongoose) connection is established before using models.
  37. await getDb();
  38. const user = await User.findOne({ username: normalizedUsername }).exec();
  39. if (!user) {
  40. return jsonResponse({ error: "Invalid credentials" }, 401);
  41. }
  42. const passwordMatches = await bcrypt.compare(password, user.passwordHash);
  43. if (!passwordMatches) {
  44. return jsonResponse({ error: "Invalid credentials" }, 401);
  45. }
  46. await createSession({
  47. userId: user._id.toString(),
  48. role: user.role,
  49. branchId: user.branchId ?? null,
  50. });
  51. return jsonResponse({ ok: true }, 200);
  52. } catch (error) {
  53. console.error("Login error:", error);
  54. return jsonResponse({ error: "Internal server error" }, 500);
  55. }
  56. }
  57. function jsonResponse(data, status = 200) {
  58. return new Response(JSON.stringify(data), {
  59. status,
  60. headers: {
  61. "Content-Type": "application/json",
  62. },
  63. });
  64. }