✨ Добавлена новая middleware для аутентификации API
- Реализована функция `requireApiAuth`, которая проверяет аутентификацию пользователя и возвращает JSON-ответ в случае неаутентифицированного доступа. - Обновлены маршруты API для использования новой middleware вместо старой `requireAuth`, улучшая обработку аутентификации для всех API-запросов.
This commit is contained in:
parent
ce803b4c20
commit
88d4a5f5d5
157
server.js
157
server.js
@ -530,6 +530,15 @@ function requireAuth(req, res, next) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Middleware для аутентификации API (возвращает JSON вместо редиректа)
|
||||||
|
function requireApiAuth(req, res, next) {
|
||||||
|
if (req.session.authenticated) {
|
||||||
|
return next();
|
||||||
|
} else {
|
||||||
|
return res.status(401).json({ error: "Не аутентифицирован" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Маршруты
|
// Маршруты
|
||||||
|
|
||||||
// Главная страница с формой входа
|
// Главная страница с формой входа
|
||||||
@ -680,7 +689,7 @@ app.get("/api/auth/status", (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для получения информации о пользователе
|
// API для получения информации о пользователе
|
||||||
app.get("/api/user", requireAuth, (req, res) => {
|
app.get("/api/user", requireApiAuth, (req, res) => {
|
||||||
if (!req.session.userId) {
|
if (!req.session.userId) {
|
||||||
return res.status(401).json({ error: "Не аутентифицирован" });
|
return res.status(401).json({ error: "Не аутентифицирован" });
|
||||||
}
|
}
|
||||||
@ -740,7 +749,7 @@ app.get("/notes", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для поиска заметок с изображениями (должен быть ПЕРЕД /api/notes/:id)
|
// API для поиска заметок с изображениями (должен быть ПЕРЕД /api/notes/:id)
|
||||||
app.get("/api/notes/search", requireAuth, (req, res) => {
|
app.get("/api/notes/search", requireApiAuth, (req, res) => {
|
||||||
const { q, tag, date } = req.query;
|
const { q, tag, date } = req.query;
|
||||||
|
|
||||||
let whereClause = "WHERE n.user_id = ?";
|
let whereClause = "WHERE n.user_id = ?";
|
||||||
@ -805,7 +814,7 @@ app.get("/api/notes/search", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для получения всех заметок с изображениями (исключая архивные)
|
// API для получения всех заметок с изображениями (исключая архивные)
|
||||||
app.get("/api/notes", requireAuth, (req, res) => {
|
app.get("/api/notes", requireApiAuth, (req, res) => {
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT
|
SELECT
|
||||||
n.*,
|
n.*,
|
||||||
@ -847,7 +856,7 @@ app.get("/api/notes", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для создания новой заметки
|
// API для создания новой заметки
|
||||||
app.post("/api/notes", requireAuth, (req, res) => {
|
app.post("/api/notes", requireApiAuth, (req, res) => {
|
||||||
const { content, date, time } = req.body;
|
const { content, date, time } = req.body;
|
||||||
|
|
||||||
if (!content || !date || !time) {
|
if (!content || !date || !time) {
|
||||||
@ -879,7 +888,7 @@ app.post("/api/notes", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для обновления заметки
|
// API для обновления заметки
|
||||||
app.put("/api/notes/:id", requireAuth, (req, res) => {
|
app.put("/api/notes/:id", requireApiAuth, (req, res) => {
|
||||||
const { content } = req.body;
|
const { content } = req.body;
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
@ -931,7 +940,7 @@ app.put("/api/notes/:id", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для удаления заметки
|
// API для удаления заметки
|
||||||
app.delete("/api/notes/:id", requireAuth, (req, res) => {
|
app.delete("/api/notes/:id", requireApiAuth, (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю
|
// Проверяем, что заметка принадлежит текущему пользователю
|
||||||
@ -1087,7 +1096,7 @@ app.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// API для получения изображений заметки
|
// API для получения изображений заметки
|
||||||
app.get("/api/notes/:id/images", requireAuth, (req, res) => {
|
app.get("/api/notes/:id/images", requireApiAuth, (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю
|
// Проверяем, что заметка принадлежит текущему пользователю
|
||||||
@ -1126,7 +1135,7 @@ app.get("/api/notes/:id/images", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для удаления изображения заметки
|
// API для удаления изображения заметки
|
||||||
app.delete("/api/notes/:noteId/images/:imageId", requireAuth, (req, res) => {
|
app.delete("/api/notes/:noteId/images/:imageId", requireApiAuth, (req, res) => {
|
||||||
const { noteId, imageId } = req.params;
|
const { noteId, imageId } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю
|
// Проверяем, что заметка принадлежит текущему пользователю
|
||||||
@ -1221,7 +1230,7 @@ app.get("/profile", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для обновления профиля
|
// API для обновления профиля
|
||||||
app.put("/api/user/profile", requireAuth, async (req, res) => {
|
app.put("/api/user/profile", requireApiAuth, async (req, res) => {
|
||||||
const { username, email, currentPassword, newPassword, accent_color } =
|
const { username, email, currentPassword, newPassword, accent_color } =
|
||||||
req.body;
|
req.body;
|
||||||
const userId = req.session.userId;
|
const userId = req.session.userId;
|
||||||
@ -1379,7 +1388,7 @@ app.post(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// API для удаления аватарки
|
// API для удаления аватарки
|
||||||
app.delete("/api/user/avatar", requireAuth, (req, res) => {
|
app.delete("/api/user/avatar", requireApiAuth, (req, res) => {
|
||||||
const userId = req.session.userId;
|
const userId = req.session.userId;
|
||||||
|
|
||||||
// Получаем текущую аватарку
|
// Получаем текущую аватарку
|
||||||
@ -1414,7 +1423,7 @@ app.delete("/api/user/avatar", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для закрепления заметки
|
// API для закрепления заметки
|
||||||
app.put("/api/notes/:id/pin", requireAuth, (req, res) => {
|
app.put("/api/notes/:id/pin", requireApiAuth, (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю
|
// Проверяем, что заметка принадлежит текущему пользователю
|
||||||
@ -1458,7 +1467,7 @@ app.put("/api/notes/:id/pin", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для архивирования заметки
|
// API для архивирования заметки
|
||||||
app.put("/api/notes/:id/archive", requireAuth, (req, res) => {
|
app.put("/api/notes/:id/archive", requireApiAuth, (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю
|
// Проверяем, что заметка принадлежит текущему пользователю
|
||||||
@ -1501,7 +1510,7 @@ app.put("/api/notes/:id/archive", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для восстановления заметки из архива
|
// API для восстановления заметки из архива
|
||||||
app.put("/api/notes/:id/unarchive", requireAuth, (req, res) => {
|
app.put("/api/notes/:id/unarchive", requireApiAuth, (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю
|
// Проверяем, что заметка принадлежит текущему пользователю
|
||||||
@ -1543,7 +1552,7 @@ app.put("/api/notes/:id/unarchive", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для получения архивных заметок
|
// API для получения архивных заметок
|
||||||
app.get("/api/notes/archived", requireAuth, (req, res) => {
|
app.get("/api/notes/archived", requireApiAuth, (req, res) => {
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT
|
SELECT
|
||||||
n.*,
|
n.*,
|
||||||
@ -1585,7 +1594,7 @@ app.get("/api/notes/archived", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для окончательного удаления всех архивных заметок пользователя
|
// API для окончательного удаления всех архивных заметок пользователя
|
||||||
app.delete("/api/notes/archived/all", requireAuth, async (req, res) => {
|
app.delete("/api/notes/archived/all", requireApiAuth, async (req, res) => {
|
||||||
const { password } = req.body;
|
const { password } = req.body;
|
||||||
|
|
||||||
if (!password) {
|
if (!password) {
|
||||||
@ -1694,7 +1703,7 @@ app.delete("/api/notes/archived/all", requireAuth, async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для окончательного удаления архивной заметки
|
// API для окончательного удаления архивной заметки
|
||||||
app.delete("/api/notes/archived/:id", requireAuth, (req, res) => {
|
app.delete("/api/notes/archived/:id", requireApiAuth, (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Проверяем, что заметка принадлежит текущему пользователю и архивирована
|
// Проверяем, что заметка принадлежит текущему пользователю и архивирована
|
||||||
@ -1762,116 +1771,8 @@ app.delete("/api/notes/archived/:id", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// API для окончательного удаления всех архивных заметок пользователя
|
|
||||||
app.delete("/api/notes/archived/all", requireAuth, async (req, res) => {
|
|
||||||
const { password } = req.body;
|
|
||||||
|
|
||||||
if (!password) {
|
|
||||||
return res.status(400).json({ error: "Пароль обязателен" });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Получаем хеш пароля пользователя
|
|
||||||
const userSql = "SELECT password FROM users WHERE id = ?";
|
|
||||||
db.get(userSql, [req.session.userId], async (err, user) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("Ошибка получения пользователя:", err.message);
|
|
||||||
return res.status(500).json({ error: "Ошибка сервера" });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
return res.status(404).json({ error: "Пользователь не найден" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверяем пароль
|
|
||||||
const validPassword = await bcrypt.compare(password, user.password);
|
|
||||||
if (!validPassword) {
|
|
||||||
return res.status(401).json({ error: "Неверный пароль" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Получаем все архивные заметки пользователя
|
|
||||||
const getNotesSql =
|
|
||||||
"SELECT id FROM notes WHERE user_id = ? AND is_archived = 1";
|
|
||||||
db.all(getNotesSql, [req.session.userId], (err, notes) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("Ошибка получения архивных заметок:", err.message);
|
|
||||||
return res.status(500).json({ error: "Ошибка сервера" });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notes.length === 0) {
|
|
||||||
return res.json({
|
|
||||||
success: true,
|
|
||||||
message: "Архив уже пуст",
|
|
||||||
deletedCount: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Удаляем изображения для всех заметок
|
|
||||||
const noteIds = notes.map((note) => note.id);
|
|
||||||
const placeholders = noteIds.map(() => "?").join(",");
|
|
||||||
|
|
||||||
const getImagesSql = `SELECT file_path FROM note_images WHERE note_id IN (${placeholders})`;
|
|
||||||
db.all(getImagesSql, noteIds, (err, images) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("Ошибка получения изображений:", err.message);
|
|
||||||
} else {
|
|
||||||
// Удаляем файлы изображений
|
|
||||||
images.forEach((image) => {
|
|
||||||
const imagePath = path.join(__dirname, "public", image.file_path);
|
|
||||||
if (fs.existsSync(imagePath)) {
|
|
||||||
try {
|
|
||||||
fs.unlinkSync(imagePath);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Ошибка удаления файла изображения:", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Удаляем записи об изображениях
|
|
||||||
const deleteImagesSql = `DELETE FROM note_images WHERE note_id IN (${placeholders})`;
|
|
||||||
db.run(deleteImagesSql, noteIds, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("Ошибка удаления изображений:", err.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Удаляем сами заметки
|
|
||||||
const deleteNotesSql = `DELETE FROM notes WHERE user_id = ? AND is_archived = 1`;
|
|
||||||
db.run(deleteNotesSql, [req.session.userId], function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.error("Ошибка удаления заметок:", err.message);
|
|
||||||
return res.status(500).json({ error: "Ошибка сервера" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const deletedCount = this.changes;
|
|
||||||
|
|
||||||
// Логируем действие
|
|
||||||
const clientIP = getClientIP(req);
|
|
||||||
logAction(
|
|
||||||
req.session.userId,
|
|
||||||
"note_delete_permanent",
|
|
||||||
`Удалены все архивные заметки (${deletedCount} шт.)`,
|
|
||||||
clientIP
|
|
||||||
);
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
success: true,
|
|
||||||
message: `Удалено ${deletedCount} архивных заметок`,
|
|
||||||
deletedCount,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка при проверке пароля:", error);
|
|
||||||
res.status(500).json({ error: "Ошибка сервера" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// API для получения логов пользователя
|
// API для получения логов пользователя
|
||||||
app.get("/api/logs", requireAuth, (req, res) => {
|
app.get("/api/logs", requireApiAuth, (req, res) => {
|
||||||
const { action_type, limit = 100, offset = 0 } = req.query;
|
const { action_type, limit = 100, offset = 0 } = req.query;
|
||||||
|
|
||||||
let sql = `
|
let sql = `
|
||||||
@ -1939,7 +1840,7 @@ app.get("/settings", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для получения AI настроек
|
// API для получения AI настроек
|
||||||
app.get("/api/user/ai-settings", requireAuth, (req, res) => {
|
app.get("/api/user/ai-settings", requireApiAuth, (req, res) => {
|
||||||
if (!req.session.userId) {
|
if (!req.session.userId) {
|
||||||
return res.status(401).json({ error: "Не аутентифицирован" });
|
return res.status(401).json({ error: "Не аутентифицирован" });
|
||||||
}
|
}
|
||||||
@ -1961,7 +1862,7 @@ app.get("/api/user/ai-settings", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для сохранения AI настроек
|
// API для сохранения AI настроек
|
||||||
app.put("/api/user/ai-settings", requireAuth, (req, res) => {
|
app.put("/api/user/ai-settings", requireApiAuth, (req, res) => {
|
||||||
const { openai_api_key, openai_base_url, openai_model } = req.body;
|
const { openai_api_key, openai_base_url, openai_model } = req.body;
|
||||||
const userId = req.session.userId;
|
const userId = req.session.userId;
|
||||||
|
|
||||||
@ -1990,7 +1891,7 @@ app.put("/api/user/ai-settings", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// API для улучшения текста через AI
|
// API для улучшения текста через AI
|
||||||
app.post("/api/ai/improve", requireAuth, async (req, res) => {
|
app.post("/api/ai/improve", requireApiAuth, async (req, res) => {
|
||||||
const { text } = req.body;
|
const { text } = req.body;
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user