diff --git a/public/settings.html b/public/settings.html
index 6e161fa..2432110 100644
--- a/public/settings.html
+++ b/public/settings.html
@@ -302,7 +302,6 @@
Дата и время |
Действие |
Детали |
- IP-адрес |
diff --git a/public/settings.js b/public/settings.js
index 0c1541a..ae36571 100644
--- a/public/settings.js
+++ b/public/settings.js
@@ -823,7 +823,6 @@ async function loadLogs(reset = false) {
log.action_type
}">${actionText}
${log.details || "-"} |
- ${log.ip_address || "-"} |
`;
tbody.appendChild(row);
diff --git a/server.js b/server.js
index c52d242..69b6cf1 100644
--- a/server.js
+++ b/server.js
@@ -360,114 +360,18 @@ function createIndexes() {
}
// Функция для логирования действий пользователя
-function logAction(userId, actionType, details, ipAddress) {
+function logAction(userId, actionType, details) {
const sql = `
INSERT INTO action_logs (user_id, action_type, details, ip_address)
- VALUES (?, ?, ?, ?)
+ VALUES (?, ?, ?, NULL)
`;
- db.run(sql, [userId, actionType, details, ipAddress], (err) => {
+ db.run(sql, [userId, actionType, details], (err) => {
if (err) {
console.error("Ошибка логирования действия:", err.message);
}
});
}
-// Функция для получения IP-адреса клиента
-function getClientIP(req) {
- // Логируем все заголовки для отладки
- console.log("=== IP Headers Debug ===");
- console.log("req.ip:", req.ip);
- console.log("x-forwarded-for:", req.headers["x-forwarded-for"]);
- console.log("x-real-ip:", req.headers["x-real-ip"]);
- console.log("x-client-ip:", req.headers["x-client-ip"]);
- console.log("cf-connecting-ip:", req.headers["cf-connecting-ip"]); // Cloudflare
- console.log("x-forwarded:", req.headers["x-forwarded"]);
- console.log("forwarded:", req.headers["forwarded"]);
- console.log("req.connection.remoteAddress:", req.connection?.remoteAddress);
- console.log("req.socket.remoteAddress:", req.socket?.remoteAddress);
- console.log("ALL HEADERS:", JSON.stringify(req.headers, null, 2));
- console.log("========================");
-
- // Приоритет для получения реального IP клиента:
- // 1. req.socket.remoteAddress (для случаев с дополнительными прокси)
- // 2. X-Real-IP (часто используется nginx)
- // 3. X-Forwarded-For (стандартный заголовок)
- // 4. CF-Connecting-IP (если используется Cloudflare)
- // 5. X-Client-IP
- // 6. req.ip (Express с trust proxy)
-
- let ip = null;
-
- // Проверяем socket_remoteAddress в первую очередь (для случаев с дополнительными прокси)
- if (
- req.socket?.remoteAddress &&
- req.socket.remoteAddress !== "::1" &&
- req.socket.remoteAddress !== "127.0.0.1"
- ) {
- ip = req.socket.remoteAddress;
- }
- // Проверяем X-Real-IP (nginx часто использует этот заголовок)
- else if (req.headers["x-real-ip"]) {
- ip = req.headers["x-real-ip"];
- }
- // Проверяем X-Forwarded-For (берем первый IP из списка)
- else if (req.headers["x-forwarded-for"]) {
- ip = req.headers["x-forwarded-for"].split(",")[0].trim();
- }
- // Проверяем CF-Connecting-IP (Cloudflare)
- else if (req.headers["cf-connecting-ip"]) {
- ip = req.headers["cf-connecting-ip"];
- }
- // Проверяем X-Client-IP
- else if (req.headers["x-client-ip"]) {
- ip = req.headers["x-client-ip"];
- }
- // Проверяем Forwarded заголовок (RFC 7239)
- else if (req.headers["forwarded"]) {
- const forwarded = req.headers["forwarded"];
- const forMatch = forwarded.match(/for=([^;,\s]+)/);
- if (forMatch) {
- ip = forMatch[1];
- }
- }
- // Используем req.ip (Express с trust proxy)
- else if (req.ip && req.ip !== "::1" && req.ip !== "127.0.0.1") {
- ip = req.ip;
- }
-
- // Очищаем IP от скобок IPv6, портов и кавычек
- if (ip && ip !== "unknown") {
- // Убираем скобки IPv6
- ip = ip.replace(/[[\]]/g, "");
- // Убираем кавычки если есть
- ip = ip.replace(/['"]/g, "");
-
- // Обрабатываем IPv6 адреса
- if (ip.startsWith("::ffff:")) {
- // IPv4-mapped IPv6 address (::ffff:192.168.1.1)
- ip = ip.substring(7); // Убираем "::ffff:"
- } else if (ip.includes("::")) {
- const ipv6Match = ip.match(/^(\[)?([^\]]+)(\])?(:(\d+))?$/);
- if (ipv6Match) {
- ip = ipv6Match[2];
- }
- } else if (ip.includes(":")) {
- // IPv4 с портом
- const parts = ip.split(":");
- if (parts.length === 2 && /^\d+$/.test(parts[1])) {
- ip = parts[0];
- }
- }
- }
-
- // Конвертируем IPv6 localhost в IPv4
- if (ip === "::1" || ip === "::ffff:127.0.0.1") {
- ip = "127.0.0.1";
- }
-
- return ip || "unknown";
-}
-
// Миграции базы данных
function runMigrations() {
// Создаем таблицу логов действий, если её нет
@@ -744,13 +648,7 @@ app.post("/api/register", async (req, res) => {
req.session.authenticated = true;
// Логируем регистрацию
- const clientIP = getClientIP(req);
- logAction(
- this.lastID,
- "register",
- `Регистрация нового пользователя`,
- clientIP
- );
+ logAction(this.lastID, "register", `Регистрация нового пользователя`);
res.json({ success: true, message: "Регистрация успешна" });
});
@@ -792,8 +690,7 @@ app.post("/api/login", async (req, res) => {
req.session.authenticated = true;
// Логируем вход
- const clientIP = getClientIP(req);
- logAction(user.id, "login", `Вход в систему`, clientIP);
+ logAction(user.id, "login", `Вход в систему`);
res.json({ success: true, message: "Вход успешен" });
} catch (err) {
@@ -851,29 +748,6 @@ app.get("/api/user", requireApiAuth, (req, res) => {
});
});
-// Тестовый эндпоинт для проверки IP-адресов (только для отладки)
-app.get("/api/debug/ip", (req, res) => {
- const clientIP = getClientIP(req);
-
- res.json({
- detected_ip: clientIP,
- headers: {
- "x-forwarded-for": req.headers["x-forwarded-for"],
- "x-real-ip": req.headers["x-real-ip"],
- "x-client-ip": req.headers["x-client-ip"],
- "cf-connecting-ip": req.headers["cf-connecting-ip"],
- "x-forwarded": req.headers["x-forwarded"],
- forwarded: req.headers["forwarded"],
- },
- express: {
- req_ip: req.ip,
- socket_remoteAddress: req.socket?.remoteAddress,
- connection_remoteAddress: req.connection?.remoteAddress,
- },
- all_headers: req.headers,
- });
-});
-
// Страница с заметками (требует аутентификации)
app.get("/notes", requireAuth, (req, res) => {
// Получаем цвет пользователя для предотвращения FOUC
@@ -1070,14 +944,8 @@ app.post("/api/notes", requireApiAuth, (req, res) => {
}
// Логируем создание заметки
- const clientIP = getClientIP(req);
const noteId = this.lastID;
- logAction(
- req.session.userId,
- "note_create",
- `Создана заметка #${noteId}`,
- clientIP
- );
+ logAction(req.session.userId, "note_create", `Создана заметка #${noteId}`);
res.json({ id: noteId, content, date, time });
});
@@ -1122,13 +990,7 @@ app.put("/api/notes/:id", requireApiAuth, (req, res) => {
}
// Логируем обновление заметки
- const clientIP = getClientIP(req);
- logAction(
- req.session.userId,
- "note_update",
- `Обновлена заметка #${id}`,
- clientIP
- );
+ logAction(req.session.userId, "note_update", `Обновлена заметка #${id}`);
res.json({ id, content, date: row.date, time: row.time });
});
@@ -1213,12 +1075,10 @@ app.delete("/api/notes/:id", requireApiAuth, (req, res) => {
}
// Логируем удаление заметки
- const clientIP = getClientIP(req);
logAction(
req.session.userId,
"note_delete",
- `Удалена заметка #${id}`,
- clientIP
+ `Удалена заметка #${id}`
);
res.json({ message: "Заметка удалена" });
@@ -1730,14 +1590,13 @@ app.put("/api/user/profile", requireApiAuth, async (req, res) => {
}
// Логируем обновление профиля
- const clientIP = getClientIP(req);
const changes = [];
if (username && username !== user.username) changes.push("логин");
if (email !== undefined) changes.push("email");
if (accent_color !== undefined) changes.push("цвет темы");
if (newPassword) changes.push("пароль");
const details = `Обновлен профиль: ${changes.join(", ")}`;
- logAction(userId, "profile_update", details, clientIP);
+ logAction(userId, "profile_update", details);
res.json({ success: true, message: "Профиль успешно обновлен" });
});
@@ -1857,14 +1716,8 @@ app.put("/api/notes/:id/pin", requireApiAuth, (req, res) => {
}
// Логируем действие
- const clientIP = getClientIP(req);
const action = newPinState ? "закреплена" : "откреплена";
- logAction(
- req.session.userId,
- "note_pin",
- `Заметка #${id} ${action}`,
- clientIP
- );
+ logAction(req.session.userId, "note_pin", `Заметка #${id} ${action}`);
res.json({ success: true, is_pinned: newPinState });
});
@@ -1901,12 +1754,10 @@ app.put("/api/notes/:id/archive", requireApiAuth, (req, res) => {
}
// Логируем действие
- const clientIP = getClientIP(req);
logAction(
req.session.userId,
"note_archive",
- `Заметка #${id} архивирована`,
- clientIP
+ `Заметка #${id} архивирована`
);
res.json({ success: true, message: "Заметка архивирована" });
@@ -1943,12 +1794,10 @@ app.put("/api/notes/:id/unarchive", requireApiAuth, (req, res) => {
}
// Логируем действие
- const clientIP = getClientIP(req);
logAction(
req.session.userId,
"note_unarchive",
- `Заметка #${id} восстановлена из архива`,
- clientIP
+ `Заметка #${id} восстановлена из архива`
);
res.json({ success: true, message: "Заметка восстановлена" });
@@ -2125,12 +1974,10 @@ app.delete("/api/notes/archived/all", requireApiAuth, async (req, res) => {
const deletedCount = this.changes;
// Логируем действие
- const clientIP = getClientIP(req);
logAction(
req.session.userId,
"note_delete_permanent",
- `Удалены все архивные заметки (${deletedCount} шт.)`,
- clientIP
+ `Удалены все архивные заметки (${deletedCount} шт.)`
);
res.json({
@@ -2228,12 +2075,10 @@ app.delete("/api/notes/archived/:id", requireApiAuth, (req, res) => {
}
// Логируем действие
- const clientIP = getClientIP(req);
logAction(
req.session.userId,
"note_delete_permanent",
- `Заметка #${id} окончательно удалена из архива`,
- clientIP
+ `Заметка #${id} окончательно удалена из архива`
);
res.json({ success: true, message: "Заметка удалена окончательно" });
@@ -2248,7 +2093,7 @@ app.get("/api/logs", requireApiAuth, (req, res) => {
const { action_type, limit = 100, offset = 0 } = req.query;
let sql = `
- SELECT id, action_type, details, ip_address, created_at
+ SELECT id, action_type, details, created_at
FROM action_logs
WHERE user_id = ?
`;
@@ -2359,8 +2204,7 @@ app.put("/api/user/ai-settings", requireApiAuth, (req, res) => {
}
// Логируем обновление AI настроек
- const clientIP = getClientIP(req);
- logAction(userId, "profile_update", "Изменен статус AI", clientIP);
+ logAction(userId, "profile_update", "Изменен статус AI");
res.json({ success: true, message: "Настройки AI успешно сохранены" });
});
@@ -2401,8 +2245,7 @@ app.put("/api/user/ai-settings", requireApiAuth, (req, res) => {
}
// Логируем обновление AI настроек
- const clientIP = getClientIP(req);
- logAction(userId, "profile_update", "Обновлены AI настройки", clientIP);
+ logAction(userId, "profile_update", "Обновлены AI настройки");
res.json({ success: true, message: "AI настройки успешно сохранены" });
});
@@ -2527,13 +2370,7 @@ app.post("/api/ai/improve", requireApiAuth, async (req, res) => {
});
// Логируем использование AI
- const clientIP = getClientIP(req);
- logAction(
- req.session.userId,
- "ai_improve",
- "Улучшен текст через AI",
- clientIP
- );
+ logAction(req.session.userId, "ai_improve", "Улучшен текст через AI");
res.json({ success: true, improvedText });
} catch (error) {
@@ -2552,11 +2389,10 @@ app.post("/api/ai/improve", requireApiAuth, async (req, res) => {
// Выход
app.post("/logout", (req, res) => {
const userId = req.session.userId;
- const clientIP = getClientIP(req);
// Логируем выход
if (userId) {
- logAction(userId, "logout", "Выход из системы", clientIP);
+ logAction(userId, "logout", "Выход из системы");
}
req.session.destroy((err) => {