final authenticated api using docker, built new image installing mysql-client and nano on top of nodejs image

This commit is contained in:
2024-09-20 11:16:08 +08:00
commit 22f21cff4c
15 changed files with 2056 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
app/node_modules
.env
+2
View File
@@ -0,0 +1,2 @@
node_modules
npm-debug.log
+23
View File
@@ -0,0 +1,23 @@
# Use the official Node.js image as the base image
FROM node:latest
# Update the package lists and install default-mysql-client
RUN apt-get update && apt-get install -y nano && apt-get install -y default-mysql-client
# Set the working directory
WORKDIR /app
# Copy application files
COPY . .
# Install application dependencies
RUN npm install
# Expose port 3000
EXPOSE 3000
# Define the command to run your application
CMD ["npm", "start"]
+23
View File
@@ -0,0 +1,23 @@
const express = require("express");
const router = express.Router();
const db = require("../../config/db");
const verifyToken = require("../../middlewares/authMiddleware");
router.get("/", verifyToken, (req, res) => {
const caseidPattern = req.query.caseidPattern + "%";
const batchno = parseInt(req.query.batchno, 10) || 1;
const sql =
"SELECT id, uuid, caseid, modified_time FROM popcen WHERE caseid LIKE ? LIMIT ? OFFSET ?";
const limit = 1000;
const offset = (batchno - 1) * limit;
db.query(sql, [caseidPattern, limit, offset], (err, results) => {
if (err) {
console.error(err);
return res.status(500).send("Server error");
}
res.json({ batchno, results });
});
});
module.exports = router;
+19
View File
@@ -0,0 +1,19 @@
const express = require("express");
const router = express.Router();
const db = require("../../config/db");
const verifyToken = require("../../middlewares/authMiddleware");
router.get("/", verifyToken, (req, res) => {
const caseidPattern = req.query.caseidPattern + "%";
const sql = "SELECT COUNT(id) AS count FROM popcen WHERE caseid LIKE ?";
db.query(sql, [caseidPattern], (err, results) => {
if (err) {
console.error(err);
return res.status(500).send("Server error");
}
res.json(results[0].count);
});
});
module.exports = router;
+48
View File
@@ -0,0 +1,48 @@
const express = require("express");
const router = express.Router();
const bcrypt = require("bcrypt"); // bcrypt for password hashing
const db = require("../../config/db");
// User registration endpoint
router.post("/", async (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).send("Username and password are required");
}
// Check if the username already exists
const sqlCheck = "SELECT * FROM tbl_user WHERE username = ?";
db.query(sqlCheck, [username], async (err, results) => {
if (err) {
console.error(err);
return res.status(500).send("Server error");
}
if (results.length > 0) {
return res.status(400).send("Username already exists");
}
try {
// Hash the password using bcrypt
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds);
// Insert the new user into the database with the hashed password
const sqlInsert = "INSERT INTO tbl_user (username, password) VALUES (?, ?)";
db.query(sqlInsert, [username, hashedPassword], (err, result) => {
if (err) {
console.error(err);
return res.status(500).send("Server error");
}
res.status(201).send("User registered successfully");
});
} catch (error) {
console.error(error);
res.status(500).send("Error registering user");
}
});
});
module.exports = router;
+46
View File
@@ -0,0 +1,46 @@
// User login endpoint
router.post("/login", (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).send("Username and password are required");
}
// Check the current database
db.query("SELECT DATABASE();", (err, results) => {
if (err) {
console.error(err);
return res.status(500).send("Error retrieving database name");
}
console.log("Current database:", results[0]['DATABASE()']); // Log the current database
const sql = "SELECT * FROM tbl_user WHERE username = ?";
db.query(sql, [username], async (err, results) => {
if (err) {
console.error(err);
return res.status(500).send("Server error");
}
if (results.length === 0) {
return res.status(401).send("Invalid credentials");
}
const user = results[0];
// Compare provided password with the hashed password in the database
const isMatch = await bcrypt.compare(password, user.password);
if (isMatch) {
let jwtSecretKey = process.env.JWT_SECRET_KEY || "defaultSecretKey";
let data = { userId: user.id, username: user.username };
// Create JWT token
const token = jwt.sign(data, jwtSecretKey, { expiresIn: "1d" });
return res.json({ token });
} else {
return res.status(401).send("Invalid credentials");
}
});
});
});
+21
View File
@@ -0,0 +1,21 @@
const mysql = require("mysql2");
const dotenv = require("dotenv");
dotenv.config();
const db = mysql.createConnection({
host: 'mysql',
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
db.connect((err) => {
if (err) {
console.error("Database connection failed:", err.stack);
return;
}
console.log("Connected to the MySQL database.");
});
module.exports = db;
+21
View File
@@ -0,0 +1,21 @@
const jwt = require("jsonwebtoken");
const verifyToken = (req, res, next) => {
const token = req.header("Authorization");
if (!token) {
return res.status(403).send("A token is required for authentication");
}
try {
const jwtSecretKey = process.env.JWT_SECRET_KEY || "default_secret_key";
const decoded = jwt.verify(token.replace("Bearer ", ""), jwtSecretKey);
req.user = decoded;
} catch (err) {
return res.status(401).send("Invalid Token");
}
return next();
};
module.exports = verifyToken;
+1731
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
{
"name": "api",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "F04C, Michael, Ronmel",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"bcryptjs": "^2.4.3",
"dotenv": "^16.4.5",
"express": "^4.21.0",
"jsonwebtoken": "^9.0.2",
"mysql": "^2.18.1",
"mysql2": "^3.11.3"
},
"keywords": [],
"description": ""
}
+41
View File
@@ -0,0 +1,41 @@
const express = require("express");
const dotenv = require("dotenv");
const bodyParser = require("body-parser");
const jwt = require("jsonwebtoken");
const app = express();
dotenv.config();
app.use(bodyParser.json());
const authenticateToken = (req, res, next) => {
const token = req.header("Authorization")?.split(" ")[1];
if (!token) {
return res.status(403).send("A token is required for authentication");
}
try {
const jwtSecretKey = process.env.JWT_SECRET_KEY || "defaultSecretKey";
const verified = jwt.verify(token, jwtSecretKey);
req.user = verified;
} catch (err) {
return res.status(401).send("Invalid token");
}
next();
};
const popcenRoutes = require("./api/routes/popcen");
const popcenCountRoutes = require("./api/routes/popcenCount");
const userRoutes = require("./api/routes/user");
const registerRoutes = require("./api/routes/register");
app.use("/user", userRoutes);
app.use("/user/register", registerRoutes);
app.use("/popcen", authenticateToken, popcenRoutes);
app.use("/popcenCount", authenticateToken, popcenCountRoutes);
const PORT = process.env.PORT || 3000;
app.listen(PORT,'0.0.0.0', () => {
console.log(`Server is running on port ${PORT}`);
});
+14
View File
@@ -0,0 +1,14 @@
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: always
ports:
- "9000:9000" # Port for Portainer web UI
- "9443:9443" # Port for Portainer HTTPS
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Access Docker daemon
- portainer_data:/data # Portainer data storage
volumes:
portainer_data:
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
cd /usr/src/app
npm install
npm start
+36
View File
@@ -0,0 +1,36 @@
services:
mysql:
image: mysql:latest
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: 12345678
MYSQL_DATABASE: popcen
MYSQL_PASSWORD: 12345678
ports:
- "3307:3306"
volumes:
- mysqldata:/var/lib/mysql
extra_hosts:
- "host.docker.internal:host-gateway"
nodejs:
image: f04c/nodemysqlv2:latest
container_name: nodejs
working_dir: /app
volumes:
- API2:/app
ports:
- "3001:3000"
environment:
DB_HOST: 192.168.23.20
DB_USER: root
DB_PASSWORD: 12345678
DB_NAME: popcen
depends_on:
- mysql
command: "node server.js"
volumes:
API2:
mysqldata: