Files
ember-market-frontend/backend/routes/auth.routes.js
2025-03-10 17:39:37 +00:00

158 lines
4.3 KiB
JavaScript

import express from "express";
import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import Vendor from "../models/Vendor.model.js";
import Store from "../models/Store.model.js";
import Invitation from "../models/Invitation.model.js";
import { protectVendor } from "../middleware/vendorAuthMiddleware.js";
const router = express.Router();
/**
* Register a New Vendor (and create a corresponding Store)
* @route POST /api/auth/register
*/
router.post("/register", async (req, res) => {
const { username, password, invitationCode } = req.body;
try {
if (!username || !password || !invitationCode) {
return res.status(400).json({ error: "All fields are required." });
}
// Verify invitation code
const invitation = await Invitation.findOne({
code: invitationCode,
isUsed: false,
});
console.log(`Invitation: ${invitation}`);
if (!invitation) {
return res.status(400).json({ error: "Invalid or used invitation code." });
}
// Check if vendor already exists
const existingVendor = await Vendor.findOne({ username });
if (existingVendor) {
return res.status(400).json({ error: "Vendor already exists." });
}
// Hash the password
const hashedPassword = await bcrypt.hash(password, 10);
// Create the vendor
const vendor = new Vendor({
username,
passwordHash: hashedPassword,
});
await vendor.save();
// Create a store for this vendor
const store = new Store({
vendorId: vendor._id,
storeName: `${username}'s Store`,
welcomeMessage: "Welcome to my store!",
categories: [],
});
await store.save();
// Attach `storeId` to vendor
vendor.storeId = store._id;
await vendor.save();
// Mark invitation as used
invitation.isUsed = true;
invitation.usedBy = vendor._id;
invitation.usedAt = new Date();
await invitation.save();
return res
.status(201)
.json({ message: "Vendor registered successfully", store });
} catch (error) {
console.error("Error registering vendor:", error);
return res.status(500).json({ error: error.message });
}
});
/**
* Vendor Login
* @route POST /api/auth/login
*/
router.post("/login", async (req, res) => {
const { username, password } = req.body;
try {
if (!username || !password) {
return res.status(400).json({ error: "Username and password are required." });
}
const vendor = await Vendor.findOne({ username });
if (!vendor) {
return res.status(401).json({ error: "Invalid credentials." });
}
const isMatch = await bcrypt.compare(password, vendor.passwordHash);
if (!isMatch) {
return res.status(401).json({ error: "Invalid credentials." });
}
// Generate a JWT
const token = jwt.sign(
{ id: vendor._id, role: "vendor" },
process.env.JWT_SECRET,
{ expiresIn: "7d" }
);
// Store the token in the DB to identify the current session
vendor.currentToken = token;
await vendor.save();
return res.json({ token, role: "vendor" });
} catch (error) {
console.error("Error logging in vendor:", error);
return res.status(500).json({ error: error.message });
}
});
/**
* Vendor Logout
* @route POST /api/auth/logout
* @access Private (Vendors only)
*/
router.post("/logout", protectVendor, async (req, res) => {
try {
await Vendor.findByIdAndUpdate(req.user._id, { currentToken: null });
return res.json({ message: "Successfully logged out." });
} catch (error) {
console.error("Error logging out vendor:", error);
return res.status(500).json({ error: "Failed to log out." });
}
});
/**
* Get Vendor Info
* @route GET /api/auth/me
* @access Private (Vendors only)
*/
router.get("/me", protectVendor, async (req, res) => {
try {
const vendor = await Vendor.findById(req.user._id).select("-passwordHash -currentToken");
if (!vendor) {
return res.status(404).json({ error: "Vendor not found." });
}
vendor.lastOnline = new Date();
await vendor.save();
const store = await Store.findOne({ vendorId: vendor._id });
return res.json({ vendor, store });
} catch (error) {
console.error("Error fetching vendor info:", error);
return res.status(500).json({ error: "Failed to fetch vendor data." });
}
});
export default router;