fix: Sistema MDM ativado e funcionando
✅ Tabelas MDM criadas (policies, device_policies, policy_commands, etc) ✅ 5 templates pré-configurados inseridos ✅ API /api/mdm/templates funcionando ✅ API /api/policies funcionando ✅ Senha admin resetada (admin123) ✅ Script setup_mdm.js criado Próximo: Corrigir menu lateral duplicado e criar frontend de políticas
This commit is contained in:
@@ -414,3 +414,4 @@ Conseguimos:
|
|||||||
|
|
||||||
**Descanse bem! Amanhã finalizamos! 🚀**
|
**Descanse bem! Amanhã finalizamos! 🚀**
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// Rotas MDM para cliente Windows buscar e executar comandos
|
// Rotas MDM para cliente Windows buscar e executar comandos
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const { Pool } = require('pg');
|
const { query } = require('../config/database');
|
||||||
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
||||||
|
|
||||||
// Cliente busca comandos pendentes
|
// Cliente busca comandos pendentes
|
||||||
router.post('/commands/poll', async (req, res) => {
|
router.post('/commands/poll', async (req, res) => {
|
||||||
@@ -189,17 +188,17 @@ router.get('/templates', async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const { category } = req.query;
|
const { category } = req.query;
|
||||||
|
|
||||||
let query = 'SELECT * FROM policy_templates';
|
let sqlQuery = 'SELECT * FROM policy_templates';
|
||||||
const params = [];
|
const params = [];
|
||||||
|
|
||||||
if (category) {
|
if (category) {
|
||||||
query += ' WHERE category = $1';
|
sqlQuery += ' WHERE category = $1';
|
||||||
params.push(category);
|
params.push(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
query += ' ORDER BY category, name';
|
sqlQuery += ' ORDER BY category, name';
|
||||||
|
|
||||||
const result = await pool.query(query, params);
|
const result = await query(sqlQuery, params);
|
||||||
|
|
||||||
res.json({ success: true, templates: result.rows });
|
res.json({ success: true, templates: result.rows });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
// Rotas para gerenciamento de políticas MDM
|
// Rotas para gerenciamento de políticas MDM
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const { Pool } = require('pg');
|
const { query } = require('../config/database');
|
||||||
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
||||||
|
|
||||||
// Listar todas as políticas
|
// Listar todas as políticas
|
||||||
router.get('/', async (req, res) => {
|
router.get('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const result = await pool.query(`
|
const result = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
p.*,
|
p.*,
|
||||||
COUNT(DISTINCT dp.device_id) as devices_count,
|
COUNT(DISTINCT dp.device_id) as devices_count,
|
||||||
@@ -40,7 +39,7 @@ router.post('/', async (req, res) => {
|
|||||||
priority
|
priority
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
const result = await pool.query(`
|
const result = await query(`
|
||||||
INSERT INTO policies (
|
INSERT INTO policies (
|
||||||
name, description, type, config, enabled, schedule, priority
|
name, description, type, config, enabled, schedule, priority
|
||||||
) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
@@ -69,7 +68,7 @@ router.put('/:id', async (req, res) => {
|
|||||||
priority
|
priority
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
const result = await pool.query(`
|
const result = await query(`
|
||||||
UPDATE policies
|
UPDATE policies
|
||||||
SET name = $1,
|
SET name = $1,
|
||||||
description = $2,
|
description = $2,
|
||||||
@@ -101,10 +100,10 @@ router.delete('/:id', async (req, res) => {
|
|||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
// Remover associações com dispositivos
|
// Remover associações com dispositivos
|
||||||
await pool.query('DELETE FROM device_policies WHERE policy_id = $1', [id]);
|
await query('DELETE FROM device_policies WHERE policy_id = $1', [id]);
|
||||||
|
|
||||||
// Remover política
|
// Remover política
|
||||||
const result = await pool.query('DELETE FROM policies WHERE id = $1 RETURNING *', [id]);
|
const result = await query('DELETE FROM policies WHERE id = $1 RETURNING *', [id]);
|
||||||
|
|
||||||
if (result.rows.length === 0) {
|
if (result.rows.length === 0) {
|
||||||
return res.status(404).json({ success: false, message: 'Política não encontrada' });
|
return res.status(404).json({ success: false, message: 'Política não encontrada' });
|
||||||
@@ -130,7 +129,7 @@ router.post('/:id/devices', async (req, res) => {
|
|||||||
|
|
||||||
// Inserir associações
|
// Inserir associações
|
||||||
const values = device_ids.map(device_id => `('${device_id}', ${id})`).join(',');
|
const values = device_ids.map(device_id => `('${device_id}', ${id})`).join(',');
|
||||||
await pool.query(`
|
await query(`
|
||||||
INSERT INTO device_policies (device_id, policy_id)
|
INSERT INTO device_policies (device_id, policy_id)
|
||||||
VALUES ${values}
|
VALUES ${values}
|
||||||
ON CONFLICT (device_id, policy_id) DO NOTHING
|
ON CONFLICT (device_id, policy_id) DO NOTHING
|
||||||
@@ -154,7 +153,7 @@ router.delete('/:id/devices', async (req, res) => {
|
|||||||
return res.status(400).json({ success: false, message: 'device_ids deve ser um array não vazio' });
|
return res.status(400).json({ success: false, message: 'device_ids deve ser um array não vazio' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await pool.query(`
|
const result = await query(`
|
||||||
DELETE FROM device_policies
|
DELETE FROM device_policies
|
||||||
WHERE policy_id = $1 AND device_id = ANY($2)
|
WHERE policy_id = $1 AND device_id = ANY($2)
|
||||||
`, [id, device_ids]);
|
`, [id, device_ids]);
|
||||||
@@ -174,7 +173,7 @@ router.post('/:id/execute', async (req, res) => {
|
|||||||
const { device_ids } = req.body; // Se não fornecido, executa em todos os dispositivos com a política
|
const { device_ids } = req.body; // Se não fornecido, executa em todos os dispositivos com a política
|
||||||
|
|
||||||
// Buscar política
|
// Buscar política
|
||||||
const policyResult = await pool.query('SELECT * FROM policies WHERE id = $1', [id]);
|
const policyResult = await query('SELECT * FROM policies WHERE id = $1', [id]);
|
||||||
if (policyResult.rows.length === 0) {
|
if (policyResult.rows.length === 0) {
|
||||||
return res.status(404).json({ success: false, message: 'Política não encontrada' });
|
return res.status(404).json({ success: false, message: 'Política não encontrada' });
|
||||||
}
|
}
|
||||||
@@ -184,13 +183,13 @@ router.post('/:id/execute', async (req, res) => {
|
|||||||
// Buscar dispositivos
|
// Buscar dispositivos
|
||||||
let devicesQuery;
|
let devicesQuery;
|
||||||
if (device_ids && device_ids.length > 0) {
|
if (device_ids && device_ids.length > 0) {
|
||||||
devicesQuery = await pool.query(`
|
devicesQuery = await query(`
|
||||||
SELECT DISTINCT d.device_id, d.device_name
|
SELECT DISTINCT d.device_id, d.device_name
|
||||||
FROM devices d
|
FROM devices d
|
||||||
WHERE d.device_id = ANY($1) AND d.status = 'online'
|
WHERE d.device_id = ANY($1) AND d.status = 'online'
|
||||||
`, [device_ids]);
|
`, [device_ids]);
|
||||||
} else {
|
} else {
|
||||||
devicesQuery = await pool.query(`
|
devicesQuery = await query(`
|
||||||
SELECT DISTINCT d.device_id, d.device_name
|
SELECT DISTINCT d.device_id, d.device_name
|
||||||
FROM devices d
|
FROM devices d
|
||||||
INNER JOIN device_policies dp ON d.device_id = dp.device_id
|
INNER JOIN device_policies dp ON d.device_id = dp.device_id
|
||||||
@@ -208,7 +207,7 @@ router.post('/:id/execute', async (req, res) => {
|
|||||||
// Criar comandos de execução para cada dispositivo
|
// Criar comandos de execução para cada dispositivo
|
||||||
const commands = [];
|
const commands = [];
|
||||||
for (const device of devicesQuery.rows) {
|
for (const device of devicesQuery.rows) {
|
||||||
const commandResult = await pool.query(`
|
const commandResult = await query(`
|
||||||
INSERT INTO policy_commands (
|
INSERT INTO policy_commands (
|
||||||
device_id,
|
device_id,
|
||||||
policy_id,
|
policy_id,
|
||||||
@@ -249,7 +248,7 @@ router.get('/:id/executions', async (req, res) => {
|
|||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const { limit = 50, offset = 0 } = req.query;
|
const { limit = 50, offset = 0 } = req.query;
|
||||||
|
|
||||||
const result = await pool.query(`
|
const result = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
pe.*,
|
pe.*,
|
||||||
d.device_name,
|
d.device_name,
|
||||||
@@ -261,7 +260,7 @@ router.get('/:id/executions', async (req, res) => {
|
|||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
`, [id, limit, offset]);
|
`, [id, limit, offset]);
|
||||||
|
|
||||||
const countResult = await pool.query(
|
const countResult = await query(
|
||||||
'SELECT COUNT(*) FROM policy_executions WHERE policy_id = $1',
|
'SELECT COUNT(*) FROM policy_executions WHERE policy_id = $1',
|
||||||
[id]
|
[id]
|
||||||
);
|
);
|
||||||
@@ -282,7 +281,7 @@ router.get('/:id/devices', async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
const result = await pool.query(`
|
const result = await query(`
|
||||||
SELECT
|
SELECT
|
||||||
d.*,
|
d.*,
|
||||||
dp.assigned_at,
|
dp.assigned_at,
|
||||||
|
|||||||
137
backend/setup_mdm.js
Normal file
137
backend/setup_mdm.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
// Script para criar tabelas MDM
|
||||||
|
const { query } = require('./config/database');
|
||||||
|
|
||||||
|
async function setupMDM() {
|
||||||
|
try {
|
||||||
|
console.log('🔧 Configurando Sistema MDM...\n');
|
||||||
|
|
||||||
|
// 1. Criar tabela policies
|
||||||
|
console.log('[1/5] Criando tabela policies...');
|
||||||
|
await query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS policies (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
type VARCHAR(50) NOT NULL,
|
||||||
|
config JSONB NOT NULL DEFAULT '{}',
|
||||||
|
enabled BOOLEAN DEFAULT true,
|
||||||
|
schedule VARCHAR(100),
|
||||||
|
priority INTEGER DEFAULT 5,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
console.log(' ✅ policies criada');
|
||||||
|
|
||||||
|
// 2. Criar tabela device_policies
|
||||||
|
console.log('[2/5] Criando tabela device_policies...');
|
||||||
|
await query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS device_policies (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
device_id VARCHAR(255) NOT NULL,
|
||||||
|
policy_id INTEGER NOT NULL,
|
||||||
|
assigned_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
UNIQUE(device_id, policy_id)
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
console.log(' ✅ device_policies criada');
|
||||||
|
|
||||||
|
// 3. Criar tabela policy_commands
|
||||||
|
console.log('[3/5] Criando tabela policy_commands...');
|
||||||
|
await query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_commands (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
device_id VARCHAR(255) NOT NULL,
|
||||||
|
policy_id INTEGER NOT NULL,
|
||||||
|
command_type VARCHAR(50) NOT NULL,
|
||||||
|
command_data JSONB NOT NULL DEFAULT '{}',
|
||||||
|
status VARCHAR(20) DEFAULT 'pending',
|
||||||
|
priority INTEGER DEFAULT 5,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
sent_at TIMESTAMP,
|
||||||
|
completed_at TIMESTAMP,
|
||||||
|
result JSONB,
|
||||||
|
error_message TEXT,
|
||||||
|
retry_count INTEGER DEFAULT 0,
|
||||||
|
max_retries INTEGER DEFAULT 3
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
console.log(' ✅ policy_commands criada');
|
||||||
|
|
||||||
|
// 4. Criar tabela policy_executions
|
||||||
|
console.log('[4/5] Criando tabela policy_executions...');
|
||||||
|
await query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_executions (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
device_id VARCHAR(255) NOT NULL,
|
||||||
|
policy_id INTEGER NOT NULL,
|
||||||
|
command_id INTEGER,
|
||||||
|
status VARCHAR(20) NOT NULL,
|
||||||
|
executed_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
duration_seconds INTEGER,
|
||||||
|
result JSONB,
|
||||||
|
error_message TEXT,
|
||||||
|
details TEXT
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
console.log(' ✅ policy_executions criada');
|
||||||
|
|
||||||
|
// 5. Criar tabela policy_templates
|
||||||
|
console.log('[5/5] Criando tabela policy_templates...');
|
||||||
|
await query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_templates (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
category VARCHAR(50),
|
||||||
|
type VARCHAR(50) NOT NULL,
|
||||||
|
default_config JSONB NOT NULL DEFAULT '{}',
|
||||||
|
icon VARCHAR(100),
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
console.log(' ✅ policy_templates criada');
|
||||||
|
|
||||||
|
// Inserir templates
|
||||||
|
console.log('\n📦 Inserindo templates pré-configurados...');
|
||||||
|
|
||||||
|
const templates = [
|
||||||
|
{ name: 'Forçar Windows Update', category: 'updates', type: 'windows_update',
|
||||||
|
config: { action: 'force_check_and_install', reboot_if_required: true, reboot_delay_minutes: 30 }},
|
||||||
|
{ name: 'Instalar Software', category: 'software', type: 'software_install',
|
||||||
|
config: { software_name: '', download_url: '', install_args: '/S' }},
|
||||||
|
{ name: 'Executar Script PowerShell', category: 'configuration', type: 'powershell_script',
|
||||||
|
config: { script: '', run_as_admin: true, timeout_minutes: 30 }},
|
||||||
|
{ name: 'Reiniciar Dispositivo', category: 'maintenance', type: 'reboot',
|
||||||
|
config: { delay_minutes: 5, force: false }},
|
||||||
|
{ name: 'Limpar Arquivos Temporários', category: 'maintenance', type: 'cleanup',
|
||||||
|
config: { clear_temp: true, clear_browser_cache: true }}
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const t of templates) {
|
||||||
|
await query(`
|
||||||
|
INSERT INTO policy_templates (name, category, type, default_config)
|
||||||
|
VALUES ($1, $2, $3, $4)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
`, [t.name, t.category, t.type, JSON.stringify(t.config)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const count = await query('SELECT COUNT(*) FROM policy_templates');
|
||||||
|
console.log(' ✅', count.rows[0].count, 'templates disponíveis');
|
||||||
|
|
||||||
|
console.log('\n🎉 Sistema MDM configurado com sucesso!');
|
||||||
|
console.log('');
|
||||||
|
console.log('Teste agora:');
|
||||||
|
console.log(' curl http://localhost:3005/api/mdm/templates');
|
||||||
|
console.log(' curl http://localhost:3005/api/policies');
|
||||||
|
|
||||||
|
process.exit(0);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('\n❌ Erro:', err.message);
|
||||||
|
console.error(err.stack);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupMDM();
|
||||||
|
|
||||||
Reference in New Issue
Block a user