first commit
This commit is contained in:
commit
c9fb67e751
423 files changed
+53287
No files matched your search
@@ -0,0 +1,241 @@
|
||||
import express from 'express';
|
||||
import multer from 'multer';
|
||||
import { ProvaService } from '../services/ProvaService';
|
||||
import { prisma } from '../prismaClient';
|
||||
import * as fsPromises from 'fs/promises';
|
||||
import * as fs from 'fs'; // Importando o módulo fs padrão
|
||||
import * as path from 'path';
|
||||
|
||||
const router = express.Router();
|
||||
const storage = multer.memoryStorage();
|
||||
const upload = multer({ storage });
|
||||
const provaService = new ProvaService();
|
||||
|
||||
// Upload de arquivo para validação
|
||||
router.post('/upload', upload.array('files'), async (req, res) => {
|
||||
try {
|
||||
console.log('Iniciando upload de arquivos...');
|
||||
|
||||
if (!req.files || !Array.isArray(req.files) || req.files.length === 0) {
|
||||
return res.status(400).json({ error: 'Nenhum arquivo recebido' });
|
||||
}
|
||||
|
||||
// Extrair informações sobre o endereço IP e porta do cliente
|
||||
const forwarded = req.headers['x-forwarded-for'] as string;
|
||||
const socketInfo = req.socket.remoteAddress ? {
|
||||
address: req.socket.remoteAddress,
|
||||
port: req.socket.remotePort || 'desconhecida'
|
||||
} : null;
|
||||
|
||||
// Metadata avançada seguindo RFC 3227
|
||||
const metadata = {
|
||||
userAgent: req.body.user_agent,
|
||||
language: req.body.language,
|
||||
viewportWidth: req.body.viewport_width,
|
||||
viewportHeight: req.body.viewport_height,
|
||||
ipAddress: req.ip || req.socket.remoteAddress,
|
||||
clientPort: req.socket.remotePort || 'desconhecida',
|
||||
connectionInfo: {
|
||||
ip: req.ip || req.socket.remoteAddress,
|
||||
forwardedIp: forwarded,
|
||||
socketAddress: socketInfo?.address,
|
||||
socketPort: socketInfo?.port,
|
||||
remoteFamily: req.socket.remoteFamily
|
||||
},
|
||||
timestamp: new Date(),
|
||||
modification_times: req.body.modification_times,
|
||||
referrer: req.body.referrer,
|
||||
timezone: req.body.timezone,
|
||||
timezone_offset: req.body.timezone_offset,
|
||||
platform: req.body.platform,
|
||||
cookies_enabled: req.body.cookies_enabled,
|
||||
browser_plugins: req.body.browser_plugins,
|
||||
latitude: req.body.latitude,
|
||||
longitude: req.body.longitude,
|
||||
location_permission: req.body.location_permission,
|
||||
client_timestamp: req.body.client_timestamp,
|
||||
headers: {
|
||||
'x-forwarded-for': req.headers['x-forwarded-for'],
|
||||
'user-agent': req.headers['user-agent'],
|
||||
'accept-language': req.headers['accept-language'],
|
||||
'referer': req.headers['referer'],
|
||||
'host': req.headers['host'],
|
||||
'connection': req.headers['connection'],
|
||||
},
|
||||
server: {
|
||||
timestamp: new Date().toISOString(),
|
||||
hostname: require('os').hostname(),
|
||||
process: process.pid,
|
||||
nodeVersion: process.version,
|
||||
}
|
||||
};
|
||||
|
||||
console.log('Metadata recebida:', metadata);
|
||||
console.log('Informações de conexão do cliente:', metadata.connectionInfo);
|
||||
|
||||
// Adicionar informações de segurança
|
||||
const securityInfo = {
|
||||
requestMethod: req.method,
|
||||
protocol: req.protocol,
|
||||
isSecure: req.secure,
|
||||
originalUrl: req.originalUrl,
|
||||
contentType: req.headers['content-type'],
|
||||
};
|
||||
|
||||
console.log('Informações de segurança:', securityInfo);
|
||||
|
||||
// Processar cada arquivo
|
||||
const results = [];
|
||||
for (const file of req.files as Express.Multer.File[]) {
|
||||
try {
|
||||
// Adicionar metadados específicos do arquivo atual
|
||||
const fileIndex = (req.files as Express.Multer.File[]).indexOf(file);
|
||||
|
||||
// Extrair e formatar a data de modificação do arquivo
|
||||
let fileModifiedDate = null;
|
||||
const modificationTime = req.body.modification_times ?
|
||||
(Array.isArray(req.body.modification_times) ? req.body.modification_times[fileIndex] : req.body.modification_times) :
|
||||
null;
|
||||
|
||||
if (modificationTime) {
|
||||
try {
|
||||
// Converter timestamp para objeto Date
|
||||
const timestamp = parseInt(modificationTime);
|
||||
if (!isNaN(timestamp)) {
|
||||
fileModifiedDate = new Date(timestamp);
|
||||
}
|
||||
} catch (dateError) {
|
||||
console.warn(`Erro ao processar data de modificação para ${file.originalname}:`, dateError);
|
||||
}
|
||||
}
|
||||
|
||||
const fileMetadata = {
|
||||
...metadata,
|
||||
file_specific: {
|
||||
name: req.body.file_names ?
|
||||
(Array.isArray(req.body.file_names) ? req.body.file_names[fileIndex] : req.body.file_names) :
|
||||
file.originalname,
|
||||
size: req.body.file_sizes ?
|
||||
(Array.isArray(req.body.file_sizes) ? req.body.file_sizes[fileIndex] : req.body.file_sizes) :
|
||||
file.size,
|
||||
type: req.body.file_types ?
|
||||
(Array.isArray(req.body.file_types) ? req.body.file_types[fileIndex] : req.body.file_types) :
|
||||
file.mimetype,
|
||||
modified: fileModifiedDate ? fileModifiedDate.toISOString() : null,
|
||||
modifiedTimestamp: modificationTime
|
||||
},
|
||||
security: securityInfo
|
||||
};
|
||||
|
||||
// Adicionar log para debug de data de modificação
|
||||
console.log(`Informações de modificação do arquivo ${file.originalname}:`, {
|
||||
rawTimestamp: modificationTime,
|
||||
processedDate: fileModifiedDate,
|
||||
isoString: fileModifiedDate ? fileModifiedDate.toISOString() : null
|
||||
});
|
||||
|
||||
const result = await provaService.processFile(file, fileMetadata);
|
||||
results.push(result);
|
||||
} catch (error) {
|
||||
console.error(`Erro ao processar arquivo ${file.originalname}:`, error);
|
||||
return res.status(500).json({
|
||||
error: `Erro ao processar arquivo ${file.originalname}`,
|
||||
details: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
results,
|
||||
id: results[0].id
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erro no upload:', error);
|
||||
res.status(500).json({ error: 'Erro ao processar arquivos' });
|
||||
}
|
||||
});
|
||||
|
||||
// Status da prova
|
||||
router.get('/:id/status', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const prova = await prisma.prova.findUnique({
|
||||
where: { id }
|
||||
});
|
||||
|
||||
if (!prova) {
|
||||
return res.status(404).json({ error: 'Prova não encontrada' });
|
||||
}
|
||||
|
||||
res.json(prova);
|
||||
} catch (error) {
|
||||
console.error('Erro ao buscar status:', error);
|
||||
res.status(500).json({ error: 'Erro ao buscar status da prova' });
|
||||
}
|
||||
});
|
||||
|
||||
// Verificar documento
|
||||
router.get('/verificar/:hash', async (req, res) => {
|
||||
try {
|
||||
const { hash } = req.params;
|
||||
const result = await provaService.verifyFile(hash);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar documento:', error);
|
||||
res.status(500).json({ error: 'Erro ao verificar documento' });
|
||||
}
|
||||
});
|
||||
|
||||
// Modificar/adicionar esta rota para servir o relatório a partir do hash
|
||||
router.get('/relatorio/:hash', async (req, res) => {
|
||||
try {
|
||||
const { hash } = req.params;
|
||||
|
||||
// Buscar a prova pelo hash
|
||||
const prova = await prisma.prova.findFirst({
|
||||
where: { checksumSha256: hash }
|
||||
});
|
||||
|
||||
if (!prova || prova.status !== 'CONCLUIDO') {
|
||||
return res.status(404).json({ error: 'Relatório não encontrado' });
|
||||
}
|
||||
|
||||
// Construir o caminho para o arquivo do relatório
|
||||
const reportPath = path.join(process.cwd(), 'storage', 'provas', `${hash}_report.pdf`);
|
||||
|
||||
// Verificar se o arquivo existe
|
||||
try {
|
||||
await fsPromises.access(reportPath); // Usando fsPromises para operação assíncrona
|
||||
} catch (error) {
|
||||
console.error('Erro ao acessar relatório:', error);
|
||||
return res.status(404).json({ error: 'Arquivo do relatório não encontrado' });
|
||||
}
|
||||
|
||||
// Enviar o arquivo como resposta
|
||||
res.setHeader('Content-Type', 'application/pdf');
|
||||
res.setHeader('Content-Disposition', `inline; filename="${prova.fileName.replace(/\.[^/.]+$/, '')}_relatorio.pdf"`);
|
||||
|
||||
// Criar stream de leitura e enviar para o cliente
|
||||
const fileStream = fs.createReadStream(reportPath); // Usando fs padrão para createReadStream
|
||||
fileStream.pipe(res);
|
||||
} catch (error) {
|
||||
console.error('Erro ao servir relatório:', error);
|
||||
res.status(500).json({ error: 'Erro ao gerar relatório' });
|
||||
}
|
||||
});
|
||||
|
||||
// Listar provas (admin)
|
||||
router.get('/admin', async (req, res) => {
|
||||
try {
|
||||
const provas = await prisma.prova.findMany({
|
||||
orderBy: { dataCriacao: 'desc' }
|
||||
});
|
||||
res.json(provas);
|
||||
} catch (error) {
|
||||
console.error('Erro ao listar provas:', error);
|
||||
res.status(500).json({ error: 'Erro ao listar provas' });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in new issue
Block a user