поправил авторизацию

This commit is contained in:
kalugin66
2025-11-30 14:11:05 +05:00
committed by GitHub
parent bf5e35c61f
commit 92e3ed50c5
2 changed files with 128 additions and 57 deletions

36
auth.js
View File

@@ -91,6 +91,9 @@ class AuthService {
const isValid = await bcrypt.compare(password, user.password); const isValid = await bcrypt.compare(password, user.password);
if (isValid) { if (isValid) {
// Обновляем last_login
db.run("UPDATE users SET last_login = datetime('now') WHERE id = ?", [user.id]);
// Не возвращаем пароль // Не возвращаем пароль
const { password, ...userWithoutPassword } = user; const { password, ...userWithoutPassword } = user;
resolve(userWithoutPassword); resolve(userWithoutPassword);
@@ -135,7 +138,7 @@ class AuthService {
const allowedGroups = process.env.ALLOWED_GROUPS ? const allowedGroups = process.env.ALLOWED_GROUPS ?
process.env.ALLOWED_GROUPS.split(',').map(g => g.trim()) : []; process.env.ALLOWED_GROUPS.split(',').map(g => g.trim()) : [];
const isAdmin = groups.some(group => const isAdmin = groups && groups.some(group =>
allowedGroups.includes(group) allowedGroups.includes(group)
); );
@@ -151,11 +154,11 @@ class AuthService {
const userData = { const userData = {
login: username, login: username,
name: full_name, name: full_name || username,
email: `${username}@school25.ru`, email: `${username}@school25.ru`,
role: role, role: role,
auth_type: 'ldap', auth_type: 'ldap',
groups: JSON.stringify(groups), groups: groups ? JSON.stringify(groups) : '[]',
description: description || '', description: description || '',
last_login: new Date().toISOString() last_login: new Date().toISOString()
}; };
@@ -164,14 +167,26 @@ class AuthService {
// Обновляем существующего пользователя // Обновляем существующего пользователя
db.run( db.run(
`UPDATE users SET `UPDATE users SET
name = ?, email = ?, role = ?, groups = ?, description = ?, last_login = datetime('now') name = ?, email = ?, role = ?, groups = ?, description = ?, last_login = datetime('now'),
updated_at = datetime('now')
WHERE id = ?`, WHERE id = ?`,
[userData.name, userData.email, userData.role, userData.groups, userData.description, existingUser.id], [userData.name, userData.email, userData.role, userData.groups, userData.description, existingUser.id],
function(err) { function(err) {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
resolve({ ...existingUser, ...userData }); // Возвращаем полные данные пользователя
resolve({
id: existingUser.id,
login: userData.login,
name: userData.name,
email: userData.email,
role: userData.role,
auth_type: userData.auth_type,
groups: userData.groups,
description: userData.description,
last_login: new Date().toISOString()
});
} }
} }
); );
@@ -188,7 +203,14 @@ class AuthService {
} else { } else {
resolve({ resolve({
id: this.lastID, id: this.lastID,
...userData login: userData.login,
name: userData.name,
email: userData.email,
role: userData.role,
auth_type: userData.auth_type,
groups: userData.groups,
description: userData.description,
last_login: new Date().toISOString()
}); });
} }
} }
@@ -216,7 +238,7 @@ class AuthService {
getUserById(id) { getUserById(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.get("SELECT id, login, name, email, role, auth_type, groups, description FROM users WHERE id = ?", [id], (err, user) => { db.get("SELECT id, login, name, email, role, auth_type, groups, description, last_login FROM users WHERE id = ?", [id], (err, user) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {

149
server.js
View File

@@ -21,10 +21,14 @@ app.use('/uploads', express.static(path.join(__dirname, 'data', 'uploads')));
// Сессии // Сессии
app.use(session({ app.use(session({
secret: process.env.SESSION_SECRET || 'fallback_secret', secret: process.env.SESSION_SECRET || 'fallback_secret_change_in_production',
resave: false, resave: true, // Изменено на true для лучшей поддержки LDAP
saveUninitialized: false, saveUninitialized: false,
cookie: { secure: false, maxAge: 24 * 60 * 60 * 1000 } cookie: {
secure: false,
maxAge: 24 * 60 * 60 * 1000,
httpOnly: true
}
})); }));
// Middleware для проверки аутентификации // Middleware для проверки аутентификации
@@ -80,6 +84,7 @@ function checkIfOverdue(dueDate, status) {
const due = new Date(dueDate); const due = new Date(dueDate);
return due < now; return due < now;
} }
// Функция для проверки просроченных задач // Функция для проверки просроченных задач
function checkOverdueTasks() { function checkOverdueTasks() {
const now = new Date().toISOString(); const now = new Date().toISOString();
@@ -111,6 +116,7 @@ function checkOverdueTasks() {
}); });
}); });
} }
// ==================== МАРШРУТЫ АУТЕНТИФИКАЦИИ ==================== // ==================== МАРШРУТЫ АУТЕНТИФИКАЦИИ ====================
app.post('/api/login', async (req, res) => { app.post('/api/login', async (req, res) => {
@@ -123,25 +129,37 @@ app.post('/api/login', async (req, res) => {
try { try {
const user = await authService.authenticate(login, password); const user = await authService.authenticate(login, password);
if (user) { if (user) {
req.session.user = user; // Подготавливаем данные пользователя для сессии
const sessionUser = {
id: user.id,
login: user.login,
name: user.name,
email: user.email,
role: user.role,
auth_type: user.auth_type,
groups: user.groups ? (typeof user.groups === 'string' ? JSON.parse(user.groups) : user.groups) : []
};
// Сохраняем в сессию
req.session.user = sessionUser;
// Логируем успешный вход // Явно сохраняем сессию
console.log(`Успешная авторизация: ${user.name} (${user.login}) через ${user.auth_type}`); req.session.save((err) => {
if (user.groups) { if (err) {
console.log(`Группы пользователя: ${user.groups}`); console.error('Ошибка сохранения сессии:', err);
} return res.status(500).json({ error: 'Ошибка сохранения сессии' });
res.json({
success: true,
user: {
id: user.id,
login: user.login,
name: user.name,
email: user.email,
role: user.role,
auth_type: user.auth_type,
groups: user.groups ? JSON.parse(user.groups) : []
} }
// Логируем успешный вход
console.log(`Успешная авторизация: ${user.name} (${user.login}) через ${user.auth_type}`);
if (user.groups) {
console.log(`Группы пользователя: ${user.groups}`);
}
res.json({
success: true,
user: sessionUser
});
}); });
} else { } else {
console.log(`Неудачная попытка входа: ${login}`); console.log(`Неудачная попытка входа: ${login}`);
@@ -154,13 +172,44 @@ app.post('/api/login', async (req, res) => {
}); });
app.post('/api/logout', (req, res) => { app.post('/api/logout', (req, res) => {
req.session.destroy(); req.session.destroy((err) => {
res.json({ success: true }); if (err) {
console.error('Ошибка при выходе:', err);
return res.status(500).json({ error: 'Ошибка при выходе' });
}
res.json({ success: true });
});
}); });
app.get('/api/user', (req, res) => { app.get('/api/user', (req, res) => {
if (req.session.user) { if (req.session.user) {
res.json({ user: req.session.user }); // Обновляем данные пользователя из базы на случай изменений
authService.getUserById(req.session.user.id)
.then(user => {
if (user) {
const updatedUser = {
id: user.id,
login: user.login,
name: user.name,
email: user.email,
role: user.role,
auth_type: user.auth_type,
groups: user.groups ? (typeof user.groups === 'string' ? JSON.parse(user.groups) : user.groups) : []
};
// Обновляем сессию
req.session.user = updatedUser;
res.json({ user: updatedUser });
} else {
// Пользователь не найден в базе - разлогиниваем
req.session.destroy();
res.status(401).json({ error: 'Пользователь не найден' });
}
})
.catch(err => {
console.error('Ошибка получения пользователя:', err);
res.status(500).json({ error: 'Ошибка сервера' });
});
} else { } else {
res.status(401).json({ error: 'Не аутентифицирован' }); res.status(401).json({ error: 'Не аутентифицирован' });
} }
@@ -435,29 +484,29 @@ app.post('/api/tasks/:taskId/copy', requireAuth, (req, res) => {
logActivity(newTaskId, createdBy, 'TASK_COPIED', `Создана копия задачи: ${newTitle}`); logActivity(newTaskId, createdBy, 'TASK_COPIED', `Создана копия задачи: ${newTitle}`);
// Копируем файлы из оригинальной задачи // Копируем файлы из оригинальной задачи
db.all("SELECT * FROM task_files WHERE task_id = ?", [taskId], (err, originalFiles) => { db.all("SELECT * FROM task_files WHERE task_id = ?", [taskId], (err, originalFiles) => {
if (!err && originalFiles && originalFiles.length > 0) { if (!err && originalFiles && originalFiles.length > 0) {
originalFiles.forEach(originalFile => { originalFiles.forEach(originalFile => {
const originalFilePath = originalFile.file_path; const originalFilePath = originalFile.file_path;
const newFilename = Date.now() + '-' + Math.round(Math.random() * 1E9) + path.extname(originalFile.original_name); const newFilename = Date.now() + '-' + Math.round(Math.random() * 1E9) + path.extname(originalFile.original_name);
const userFolder = createUserTaskFolder(newTaskId, req.session.user.login); const userFolder = createUserTaskFolder(newTaskId, req.session.user.login);
const newFilePath = path.join(userFolder, newFilename); const newFilePath = path.join(userFolder, newFilename);
// Копируем файл // Копируем файл
if (fs.existsSync(originalFilePath)) { if (fs.existsSync(originalFilePath)) {
fs.copyFileSync(originalFilePath, newFilePath); fs.copyFileSync(originalFilePath, newFilePath);
db.run( db.run(
"INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)", "INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)",
[newTaskId, createdBy, newFilename, originalFile.original_name, newFilePath, originalFile.file_size] [newTaskId, createdBy, newFilename, originalFile.original_name, newFilePath, originalFile.file_size]
); );
logActivity(newTaskId, createdBy, 'FILE_COPIED', `Скопирован файл: ${originalFile.original_name}`); logActivity(newTaskId, createdBy, 'FILE_COPIED', `Скопирован файл: ${originalFile.original_name}`);
} }
}); });
} }
}); });
// Назначаем пользователей // Назначаем пользователей
if (assignedUsers && assignedUsers.length > 0) { if (assignedUsers && assignedUsers.length > 0) {
@@ -740,9 +789,6 @@ app.post('/api/tasks/:taskId/reopen', requireAuth, (req, res) => {
}); });
}); });
// Остальные маршруты остаются без изменений...
// (Обновить сроки исполнителя, Удалить задачу, Восстановить задачу, Обновить статус, Файлы, Логи)
// Обновить сроки для конкретного исполнителя // Обновить сроки для конкретного исполнителя
app.put('/api/tasks/:taskId/assignment/:userId', requireAuth, (req, res) => { app.put('/api/tasks/:taskId/assignment/:userId', requireAuth, (req, res) => {
const { taskId, userId } = req.params; const { taskId, userId } = req.params;
@@ -756,7 +802,7 @@ app.put('/api/tasks/:taskId/assignment/:userId', requireAuth, (req, res) => {
} }
if (req.session.user.role !== 'admin' && task.created_by !== currentUserId) { if (req.session.user.role !== 'admin' && task.created_by !== currentUserId) {
return res.status(403).json({ error: 'У вас нет прав для редактирования сроков' }); return res.status(403).json({ error: 'У вас нет прав для редактирования сроки' });
} }
db.run( db.run(
@@ -1026,4 +1072,7 @@ app.listen(PORT, () => {
console.log('- Логин: teacher, Пароль: teacher123'); console.log('- Логин: teacher, Пароль: teacher123');
console.log('LDAP авторизация доступна для пользователей школы'); console.log('LDAP авторизация доступна для пользователей школы');
console.log(`Разрешенные группы: ${process.env.ALLOWED_GROUPS}`); console.log(`Разрешенные группы: ${process.env.ALLOWED_GROUPS}`);
// Запускаем проверку просроченных задач каждую минуту
setInterval(checkOverdueTasks, 60000);
}); });