383 lines
16 KiB
JavaScript
383 lines
16 KiB
JavaScript
// group-management.js
|
||
const express = require('express');
|
||
const router = express.Router();
|
||
|
||
function setupGroupManagement(app, db) {
|
||
|
||
// Middleware для проверки администратора
|
||
function requireAdmin(req, res, next) {
|
||
if (!req.session.user || req.session.user.role !== 'admin') {
|
||
return res.status(403).json({ error: 'Недостаточно прав' });
|
||
}
|
||
next();
|
||
}
|
||
|
||
// API для получения всех групп
|
||
router.get('/api/groups', requireAdmin, (req, res) => {
|
||
db.all(`
|
||
SELECT g.*,
|
||
COUNT(DISTINCT ugm.user_id) as member_count
|
||
FROM user_groups g
|
||
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id
|
||
GROUP BY g.id
|
||
ORDER BY g.name
|
||
`, [], (err, groups) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка получения групп:', err);
|
||
return res.status(500).json({ error: 'Ошибка получения групп' });
|
||
}
|
||
res.json(groups || []);
|
||
});
|
||
});
|
||
|
||
// API для получения одной группы с участниками
|
||
router.get('/api/groups/:groupId', requireAdmin, (req, res) => {
|
||
const { groupId } = req.params;
|
||
|
||
db.get(`
|
||
SELECT g.*,
|
||
COUNT(DISTINCT ugm.user_id) as member_count
|
||
FROM user_groups g
|
||
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id
|
||
WHERE g.id = ?
|
||
GROUP BY g.id
|
||
`, [groupId], (err, group) => {
|
||
if (err || !group) {
|
||
return res.status(404).json({ error: 'Группа не найдена' });
|
||
}
|
||
|
||
// Получаем участников группы
|
||
db.all(`
|
||
SELECT u.id, u.login, u.name, u.email, u.role
|
||
FROM users u
|
||
JOIN user_group_memberships ugm ON u.id = ugm.user_id
|
||
WHERE ugm.group_id = ?
|
||
ORDER BY u.name
|
||
`, [groupId], (err, members) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка получения участников:', err);
|
||
return res.status(500).json({ error: 'Ошибка получения участников' });
|
||
}
|
||
|
||
res.json({
|
||
...group,
|
||
members: members || []
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для создания новой группы
|
||
router.post('/api/groups', requireAdmin, (req, res) => {
|
||
const { name, description, color, can_approve_documents } = req.body;
|
||
|
||
if (!name) {
|
||
return res.status(400).json({ error: 'Название группы обязательно' });
|
||
}
|
||
|
||
db.run(`
|
||
INSERT INTO user_groups (name, description, color, can_approve_documents)
|
||
VALUES (?, ?, ?, ?)
|
||
`, [
|
||
name.trim(),
|
||
description || '',
|
||
color || '#3498db',
|
||
can_approve_documents ? 1 : 0
|
||
], function(err) {
|
||
if (err) {
|
||
console.error('❌ Ошибка создания группы:', err);
|
||
return res.status(500).json({
|
||
error: 'Ошибка создания группы',
|
||
details: err.message.includes('UNIQUE') ? 'Группа с таким названием уже существует' : err.message
|
||
});
|
||
}
|
||
|
||
res.json({
|
||
success: true,
|
||
groupId: this.lastID,
|
||
message: 'Группа создана успешно'
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для обновления группы
|
||
router.put('/api/groups/:groupId', requireAdmin, (req, res) => {
|
||
const { groupId } = req.params;
|
||
const { name, description, color, can_approve_documents } = req.body;
|
||
|
||
if (!name) {
|
||
return res.status(400).json({ error: 'Название группы обязательно' });
|
||
}
|
||
|
||
db.run(`
|
||
UPDATE user_groups
|
||
SET name = ?, description = ?, color = ?, can_approve_documents = ?, updated_at = CURRENT_TIMESTAMP
|
||
WHERE id = ?
|
||
`, [
|
||
name.trim(),
|
||
description || '',
|
||
color || '#3498db',
|
||
can_approve_documents ? 1 : 0,
|
||
groupId
|
||
], function(err) {
|
||
if (err) {
|
||
console.error('❌ Ошибка обновления группы:', err);
|
||
return res.status(500).json({
|
||
error: 'Ошибка обновления группы',
|
||
details: err.message.includes('UNIQUE') ? 'Группа с таким названием уже существует' : err.message
|
||
});
|
||
}
|
||
|
||
if (this.changes === 0) {
|
||
return res.status(404).json({ error: 'Группа не найдена' });
|
||
}
|
||
|
||
res.json({
|
||
success: true,
|
||
message: 'Группа обновлена успешно'
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для удаления группы
|
||
router.delete('/api/groups/:groupId', requireAdmin, (req, res) => {
|
||
const { groupId } = req.params;
|
||
|
||
db.run(`DELETE FROM user_groups WHERE id = ?`, [groupId], function(err) {
|
||
if (err) {
|
||
console.error('❌ Ошибка удаления группы:', err);
|
||
return res.status(500).json({ error: 'Ошибка удаления группы' });
|
||
}
|
||
|
||
if (this.changes === 0) {
|
||
return res.status(404).json({ error: 'Группа не найдена' });
|
||
}
|
||
|
||
res.json({
|
||
success: true,
|
||
message: 'Группа удалена успешно'
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для добавления пользователя в группу
|
||
router.post('/api/groups/:groupId/members', requireAdmin, (req, res) => {
|
||
const { groupId } = req.params;
|
||
const { userId } = req.body;
|
||
|
||
if (!userId) {
|
||
return res.status(400).json({ error: 'ID пользователя обязательно' });
|
||
}
|
||
|
||
// Проверяем существование группы и пользователя
|
||
db.get(`SELECT id FROM user_groups WHERE id = ?`, [groupId], (err, group) => {
|
||
if (err || !group) {
|
||
return res.status(404).json({ error: 'Группа не найдена' });
|
||
}
|
||
|
||
db.get(`SELECT id FROM users WHERE id = ?`, [userId], (err, user) => {
|
||
if (err || !user) {
|
||
return res.status(404).json({ error: 'Пользователь не найден' });
|
||
}
|
||
|
||
db.run(`
|
||
INSERT OR IGNORE INTO user_group_memberships (user_id, group_id)
|
||
VALUES (?, ?)
|
||
`, [userId, groupId], function(err) {
|
||
if (err) {
|
||
console.error('❌ Ошибка добавления пользователя в группу:', err);
|
||
return res.status(500).json({ error: 'Ошибка добавления пользователя в группу' });
|
||
}
|
||
|
||
res.json({
|
||
success: true,
|
||
message: 'Пользователь добавлен в группу'
|
||
});
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для удаления пользователя из группы
|
||
router.delete('/api/groups/:groupId/members/:userId', requireAdmin, (req, res) => {
|
||
const { groupId, userId } = req.params;
|
||
|
||
db.run(`
|
||
DELETE FROM user_group_memberships
|
||
WHERE user_id = ? AND group_id = ?
|
||
`, [userId, groupId], function(err) {
|
||
if (err) {
|
||
console.error('❌ Ошибка удаления пользователя из группы:', err);
|
||
return res.status(500).json({ error: 'Ошибка удаления пользователя из группы' });
|
||
}
|
||
|
||
if (this.changes === 0) {
|
||
return res.status(404).json({ error: 'Пользователь не найден в группе' });
|
||
}
|
||
|
||
res.json({
|
||
success: true,
|
||
message: 'Пользователь удален из группы'
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для получения всех пользователей с их группами
|
||
router.get('/api/users-with-groups', requireAdmin, (req, res) => {
|
||
db.all(`
|
||
SELECT u.id, u.login, u.name, u.email, u.role,
|
||
GROUP_CONCAT(DISTINCT g.name) as group_names,
|
||
GROUP_CONCAT(DISTINCT g.id) as group_ids
|
||
FROM users u
|
||
LEFT JOIN user_group_memberships ugm ON u.id = ugm.user_id
|
||
LEFT JOIN user_groups g ON ugm.group_id = g.id
|
||
WHERE u.role IN ('admin', 'teacher')
|
||
GROUP BY u.id
|
||
ORDER BY u.name
|
||
`, [], (err, users) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка получения пользователей с группами:', err);
|
||
return res.status(500).json({ error: 'Ошибка получения данных' });
|
||
}
|
||
|
||
// Преобразуем строки в массивы
|
||
const formattedUsers = users.map(user => ({
|
||
...user,
|
||
group_names: user.group_names ? user.group_names.split(',') : [],
|
||
group_ids: user.group_ids ? user.group_ids.split(',').map(id => parseInt(id)) : []
|
||
}));
|
||
|
||
res.json(formattedUsers);
|
||
});
|
||
});
|
||
|
||
// API для получения доступных групп для пользователя
|
||
router.get('/api/users/:userId/available-groups', requireAdmin, (req, res) => {
|
||
const { userId } = req.params;
|
||
|
||
db.all(`
|
||
SELECT g.*,
|
||
CASE WHEN ugm.user_id IS NOT NULL THEN 1 ELSE 0 END as is_member
|
||
FROM user_groups g
|
||
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id AND ugm.user_id = ?
|
||
ORDER BY g.name
|
||
`, [userId], (err, groups) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка получения групп:', err);
|
||
return res.status(500).json({ error: 'Ошибка получения данных' });
|
||
}
|
||
|
||
res.json(groups || []);
|
||
});
|
||
});
|
||
|
||
// API для массового обновления групп пользователя
|
||
router.put('/api/users/:userId/groups', requireAdmin, (req, res) => {
|
||
const { userId } = req.params;
|
||
const { groupIds } = req.body; // массив ID групп
|
||
|
||
if (!Array.isArray(groupIds)) {
|
||
return res.status(400).json({ error: 'groupIds должен быть массивом' });
|
||
}
|
||
|
||
// Проверяем существование пользователя
|
||
db.get(`SELECT id FROM users WHERE id = ?`, [userId], (err, user) => {
|
||
if (err || !user) {
|
||
return res.status(404).json({ error: 'Пользователь не найден' });
|
||
}
|
||
|
||
db.serialize(() => {
|
||
// Удаляем все текущие группы пользователя
|
||
db.run(`DELETE FROM user_group_memberships WHERE user_id = ?`, [userId], (err) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка удаления старых групп:', err);
|
||
return res.status(500).json({ error: 'Ошибка обновления групп' });
|
||
}
|
||
|
||
// Добавляем новые группы
|
||
if (groupIds.length > 0) {
|
||
const placeholders = groupIds.map(() => '(?, ?)').join(',');
|
||
const values = groupIds.reduce((acc, groupId) => {
|
||
acc.push(userId, groupId);
|
||
return acc;
|
||
}, []);
|
||
|
||
db.run(`
|
||
INSERT INTO user_group_memberships (user_id, group_id)
|
||
VALUES ${placeholders}
|
||
`, values, (err) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка добавления новых групп:', err);
|
||
return res.status(500).json({ error: 'Ошибка обновления групп' });
|
||
}
|
||
|
||
res.json({
|
||
success: true,
|
||
message: 'Группы пользователя обновлены'
|
||
});
|
||
});
|
||
} else {
|
||
res.json({
|
||
success: true,
|
||
message: 'Группы пользователя обновлены'
|
||
});
|
||
}
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
// API для получения пользователей, которые могут согласовывать документы
|
||
router.get('/api/approvers', requireAdmin, (req, res) => {
|
||
db.all(`
|
||
SELECT DISTINCT u.id, u.login, u.name, u.email, u.role,
|
||
g.name as group_name, g.color as group_color
|
||
FROM users u
|
||
JOIN user_group_memberships ugm ON u.id = ugm.user_id
|
||
JOIN user_groups g ON ugm.group_id = g.id
|
||
WHERE g.can_approve_documents = 1
|
||
ORDER BY u.name
|
||
`, [], (err, approvers) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка получения согласующих:', err);
|
||
return res.status(500).json({ error: 'Ошибка получения данных' });
|
||
}
|
||
|
||
res.json(approvers || []);
|
||
});
|
||
});
|
||
|
||
// API для получения групп, которые могут согласовывать документы
|
||
router.get('/api/approver-groups', (req, res) => {
|
||
const isAdmin = req.session.user && req.session.user.role === 'admin';
|
||
|
||
db.all(`
|
||
SELECT g.*,
|
||
COUNT(DISTINCT ugm.user_id) as member_count
|
||
FROM user_groups g
|
||
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id
|
||
WHERE g.can_approve_documents = 1
|
||
GROUP BY g.id
|
||
ORDER BY g.name
|
||
`, [], (err, groups) => {
|
||
if (err) {
|
||
console.error('❌ Ошибка получения групп согласующих:', err);
|
||
return res.status(500).json({ error: 'Ошибка получения данных' });
|
||
}
|
||
|
||
// Для обычных пользователей скрываем ID пользователей в группах
|
||
if (!isAdmin) {
|
||
groups = groups.map(group => ({
|
||
...group,
|
||
members: undefined
|
||
}));
|
||
}
|
||
|
||
res.json(groups || []);
|
||
});
|
||
});
|
||
|
||
return router;
|
||
}
|
||
|
||
module.exports = { setupGroupManagement }; |