Finish admin dashboard and update sql

This commit is contained in:
estherdev03
2025-04-20 06:59:32 -06:00
parent 68d2b950c0
commit b5c4a783a9
1420 changed files with 182156 additions and 0 deletions

47
controllers/category.js Normal file
View File

@@ -0,0 +1,47 @@
const db = require("../utils/database");
exports.getAllCategoriesWithPagination = async (req, res) => {
const limit = +req.query?.limit;
const page = +req.query?.page;
const offset = (page - 1) * limit;
try {
const [data, _] = await db.execute(
"SELECT * FROM Category C ORDER BY C.CategoryID ASC LIMIT ? OFFSET ?",
[limit.toString(), offset.toString()]
);
const [result] = await db.execute("SELECT COUNT(*) AS count FROM Category");
const { count: total } = result[0];
return res.json({ data, total });
} catch (error) {
res.json({ error: "Cannot fetch categories from database!" });
}
};
exports.addCategory = async (req, res) => {
const { name } = req.body;
try {
const [result] = await db.execute(
"INSERT INTO Category (Name) VALUES (?)",
[name]
);
res.json({ message: "Adding new category successfully!" });
} catch (error) {
res.json({ error: "Cannot add new category!" });
}
};
exports.removeCategory = async (req, res) => {
const { id } = req.params;
try {
const [result] = await db.execute(
`DELETE FROM Category WHERE CategoryID = ?`,
[id]
);
res.json({ message: "Delete category successfully!" });
} catch (error) {
res.json({ error: "Cannot remove category from database!" });
}
};

90
controllers/history.js Normal file
View File

@@ -0,0 +1,90 @@
const db = require("../utils/database");
exports.HistoryByUserId = async (req, res) => {
const { id } = req.body;
try {
const [data] = await db.execute(
`
WITH RankedImages AS (
SELECT
P.ProductID,
P.Name AS ProductName,
P.Price,
P.Date AS DateUploaded,
U.Name AS SellerName,
I.URL AS ProductImage,
C.Name AS Category,
ROW_NUMBER() OVER (PARTITION BY P.ProductID ORDER BY I.URL) AS RowNum
FROM Product P
JOIN Image_URL I ON P.ProductID = I.ProductID
JOIN User U ON P.UserID = U.UserID
JOIN Category C ON P.CategoryID = C.CategoryID
JOIN History H ON H.ProductID = P.ProductID
WHERE H.UserID = ?
)
SELECT
ProductID,
ProductName,
Price,
DateUploaded,
SellerName,
ProductImage,
Category
FROM RankedImages
WHERE RowNum = 1;
`,
[id],
);
res.json({
success: true,
message: "Products fetched successfully",
data,
});
} catch (error) {
console.error("Error finding products:", error);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
};
exports.AddHistory = async (req, res) => {
const { userID, productID } = req.body;
console.log(userID);
try {
// Use parameterized query to prevent SQL injection
const [result] = await db.execute(
`INSERT INTO History (UserID, ProductID) VALUES (?, ?)`,
[userID, productID],
);
res.json({
success: true,
message: "Product added to history successfully",
});
} catch (error) {
console.error("Error adding favorite product:", error);
return res.json({ error: "Could not add favorite product" });
}
};
exports.DelHistory = async (req, res) => {
const { userID, productID } = req.body;
console.log(userID);
try {
// Use parameterized query to prevent SQL injection
const [result] = await db.execute(`DELETE FROM History WHERE UserID=?`, [
userID,
]);
res.json({
success: true,
message: "Product deleted from History successfully",
});
} catch (error) {
console.error("Error adding favorite product:", error);
return res.json({ error: "Could not add favorite product" });
}
};

301
controllers/product.js Normal file
View File

@@ -0,0 +1,301 @@
const db = require("../utils/database");
exports.addProduct = async (req, res) => {
const { userID, name, price, qty, description, category, images } = req.body;
try {
const [result] = await db.execute(
`INSERT INTO Product (Name, Price, StockQuantity, UserID, Description, CategoryID) VALUES (?, ?, ?, ?, ?, ?)`,
[name, price, qty, userID, description, category]
);
const productID = result.insertId;
if (images && images.length > 0) {
const imageInsertPromises = images.map((imagePath) =>
db.execute(`INSERT INTO Image_URL (URL, ProductID) VALUES (?, ?)`, [
imagePath,
productID,
])
);
await Promise.all(imageInsertPromises); //perallel
}
res.json({
success: true,
message: "Product and images added successfully",
});
} catch (error) {
console.error("Error adding product or images:", error);
console.log(error);
return res.json({ error: "Could not add product or images" });
}
};
exports.addFavorite = async (req, res) => {
const { userID, productID } = req.body;
console.log(userID);
try {
// Use parameterized query to prevent SQL injection
const [result] = await db.execute(
`INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)`,
[userID, productID]
);
res.json({
success: true,
message: "Product added to favorites successfully",
});
} catch (error) {
console.error("Error adding favorite product:", error);
return res.json({ error: "Could not add favorite product" });
}
};
exports.removeFavorite = async (req, res) => {
const { userID, productID } = req.body;
console.log(userID);
try {
// Use parameterized query to prevent SQL injection
const [result] = await db.execute(
`DELETE FROM Favorites WHERE UserID = ? AND ProductID = ?`,
[userID, productID]
);
res.json({
success: true,
message: "Product removed from favorites successfully",
});
} catch (error) {
console.error("Error removing favorite product:", error);
return res.json({ error: "Could not remove favorite product" });
}
};
exports.getFavorites = async (req, res) => {
const { userID } = req.body;
try {
const [favorites] = await db.execute(
`
SELECT
p.ProductID,
p.Name,
p.Description,
p.Price,
p.CategoryID,
p.UserID,
p.Date,
u.Name AS SellerName,
MIN(i.URL) AS image_url
FROM Favorites f
JOIN Product p ON f.ProductID = p.ProductID
JOIN User u ON p.UserID = u.UserID
LEFT JOIN Image_URL i ON p.ProductID = i.ProductID
WHERE f.UserID = ?
GROUP BY
p.ProductID,
p.Name,
p.Description,
p.Price,
p.CategoryID,
p.UserID,
p.Date,
u.Name;
`,
[userID]
);
res.json({
success: true,
favorites: favorites,
});
} catch (error) {
console.error("Error retrieving favorites:", error);
res.status(500).json({ error: "Could not retrieve favorite products" });
}
};
// Get all products along with their image URLs
exports.getAllProducts = async (req, res) => {
try {
const [data, fields] = await db.execute(`
SELECT
P.ProductID,
P.Name AS ProductName,
P.Price,
P.Date AS DateUploaded,
U.Name AS SellerName,
MIN(I.URL) AS ProductImage,
C.Name AS Category
FROM Product P
JOIN Image_URL I ON P.ProductID = I.ProductID
JOIN User U ON P.UserID = U.UserID
JOIN Category C ON P.CategoryID = C.CategoryID
GROUP BY
P.ProductID,
P.Name,
P.Price,
P.Date,
U.Name,
C.Name;
`);
res.json({
success: true,
message: "Products fetched successfully",
data,
});
} catch (error) {
console.error("Error finding products:", error);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
};
exports.getProductById = async (req, res) => {
const { id } = req.params;
console.log("Received Product ID:", id);
try {
const [data] = await db.execute(
`
SELECT p.*,U.Name AS SellerName,U.Email as SellerEmail,U.Phone as SellerPhone, i.URL AS image_url
FROM Product p
LEFT JOIN Image_URL i ON p.ProductID = i.ProductID
JOIN User U ON p.UserID = U.UserID
WHERE p.ProductID = ?
`,
[id]
);
// Log raw data for debugging
console.log("Raw Database Result:", data);
if (data.length === 0) {
console.log("No product found with ID:", id);
return res.status(404).json({
success: false,
message: "Product not found",
});
}
// Collect all image URLs
const images = data
.map((row) => row.image_url)
.filter((url) => url !== null);
// Create product object with all details from first row and collected images
const product = {
...data[0], // Base product details
images: images, // Collected image URLs
};
// Log processed product for debugging
console.log("Processed Product:", product);
res.json({
success: true,
message: "Product fetched successfully",
data: product,
});
} catch (error) {
console.error("Full Error Details:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message,
});
}
};
exports.getProductWithPagination = async (req, res) => {
const limit = +req.query.limit;
const page = +req.query.page;
const offset = (page - 1) * limit;
try {
const [data, fields] = await db.execute(
`
SELECT
P.ProductID,
P.Name AS ProductName,
P.Price,
P.Date AS DateUploaded,
U.Name AS SellerName,
MIN(I.URL) AS ProductImage,
C.Name AS Category
FROM Product P
LEFT JOIN Image_URL I ON P.ProductID = I.ProductID
LEFT JOIN User U ON P.UserID = U.UserID
LEFT JOIN Category C ON P.CategoryID = C.CategoryID
GROUP BY
P.ProductID,
P.Name,
P.Price,
P.Date,
U.Name,
C.Name
ORDER BY P.ProductID ASC
LIMIT ? OFFSET ?
`,
[limit.toString(), offset.toString()]
);
const [result] = await db.execute(
`SELECT COUNT(*) AS totalProd FROM Product`
);
const { totalProd } = result[0];
return res.json({ totalProd, products: data });
} catch (error) {
res.json({ error: "Error fetching products!" });
}
};
exports.removeProduct = async (req, res) => {
const { id } = req.params;
try {
const [result] = await db.execute(
`DELETE FROM Product WHERE ProductID = ?`,
[id]
);
res.json({ message: "Delete product successfully!" });
} catch (error) {
res.json({ error: "Cannot remove product from database!" });
}
};
// db_con.query(
// "SELECT ProductID FROM product WHERE ProductID = ?",
// [productID],
// (err, results) => {
// if (err) {
// console.error("Error checking product:", err);
// return res.json({ error: "Database error" });
// }
// if (results.length === 0) {
// return res.json({ error: "Product does not exist" });
// }
// },
// );
// db_con.query(
// "INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)",
// [userID, productID],
// (err, result) => {
// if (err) {
// console.error("Error adding favorite product:", err);
// return res.json({ error: "Could not add favorite product" });
// }
// res.json({
// success: true,
// message: "Product added to favorites successfully",
// });
// },
// );

View File

@@ -0,0 +1,53 @@
const db = require("../utils/database");
// TODO: Get the recommondaed product given the userID
exports.RecommondationByUserId = async (req, res) => {
const { id } = req.body;
try {
const [data, fields] = await db.execute(
`
WITH RankedImages AS (
SELECT
P.ProductID,
P.Name AS ProductName,
P.Price,
P.Date AS DateUploaded,
U.Name AS SellerName,
I.URL AS ProductImage,
C.Name AS Category,
ROW_NUMBER() OVER (PARTITION BY P.ProductID ORDER BY I.URL) AS RowNum
FROM Product P
JOIN Image_URL I ON P.ProductID = I.ProductID
JOIN User U ON P.UserID = U.UserID
JOIN Category C ON P.CategoryID = C.CategoryID
JOIN Recommendation R ON P.ProductID = R.RecommendedProductID
WHERE R.UserID = ?
)
SELECT
ProductID,
ProductName,
Price,
DateUploaded,
SellerName,
ProductImage,
Category
FROM RankedImages
WHERE RowNum = 1;
`,
[id],
);
console.log(data);
res.json({
success: true,
message: "Products fetched successfully",
data,
});
} catch (error) {
console.error("Error finding products:", error);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
};

302
controllers/review.js Normal file
View File

@@ -0,0 +1,302 @@
const db = require("../utils/database");
/**
* Get reviews for a specific product
* Returns both reviews for the product and reviews by the product owner for other products
*/
exports.getReviews = async (req, res) => {
const { id } = req.params;
console.log("Received Product ID:", id);
try {
// First query: Get reviews for this specific product
const [productReviews] = await db.execute(
`SELECT
R.ReviewID,
R.UserID,
R.ProductID,
R.Comment,
R.Rating,
R.Date AS ReviewDate,
U.Name AS ReviewerName,
P.Name AS ProductName,
'product' AS ReviewType
FROM Review R
JOIN User U ON R.UserID = U.UserID
JOIN Product P ON R.ProductID = P.ProductID
WHERE R.ProductID = ?`,
[id],
);
// // Second query: Get reviews written by the product owner for other products
// const [sellerReviews] = await db.execute(
// `SELECT
// R.ReviewID,
// R.UserID,
// R.ProductID,
// R.Comment,
// R.Rating,
// R.Date AS ReviewDate,
// U.Name AS ReviewerName,
// P.Name AS ProductName,
// 'seller' AS ReviewType
// FROM Review R
// JOIN User U ON R.UserID = U.UserID
// JOIN Product P ON R.ProductID = P.ProductID
// WHERE R.UserID = (
// SELECT UserID
// FROM Product
// WHERE ProductID = ?
// )
// AND R.ProductID != ?`,
// [id, id],
// );
// Combine the results
const combinedReviews = [...productReviews];
// Log data for debugging
console.log("Combined Reviews:", combinedReviews);
res.json({
success: true,
message: "Reviews fetched successfully",
data: combinedReviews,
});
} catch (error) {
console.error("Full Error Details:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message,
});
}
};
/**
* Submit a new review for a product
*/
exports.submitReview = async (req, res) => {
const { productId, userId, rating, comment } = req.body;
// Validate required fields
if (!productId || !userId || !rating || !comment) {
return res.status(400).json({
success: false,
message: "Missing required fields",
});
}
// Validate rating is between 1 and 5
if (rating < 1 || rating > 5) {
return res.status(400).json({
success: false,
message: "Rating must be between 1 and 5",
});
}
try {
// Check if user has already reviewed this product
const [existingReview] = await db.execute(
`SELECT ReviewID FROM Review WHERE ProductID = ? AND UserID = ?`,
[productId, userId],
);
if (existingReview.length > 0) {
return res.status(400).json({
success: false,
message: "You have already reviewed this product",
});
}
// Check if user is trying to review their own product
const [productOwner] = await db.execute(
`SELECT UserID FROM Product WHERE ProductID = ?`,
[productId],
);
if (productOwner.length > 0 && productOwner[0].UserID === userId) {
return res.status(400).json({
success: false,
message: "You cannot review your own product",
});
}
// Insert the review into the database
const [result] = await db.execute(
`INSERT INTO Review (
ProductID,
UserID,
Rating,
Comment,
Date
) VALUES (?, ?, ?, ?, NOW())`,
[productId, userId, rating, comment],
);
// Get the inserted review id
const reviewId = result.insertId;
// Fetch the newly created review to return to client
const [newReview] = await db.execute(
`SELECT
R.ReviewID,
R.ProductID,
R.UserID,
R.Rating,
R.Comment,
R.Date AS ReviewDate,
U.Name AS ReviewerName,
P.Name AS ProductName
FROM Review R
JOIN User U ON R.UserID = U.UserID
JOIN Product P ON R.ProductID = P.ProductID
WHERE R.ReviewID = ?`,
[reviewId],
);
res.status(201).json({
success: true, // Fixed from false to true
message: "Review submitted successfully",
data: newReview[0],
});
} catch (error) {
console.error("Error submitting review:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message,
});
}
};
// /**
// * Update an existing review
// */
// exports.updateReview = async (req, res) => {
// const { reviewId } = req.params;
// const { rating, comment } = req.body;
// const userId = req.body.userId; // Assuming you have middleware that validates the user
// // Validate required fields
// if (!reviewId || !rating || !comment) {
// return res.status(400).json({
// success: false,
// message: "Missing required fields",
// });
// }
// // Validate rating is between 1 and 5
// if (rating < 1 || rating > 5) {
// return res.status(400).json({
// success: false,
// message: "Rating must be between 1 and 5",
// });
// }
// try {
// // Check if review exists and belongs to the user
// const [existingReview] = await db.execute(
// `SELECT ReviewID, UserID FROM Review WHERE ReviewID = ?`,
// [reviewId],
// );
// if (existingReview.length === 0) {
// return res.status(404).json({
// success: false,
// message: "Review not found",
// });
// }
// if (existingReview[0].UserID !== userId) {
// return res.status(403).json({
// success: false,
// message: "You can only update your own reviews",
// });
// }
// // Update the review
// await db.execute(
// `UPDATE Review
// SET Rating = ?, Comment = ?, Date = NOW()
// WHERE ReviewID = ?`,
// [rating, comment, reviewId],
// );
// // Fetch the updated review
// const [updatedReview] = await db.execute(
// `SELECT
// R.ReviewID,
// R.ProductID,
// R.UserID,
// R.Rating,
// R.Comment,
// R.Date AS ReviewDate,
// U.Name AS ReviewerName,
// P.Name AS ProductName
// FROM Review R
// JOIN User U ON R.UserID = U.UserID
// JOIN Product P ON R.ProductID = P.ProductID
// WHERE R.ReviewID = ?`,
// [reviewId],
// );
// res.json({
// success: true,
// message: "Review updated successfully",
// data: updatedReview[0],
// });
// } catch (error) {
// console.error("Error updating review:", error);
// return res.status(500).json({
// success: false,
// message: "Database error occurred",
// error: error.message,
// });
// }
// };
// /**
// * Delete a review
// */
// exports.deleteReview = async (req, res) => {
// const { reviewId } = req.params;
// const userId = req.body.userId; // Assuming you have middleware that validates the user
// try {
// // Check if review exists and belongs to the user
// const [existingReview] = await db.execute(
// `SELECT ReviewID, UserID FROM Review WHERE ReviewID = ?`,
// [reviewId],
// );
// if (existingReview.length === 0) {
// return res.status(404).json({
// success: false,
// message: "Review not found",
// });
// }
// if (existingReview[0].UserID !== userId) {
// return res.status(403).json({
// success: false,
// message: "You can only delete your own reviews",
// });
// }
// // Delete the review
// await db.execute(`DELETE FROM Review WHERE ReviewID = ?`, [reviewId]);
// res.json({
// success: true,
// message: "Review deleted successfully",
// });
// } catch (error) {
// console.error("Error deleting review:", error);
// return res.status(500).json({
// success: false,
// message: "Database error occurred",
// error: error.message,
// });
// }
// };

164
controllers/search.js Normal file
View File

@@ -0,0 +1,164 @@
const db = require("../utils/database");
exports.searchProductsByName = async (req, res) => {
const { name } = req.query;
if (name.length === 0) {
console.log("Searching for products with no name", name);
}
console.log("Searching for products with name:", name);
try {
// Modify SQL to return all products when no search term is provided
const sql = `
SELECT p.*, i.URL as image
FROM Product p
LEFT JOIN Image_URL i ON p.ProductID = i.ProductID
${name ? "WHERE p.Name LIKE ?" : ""}
ORDER BY p.ProductID
`;
const params = name ? [`%${name}%`] : [];
console.log("Executing SQL:", sql);
console.log("With parameters:", params);
const [data] = await db.execute(sql, params);
console.log("Raw Database Result:", data);
if (data.length === 0) {
console.log("No products found matching:", name);
return res.status(404).json({
success: false,
message: "No products found matching your search",
});
}
// Group products by ProductID to handle multiple images per product
const productsMap = new Map();
data.forEach((row) => {
if (!productsMap.has(row.ProductID)) {
const product = {
ProductID: row.ProductID,
Name: row.Name,
Description: row.Description,
Price: row.Price,
images: row.image,
};
productsMap.set(row.ProductID, product);
} else if (row.image_url) {
productsMap.get(row.ProductID).images.push(row.image_url);
}
});
const products = Array.from(productsMap.values());
console.log("Processed Products:", products);
res.json({
success: true,
message: "Products fetched successfully",
data: products,
count: products.length,
});
} catch (error) {
console.error("Database Error:", error);
return res.status(500).json({
success: false,
message: "Database error occurred",
error: error.message || "Unknown database error",
});
}
};
// exports.searchProductsByName = async (req, res) => {
// const { name } = req.query;
// // Add better validation and error handling
// if (!name || typeof name !== "string") {
// return res.status(400).json({
// success: false,
// message: "Valid search term is required",
// });
// }
// console.log("Searching for products with name:", name);
// try {
// // Log the SQL query and parameters for debugging
// const sql = `
// SELECT p.*, i.URL AS image_url
// FROM Product p
// LEFT JOIN Image_URL i ON p.ProductID = i.ProductID
// WHERE p.Name LIKE ?
// `;
// const params = [`%${name}%`];
// console.log("Executing SQL:", sql);
// console.log("With parameters:", params);
// const [data] = await db.execute(sql, params);
// // Log raw data for debugging
// console.log("Raw Database Result:", data);
// if (data.length === 0) {
// console.log("No products found matching:", name);
// return res.status(404).json({
// success: false,
// message: "No products found matching your search",
// });
// }
// // Group products by ProductID to handle multiple images per product
// const productsMap = new Map();
// data.forEach((row) => {
// if (!productsMap.has(row.ProductID)) {
// // Create a clean object without circular references
// const product = {
// ProductID: row.ProductID,
// Name: row.Name,
// Description: row.Description,
// Price: row.Price,
// // Add any other product fields you need
// images: row.image_url ? [row.image_url] : [],
// };
// productsMap.set(row.ProductID, product);
// } else if (row.image_url) {
// // Add additional image to existing product
// productsMap.get(row.ProductID).images.push(row.image_url);
// }
// });
// // Convert map to array of products
// const products = Array.from(productsMap.values());
// // Log processed products for debugging
// console.log("Processed Products:", products);
// res.json({
// success: true,
// message: "Products fetched successfully",
// data: products,
// count: products.length,
// });
// } catch (error) {
// // Enhanced error logging
// console.error("Database Error Details:", {
// message: error.message,
// code: error.code,
// errno: error.errno,
// sqlState: error.sqlState,
// sqlMessage: error.sqlMessage,
// sql: error.sql,
// });
// return res.status(500).json({
// success: false,
// message: "Database error occurred",
// error: error.message || "Unknown database error",
// });
// }
// };

365
controllers/user.js Normal file
View File

@@ -0,0 +1,365 @@
const crypto = require("crypto");
const db = require("../utils/database");
const { sendVerificationEmail } = require("../utils/helper");
exports.sendVerificationCode = async (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: "Email is required" });
}
try {
// Generate a random 6-digit code
const verificationCode = crypto.randomInt(100000, 999999).toString();
console.log(
`Generated verification code for ${email}: ${verificationCode}`
);
// Check if email already exists in verification table
const [results, fields] = await db.execute(
"SELECT * FROM AuthVerification WHERE Email = ?",
[email]
);
if (results.length > 0) {
// Update existing record
const [result] = await db.execute(
`UPDATE AuthVerification SET VerificationCode = ?, Authenticated = FALSE, Date = CURRENT_TIMESTAMP
WHERE Email = ?`,
[verificationCode, email]
);
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
} else {
// Insert new record
const [result] = await db.execute(
"INSERT INTO AuthVerification (Email, VerificationCode, Authenticated) VALUES (?, ?, FALSE)",
[email, verificationCode]
);
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
}
} catch (error) {
console.error("Error:", error);
res.status(500).json({ error: "Server error" });
}
};
exports.verifyCode = async (req, res) => {
const { email, code } = req.body;
if (!email || !code) {
return res.status(400).json({ error: "Email and code are required" });
}
console.log(`Attempting to verify code for ${email}: ${code}`);
try {
// Check verification code
const [results, fields] = await db.execute(
"SELECT * FROM AuthVerification WHERE Email = ? AND VerificationCode = ? AND Authenticated = 0 AND Date > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
[email, code]
);
if (results.length === 0) {
console.log(`Invalid or expired verification code for email ${email}`);
return res
.status(400)
.json({ error: "Invalid or expired verification code" });
}
const userId = results[0].UserID;
// Mark as authenticated
const [result] = await db.execute(
"UPDATE AuthVerification SET Authenticated = TRUE WHERE Email = ?",
[email]
);
res.json({
success: true,
message: "Verification successful",
userId,
});
} catch (error) {
console.log("Error: ", error);
res.status(500).json({ error: "Database error!" });
}
};
exports.completeSignUp = async (req, res) => {
const data = req.body;
try {
const [results, fields] = await db.execute(
`SELECT * FROM AuthVerification WHERE Email = ? AND Authenticated = 1;`,
[data.email]
);
if (results.length === 0) {
return res.status(400).json({ error: "Email not verified" });
}
// Create the user
const [createResult] = await db.execute(
`INSERT INTO User (Name, Email, UCID, Password, Phone, Address)
VALUES ('${data.name}', '${data.email}', '${data.UCID}', '${data.password}', '${data.phone}', '${data.address}')`
);
// Insert role using the user's ID
const [insertResult] = await db.execute(
`INSERT INTO UserRole (UserID, Client, Admin)
VALUES (LAST_INSERT_ID(), ${data.client || true}, ${
data.admin || false
})`
);
// Delete verification record
const [deleteResult] = await db.execute(
`DELETE FROM AuthVerification WHERE Email = '${data.email}'`
);
res.json({
success: true,
message: "User registration completed successfully",
name: data.name,
email: data.email,
UCID: data.UCID,
});
} catch (error) {
console.log("Error: ", error);
res.status(500).json({ error: "Database error!" });
}
};
exports.doLogin = async (req, res) => {
const { email, password } = req.body;
// Input validation
if (!email || !password) {
return res.status(400).json({
found: false,
error: "Email and password are required",
});
}
try {
// Query to find user with matching email
const query = "SELECT * FROM User WHERE email = ?";
const [data, fields] = await db.execute(query, [email]);
// Check if user was found
if (data && data.length > 0) {
const user = data[0];
// Verify password match
if (user.Password === password) {
// Consider using bcrypt for secure password comparison
// Return user data without password
return res.json({
found: true,
userID: user.UserID,
name: user.Name,
email: user.Email,
UCID: user.UCID,
phone: user.Phone,
address: user.Address,
});
} else {
// Password doesn't match
return res.json({
found: false,
error: "Invalid email or password",
});
}
} else {
// User not found
return res.json({
found: false,
error: "Invalid email or password",
});
}
} catch (error) {
console.error("Error logging in:", error);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
};
exports.getAllUser = async (req, res) => {
try {
const [users, fields] = await db.execute("SELECT * FROM User;");
res.json({ Users: users });
} catch (error) {
console.error("Errors: ", error);
return res.status(500).json({ error: "\nCould not fetch users!" });
}
};
exports.findUserByEmail = async (req, res) => {
const { email } = req.body;
// Input validation
if (!email) {
return res.status(400).json({
found: false,
error: "Email is required",
});
}
try {
// Query to find user with matching email and password
const query = "SELECT * FROM User WHERE email = ?";
const [data, fields] = await db.execute(query, [email]);
// Check if user was found
if (data && data.length > 0) {
console.log(data);
const user = data[0];
// Return all user data except password
return res.json({
found: true,
userID: user.UserID,
name: user.Name,
email: user.Email,
UCID: user.UCID,
phone: user.Phone,
address: user.Address,
password: user.Password,
// Include any other fields your user might have
// Make sure the field names match exactly with your database column names
});
} else {
// User not found or invalid credentials
return res.json({
found: false,
error: "Invalid email or password",
});
}
} catch (error) {
console.error("Error finding user:", error);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
};
exports.updateUser = async (req, res) => {
try {
const userId = req.body?.userId;
const name = req.body?.name;
const email = req.body?.email;
const phone = req.body?.phone;
const UCID = req.body?.UCID;
const address = req.body?.address;
const password = req.body?.password;
if (!userId) {
return res.status(400).json({ error: "User ID is required" });
}
// Build updateData manually
const updateData = {};
if (name) updateData.name = name;
if (email) updateData.email = email;
if (phone) updateData.phone = phone;
if (UCID) updateData.UCID = UCID;
if (address) updateData.address = address;
if (password) updateData.password = password;
if (Object.keys(updateData).length === 0) {
return res.status(400).json({ error: "No valid fields to update" });
}
const updateFields = [];
const values = [];
Object.entries(updateData).forEach(([key, value]) => {
updateFields.push(`${key} = ?`);
values.push(value);
});
values.push(userId);
const query = `UPDATE User SET ${updateFields.join(", ")} WHERE userId = ?`;
const [updateResult] = await db.execute(query, values);
if (updateResult.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ success: true, message: "User updated successfully" });
} catch (error) {
console.error("Error updating user:", error);
return res.status(500).json({ error: "Could not update user" });
}
};
exports.deleteUser = async (req, res) => {
const { userId } = req.body;
if (!userId) {
return res.status(400).json({ error: "User ID is required" });
}
try {
// Delete from UserRole first (assuming foreign key constraint)
const [result1] = await db.execute(
"DELETE FROM UserRole WHERE UserID = ?",
[userId]
);
// Then delete from User table
const [result2] = await db.execute("DELETE FROM User WHERE UserID = ?", [
userId,
]);
if (result2.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ success: true, message: "User deleted successfully" });
} catch (error) {
console.error("Error: ", error);
return res.status(500).json({ error: "Could not delete user!" });
}
};
exports.getUsersWithPagination = async (req, res) => {
const limit = +req.query.limit;
const page = +req.query.page;
const offset = (page - 1) * limit;
try {
const [users, fields] = await db.execute(
"SELECT * FROM User LIMIT ? OFFSET ?",
[limit.toString(), offset.toString()]
);
const [result] = await db.execute("SELECT COUNT(*) AS count FROM User");
const { count: total } = result[0];
res.json({ users, total });
} catch (error) {
console.error("Errors: ", error);
return res.status(500).json({ error: "\nCould not fetch users!" });
}
};
exports.isAdmin = async (req, res) => {
const { id } = req.params;
try {
const [result] = await db.execute(
"SELECT R.Admin FROM marketplace.userrole R WHERE R.UserID = ?",
[id]
);
const { Admin } = result[0];
res.json({ isAdmin: Admin });
} catch (error) {
res.json({ error: "Cannot verify admin status!" });
}
};