update authentication
This commit is contained in:
parent
063f96c19d
commit
2a6fcd6227
|
|
@ -123,23 +123,29 @@
|
||||||
|
|
||||||
async function getProfile() {
|
async function getProfile() {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
|
const user = JSON.parse(localStorage.getItem("user"));
|
||||||
|
|
||||||
await fetch("/api/profile", {
|
await fetch("/api/confirm-count", {
|
||||||
method: "GET",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
email: user.email,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
document.getElementById(
|
document.getElementById(
|
||||||
"welcome-user",
|
"welcome-user",
|
||||||
).innerHTML = `Welcome, <strong>${data?.user?.name}</strong> ▼`;
|
).innerHTML = `Welcome, <strong>${
|
||||||
|
JSON.parse(localStorage.getItem("user")).name
|
||||||
|
}</strong> ▼`;
|
||||||
|
|
||||||
document.getElementById(
|
document.getElementById(
|
||||||
"confirm-count-user",
|
"confirm-count-user",
|
||||||
).innerHTML = `Confirmed: <strong>${data?.user?.confirm_count}</strong>`;
|
).innerHTML = `Confirmed: <strong>${data?.count}</strong>`;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
@ -304,8 +310,7 @@
|
||||||
);
|
);
|
||||||
if (currentVerUser) {
|
if (currentVerUser) {
|
||||||
deviceConfirmBtn.style.display = "none";
|
deviceConfirmBtn.style.display = "none";
|
||||||
confirmedUserName.textContent =
|
confirmedUserName.textContent = currentVerUser.user;
|
||||||
currentVerUser.user.name;
|
|
||||||
confirmUserText.style.display = "inline";
|
confirmUserText.style.display = "inline";
|
||||||
} else {
|
} else {
|
||||||
deviceConfirmBtn.style.display = "inline-block";
|
deviceConfirmBtn.style.display = "inline-block";
|
||||||
|
|
@ -602,6 +607,7 @@ ${license}`.trim();
|
||||||
if (!pendingDevice) return;
|
if (!pendingDevice) return;
|
||||||
|
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
|
const user = JSON.parse(localStorage.getItem("user"));
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/confirm-device", {
|
const res = await fetch("/api/confirm-device", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -609,7 +615,11 @@ ${license}`.trim();
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(pendingDevice),
|
body: JSON.stringify({
|
||||||
|
...pendingDevice,
|
||||||
|
name: user.name,
|
||||||
|
email: user.email,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,17 @@
|
||||||
const errorMsg = document.querySelector(".error-msg");
|
const errorMsg = document.querySelector(".error-msg");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/login", {
|
const res = await fetch(
|
||||||
|
"https://stage.nswteam.net/api/login",
|
||||||
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ email, password }),
|
body: JSON.stringify({
|
||||||
});
|
userEmail: email,
|
||||||
|
password,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
|
|
@ -83,7 +89,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("token", data.token);
|
localStorage.setItem("token", data.token);
|
||||||
localStorage.setItem("user", JSON.stringify(data.user));
|
localStorage.setItem(
|
||||||
|
"user",
|
||||||
|
JSON.stringify({
|
||||||
|
name:
|
||||||
|
data.data.firstName +
|
||||||
|
" " +
|
||||||
|
data.data.lastName,
|
||||||
|
email: data.data.userEmail,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
58
route/web.js
58
route/web.js
|
|
@ -1,8 +1,5 @@
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const bcrypt = require("bcrypt");
|
|
||||||
const { createToken } = require("../utils/jwt");
|
|
||||||
const { authenticateToken } = require("../middleware/auth");
|
|
||||||
|
|
||||||
let router = express.Router();
|
let router = express.Router();
|
||||||
|
|
||||||
|
|
@ -15,60 +12,5 @@ module.exports = (app, db) => {
|
||||||
res.sendFile(path.join(__dirname, "../public/login.html"));
|
res.sendFile(path.join(__dirname, "../public/login.html"));
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/api/login", async (req, res) => {
|
|
||||||
const { email, password } = req.body;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [rows] = await db.query(
|
|
||||||
"SELECT * FROM users WHERE email = ?",
|
|
||||||
[email],
|
|
||||||
);
|
|
||||||
const user = rows[0];
|
|
||||||
const isMatch = await bcrypt.compare(
|
|
||||||
password,
|
|
||||||
user?.password || "!@#",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!user || !isMatch) {
|
|
||||||
return res
|
|
||||||
.status(401)
|
|
||||||
.json({ message: "Invalid email or password" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = createToken({
|
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
});
|
|
||||||
return res
|
|
||||||
.status(200)
|
|
||||||
.json({ token, user: { name: user.name, email: user.email } });
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Login error:", err);
|
|
||||||
return res.status(500).json({ message: "Internal Server Error" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get("/api/profile", authenticateToken, async (req, res) => {
|
|
||||||
const userId = req.user?.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [rows] = await db.query("SELECT * FROM users WHERE id = ?", [
|
|
||||||
userId,
|
|
||||||
]);
|
|
||||||
const user = rows[0];
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
user: {
|
|
||||||
name: user.name,
|
|
||||||
confirm_count: user.confirm_count,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return res.status(500).json({ message: "Internal Server Error" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use("/", router);
|
app.use("/", router);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
109
server.js
109
server.js
|
|
@ -5,9 +5,7 @@ const dotenv = require("dotenv");
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const stringSimilarity = require("string-similarity");
|
const stringSimilarity = require("string-similarity");
|
||||||
const bcrypt = require("bcrypt");
|
|
||||||
const inititalWebRoute = require("./route/web");
|
const inititalWebRoute = require("./route/web");
|
||||||
const { authenticateToken } = require("./middleware/auth");
|
|
||||||
|
|
||||||
// Nhận mảng message đầu vào, trả về mảng message đã loại bỏ trùng lặp
|
// Nhận mảng message đầu vào, trả về mảng message đã loại bỏ trùng lặp
|
||||||
function deduplicateErrors(errors, threshold = 0.3) {
|
function deduplicateErrors(errors, threshold = 0.3) {
|
||||||
|
|
@ -37,10 +35,17 @@ app.use(bodyParser.json());
|
||||||
app.use(express.static("public"));
|
app.use(express.static("public"));
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
// const db = mysql.createPool({
|
||||||
|
// host: "localhost",
|
||||||
|
// user: "admin",
|
||||||
|
// password: "Work1234",
|
||||||
|
// database: "log_analysis",
|
||||||
|
// });
|
||||||
|
|
||||||
const db = mysql.createPool({
|
const db = mysql.createPool({
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
user: "admin",
|
user: "root",
|
||||||
password: "Work1234",
|
password: "",
|
||||||
database: "log_analysis",
|
database: "log_analysis",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -54,21 +59,6 @@ async function columnExists(table, column) {
|
||||||
return rows[0].count > 0;
|
return rows[0].count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkAndInsertAdminUser = async () => {
|
|
||||||
const [rows] = await db.query(`SELECT id FROM users WHERE email = ?`, [
|
|
||||||
"admin@apactech.io",
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (rows.length === 0) {
|
|
||||||
const hashedPassword = await bcrypt.hash("admin0312", 10);
|
|
||||||
|
|
||||||
await db.query(
|
|
||||||
`INSERT INTO users (name, email, password) VALUES (?, ?, ?)`,
|
|
||||||
["Admin", "admin@apactech.io", hashedPassword],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// === Tạo bảng
|
// === Tạo bảng
|
||||||
(async () => {
|
(async () => {
|
||||||
await db.query(`
|
await db.query(`
|
||||||
|
|
@ -94,11 +84,24 @@ const checkAndInsertAdminUser = async () => {
|
||||||
await db.query(`ALTER TABLE devices DROP COLUMN updated_by`);
|
await db.query(`ALTER TABLE devices DROP COLUMN updated_by`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(await columnExists("devices", "updated_user"))) {
|
if (await columnExists("devices", "updated_user")) {
|
||||||
|
await db.query(
|
||||||
|
`ALTER TABLE devices DROP FOREIGN KEY fk_updated_by_user`,
|
||||||
|
);
|
||||||
|
await db.query(`ALTER TABLE devices DROP COLUMN updated_user`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await columnExists("devices", "update_name"))) {
|
||||||
await db.query(`
|
await db.query(`
|
||||||
ALTER TABLE devices
|
ALTER TABLE devices
|
||||||
ADD COLUMN updated_user INT DEFAULT NULL,
|
ADD COLUMN update_name VARCHAR(255)
|
||||||
ADD CONSTRAINT fk_updated_by_user FOREIGN KEY (updated_user) REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await columnExists("devices", "update_email"))) {
|
||||||
|
await db.query(`
|
||||||
|
ALTER TABLE devices
|
||||||
|
ADD COLUMN update_email VARCHAR(255)
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,9 +124,9 @@ const checkAndInsertAdminUser = async () => {
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
if (!(await columnExists(`${command}_outputs`, "is_deleted"))) {
|
if (await columnExists(`${command}_outputs`, "is_deleted")) {
|
||||||
await db.query(
|
await db.query(
|
||||||
`ALTER TABLE ${command}_outputs ADD COLUMN is_deleted BOOLEAN DEFAULT FALSE`,
|
`ALTER TABLE ${command}_outputs DROP COLUMN is_deleted`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -134,18 +137,8 @@ const checkAndInsertAdminUser = async () => {
|
||||||
await createOutputTable("logging");
|
await createOutputTable("logging");
|
||||||
|
|
||||||
await db.query(`
|
await db.query(`
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
DROP TABLE IF EXISTS users
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
name VARCHAR(100) NOT NULL,
|
|
||||||
email VARCHAR(100) NOT NULL UNIQUE,
|
|
||||||
password VARCHAR(255) NOT NULL,
|
|
||||||
confirm_count INT DEFAULT 0,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await checkAndInsertAdminUser();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// === APIs ===
|
// === APIs ===
|
||||||
|
|
@ -162,7 +155,7 @@ app.get("/api/pid/:pid/versions", async (req, res) => {
|
||||||
|
|
||||||
// Lấy danh sách các version tương ứng với PID
|
// Lấy danh sách các version tương ứng với PID
|
||||||
const [devices] = await db.query(
|
const [devices] = await db.query(
|
||||||
"SELECT id, version, updated_user FROM devices WHERE pid = ?",
|
"SELECT id, version, update_name FROM devices WHERE pid = ?",
|
||||||
[pid],
|
[pid],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -171,12 +164,7 @@ app.get("/api/pid/:pid/versions", async (req, res) => {
|
||||||
for (const device of devices) {
|
for (const device of devices) {
|
||||||
const deviceId = device.id;
|
const deviceId = device.id;
|
||||||
const version = device.version;
|
const version = device.version;
|
||||||
const userId = device.updated_user;
|
|
||||||
|
|
||||||
const [user] = await db.query(
|
|
||||||
"SELECT id, name FROM users WHERE id = ?",
|
|
||||||
[userId],
|
|
||||||
);
|
|
||||||
const [[inv]] = await db.query(
|
const [[inv]] = await db.query(
|
||||||
"SELECT COUNT(*) AS c FROM inventory_outputs WHERE device_id = ?",
|
"SELECT COUNT(*) AS c FROM inventory_outputs WHERE device_id = ?",
|
||||||
[deviceId],
|
[deviceId],
|
||||||
|
|
@ -195,7 +183,7 @@ app.get("/api/pid/:pid/versions", async (req, res) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
user: user[0],
|
user: device.update_name,
|
||||||
version,
|
version,
|
||||||
commands: {
|
commands: {
|
||||||
inventory: inv.c,
|
inventory: inv.c,
|
||||||
|
|
@ -219,16 +207,15 @@ app.get("/api/device/:pid/:version/:command", async (req, res) => {
|
||||||
if (!device) return res.status(404).json({ message: "Not found" });
|
if (!device) return res.status(404).json({ message: "Not found" });
|
||||||
|
|
||||||
const [logs] = await db.query(
|
const [logs] = await db.query(
|
||||||
`SELECT id, filename, output, created_at, is_deleted FROM ${command}_outputs WHERE device_id = ? ORDER BY created_at DESC`,
|
`SELECT id, filename, output, created_at FROM ${command}_outputs WHERE device_id = ? ORDER BY created_at DESC`,
|
||||||
[device.id],
|
[device.id],
|
||||||
);
|
);
|
||||||
|
|
||||||
res.json(logs);
|
res.json(logs);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/confirm-device", authenticateToken, async (req, res) => {
|
app.post("/api/confirm-device", async (req, res) => {
|
||||||
const { pid, version, deletedLogs } = req.body;
|
const { pid, version, deletedLogs, name, email } = req.body;
|
||||||
const updatedBy = req.user?.id;
|
|
||||||
|
|
||||||
if (!pid || !version) {
|
if (!pid || !version) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
|
|
@ -263,9 +250,10 @@ app.post("/api/confirm-device", authenticateToken, async (req, res) => {
|
||||||
`UPDATE devices
|
`UPDATE devices
|
||||||
SET is_confirmed = true,
|
SET is_confirmed = true,
|
||||||
updated_at = CURRENT_TIMESTAMP,
|
updated_at = CURRENT_TIMESTAMP,
|
||||||
updated_user = ?
|
update_name = ?,
|
||||||
|
update_email = ?
|
||||||
WHERE pid = ? AND version = ?`,
|
WHERE pid = ? AND version = ?`,
|
||||||
[updatedBy, pid, version],
|
[name, email, pid, version],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Delete Log
|
// Delete Log
|
||||||
|
|
@ -297,11 +285,6 @@ app.post("/api/confirm-device", authenticateToken, async (req, res) => {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.query(
|
|
||||||
"UPDATE users SET confirm_count = confirm_count + 1 WHERE id = ?",
|
|
||||||
[updatedBy],
|
|
||||||
);
|
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: "Device confirmed successfully!",
|
message: "Device confirmed successfully!",
|
||||||
|
|
@ -315,6 +298,26 @@ app.post("/api/confirm-device", authenticateToken, async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post("/api/confirm-count", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { email } = req.body;
|
||||||
|
|
||||||
|
if (!email) {
|
||||||
|
return res.status(400).json({ error: "Email is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const [[result]] = await db.query(
|
||||||
|
"SELECT COUNT(*) AS c FROM devices WHERE update_email = ?",
|
||||||
|
[email],
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json({ count: result.c });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching confirm count:", err);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Danh sách regex lọc lỗi
|
// Danh sách regex lọc lỗi
|
||||||
const errorPatterns = [
|
const errorPatterns = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue