diff --git a/package.json b/package.json index 5eb0b65..2f505f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.54", + "version": "0.5.55", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/src/api/routes/entries.js b/src/api/routes/entries.js index 1e4f96e..d034462 100644 --- a/src/api/routes/entries.js +++ b/src/api/routes/entries.js @@ -121,7 +121,7 @@ function createEntriesRouter({ q }) { if (comment && comment.length > 255) return res.status(400).json({ error: 'Комментарий слишком длинный (максимум 255 символов)' }); try { const company = await resolveCompany(req); - const { entry, wasNormalized } = await q.createEntry(company.id, value, comment || '', req.user.email); + const { entry, wasNormalized } = await q.createEntry(company.id, value, comment || '', req.user.email, req.user.originalUserEmail); res.status(201).json({ entry, wasNormalized }); } catch (e) { if (e.status) return res.status(e.status).json({ error: e.message }); @@ -136,7 +136,7 @@ function createEntriesRouter({ q }) { if (comment && comment.length > 255) return res.status(400).json({ error: 'Комментарий слишком длинный (максимум 255 символов)' }); try { const company = await resolveCompany(req); - const { entry, wasNormalized } = await q.updateEntry(req.params.id, company.id, value, comment ?? '', req.user.email); + const { entry, wasNormalized } = await q.updateEntry(req.params.id, company.id, value, comment ?? '', req.user.email, req.user.originalUserEmail); res.json({ entry, wasNormalized }); } catch (e) { if (e.status) return res.status(e.status).json({ error: e.message }); @@ -148,7 +148,7 @@ function createEntriesRouter({ q }) { router.delete('/:id', async (req, res) => { try { const company = await resolveCompany(req); - await q.deleteEntry(req.params.id, company.id, req.user.email); + await q.deleteEntry(req.params.id, company.id, req.user.email, req.user.originalUserEmail); res.status(204).send(); } catch (e) { if (e.status) return res.status(e.status).json({ error: e.message }); diff --git a/src/db.js b/src/db.js index 083476d..5b83730 100644 --- a/src/db.js +++ b/src/db.js @@ -56,6 +56,7 @@ async function ensureSchema() { old_value TEXT, new_value TEXT, entry_id INTEGER, + impersonated_by VARCHAR(255) DEFAULT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_audit_company_time ON audit_log(company_id, created_at DESC); diff --git a/src/queries.js b/src/queries.js index 8fe0a1e..c591269 100644 --- a/src/queries.js +++ b/src/queries.js @@ -30,7 +30,7 @@ async function listEntries(companyId, includeDeleted = false) { return (await pool.query(sql, [companyId])).rows; } -async function createEntry(companyId, rawValue, comment, userEmail) { +async function createEntry(companyId, rawValue, comment, userEmail, impersonatedBy) { const { cidr, wasNormalized } = validate(rawValue); const client = await pool.connect(); try { @@ -64,7 +64,7 @@ async function createEntry(companyId, rawValue, comment, userEmail) { VALUES ($1, $2, $3, $4) RETURNING *`, [companyId, cidr, comment || null, userEmail] ); - await logAudit(userEmail, companyId, 'CREATE', null, cidr, res.rows[0].id, client); + await logAudit(userEmail, companyId, 'CREATE', null, cidr, res.rows[0].id, impersonatedBy, client); await client.query('COMMIT'); return { entry: res.rows[0], wasNormalized }; } catch (e) { @@ -75,7 +75,7 @@ async function createEntry(companyId, rawValue, comment, userEmail) { } } -async function updateEntry(entryId, companyId, rawValue, comment, userEmail) { +async function updateEntry(entryId, companyId, rawValue, comment, userEmail, impersonatedBy) { const { cidr, wasNormalized } = validate(rawValue); const client = await pool.connect(); try { @@ -105,7 +105,7 @@ async function updateEntry(entryId, companyId, rawValue, comment, userEmail) { WHERE id = $4 AND company_id = $5 RETURNING *`, [cidr, comment || old.comment, userEmail, entryId, companyId] ); - await logAudit(userEmail, companyId, 'UPDATE', old.value_cidr, cidr, entryId, client); + await logAudit(userEmail, companyId, 'UPDATE', old.value_cidr, cidr, entryId, impersonatedBy, client); await client.query('COMMIT'); return { entry: res.rows[0], wasNormalized }; } catch (e) { @@ -116,7 +116,7 @@ async function updateEntry(entryId, companyId, rawValue, comment, userEmail) { } } -async function deleteEntry(entryId, companyId, userEmail) { +async function deleteEntry(entryId, companyId, userEmail, impersonatedBy) { const client = await pool.connect(); try { await client.query('BEGIN'); @@ -132,7 +132,7 @@ async function deleteEntry(entryId, companyId, userEmail) { 'UPDATE whitelist_entries SET deleted_by = $1, deleted_at = NOW() WHERE id = $2 AND company_id = $3', [userEmail, entryId, companyId] ); - await logAudit(userEmail, companyId, 'DELETE', old.value_cidr, null, entryId, client); + await logAudit(userEmail, companyId, 'DELETE', old.value_cidr, null, entryId, impersonatedBy, client); await client.query('COMMIT'); } catch (e) { await client.query('ROLLBACK'); @@ -214,11 +214,11 @@ async function getExportCIDRs(companyId = null) { // ── Audit ── -async function logAudit(userEmail, companyId, action, oldValue, newValue, entryId, db = pool) { +async function logAudit(userEmail, companyId, action, oldValue, newValue, entryId, impersonatedBy, db = pool) { await db.query( - `INSERT INTO audit_log (user_email, company_id, action, old_value, new_value, entry_id) - VALUES ($1, $2, $3, $4, $5, $6)`, - [userEmail, companyId, action, oldValue, newValue, entryId || null] + `INSERT INTO audit_log (user_email, company_id, action, old_value, new_value, entry_id, impersonated_by) + VALUES ($1, $2, $3, $4, $5, $6, $7)`, + [userEmail, companyId, action, oldValue, newValue, entryId || null, impersonatedBy || null] ); }