route.js 1.6 KB

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