Add CORS middleware and user database schema

- Implemented CORS middleware in the project to handle cross-origin requests.
- Added necessary files for the CORS package including README, LICENSE, and history documentation.
- Created a SQL schema for the users table with appropriate fields and constraints.
- Inserted mock data into the users table for testing purposes.
This commit is contained in:
2025-07-21 17:38:25 +02:00
parent 46fa608a47
commit e4bceb8258
24 changed files with 1644 additions and 29 deletions

4
backend/.env Executable file
View File

@@ -0,0 +1,4 @@
DB_HOST=mysql
DB_USER=root
DB_PASSWORD=D7Ze0lwV9hMrNQHdz1Q8yi0MIQuOO8
DB_NAME=bikelane

142
backend/database.js Normal file
View File

@@ -0,0 +1,142 @@
import mysql from "mysql2";
import dotenv from "dotenv";
import { error } from "console";
dotenv.config();
// Create a MySQL connection pool using environment variables for configuration
const pool = mysql
.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
})
.promise();
// Function to authenticate a user by username and password
export async function loginUser(username, password) {
// Query the users table for a matching username and password
const [result] = await pool.query(
"SELECT * FROM users WHERE username = ? AND password = ?",
[username, password]
);
// If a user is found, return success and user data
if (result.length > 0) {
console.log("User found: ", result[0].username, " ", result[0].id);
return { success: true, user: result[0] };
} else {
// If no user is found, return failure message
console.error(`Invalid username or password!; ${result[0]}`);
return { success: false, message: "Invalid username or password" };
}
}
// Function to create a new user in the database
export async function createUser(
username,
first_name,
last_name,
password,
email
) {
try {
// Insert a new user record into the users table
const [result] = await pool.query(
"INSERT INTO users (username, first_name, last_name, password, email) VALUES (?, ?, ?, ?, ?)",
[username, first_name, last_name, password, email]
);
console.log("User created successfully!");
return { success: true, message: "User created successfully!" };
} catch (error) {
// Handle errors during user creation
console.log("Error creating user: ", error);
return { success: false, message: "Error creating user!" };
}
}
// Function to update an existing user's information
export async function updateUser(
username,
first_name,
last_name,
password,
email
) {
try {
// Update user details based on username
const [result] = await pool.query(
"UPDATE users SET first_name = ?, last_name = ?, password = ?, email = ? WHERE username = ?",
[first_name, last_name, password, email, username]
);
const resultOfquery = result.affectedRows;
// If a user was updated, return success
if (resultOfquery > 0) {
console.log("User updated successfully!");
return {
success: true,
message: "User updated successfully!",
resultOfquery: result,
};
}
// If no user was updated, return failure
if (resultOfquery === 0) {
console.log("Error updating user!");
return {
success: false,
message: "Error updating user!",
resultOfquery: null,
};
}
} catch (err) {}
}
// Function to delete a user from the database
export async function deleteUser(
username,
first_name,
last_name,
password,
email
) {
try {
// Delete user based on username and password
const [result] = await pool.query(
"DELETE FROM users WHERE username = ? AND password = ?",
[username, password]
);
const resultOfquery = result.affectedRows;
// If a user was deleted, return success
if (resultOfquery > 0) {
console.log("User deleted successfully!");
return {
success: true,
message: "User deleted successfully!",
resultOfquery: result,
};
}
// If no user was deleted, return failure
if (resultOfquery === 0) {
console.log("Error deleting user!");
return {
success: false,
message: "Error deleting user!",
resultOfquery: null,
};
}
} catch (err) {}
}
export async function getAllUsers() {
try {
const [data] = await pool.query("SELECT * FROM users;");
return { result: data, success: true };
} catch (err) {
return { result: err, success: false };
}
}

View File

@@ -9,8 +9,11 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^17.2.0",
"ejs": "^3.1.10",
"express": "^5.1.0"
"express": "^5.1.0",
"mysql2": "^3.14.2"
}
},
"node_modules/accepts": {
@@ -47,6 +50,15 @@
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"license": "MIT"
},
"node_modules/aws-ssl-profiles": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
"integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -200,6 +212,19 @@
"node": ">=6.6.0"
}
},
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"license": "MIT",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
@@ -217,6 +242,15 @@
}
}
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -226,6 +260,18 @@
"node": ">= 0.8"
}
},
"node_modules/dotenv": {
"version": "17.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.0.tgz",
"integrity": "sha512-Q4sgBT60gzd0BB0lSyYD3xM4YxrXA9y4uBDof1JNYGzOXrQdQ6yX+7XIAqoFOGQFOTK1D3Hts5OllpxMDZFONQ==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -431,6 +477,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"license": "MIT",
"dependencies": {
"is-property": "^1.0.2"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -571,6 +626,12 @@
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
"license": "MIT"
},
"node_modules/jake": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
@@ -589,6 +650,36 @@
"node": ">=10"
}
},
"node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"license": "Apache-2.0"
},
"node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/lru.min": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz",
"integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==",
"license": "MIT",
"engines": {
"bun": ">=1.0.0",
"deno": ">=1.30.0",
"node": ">=8.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wellwelwel"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -658,6 +749,38 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/mysql2": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.2.tgz",
"integrity": "sha512-YD6mZMeoypmheHT6b2BrVmQFvouEpRICuvPIREulx2OvP1xAxxeqkMQqZSTBefv0PiOBKGYFa2zQtY+gf/4eQw==",
"license": "MIT",
"dependencies": {
"aws-ssl-profiles": "^1.1.1",
"denque": "^2.1.0",
"generate-function": "^2.3.1",
"iconv-lite": "^0.6.3",
"long": "^5.2.1",
"lru.min": "^1.0.0",
"named-placeholders": "^1.1.3",
"seq-queue": "^0.0.5",
"sqlstring": "^2.3.2"
},
"engines": {
"node": ">= 8.0"
}
},
"node_modules/named-placeholders": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
"license": "MIT",
"dependencies": {
"lru-cache": "^7.14.1"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
@@ -667,6 +790,15 @@
"node": ">= 0.6"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -834,6 +966,11 @@
"node": ">= 18"
}
},
"node_modules/seq-queue": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
},
"node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
@@ -927,6 +1064,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",

View File

@@ -12,7 +12,10 @@
"license": "ISC",
"description": "",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^17.2.0",
"ejs": "^3.1.10",
"express": "^5.1.0"
"express": "^5.1.0",
"mysql2": "^3.14.2"
}
}

View File

@@ -1,15 +1,46 @@
//statics
import express from "express";
import cors from "cors";
const app = express();
const port = 5002;
import {
loginUser,
createUser,
updateUser,
deleteUser,
getAllUsers,
} from "./database.js";
//view engine ejs
app.set("view engine", "ejs");
app.use(express.json());
app.use(cors());
app.get("/", (req, res) => {
res.render("index.ejs");
});
app.post("/api/login", async (req, res) => {
console.log(req.body);
loginUser(req.body.username, req.body.password)
.then((result) => {
if (result.success) {
res.status(200).json(result);
} else {
res.status(401).json(result);
}
})
.catch((err) => {
console.error("Error logging in:", err);
res
.status(500)
.json({ success: false, message: "Internal server error" });
});
});
app.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
});