SQL CODE BUGS FIXES

Login Auth now implemented
Persistance login page
AI app.jsx formating
This commit is contained in:
Mann Patel
2025-03-12 16:13:03 -06:00
parent 864a386ba2
commit 6798a5c6a6
8 changed files with 756 additions and 319 deletions

View File

@@ -1,10 +1,13 @@
import express, { json } from "express";
import cors from "cors";
import mysql from "mysql2";
import nodemailer from "nodemailer";
import crypto from "crypto";
import jwt from "jsonwebtoken";
const app = express();
app.use(cors());
app.use(json());
app.use(express.json());
//TODO: Connect with the database:
const db_con = mysql.createConnection({
@@ -23,24 +26,236 @@ db_con.connect((err) => {
console.log("Connected to MySQL database.");
});
//TODO: Create a users:
app.post("/create_users", (req, res) => {
const data = req.body;
db_con.query(
`INSERT INTO Users (Name, Email, UCID, Password, Phone, Address)
VALUES ('${data.name}', '${data.email}', '${data.UCID}', '${data.password}', '${data.phone}', '${data.address}');`,
);
db_con.query(
`INSERT INTO UserRole (Role)
VALUES ('${data.role}');`,
);
console.log(data);
res.send();
// Configure email transporter for Zoho
const transporter = nodemailer.createTransport({
host: "smtp.zohocloud.ca",
secure: true,
port: 465,
auth: {
user: "campusplug@zohomailcloud.ca", //Zoho email
pass: "NzaZ7FFKNh18", //Zoho password
},
});
// Test the email connection
transporter
.verify()
.then(() => {
console.log("Email connection successful!");
})
.catch((error) => {
console.error("Email connection failed:", error);
});
// Generate and send verification code for signup
app.post("/send-verification", 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
db_con.query(
"SELECT * FROM AuthVerification WHERE Email = ?",
[email],
async (err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length > 0) {
// Update existing record
db_con.query(
"UPDATE AuthVerification SET VerificationCode = ?, Authenticated = FALSE, Date = CURRENT_TIMESTAMP WHERE Email = ?",
[verificationCode, email],
async (err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
},
);
} else {
// Insert new record
db_con.query(
"INSERT INTO AuthVerification (Email, VerificationCode, Authenticated) VALUES (?, ?, FALSE)",
[email, verificationCode],
async (err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
// 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" });
}
});
// Helper function to send email
async function sendVerificationEmail(email, verificationCode) {
// Send the email with Zoho
await transporter.sendMail({
from: "campusplug@zohomailcloud.ca",
to: email,
subject: "Your Verification Code",
text: `Your verification code is: ${verificationCode}. This code will expire in 15 minutes.`,
html: `<p>Your verification code is: <strong>${verificationCode}</strong></p><p>This code will expire in 15 minutes.</p>`,
});
console.log(`Verification code sent to ${email}`);
}
// Verify the code
app.post("/verify-code", (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}`);
// Check verification code
db_con.query(
"SELECT * FROM AuthVerification WHERE Email = ? AND VerificationCode = ? AND Authenticated = FALSE AND Date > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
[email, code],
(err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
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
db_con.query(
"UPDATE AuthVerification SET Authenticated = TRUE WHERE Email = ?",
[email],
(err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
console.log(`Email ${email} successfully verified`);
res.json({
success: true,
message: "Verification successful",
userId,
});
},
);
},
);
});
// Create a users and Complete user registration after verification
app.post("/complete-registration", (req, res) => {
const data = req.body;
db_con.query(
`SELECT * FROM AuthVerification WHERE Email = ${data.email} AND Authenticated = 1`,
(err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length === 0) {
return res.status(400).json({ error: "Email not verified" });
}
// Create the user
db_con.query(
`INSERT INTO User (Name, Email, UCID, Password, Phone, Address)
VALUES (${data.name}, ${data.email}, ${data.UCID}, ${data.password}, ${data.phone}, ${data.address})`,
(err, result) => {
if (err) {
console.error("Error creating user:", err);
return res.status(500).json({ error: "Could not create user" });
}
// Insert role using the user's ID
db_con.query(
`INSERT INTO UserRole (UserID, Client, Admin)
VALUES (LAST_INSERT_ID(), ${data.client || true}, ${data.admin || false})`,
(roleErr) => {
if (roleErr) {
console.error("Error creating role:", roleErr);
return res.status(500).json({ error: "Could not create role" });
}
// Delete verification record
db_con.query(
`DELETE FROM AuthVerification WHERE Email = ${data.email}`,
(deleteErr) => {
if (deleteErr) {
console.error("Error deleting verification:", deleteErr);
}
res.json({
success: true,
message: "User registration completed successfully",
userId: result.insertId,
});
},
);
},
);
},
);
},
);
});
// Clean up expired verification codes (run this periodically)
function cleanupExpiredCodes() {
db_con.query(
"DELETE FROM AuthVerification WHERE Date < DATE_SUB(NOW(), INTERVAL 15 MINUTE) AND Authenticated = 0",
(err, result) => {
if (err) {
console.error("Error cleaning up expired codes:", err);
} else {
console.log(
`Cleaned up ${result.affectedRows} expired verification codes`,
);
}
},
);
}
// Set up a scheduler to run cleanup every hour
setInterval(cleanupExpiredCodes, 60 * 60 * 1000);
//TODO: Fetch all users data:
app.get("/fetch_all_users", (req, res) => {
db_con.query("SELECT * FROM Users;", (err, data) => {
db_con.query("SELECT * FROM User;", (err, data) => {
if (err) {
console.error("Errors: ", err);
return res.status(500).json({ error: "\nCould not fetch users!" });
@@ -50,9 +265,55 @@ app.get("/fetch_all_users", (req, res) => {
});
//TODO: Fetch One user Data:
app.post("/find_user", (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",
});
}
// Query to find user with matching email and password
const query = "SELECT * FROM User WHERE email = ? AND password = ?";
db_con.query(query, [email, password], (err, data) => {
if (err) {
console.error("Error finding user:", err);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
// Check if user was found
if (data && data.length > 0) {
console.log(data);
const user = data[0];
// Return user data without sensitive information
return res.json({
found: true,
name: user.Name,
email: user.Email,
});
} else {
// User not found or invalid credentials
return res.json({
found: false,
error: "Invalid email or password",
});
}
});
});
//TODO: Update A uses Data:
//TODO: Delete A uses Data:
app.listen(3030, () => {
console.log("Running Backend on http://localhost:3030/");
console.log(`Running Backend on http://localhost:3030/`);
console.log(`Send verification code: POST /send-verification`);
console.log(`Verify code: POST /verify-code`);
});

View File

@@ -9,11 +9,15 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.3",
"cors": "^2.8.5",
"crypto": "^1.0.1",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"jsonwebtoken": "^9.0.2",
"mysql": "^2.18.1",
"mysql2": "^3.12.0"
"mysql2": "^3.12.0",
"nodemailer": "^6.10.0"
}
},
"node_modules/accepts": {
@@ -77,6 +81,12 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -170,6 +180,13 @@
"node": ">= 0.10"
}
},
"node_modules/crypto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.",
"license": "ISC"
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -233,6 +250,15 @@
"node": ">= 0.4"
}
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -521,6 +547,97 @@
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/jsonwebtoken": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
"license": "MIT",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^7.5.4"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jsonwebtoken/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"license": "MIT",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
"license": "MIT"
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
"license": "MIT"
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
"license": "MIT"
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
"license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"license": "MIT"
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
"license": "MIT"
},
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
"license": "MIT"
},
"node_modules/long": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz",
@@ -709,6 +826,15 @@
"node": ">= 0.6"
}
},
"node_modules/nodemailer": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz",
"integrity": "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -862,6 +988,18 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/send": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",

View File

@@ -5,17 +5,21 @@
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
"dev": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"body-parser": "^1.20.3",
"cors": "^2.8.5",
"crypto": "^1.0.1",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"jsonwebtoken": "^9.0.2",
"mysql": "^2.18.1",
"mysql2": "^3.12.0"
"mysql2": "^3.12.0",
"nodemailer": "^6.10.0"
}
}