mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-30 08:49:16 +02:00
new chat window, bugfixes, component update
This commit is contained in:
+27
-4
@@ -179,21 +179,44 @@ router.get('/api', (req, res) => {
|
||||
});
|
||||
|
||||
|
||||
const loginAttempts = {}; // Format: { 'ip': { count: 1, lastAttempt: 1234567890 } }
|
||||
const MAX_ATTEMPTS = 25;
|
||||
const WINDOW_MS = 15 * 60 * 1000;
|
||||
|
||||
const authenticate = (req, res, next) => {
|
||||
const ip = req.ip || req.connection.remoteAddress;
|
||||
const now = Date.now();
|
||||
|
||||
if (!loginAttempts[ip]) {
|
||||
loginAttempts[ip] = { count: 0, lastAttempt: now };
|
||||
} else if (now - loginAttempts[ip].lastAttempt > WINDOW_MS) {
|
||||
loginAttempts[ip] = { count: 0, lastAttempt: now };
|
||||
}
|
||||
|
||||
if (loginAttempts[ip].count >= MAX_ATTEMPTS) {
|
||||
return res.status(403).json({
|
||||
message: 'Too many login attempts. Please try again later.'
|
||||
});
|
||||
}
|
||||
|
||||
const { password } = req.body;
|
||||
|
||||
// Check if the entered password matches the admin password
|
||||
|
||||
loginAttempts[ip].lastAttempt = now;
|
||||
|
||||
if (password === serverConfig.password.adminPass) {
|
||||
req.session.isAdminAuthenticated = true;
|
||||
req.session.isTuneAuthenticated = true;
|
||||
logInfo('User from ' + req.connection.remoteAddress + ' logged in as an administrator.');
|
||||
logInfo(`User from ${ip} logged in as an administrator.`);
|
||||
loginAttempts[ip].count = 0;
|
||||
next();
|
||||
} else if (password === serverConfig.password.tunePass) {
|
||||
req.session.isAdminAuthenticated = false;
|
||||
req.session.isTuneAuthenticated = true;
|
||||
logInfo('User from ' + req.connection.remoteAddress + ' logged in with tune permissions.');
|
||||
logInfo(`User from ${ip} logged in with tune permissions.`);
|
||||
loginAttempts[ip].count = 0;
|
||||
next();
|
||||
} else {
|
||||
loginAttempts[ip].count += 1;
|
||||
res.status(403).json({ message: 'Login failed. Wrong password?' });
|
||||
}
|
||||
};
|
||||
|
||||
+2
-1
@@ -132,6 +132,7 @@ function fetchBannedAS(callback) {
|
||||
function processConnection(clientIp, locationInfo, currentUsers, ws, callback) {
|
||||
const options = { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit" };
|
||||
const connectionTime = new Date().toLocaleString([], options);
|
||||
const normalizedClientIp = clientIp?.replace(/^::ffff:/, '');
|
||||
|
||||
fetchBannedAS((error, bannedAS) => {
|
||||
if (error) {
|
||||
@@ -155,7 +156,7 @@ function processConnection(clientIp, locationInfo, currentUsers, ws, callback) {
|
||||
});
|
||||
|
||||
consoleCmd.logInfo(
|
||||
`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${userLocation}`
|
||||
`Web client \x1b[32mconnected\x1b[0m (${normalizedClientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${userLocation}`
|
||||
);
|
||||
|
||||
callback("User allowed");
|
||||
|
||||
+2
-1
@@ -388,6 +388,7 @@ wss.on('connection', (ws, request) => {
|
||||
const output = serverConfig.xdrd.wirelessConnection ? client : serialport;
|
||||
let clientIp = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
|
||||
const userCommandHistory = {};
|
||||
const normalizedClientIp = clientIp?.replace(/^::ffff:/, '');
|
||||
|
||||
if (serverConfig.webserver.banlist?.includes(clientIp)) {
|
||||
ws.close(1008, 'Banned IP');
|
||||
@@ -509,7 +510,7 @@ wss.on('connection', (ws, request) => {
|
||||
}
|
||||
|
||||
if (code !== 1008) {
|
||||
logInfo(`Web client \x1b[31mdisconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]`);
|
||||
logInfo(`Web client \x1b[31mdisconnected\x1b[0m (${normalizedClientIp}) \x1b[90m[${currentUsers}]`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+27
-12
@@ -87,14 +87,11 @@ async function fetchTx(freq, piCode, rdsPs) {
|
||||
const now = Date.now();
|
||||
freq = parseFloat(freq);
|
||||
|
||||
if (isNaN(freq)) {
|
||||
return;
|
||||
}
|
||||
if (isNaN(freq)) return;
|
||||
if (now - lastFetchTime < fetchInterval
|
||||
|| serverConfig.identification.lat.length < 2
|
||||
|| freq < 87
|
||||
|| (currentPiCode == piCode && currentRdsPs == rdsPs))
|
||||
{
|
||||
|| (currentPiCode == piCode && currentRdsPs == rdsPs)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -107,15 +104,33 @@ async function fetchTx(freq, piCode, rdsPs) {
|
||||
const url = "https://maps.fmdx.org/api/?freq=" + freq;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, { redirect: 'manual' });
|
||||
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
const data = await response.json();
|
||||
// Try POST first
|
||||
const postResponse = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ freq }), // You can omit or customize this
|
||||
redirect: 'manual'
|
||||
});
|
||||
|
||||
if (!postResponse.ok) throw new Error(`POST failed: ${postResponse.status}`);
|
||||
const data = await postResponse.json();
|
||||
cachedData[freq] = data;
|
||||
if(serverConfig.webserver.rdsMode == true) await loadUsStatesGeoJson();
|
||||
if (serverConfig.webserver.rdsMode === true) await loadUsStatesGeoJson();
|
||||
return processData(data, piCode, rdsPs);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return null; // Return null to indicate failure
|
||||
} catch (postError) {
|
||||
console.warn("POST failed, trying GET:", postError);
|
||||
|
||||
try {
|
||||
const getResponse = await fetch(url, { redirect: 'manual' });
|
||||
if (!getResponse.ok) throw new Error(`GET failed: ${getResponse.status}`);
|
||||
const data = await getResponse.json();
|
||||
cachedData[freq] = data;
|
||||
if (serverConfig.webserver.rdsMode === true) await loadUsStatesGeoJson();
|
||||
return processData(data, piCode, rdsPs);
|
||||
} catch (getError) {
|
||||
console.error("GET also failed:", getError);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user