This commit is contained in:
2026-02-07 14:21:10 +05:00
parent b13eace9da
commit 4f33ef782f
7 changed files with 978 additions and 2681 deletions

971
api2-groups.js Normal file
View File

@@ -0,0 +1,971 @@
// api2-groups.js
// API для управления внешними идентификаторами пользователей
const express = require('express');
const router = express.Router();
module.exports = function(app, db) {
// Middleware для проверки аутентификации
const requireAuth = (req, res, next) => {
if (!req.session || !req.session.user) {
return res.status(401).json({ error: 'Требуется аутентификация' });
}
next();
};
// Middleware для проверки прав администратора
const requireAdmin = (req, res, next) => {
if (!req.session || !req.session.user || req.session.user.role !== 'admin') {
return res.status(403).json({ error: 'Недостаточно прав' });
}
next();
};
// 1. Создание таблиц при инициализации
function createIdTables() {
return new Promise((resolve, reject) => {
// Таблица с группами для идентификаторов
db.run(`
CREATE TABLE IF NOT EXISTS idgroups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
description TEXT,
service_type TEXT NOT NULL, -- 'sberbank', 'yandex', 'ldap', 'other'
is_active BOOLEAN DEFAULT true,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`, (err) => {
if (err) {
console.error('❌ Ошибка создания таблицы idgroups:', err.message);
reject(err);
return;
}
// Таблица с идентификаторами пользователей
db.run(`
CREATE TABLE IF NOT EXISTS idusers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
service_type TEXT NOT NULL, -- 'sberbank', 'yandex', 'ldap', 'other'
external_id TEXT NOT NULL,
login TEXT, -- Логин LDAP (если есть)
ldap_group TEXT, -- Группа LDAP (если есть)
group_id INTEGER, -- Ссылка на группу в idgroups
metadata TEXT, -- Дополнительные данные в JSON
is_active BOOLEAN DEFAULT true,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (group_id) REFERENCES idgroups (id) ON DELETE SET NULL,
UNIQUE(user_id, service_type, external_id)
)
`, (err) => {
if (err) {
console.error('❌ Ошибка создания таблицы idusers:', err.message);
reject(err);
return;
}
// Создаем индексы
db.run('CREATE INDEX IF NOT EXISTS idx_idusers_user_id ON idusers(user_id)', (err) => {
if (err) console.error('❌ Ошибка создания индекса idx_idusers_user_id:', err.message);
});
db.run('CREATE INDEX IF NOT EXISTS idx_idusers_service_type ON idusers(service_type)', (err) => {
if (err) console.error('❌ Ошибка создания индекса idx_idusers_service_type:', err.message);
});
db.run('CREATE INDEX IF NOT EXISTS idx_idusers_external_id ON idusers(external_id)', (err) => {
if (err) console.error('❌ Ошибка создания индекса idx_idusers_external_id:', err.message);
});
db.run('CREATE INDEX IF NOT EXISTS idx_idgroups_service_type ON idgroups(service_type)', (err) => {
if (err) console.error('❌ Ошибка создания индекса idx_idgroups_service_type:', err.message);
});
console.log('✅ Таблицы для внешних идентификаторов созданы');
resolve();
});
});
});
}
// 2. Добавление стандартных групп
function addDefaultGroups() {
const defaultGroups = [
{
name: 'Сбербанк - Сотрудники',
description: 'Идентификаторы сотрудников в системе Сбербанка',
service_type: 'sberbank',
is_active: true
},
{
name: 'Сбербанк - Контрагенты',
description: 'Идентификаторы контрагентов в системе Сбербанка',
service_type: 'sberbank',
is_active: true
},
{
name: 'Яндекс - Работники',
description: 'Идентификаторы работников в системе Яндекса',
service_type: 'yandex',
is_active: true
},
{
name: 'Яндекс - Партнеры',
description: 'Идентификаторы партнеров в системе Яндекса',
service_type: 'yandex',
is_active: true
},
{
name: 'LDAP - Преподаватели',
description: 'Пользователи из LDAP с ролью преподавателя',
service_type: 'ldap',
is_active: true
},
{
name: 'LDAP - Администрация',
description: 'Пользователи из LDAP с ролью администрации',
service_type: 'ldap',
is_active: true
},
{
name: 'Прочие системы',
description: 'Идентификаторы из других систем',
service_type: 'other',
is_active: true
}
];
defaultGroups.forEach(group => {
db.get("SELECT id FROM idgroups WHERE name = ?", [group.name], (err, existing) => {
if (err) {
console.error(`❌ Ошибка проверки группы ${group.name}:`, err.message);
return;
}
if (!existing) {
db.run(
`INSERT INTO idgroups (name, description, service_type, is_active)
VALUES (?, ?, ?, ?)`,
[group.name, group.description, group.service_type, group.is_active ? 1 : 0],
(insertErr) => {
if (insertErr) {
console.error(`❌ Ошибка создания группы ${group.name}:`, insertErr.message);
} else {
console.log(`✅ Группа "${group.name}" создана по умолчанию`);
}
}
);
}
});
});
}
// 3. API эндпоинты
// GET /api2/groups - Получить все группы (доступно всем аутентифицированным)
router.get('/api2/groups', requireAuth, (req, res) => {
const { service_type, is_active } = req.query;
let query = 'SELECT * FROM idgroups WHERE 1=1';
const params = [];
if (service_type) {
query += ' AND service_type = ?';
params.push(service_type);
}
if (is_active !== undefined) {
query += ' AND is_active = ?';
params.push(is_active === 'true' ? 1 : 0);
}
query += ' ORDER BY service_type, name';
db.all(query, params, (err, groups) => {
if (err) {
console.error('❌ Ошибка получения групп:', err);
return res.status(500).json({ error: 'Ошибка получения групп' });
}
res.json(groups || []);
});
});
// GET /api2/groups/:id - Получить группу по ID (доступно всем аутентифицированным)
router.get('/api2/groups/:id', requireAuth, (req, res) => {
const { id } = req.params;
db.get('SELECT * FROM idgroups WHERE id = ?', [id], (err, group) => {
if (err) {
console.error('❌ Ошибка получения группы:', err);
return res.status(500).json({ error: 'Ошибка получения группы' });
}
if (!group) {
return res.status(404).json({ error: 'Группа не найдена' });
}
res.json(group);
});
});
// POST /api2/groups - Создать новую группу (только админ)
router.post('/api2/groups', requireAuth, requireAdmin, (req, res) => {
const { name, description, service_type, is_active } = req.body;
if (!name || !service_type) {
return res.status(400).json({
error: 'Обязательные поля: name, service_type'
});
}
const validServiceTypes = ['sberbank', 'yandex', 'ldap', 'other'];
if (!validServiceTypes.includes(service_type)) {
return res.status(400).json({
error: `Недопустимый тип сервиса. Допустимые значения: ${validServiceTypes.join(', ')}`
});
}
db.run(
`INSERT INTO idgroups (name, description, service_type, is_active)
VALUES (?, ?, ?, ?)`,
[
name,
description || '',
service_type,
is_active !== undefined ? (is_active ? 1 : 0) : 1
],
function(err) {
if (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
return res.status(409).json({ error: 'Группа с таким именем уже существует' });
}
console.error('❌ Ошибка создания группы:', err);
return res.status(500).json({ error: 'Ошибка создания группы' });
}
res.status(201).json({
success: true,
id: this.lastID,
message: 'Группа успешно создана'
});
}
);
});
// PUT /api2/groups/:id - Обновить группу (только админ)
router.put('/api2/groups/:id', requireAuth, requireAdmin, (req, res) => {
const { id } = req.params;
const { name, description, service_type, is_active } = req.body;
// Проверяем существование группы
db.get('SELECT id FROM idgroups WHERE id = ?', [id], (err, existing) => {
if (err) {
console.error('❌ Ошибка проверки группы:', err);
return res.status(500).json({ error: 'Ошибка проверки группы' });
}
if (!existing) {
return res.status(404).json({ error: 'Группа не найдена' });
}
// Собираем поля для обновления
const updates = [];
const params = [];
if (name !== undefined) {
updates.push('name = ?');
params.push(name);
}
if (description !== undefined) {
updates.push('description = ?');
params.push(description);
}
if (service_type !== undefined) {
const validServiceTypes = ['sberbank', 'yandex', 'ldap', 'other'];
if (!validServiceTypes.includes(service_type)) {
return res.status(400).json({
error: `Недопустимый тип сервиса. Допустимые значения: ${validServiceTypes.join(', ')}`
});
}
updates.push('service_type = ?');
params.push(service_type);
}
if (is_active !== undefined) {
updates.push('is_active = ?');
params.push(is_active ? 1 : 0);
}
if (updates.length === 0) {
return res.status(400).json({ error: 'Нет данных для обновления' });
}
updates.push('updated_at = CURRENT_TIMESTAMP');
params.push(id);
const query = `UPDATE idgroups SET ${updates.join(', ')} WHERE id = ?`;
db.run(query, params, function(err) {
if (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
return res.status(409).json({ error: 'Группа с таким именем уже существует' });
}
console.error('❌ Ошибка обновления группы:', err);
return res.status(500).json({ error: 'Ошибка обновления группы' });
}
res.json({
success: true,
changes: this.changes,
message: 'Группа успешно обновлена'
});
});
});
});
// DELETE /api2/groups/:id - Удалить группу (только админ)
router.delete('/api2/groups/:id', requireAuth, requireAdmin, (req, res) => {
const { id } = req.params;
// Проверяем, используется ли группа
db.get('SELECT COUNT(*) as count FROM idusers WHERE group_id = ?', [id], (err, result) => {
if (err) {
console.error('❌ Ошибка проверки использования группы:', err);
return res.status(500).json({ error: 'Ошибка проверки группы' });
}
if (result.count > 0) {
return res.status(400).json({
error: 'Невозможно удалить группу, так как она используется в идентификаторах пользователей',
used_count: result.count
});
}
db.run('DELETE FROM idgroups WHERE id = ?', [id], function(err) {
if (err) {
console.error('❌ Ошибка удаления группы:', err);
return res.status(500).json({ error: 'Ошибка удаления группы' });
}
res.json({
success: true,
changes: this.changes,
message: 'Группа успешно удалена'
});
});
});
});
// GET /api2/idusers - Получить все идентификаторы пользователей (доступно всем аутентифицированным)
router.get('/api2/idusers', requireAuth, (req, res) => {
const { user_id, service_type, external_id, group_id, is_active } = req.query;
let query = `
SELECT iu.*,
u.name as user_name,
u.login as user_login,
u.email as user_email,
g.name as group_name
FROM idusers iu
LEFT JOIN users u ON iu.user_id = u.id
LEFT JOIN idgroups g ON iu.group_id = g.id
WHERE 1=1
`;
const params = [];
if (user_id) {
query += ' AND iu.user_id = ?';
params.push(user_id);
}
if (service_type) {
query += ' AND iu.service_type = ?';
params.push(service_type);
}
if (external_id) {
query += ' AND iu.external_id LIKE ?';
params.push(`%${external_id}%`);
}
if (group_id) {
query += ' AND iu.group_id = ?';
params.push(group_id);
}
if (is_active !== undefined) {
query += ' AND iu.is_active = ?';
params.push(is_active === 'true' ? 1 : 0);
}
query += ' ORDER BY iu.service_type, iu.external_id';
db.all(query, params, (err, idusers) => {
if (err) {
console.error('❌ Ошибка получения идентификаторов пользователей:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
// Парсим JSON metadata если есть
const result = (idusers || []).map(item => {
if (item.metadata) {
try {
item.metadata = JSON.parse(item.metadata);
} catch (e) {
item.metadata = {};
}
} else {
item.metadata = {};
}
return item;
});
res.json(result);
});
});
// GET /api2/idusers/:id - Получить идентификатор по ID (доступно всем аутентифицированным)
router.get('/api2/idusers/:id', requireAuth, (req, res) => {
const { id } = req.params;
db.get(`
SELECT iu.*,
u.name as user_name,
u.login as user_login,
u.email as user_email,
g.name as group_name
FROM idusers iu
LEFT JOIN users u ON iu.user_id = u.id
LEFT JOIN idgroups g ON iu.group_id = g.id
WHERE iu.id = ?
`, [id], (err, iduser) => {
if (err) {
console.error('❌ Ошибка получения идентификатора:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
if (!iduser) {
return res.status(404).json({ error: 'Идентификатор не найден' });
}
// Парсим JSON metadata если есть
if (iduser.metadata) {
try {
iduser.metadata = JSON.parse(iduser.metadata);
} catch (e) {
iduser.metadata = {};
}
} else {
iduser.metadata = {};
}
res.json(iduser);
});
});
// GET /api2/idusers/user/:userId - Получить идентификаторы конкретного пользователя (доступно всем аутентифицированным)
router.get('/api2/idusers/user/:userId', requireAuth, (req, res) => {
const { userId } = req.params;
const { service_type } = req.query;
let query = `
SELECT iu.*, g.name as group_name
FROM idusers iu
LEFT JOIN idgroups g ON iu.group_id = g.id
WHERE iu.user_id = ?
`;
const params = [userId];
if (service_type) {
query += ' AND iu.service_type = ?';
params.push(service_type);
}
query += ' ORDER BY iu.service_type, iu.external_id';
db.all(query, params, (err, idusers) => {
if (err) {
console.error('❌ Ошибка получения идентификаторов пользователя:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
// Парсим JSON metadata если есть
const result = (idusers || []).map(item => {
if (item.metadata) {
try {
item.metadata = JSON.parse(item.metadata);
} catch (e) {
item.metadata = {};
}
} else {
item.metadata = {};
}
return item;
});
res.json(result);
});
});
// POST /api2/idusers - Создать новый идентификатор пользователя (только админ)
router.post('/api2/idusers', requireAuth, requireAdmin, (req, res) => {
const {
user_id,
service_type,
external_id,
login,
ldap_group,
group_id,
metadata,
is_active
} = req.body;
// Валидация обязательных полей
if (!user_id || !service_type || !external_id) {
return res.status(400).json({
error: 'Обязательные поля: user_id, service_type, external_id'
});
}
const validServiceTypes = ['sberbank', 'yandex', 'ldap', 'other'];
if (!validServiceTypes.includes(service_type)) {
return res.status(400).json({
error: `Недопустимый тип сервиса. Допустимые значения: ${validServiceTypes.join(', ')}`
});
}
// Проверяем существование пользователя
db.get('SELECT id FROM users WHERE id = ?', [user_id], (err, user) => {
if (err) {
console.error('❌ Ошибка проверки пользователя:', err);
return res.status(500).json({ error: 'Ошибка проверки пользователя' });
}
if (!user) {
return res.status(404).json({ error: 'Пользователь не найден' });
}
// Если указана группа, проверяем ее существование
if (group_id) {
db.get('SELECT id, service_type FROM idgroups WHERE id = ?', [group_id], (err, group) => {
if (err) {
console.error('❌ Ошибка проверки группы:', err);
return res.status(500).json({ error: 'Ошибка проверки группы' });
}
if (!group) {
return res.status(404).json({ error: 'Указанная группа не найдена' });
}
// Проверяем соответствие типа сервиса
if (group.service_type !== service_type) {
return res.status(400).json({
error: `Тип сервиса группы (${group.service_type}) не соответствует типу сервиса идентификатора (${service_type})`
});
}
// Создаем идентификатор
createIdUser();
});
} else {
// Создаем идентификатор без группы
createIdUser();
}
function createIdUser() {
const metadataJson = metadata ? JSON.stringify(metadata) : null;
db.run(
`INSERT INTO idusers
(user_id, service_type, external_id, login, ldap_group, group_id, metadata, is_active)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[
user_id,
service_type,
external_id,
login || null,
ldap_group || null,
group_id || null,
metadataJson,
is_active !== undefined ? (is_active ? 1 : 0) : 1
],
function(err) {
if (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
return res.status(409).json({
error: 'Идентификатор с такими параметрами уже существует для этого пользователя'
});
}
console.error('❌ Ошибка создания идентификатора:', err);
return res.status(500).json({ error: 'Ошибка создания идентификатора' });
}
res.status(201).json({
success: true,
id: this.lastID,
message: 'Идентификатор успешно создан'
});
}
);
}
});
});
// PUT /api2/idusers/:id - Обновить идентификатор пользователя (только админ)
router.put('/api2/idusers/:id', requireAuth, requireAdmin, (req, res) => {
const { id } = req.params;
const {
user_id,
service_type,
external_id,
login,
ldap_group,
group_id,
metadata,
is_active
} = req.body;
// Проверяем существование идентификатора
db.get('SELECT * FROM idusers WHERE id = ?', [id], (err, existing) => {
if (err) {
console.error('❌ Ошибка проверки идентификатора:', err);
return res.status(500).json({ error: 'Ошибка проверки идентификатора' });
}
if (!existing) {
return res.status(404).json({ error: 'Идентификатор не найден' });
}
// Собираем поля для обновления
const updates = [];
const params = [];
if (user_id !== undefined) {
updates.push('user_id = ?');
params.push(user_id);
}
if (service_type !== undefined) {
const validServiceTypes = ['sberbank', 'yandex', 'ldap', 'other'];
if (!validServiceTypes.includes(service_type)) {
return res.status(400).json({
error: `Недопустимый тип сервиса. Допустимые значения: ${validServiceTypes.join(', ')}`
});
}
updates.push('service_type = ?');
params.push(service_type);
}
if (external_id !== undefined) {
updates.push('external_id = ?');
params.push(external_id);
}
if (login !== undefined) {
updates.push('login = ?');
params.push(login || null);
}
if (ldap_group !== undefined) {
updates.push('ldap_group = ?');
params.push(ldap_group || null);
}
if (group_id !== undefined) {
updates.push('group_id = ?');
params.push(group_id || null);
}
if (metadata !== undefined) {
updates.push('metadata = ?');
params.push(metadata ? JSON.stringify(metadata) : null);
}
if (is_active !== undefined) {
updates.push('is_active = ?');
params.push(is_active ? 1 : 0);
}
if (updates.length === 0) {
return res.status(400).json({ error: 'Нет данных для обновления' });
}
updates.push('updated_at = CURRENT_TIMESTAMP');
params.push(id);
const query = `UPDATE idusers SET ${updates.join(', ')} WHERE id = ?`;
db.run(query, params, function(err) {
if (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
return res.status(409).json({
error: 'Идентификатор с такими параметрами уже существует'
});
}
console.error('❌ Ошибка обновления идентификатора:', err);
return res.status(500).json({ error: 'Ошибка обновления идентификатора' });
}
res.json({
success: true,
changes: this.changes,
message: 'Идентификатор успешно обновлен'
});
});
});
});
// DELETE /api2/idusers/:id - Удалить идентификатор пользователя (только админ)
router.delete('/api2/idusers/:id', requireAuth, requireAdmin, (req, res) => {
const { id } = req.params;
db.run('DELETE FROM idusers WHERE id = ?', [id], function(err) {
if (err) {
console.error('❌ Ошибка удаления идентификатора:', err);
return res.status(500).json({ error: 'Ошибка удаления идентификатора' });
}
res.json({
success: true,
changes: this.changes,
message: 'Идентификатор успешно удален'
});
});
});
// GET /api2/idusers/search - Поиск идентификаторов (доступно всем аутентифицированным)
router.get('/api2/idusers/search', requireAuth, (req, res) => {
const { q, service_type } = req.query;
if (!q || q.length < 2) {
return res.status(400).json({
error: 'Строка поиска должна содержать минимум 2 символа'
});
}
let query = `
SELECT iu.*,
u.name as user_name,
u.login as user_login,
u.email as user_email,
g.name as group_name
FROM idusers iu
LEFT JOIN users u ON iu.user_id = u.id
LEFT JOIN idgroups g ON iu.group_id = g.id
WHERE (iu.external_id LIKE ? OR iu.login LIKE ? OR u.name LIKE ? OR u.login LIKE ?)
`;
const params = [`%${q}%`, `%${q}%`, `%${q}%`, `%${q}%`];
if (service_type) {
query += ' AND iu.service_type = ?';
params.push(service_type);
}
query += ' ORDER BY iu.service_type, iu.external_id LIMIT 50';
db.all(query, params, (err, idusers) => {
if (err) {
console.error('❌ Ошибка поиска идентификаторов:', err);
return res.status(500).json({ error: 'Ошибка поиска' });
}
// Парсим JSON metadata если есть
const result = (idusers || []).map(item => {
if (item.metadata) {
try {
item.metadata = JSON.parse(item.metadata);
} catch (e) {
item.metadata = {};
}
} else {
item.metadata = {};
}
return item;
});
res.json(result);
});
});
// GET /api2/idusers/stats - Статистика по идентификаторам (доступно всем аутентифицированным)
router.get('/api2/idusers/stats', requireAuth, (req, res) => {
// Получаем статистику по типам сервисов
const query = `
SELECT
service_type,
COUNT(*) as total_count,
COUNT(CASE WHEN is_active = 1 THEN 1 END) as active_count,
COUNT(DISTINCT user_id) as unique_users
FROM idusers
GROUP BY service_type
ORDER BY total_count DESC
`;
db.all(query, [], (err, stats) => {
if (err) {
console.error('❌ Ошибка получения статистики:', err);
return res.status(500).json({ error: 'Ошибка получения статистики' });
}
// Получаем общую статистику
db.get(`
SELECT
COUNT(*) as total_identifiers,
COUNT(DISTINCT user_id) as total_users,
COUNT(CASE WHEN is_active = 1 THEN 1 END) as total_active
FROM idusers
`, [], (err, totalStats) => {
if (err) {
console.error('❌ Ошибка получения общей статистики:', err);
return res.status(500).json({ error: 'Ошибка получения статистики' });
}
res.json({
by_service_type: stats || [],
totals: totalStats || {},
timestamp: new Date().toISOString()
});
});
});
});
// 4. Инициализация при подключении модуля
const init = async () => {
try {
await createIdTables();
addDefaultGroups();
console.log('✅ API для внешних идентификаторов инициализирован');
} catch (error) {
console.error('❌ Ошибка инициализации API для внешних идентификаторов:', error.message);
}
};
// Запускаем инициализацию
init();
// Подключаем роутер к приложению
app.use(router);
// Экспортируем функции для использования в других модулях
return {
// Функция для получения внешнего идентификатора пользователя
getUserIdByExternalId: function(service_type, external_id, callback) {
db.get(
'SELECT user_id FROM idusers WHERE service_type = ? AND external_id = ? AND is_active = 1',
[service_type, external_id],
(err, result) => {
if (err) {
console.error('❌ Ошибка получения идентификатора пользователя:', err);
return callback(err, null);
}
callback(null, result ? result.user_id : null);
}
);
},
// Функция для получения внешних идентификаторов пользователя
getUserExternalIds: function(user_id, service_type, callback) {
let query = 'SELECT * FROM idusers WHERE user_id = ? AND is_active = 1';
const params = [user_id];
if (service_type) {
query += ' AND service_type = ?';
params.push(service_type);
}
db.all(query, params, (err, results) => {
if (err) {
console.error('❌ Ошибка получения внешних идентификаторов:', err);
return callback(err, null);
}
// Парсим JSON metadata если есть
const formattedResults = (results || []).map(item => {
if (item.metadata) {
try {
item.metadata = JSON.parse(item.metadata);
} catch (e) {
item.metadata = {};
}
} else {
item.metadata = {};
}
return item;
});
callback(null, formattedResults);
});
},
// Функция для добавления или обновления идентификатора
upsertUserId: function(user_id, service_type, external_id, data, callback) {
const { login, ldap_group, group_id, metadata, is_active } = data || {};
db.get(
'SELECT id FROM idusers WHERE user_id = ? AND service_type = ? AND external_id = ?',
[user_id, service_type, external_id],
(err, existing) => {
if (err) {
return callback(err);
}
const metadataJson = metadata ? JSON.stringify(metadata) : null;
if (existing) {
// Обновляем существующий
db.run(
`UPDATE idusers SET
login = COALESCE(?, login),
ldap_group = COALESCE(?, ldap_group),
group_id = COALESCE(?, group_id),
metadata = COALESCE(?, metadata),
is_active = COALESCE(?, is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = ?`,
[
login || null,
ldap_group || null,
group_id || null,
metadataJson,
is_active !== undefined ? (is_active ? 1 : 0) : 1,
existing.id
],
function(err) {
callback(err, { updated: true, id: existing.id });
}
);
} else {
// Создаем новый
db.run(
`INSERT INTO idusers
(user_id, service_type, external_id, login, ldap_group, group_id, metadata, is_active)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[
user_id,
service_type,
external_id,
login || null,
ldap_group || null,
group_id || null,
metadataJson,
is_active !== undefined ? (is_active ? 1 : 0) : 1
],
function(err) {
callback(err, { created: true, id: this.lastID });
}
);
}
}
);
}
};
};