Merge branch 'main' of https://github.com/Newtbot/MP
This commit is contained in:
commit
899eaf202a
@ -1,12 +1,13 @@
|
||||
const nodemailer = require("nodemailer");
|
||||
const otpGenerator = require('otp-generator');
|
||||
const path = require('path')
|
||||
const path = require('path');
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const generateOTP = () => {
|
||||
const otp = otpGenerator.generate(6, { upperCase: false, specialChars: false });
|
||||
const otp = otpGenerator.generate(8, { upperCase: true, specialChars: true });
|
||||
const expirationTime = Date.now() + 5 * 60 * 1000; // 5 minutes expiration
|
||||
return { otp, expirationTime };
|
||||
|
||||
};
|
||||
const sendOTPByEmail = async (email, otp) => {
|
||||
try {
|
||||
|
@ -20,7 +20,7 @@ const locationdeleteValidation = [
|
||||
const sensorValidation = [
|
||||
body('sensorname').trim().isLength({ min: 1 }).withMessage('Sensor Name must not be empty').escape(),
|
||||
body('added_by').trim().isLength({ min: 1 }).withMessage('Added by must not be empty').escape(),
|
||||
body('macAddress').custom(value => {
|
||||
body('macAddress').escape().custom(value => {
|
||||
const macAddressRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
|
||||
if (!macAddressRegex.test(value)) {
|
||||
throw new Error('Invalid MAC address format');
|
||||
@ -35,7 +35,7 @@ const sensorupdateValidation = [
|
||||
body('id').trim().escape(),
|
||||
body('sensorname').trim().isLength({ min: 1 }).withMessage('Sensor Name must not be empty').escape(),
|
||||
body('added_by').trim().isLength({ min: 1 }).withMessage('Added by must not be empty').escape(),
|
||||
body('macAddress').custom(value => {
|
||||
body('macAddress').escape().custom(value => {
|
||||
const macAddressRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
|
||||
if (!macAddressRegex.test(value)) {
|
||||
throw new Error('Invalid MAC address format');
|
||||
|
@ -77,6 +77,7 @@ app.post('/login', loginValidation, async (req, res) => {
|
||||
req.session.otp = otp;
|
||||
req.session.otpExpiration = expirationTime;
|
||||
req.session.save();
|
||||
console.log(otp);
|
||||
|
||||
try {
|
||||
await sendOTPByEmail(user.email, otp);
|
||||
@ -160,7 +161,7 @@ app.post("/verify-otp", otpValidation ,async (req, res) => {
|
||||
req.session.authenticated = true;
|
||||
req.session.username = req.body.username;
|
||||
req.session.sessionToken = sessionToken;
|
||||
csrfTokenSession = crypto.randomBytes(32).toString('hex');
|
||||
req.session.csrfToken = crypto.randomBytes(32).toString('hex');
|
||||
|
||||
res.cookie('sessionToken', sessionToken, { secure: true, httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000) }); // Expires in 1 day
|
||||
|
||||
@ -205,16 +206,27 @@ app.post("/verify-otp", otpValidation ,async (req, res) => {
|
||||
res.status(500).send("Internal Server Error");
|
||||
}
|
||||
});
|
||||
|
||||
const getDatabaseStatus = async () => {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
return { connected: true };
|
||||
} catch (error) {
|
||||
console.error('Database connection error:', error);
|
||||
return { connected: false, error: error.message };
|
||||
}
|
||||
};
|
||||
|
||||
const getSystemHealth = async () => {
|
||||
const cpuInfo = await pidusage(process.pid);
|
||||
const databaseStatus = await getDatabaseStatus();
|
||||
return {
|
||||
serverStatus: { uptime: process.uptime() },
|
||||
databaseStatus: { connected: true }, // Replace with actual logic
|
||||
databaseStatus,
|
||||
resourceUtilization: {
|
||||
cpuUsage: cpuInfo.cpu,
|
||||
memoryUsage: process.memoryUsage(),
|
||||
},
|
||||
networkHealth: { latency: 10 }, // Replace with actual logic
|
||||
};
|
||||
};
|
||||
app.get("/home", isAuthenticated, async (req, res) => {
|
||||
@ -231,7 +243,7 @@ app.post("/verify-otp", otpValidation ,async (req, res) => {
|
||||
|
||||
const currentUsername = req.session.username;
|
||||
// Render the inusers page with JSON data
|
||||
res.render("inusers", {allUsers, csrfToken: csrfTokenSession, currentUsername });
|
||||
res.render("inusers", {allUsers, csrfToken: req.session.csrfToken, currentUsername });
|
||||
} catch (error) {
|
||||
console.error("Error fetching all users:", error);
|
||||
res.status(500).send("Internal Server Error");
|
||||
@ -286,8 +298,8 @@ app.post
|
||||
}
|
||||
// Validate the anti-CSRF token
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
|
||||
@ -519,7 +531,7 @@ app.post("/reset-password", async (req, res) => {
|
||||
const creatorUsername = req.session.username;
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const sessionTokencookie = req.cookies['sessionToken'];
|
||||
@ -632,7 +644,7 @@ app.delete('/api/deleteUser/:username', async (req, res) => {
|
||||
const { csrfToken } = req.body;
|
||||
console.log(csrfToken);
|
||||
// Compare CSRF token with the one stored in the session
|
||||
if (csrfToken !== csrfTokenSession) {
|
||||
if (csrfToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ success: false, error: 'CSRF token mismatch' });
|
||||
}
|
||||
|
||||
@ -691,7 +703,7 @@ app.get("/locations", isAuthenticated, async (req, res) => {
|
||||
const locationsData = response.data;
|
||||
|
||||
// Render the "locations" page with the fetched JSON data
|
||||
res.render("locations", { locationsData, csrfToken: csrfTokenSession});
|
||||
res.render("locations", { locationsData, csrfToken: req.session.csrfToken});
|
||||
} catch (error) {
|
||||
console.error("Error fetching locations:", error);
|
||||
res.status(500).send("Internal Server Error");
|
||||
@ -710,7 +722,7 @@ app.get("/locations", isAuthenticated, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Invalid sessionToken' });
|
||||
}
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const { name, added_by, description } = req.body;
|
||||
@ -737,7 +749,7 @@ app.get("/locations", isAuthenticated, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Invalid sessionToken' });
|
||||
}
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const { id, name, added_by, description } = req.body;
|
||||
@ -765,7 +777,7 @@ app.get("/locations", isAuthenticated, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Invalid sessionToken' });
|
||||
}
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const {id} = req.body;
|
||||
@ -787,7 +799,7 @@ app.get("/sensors", isAuthenticated, async (req, res) => {
|
||||
const locationsData = response.data;
|
||||
const response2 = await axios.get(process.env.API_ALLSENSOR);
|
||||
const sensorData = response2.data;
|
||||
res.render("sensors",{locationsData, sensorData, csrfToken: csrfTokenSession});
|
||||
res.render("sensors",{locationsData, sensorData, csrfToken: req.session.csrfToken});
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
res.status(500).send("Internal Server Error");
|
||||
@ -806,7 +818,7 @@ app.get("/sensors", isAuthenticated, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Invalid sessionToken' });
|
||||
}
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const { sensorname, added_by, macAddress, description, location} = req.body;
|
||||
@ -833,7 +845,7 @@ app.get("/sensors", isAuthenticated, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Invalid sessionToken' });
|
||||
}
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const { id, sensorname, added_by, macAddress, description, location} = req.body;
|
||||
@ -860,7 +872,7 @@ app.get("/sensors", isAuthenticated, async (req, res) => {
|
||||
return res.status(403).json({ error: 'Invalid sessionToken' });
|
||||
}
|
||||
const submittedCSRFToken = req.body.csrf_token;
|
||||
if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) {
|
||||
if (!req.session.csrfToken || submittedCSRFToken !== req.session.csrfToken) {
|
||||
return res.status(403).json({ error: 'CSRF token mismatch' });
|
||||
}
|
||||
const {id} = req.body;
|
||||
@ -875,6 +887,21 @@ app.get("/sensors", isAuthenticated, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/apilog", isAuthenticated, async (req, res) => {
|
||||
try {
|
||||
// Fetch data using Axios
|
||||
const response = await axios.get(process.env.API_LOGS);
|
||||
const logData = response.data;
|
||||
|
||||
// Render the "locations" page with the fetched JSON data
|
||||
res.render("locations", {logData});
|
||||
} catch (error) {
|
||||
console.error("Error fetching locations:", error);
|
||||
res.status(500).send("Internal Server Error");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.use(express.static("views"));
|
||||
|
||||
app.listen(PORT, () => {
|
||||
|
68
Sean/views/apilog.ejs
Normal file
68
Sean/views/apilog.ejs
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API Logs</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>ECOSAVER MANAGEMENT</h1>
|
||||
</header>
|
||||
<nav>
|
||||
<a href="/home" id="homeLink">Home</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h2>Welcome to the API Logs Users Page</h2>
|
||||
</main>
|
||||
<div id="downloadButtonContainer">
|
||||
<button id="downloadButton" onclick="downloadAsExcel()">Download as Excel</button>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Time</th>
|
||||
<th>Method</th>
|
||||
<th>Host</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% logData.forEach(entry => { %>
|
||||
<tr>
|
||||
<td><%= entry.id %></td>
|
||||
<td><%= entry.time %></td>
|
||||
<td><%= entry.method %></td>
|
||||
<td><%= entry.host %></td>
|
||||
<td><%= entry.createdAt %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<script >
|
||||
const logData = <%- JSON.stringify(logData) %>;
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.4/xlsx.full.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.2.1/exceljs.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.js"></script>
|
||||
<script src="apil;og.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
54
Sean/views/apilog.js
Normal file
54
Sean/views/apilog.js
Normal file
@ -0,0 +1,54 @@
|
||||
function downloadAsExcel() {
|
||||
// Get the current date
|
||||
var currentDate = new Date();
|
||||
var formattedDate = currentDate.toISOString().slice(0, 10); // Format as YYYY-MM-DD
|
||||
|
||||
// Create a new workbook
|
||||
var wb = XLSX.utils.book_new();
|
||||
// Convert logData to a worksheet
|
||||
var ws = XLSX.utils.json_to_sheet(logData);
|
||||
// Add the worksheet to the workbook
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'Log Data');
|
||||
// Create a blob with the Excel file content
|
||||
var blob = XLSX.write(wb, { bookType: 'xlsx', type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
|
||||
// Trigger the download with the filename including the current date
|
||||
saveAs(blob, 'log_data_' + formattedDate + '.xlsx');
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize flatpickr on the date input
|
||||
flatpickr("#datepicker", {
|
||||
dateFormat: "Y-m-d",
|
||||
onChange: function(selectedDates, dateStr, instance) {
|
||||
// Call a function to filter logs based on the selected date
|
||||
filterLogsByDate(dateStr);
|
||||
}
|
||||
});
|
||||
|
||||
function filterLogsByDate(selectedDate) {
|
||||
// Use logData to filter logs based on the selected date
|
||||
var filteredLogs = logData.filter(function(entry) {
|
||||
return entry.createdAt.startsWith(selectedDate);
|
||||
});
|
||||
|
||||
// Render the filtered logs in the table
|
||||
renderLogsTable(filteredLogs);
|
||||
}
|
||||
|
||||
function renderLogsTable(logs) {
|
||||
var tableBody = document.getElementById('logsTableBody');
|
||||
tableBody.innerHTML = '';
|
||||
|
||||
logs.forEach(function(entry) {
|
||||
var row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${entry.id}</td>
|
||||
<td>${entry.time}</td>
|
||||
<td>${entry.method}</td>
|
||||
<td>${entry.host}</td>
|
||||
<td>${entry.createdAt}</td>
|
||||
`;
|
||||
tableBody.appendChild(row);
|
||||
});
|
||||
}
|
||||
});
|
@ -22,6 +22,7 @@
|
||||
<a href="#">Users</a>
|
||||
<a href="/sensors">Sensors</a>
|
||||
<a href="/locations">Locations</a>
|
||||
<a href="/apilog">Api Logs</a>
|
||||
<a href="/logout">Logout</a>
|
||||
</nav>
|
||||
|
||||
@ -57,12 +58,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="health-container">
|
||||
<h4>Network Latency</h4>
|
||||
<ul>
|
||||
<li><strong>Latency:</strong> <%= systemHealth && systemHealth.networkHealth ? systemHealth.networkHealth.latency : 'N/A' %> ms</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<footer>
|
||||
Any Issue faced, Please contact the administrator at 11111111 or ecosaverAdmin@gmail.com
|
||||
|
Loading…
x
Reference in New Issue
Block a user