upravlenie-service
This commit is contained in:
@@ -126,63 +126,66 @@ class UpravlenieService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Создание нового подключения
|
* Создание нового подключения
|
||||||
*/
|
*/
|
||||||
async createConnection(data) {
|
async createConnection(data) {
|
||||||
const {
|
const {
|
||||||
service_id, service_name, service_type, login, password,
|
service_id, service_name, service_type, login, password,
|
||||||
api_url, local_user_id, local_user_login, sync_direction = 'outgoing',
|
api_url, local_user_id, local_user_login, sync_direction = 'outgoing',
|
||||||
sync_enabled = 1, sync_interval = 60
|
sync_enabled = 1, sync_interval = 60
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
// Валидация service_id
|
// Валидация service_id
|
||||||
if (service_id < SERVICE_ID_RANGE.min || service_id > SERVICE_ID_RANGE.max) {
|
if (service_id < SERVICE_ID_RANGE.min || service_id > SERVICE_ID_RANGE.max) {
|
||||||
throw new Error(`service_id должен быть в диапазоне ${SERVICE_ID_RANGE.min}-${SERVICE_ID_RANGE.max}`);
|
throw new Error(`service_id должен быть в диапазоне ${SERVICE_ID_RANGE.min}-${SERVICE_ID_RANGE.max}`);
|
||||||
}
|
|
||||||
|
|
||||||
// Для организатора api_url может быть пустым
|
|
||||||
if (service_type === 'executor' && !api_url) {
|
|
||||||
throw new Error('Для исполнителя необходимо указать api_url организатора');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверяем уникальность service_id для активных подключений
|
|
||||||
const existing = await this.getConnectionByServiceId(service_id);
|
|
||||||
if (existing && existing.is_active) {
|
|
||||||
throw new Error(`Подключение с service_id ${service_id} уже существует`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sql = `
|
|
||||||
INSERT INTO upravlenie (
|
|
||||||
service_id, service_name, service_type, login, password,
|
|
||||||
api_url, local_user_id, local_user_login, sync_direction,
|
|
||||||
sync_enabled, sync_interval
|
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
||||||
`;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.db.run(sql, [
|
|
||||||
service_id, service_name, service_type, login, password,
|
|
||||||
api_url, local_user_id || null, local_user_login || null,
|
|
||||||
sync_direction, sync_enabled, sync_interval
|
|
||||||
], function(err) {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
const connectionId = this.lastID;
|
|
||||||
console.log(`✅ Создано подключение ${service_name} (ID: ${connectionId}, service_id: ${service_id})`);
|
|
||||||
|
|
||||||
// Запускаем синхронизацию для нового подключения
|
|
||||||
if (sync_enabled) {
|
|
||||||
this.startSyncJob(connectionId, sync_interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve({ id: connectionId, ...data });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Для организатора api_url может быть пустым
|
||||||
|
if (service_type === 'executor' && !api_url) {
|
||||||
|
throw new Error('Для исполнителя необходимо указать api_url организатора');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем существование локального пользователя если указан
|
||||||
|
if (local_user_id) {
|
||||||
|
const userExists = await this.checkLocalUserExists(local_user_id);
|
||||||
|
if (!userExists) {
|
||||||
|
throw new Error(`Пользователь с ID ${local_user_id} не существует`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем уникальность service_id для активных подключений
|
||||||
|
const existing = await this.getConnectionByServiceId(service_id);
|
||||||
|
if (existing && existing.is_active) {
|
||||||
|
throw new Error(`Подключение с service_id ${service_id} уже существует`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO upravlenie (
|
||||||
|
service_id, service_name, service_type, login, password,
|
||||||
|
api_url, local_user_id, local_user_login, sync_direction,
|
||||||
|
sync_enabled, sync_interval
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.db.run(sql, [
|
||||||
|
service_id, service_name, service_type, login, password,
|
||||||
|
api_url, local_user_id || null, local_user_login || null,
|
||||||
|
sync_direction, sync_enabled, sync_interval
|
||||||
|
], function(err) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
const connectionId = this.lastID;
|
||||||
|
console.log(`✅ Создано подключение ${service_name} (ID: ${connectionId}, service_id: ${service_id})`);
|
||||||
|
|
||||||
|
resolve({ id: connectionId, ...data });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Получение подключения по ID
|
* Получение подключения по ID
|
||||||
*/
|
*/
|
||||||
@@ -279,12 +282,6 @@ class UpravlenieService {
|
|||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
console.log(`✅ Подключение ${id} обновлено`);
|
console.log(`✅ Подключение ${id} обновлено`);
|
||||||
|
|
||||||
// Перезапускаем задачу синхронизации если изменились настройки
|
|
||||||
if (data.sync_enabled !== undefined || data.sync_interval !== undefined) {
|
|
||||||
this.restartSyncJob(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve({ id, changes: this.changes });
|
resolve({ id, changes: this.changes });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -307,9 +304,9 @@ class UpravlenieService {
|
|||||||
sync_enabled: true
|
sync_enabled: true
|
||||||
});
|
});
|
||||||
|
|
||||||
connections.forEach(conn => {
|
for (const conn of connections) {
|
||||||
this.startSyncJob(conn.id, conn.sync_interval);
|
this.startSyncJob(conn.id, conn.sync_interval);
|
||||||
});
|
}
|
||||||
|
|
||||||
console.log(`✅ Запущено ${connections.length} задач синхронизации`);
|
console.log(`✅ Запущено ${connections.length} задач синхронизации`);
|
||||||
}
|
}
|
||||||
@@ -419,52 +416,86 @@ class UpravlenieService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Синхронизация от исполнителя к организатору
|
* Синхронизация от исполнителя к организатору
|
||||||
*/
|
*/
|
||||||
async syncToOrganizer(connection) {
|
async syncToOrganizer(connection) {
|
||||||
if (!connection.api_url) {
|
if (!connection.api_url) {
|
||||||
throw new Error('Для исполнителя не указан api_url организатора');
|
throw new Error('Для исполнителя не указан api_url организатора');
|
||||||
}
|
|
||||||
|
|
||||||
// Получаем задачи, назначенные локальному пользователю
|
|
||||||
const localTasks = await this.getTasksForLocalUser(connection.local_user_id);
|
|
||||||
|
|
||||||
// Получаем задачи от организатора
|
|
||||||
const organizerTasks = await this.fetchTasksFromOrganizer(connection);
|
|
||||||
|
|
||||||
// Обновляем локальные задачи
|
|
||||||
await this.syncTasksWithOrganizer(connection, organizerTasks, localTasks);
|
|
||||||
|
|
||||||
// Отправляем обновленные статусы организатору
|
|
||||||
await this.sendTaskStatusesToOrganizer(connection, localTasks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Проверяем наличие локального пользователя
|
||||||
* Синхронизация от организатора к исполнителям
|
if (!connection.local_user_id) {
|
||||||
*/
|
console.warn(`⚠️ Для подключения ${connection.service_name} не указан локальный пользователь. Задачи не будут создаваться.`);
|
||||||
async syncFromExecutors(connection) {
|
return;
|
||||||
// Получаем все активные подключения исполнителей с таким же service_id
|
}
|
||||||
const executors = await this.getAllConnections({
|
|
||||||
service_type: 'executor',
|
|
||||||
is_active: true,
|
|
||||||
sync_enabled: true
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const executor of executors) {
|
// Получаем задачи, назначенные локальному пользователю
|
||||||
try {
|
const localTasks = await this.getTasksForLocalUser(connection.local_user_id);
|
||||||
// Получаем статусы задач от исполнителя
|
|
||||||
const taskStatuses = await this.fetchTaskStatusesFromExecutor(executor);
|
// Получаем задачи от организатора
|
||||||
|
const organizerTasks = await this.fetchTasksFromOrganizer(connection);
|
||||||
|
|
||||||
|
if (organizerTasks.length === 0) {
|
||||||
|
console.log(`📭 Нет новых задач от организатора для ${connection.service_name}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновляем локальные задачи
|
||||||
|
await this.syncTasksWithOrganizer(connection, organizerTasks, localTasks);
|
||||||
|
|
||||||
|
// Отправляем обновленные статусы организатору
|
||||||
|
await this.sendTaskStatusesToOrganizer(connection, localTasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Синхронизация от организатора к исполнителям
|
||||||
|
*/
|
||||||
|
async syncFromExecutors(connection) {
|
||||||
|
// Получаем все активные подключения исполнителей с таким же service_id
|
||||||
|
const executors = await this.getAllConnections({
|
||||||
|
service_type: 'executor',
|
||||||
|
is_active: true,
|
||||||
|
sync_enabled: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (executors.length === 0) {
|
||||||
|
console.log(`📭 Нет активных исполнителей для организатора ${connection.service_name}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const executor of executors) {
|
||||||
|
try {
|
||||||
|
// Проверяем наличие локального пользователя у исполнителя
|
||||||
|
if (!executor.local_user_id) {
|
||||||
|
console.warn(`⚠️ Для исполнителя ${executor.service_name} не указан локальный пользователь. Пропускаем...`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем статусы задач от исполнителя
|
||||||
|
const taskStatuses = await this.fetchTaskStatusesFromExecutor(executor);
|
||||||
|
|
||||||
|
if (taskStatuses.length > 0) {
|
||||||
// Обновляем статусы в локальной БД
|
// Обновляем статусы в локальной БД
|
||||||
await this.updateTaskStatusesFromExecutor(executor, taskStatuses);
|
await this.updateTaskStatusesFromExecutor(executor, taskStatuses);
|
||||||
|
console.log(`✅ Получено ${taskStatuses.length} статусов от исполнителя ${executor.service_name}`);
|
||||||
} catch (error) {
|
|
||||||
console.error(`❌ Ошибка получения статусов от исполнителя ${executor.service_name}:`, error.message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Ошибка получения статусов от исполнителя ${executor.service_name}:`, error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Проверка существования локального пользователя
|
||||||
|
*/
|
||||||
|
async checkLocalUserExists(userId) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.db.get('SELECT id FROM users WHERE id = ?', [userId], (err, row) => {
|
||||||
|
resolve(!!row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Получение задач для локального пользователя
|
* Получение задач для локального пользователя
|
||||||
*/
|
*/
|
||||||
@@ -582,62 +613,99 @@ class UpravlenieService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// upravlenie-service.js (исправленная версия метода createTaskFromOrganizer)
|
||||||
* Создание задачи из данных организатора
|
|
||||||
*/
|
/**
|
||||||
async createTaskFromOrganizer(connection, taskData) {
|
* Создание задачи из данных организатора
|
||||||
return new Promise((resolve, reject) => {
|
*/
|
||||||
this.db.serialize(() => {
|
async createTaskFromOrganizer(connection, taskData) {
|
||||||
// Создаем задачу
|
return new Promise((resolve, reject) => {
|
||||||
|
// Проверяем, что local_user_id не NULL
|
||||||
|
if (!connection.local_user_id) {
|
||||||
|
reject(new Error('local_user_id не может быть пустым. Укажите локального пользователя для создания задач.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сначала проверяем структуру таблицы tasks
|
||||||
|
this.db.all("PRAGMA table_info(tasks)", (err, columns) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnNames = columns.map(c => c.name);
|
||||||
|
|
||||||
|
// Формируем SQL запрос динамически
|
||||||
|
let fields = ['title', 'description', 'status', 'created_by', 'start_date', 'due_date', 'task_type'];
|
||||||
|
let placeholders = ['?', '?', '?', '?', '?', '?', '?'];
|
||||||
|
let values = [
|
||||||
|
taskData.title,
|
||||||
|
taskData.description || '',
|
||||||
|
'active',
|
||||||
|
connection.local_user_id, // теперь точно не NULL
|
||||||
|
taskData.start_date || new Date().toISOString(),
|
||||||
|
taskData.due_date || null,
|
||||||
|
'external'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Добавляем external_task_id если колонка существует
|
||||||
|
if (columnNames.includes('external_task_id')) {
|
||||||
|
fields.push('external_task_id');
|
||||||
|
placeholders.push('?');
|
||||||
|
values.push(taskData.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем external_service_id если колонка существует
|
||||||
|
if (columnNames.includes('external_service_id')) {
|
||||||
|
fields.push('external_service_id');
|
||||||
|
placeholders.push('?');
|
||||||
|
values.push(connection.service_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sql = `INSERT INTO tasks (${fields.join(', ')}) VALUES (${placeholders.join(', ')})`;
|
||||||
|
|
||||||
|
console.log(`📝 Создание задачи от организатора:`, {
|
||||||
|
sql,
|
||||||
|
values,
|
||||||
|
local_user_id: connection.local_user_id,
|
||||||
|
service_id: connection.service_id
|
||||||
|
});
|
||||||
|
|
||||||
|
this.db.run(sql, values, function(err) {
|
||||||
|
if (err) {
|
||||||
|
console.error('❌ Ошибка создания задачи:', err);
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTaskId = this.lastID;
|
||||||
|
|
||||||
|
// Назначаем задачу локальному пользователю
|
||||||
this.db.run(
|
this.db.run(
|
||||||
`INSERT INTO tasks (
|
`INSERT INTO task_assignments (task_id, user_id, status, start_date, due_date)
|
||||||
title, description, status, created_by,
|
VALUES (?, ?, ?, ?, ?)`,
|
||||||
external_task_id, external_service_id, start_date, due_date, task_type
|
|
||||||
) VALUES (?, ?, 'active', ?, ?, ?, ?, ?, 'external')`,
|
|
||||||
[
|
[
|
||||||
taskData.title,
|
newTaskId,
|
||||||
taskData.description || '',
|
|
||||||
connection.local_user_id,
|
connection.local_user_id,
|
||||||
taskData.id,
|
taskData.status || 'assigned',
|
||||||
connection.service_id,
|
|
||||||
taskData.start_date || new Date().toISOString(),
|
taskData.start_date || new Date().toISOString(),
|
||||||
taskData.due_date || null
|
taskData.due_date || null
|
||||||
],
|
],
|
||||||
function(err) {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.error('❌ Ошибка назначения задачи:', err);
|
||||||
reject(err);
|
reject(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newTaskId = this.lastID;
|
console.log(`✅ Создана задача ${newTaskId} от организатора ${connection.service_name}`);
|
||||||
|
resolve(newTaskId);
|
||||||
// Назначаем задачу локальному пользователю
|
|
||||||
this.db.run(
|
|
||||||
`INSERT INTO task_assignments (task_id, user_id, status, start_date, due_date)
|
|
||||||
VALUES (?, ?, ?, ?, ?)`,
|
|
||||||
[
|
|
||||||
newTaskId,
|
|
||||||
connection.local_user_id,
|
|
||||||
taskData.status || 'assigned',
|
|
||||||
taskData.start_date || new Date().toISOString(),
|
|
||||||
taskData.due_date || null
|
|
||||||
],
|
|
||||||
(err) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`✅ Создана задача ${newTaskId} от организатора ${connection.service_name}`);
|
|
||||||
resolve(newTaskId);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Обновление задачи из данных организатора
|
* Обновление задачи из данных организатора
|
||||||
*/
|
*/
|
||||||
@@ -668,30 +736,65 @@ class UpravlenieService {
|
|||||||
this.db.run(
|
this.db.run(
|
||||||
`UPDATE task_assignments
|
`UPDATE task_assignments
|
||||||
SET status = ?, updated_at = CURRENT_TIMESTAMP
|
SET status = ?, updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE task_id = (
|
WHERE task_id = ? AND user_id = ?`,
|
||||||
SELECT id FROM tasks
|
|
||||||
WHERE external_task_id = ? AND external_service_id = ?
|
|
||||||
) AND user_id = ?`,
|
|
||||||
[
|
[
|
||||||
status.status,
|
status.status,
|
||||||
status.external_task_id,
|
status.task_id,
|
||||||
executor.service_id,
|
|
||||||
executor.local_user_id
|
executor.local_user_id
|
||||||
],
|
],
|
||||||
function(err) {
|
function(err) {
|
||||||
if (err) reject(err);
|
if (err) reject(err);
|
||||||
else {
|
else {
|
||||||
if (this.changes > 0) {
|
if (this.changes > 0) {
|
||||||
console.log(`✅ Обновлен статус задачи ${status.external_task_id}: ${status.status}`);
|
console.log(`✅ Обновлен статус задачи ${status.task_id}: ${status.status}`);
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Если статус "completed" - проверяем и закрываем задачу если все выполнили
|
||||||
|
if (status.status === 'completed') {
|
||||||
|
await this.checkAndCloseTaskIfAllCompleted(status.task_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверка и закрытие задачи если все исполнители выполнили
|
||||||
|
*/
|
||||||
|
async checkAndCloseTaskIfAllCompleted(taskId) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.db.all(
|
||||||
|
'SELECT status FROM task_assignments WHERE task_id = ?',
|
||||||
|
[taskId],
|
||||||
|
(err, assignments) => {
|
||||||
|
if (!err && assignments && assignments.length > 0) {
|
||||||
|
const allCompleted = assignments.every(a => a.status === 'completed');
|
||||||
|
|
||||||
|
if (allCompleted) {
|
||||||
|
this.db.run(
|
||||||
|
'UPDATE tasks SET closed_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
|
||||||
|
[taskId],
|
||||||
|
(err) => {
|
||||||
|
if (!err) {
|
||||||
|
console.log(`✅ Задача ${taskId} автоматически закрыта`);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Загрузка файла в удаленный сервис
|
* Загрузка файла в удаленный сервис
|
||||||
*/
|
*/
|
||||||
@@ -767,7 +870,7 @@ class UpravlenieService {
|
|||||||
|
|
||||||
// Сохраняем файл локально
|
// Сохраняем файл локально
|
||||||
const { createUserTaskFolder } = require('./database');
|
const { createUserTaskFolder } = require('./database');
|
||||||
const userFolder = createUserTaskFolder(localTaskId, connection.local_user_login);
|
const userFolder = createUserTaskFolder(localTaskId, connection.local_user_login || 'external');
|
||||||
|
|
||||||
const fileName = response.headers['x-file-name'] || `remote_${Date.now()}.bin`;
|
const fileName = response.headers['x-file-name'] || `remote_${Date.now()}.bin`;
|
||||||
const filePath = path.join(userFolder, fileName);
|
const filePath = path.join(userFolder, fileName);
|
||||||
@@ -904,7 +1007,7 @@ function setupUpravlenieEndpoints(app, db) {
|
|||||||
|
|
||||||
// Middleware для проверки аутентификации
|
// Middleware для проверки аутентификации
|
||||||
const requireAuth = (req, res, next) => {
|
const requireAuth = (req, res, next) => {
|
||||||
if (!req.session.user) {
|
if (!req.session || !req.session.user) {
|
||||||
return res.status(401).json({ error: 'Требуется аутентификация' });
|
return res.status(401).json({ error: 'Требуется аутентификация' });
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
@@ -912,7 +1015,10 @@ function setupUpravlenieEndpoints(app, db) {
|
|||||||
|
|
||||||
// Middleware для проверки прав администратора
|
// Middleware для проверки прав администратора
|
||||||
const requireAdmin = (req, res, next) => {
|
const requireAdmin = (req, res, next) => {
|
||||||
if (!req.session.user || req.session.user.role !== 'admin') {
|
if (!req.session || !req.session.user) {
|
||||||
|
return res.status(401).json({ error: 'Требуется аутентификация' });
|
||||||
|
}
|
||||||
|
if (req.session.user.role !== 'admin') {
|
||||||
return res.status(403).json({ error: 'Требуются права администратора' });
|
return res.status(403).json({ error: 'Требуются права администратора' });
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
@@ -966,7 +1072,7 @@ function setupUpravlenieEndpoints(app, db) {
|
|||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: 'Подключение создано',
|
message: 'Подключение создано',
|
||||||
connection
|
connection: connection
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Ошибка создания подключения:', error);
|
console.error('❌ Ошибка создания подключения:', error);
|
||||||
@@ -1066,6 +1172,7 @@ function setupUpravlenieEndpoints(app, db) {
|
|||||||
req.externalConnection = connection;
|
req.externalConnection = connection;
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка аутентификации:', error);
|
||||||
res.status(500).json({ error: 'Ошибка аутентификации' });
|
res.status(500).json({ error: 'Ошибка аутентификации' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1178,7 +1285,7 @@ function setupUpravlenieEndpoints(app, db) {
|
|||||||
|
|
||||||
// Если статус "completed" - закрываем задачу если все исполнители выполнили
|
// Если статус "completed" - закрываем задачу если все исполнители выполнили
|
||||||
if (status.status === 'completed') {
|
if (status.status === 'completed') {
|
||||||
await checkAndCloseTaskIfAllCompleted(status.task_id);
|
await checkAndCloseTaskIfAllCompleted(db, status.task_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,7 +1450,7 @@ function setupUpravlenieEndpoints(app, db) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Вспомогательная функция для проверки и закрытия задачи
|
// Вспомогательная функция для проверки и закрытия задачи
|
||||||
async function checkAndCloseTaskIfAllCompleted(taskId) {
|
async function checkAndCloseTaskIfAllCompleted(db, taskId) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
db.all(
|
db.all(
|
||||||
'SELECT status FROM task_assignments WHERE task_id = ?',
|
'SELECT status FROM task_assignments WHERE task_id = ?',
|
||||||
|
|||||||
Reference in New Issue
Block a user