stock-management-demo/src-server/routes/mantis.js

284 lines
No EOL
7.7 KiB
JavaScript

import express from 'express';
import { PrismaClient } from '@prisma/client'; // Import Prisma Client
import { getMantisSettings, saveTicketToDatabase } from '../services/mantisDownloader.js';
import axios from 'axios';
import reader from '@kenjiuno/msgreader';
const MsgReader = reader.default;
const prisma = new PrismaClient(); // Instantiate Prisma Client
const router = express.Router();
// GET /mantis - Fetch multiple Mantis issues with filtering and pagination
router.get('/', async(req, res) =>
{
const { page = 1, limit = 10, status, priority, severity, reporterUsername, search } = req.query;
const pageNum = parseInt(page, 10);
const limitNum = parseInt(limit, 10);
const skip = (pageNum - 1) * limitNum;
const where = {};
if (status) where.status = status;
if (priority) where.priority = priority;
if (severity) where.severity = severity;
if (reporterUsername) where.reporterUsername = reporterUsername;
if (search)
{
where.OR = [
{ title: { contains: search, mode: 'insensitive' } },
{ description: { contains: search, mode: 'insensitive' } },
];
// If the search term is a number, treat it as an ID
const searchNum = parseInt(search, 10);
if (!isNaN(searchNum))
{
where.OR.push({ id: searchNum });
}
}
try
{
let [issues, totalCount] = await prisma.$transaction([
prisma.mantisIssue.findMany({
where,
skip,
take: limitNum,
orderBy: {
updatedAt: 'desc', // Default sort order
},
// You might want to include related data like comments count later
// include: { _count: { select: { comments: true } } }
}),
prisma.mantisIssue.count({ where }),
]);
if (!issues || issues.length === 0)
{
//If it's numeric, try to download the issue from Mantis
const searchNum = parseInt(search, 10);
if (!isNaN(searchNum))
{
let data;
try
{
data = await saveTicketToDatabase(searchNum);
}
catch (error)
{
console.error('Error saving ticket to database:', error.message);
return res.status(404).json({ error: 'Mantis issue not found' });
}
if (!data)
{
return res.status(404).json({ error: 'Mantis issue not found' });
}
// Fetch the issue again from the database
issues = await prisma.mantisIssue.findMany({
where,
skip,
take: limitNum,
orderBy: {
updatedAt: 'desc', // Default sort order
},
});
if (issues.length === 0)
{
return res.status(404).json({ error: 'Mantis issue not found' });
}
totalCount = await prisma.mantisIssue.count({ where });
}
}
res.json({
data: issues,
pagination: {
total: totalCount,
page: pageNum,
limit: limitNum,
totalPages: Math.ceil(totalCount / limitNum),
},
});
}
catch (error)
{
console.error('Error fetching Mantis issues:', error.message);
res.status(500).json({ error: 'Failed to fetch Mantis issues' });
}
});
// GET /mantis/:id - Fetch a single Mantis issue by ID
router.get('/:id', async(req, res) =>
{
const { id } = req.params;
const issueId = parseInt(id, 10);
if (isNaN(issueId))
{
return res.status(400).json({ error: 'Invalid issue ID format' });
}
try
{
const issue = await prisma.mantisIssue.findUnique({
where: { id: issueId },
include: {
comments: { // Include comments
include: { attachments: true } // And include attachments for each comment
}
}
});
if (!issue)
{
//Try to download the issue from Mantis
const data = await saveTicketToDatabase(issueId);
if (!data)
{
return res.status(404).json({ error: 'Mantis issue not found' });
}
// Fetch the issue again from the database
const issue = await prisma.mantisIssue.findUnique({
where: { id: issueId },
include: {
comments: { // Include comments
include: { attachments: true } // And include attachments for each comment
}
}
});
}
res.json(issue);
}
catch (error)
{
console.error(`Error fetching Mantis issue ${issueId}:`, error.message);
res.status(500).json({ error: 'Failed to fetch Mantis issue' });
}
});
router.get('/attachment/:ticketId/:attachmentId', async(req, res) =>
{
const { url, headers } = await getMantisSettings();
const { ticketId, attachmentId } = req.params;
const attachmentUrl = `${url}/issues/${ticketId}/files/${attachmentId}`;
console.log('Fetching Mantis attachment from URL:', attachmentUrl);
try
{
const response = await axios.get(attachmentUrl, { headers });
const attachment = response.data.files[0];
if (!attachment)
{
return res.status(404).json({ error: 'Attachment not found' });
}
const buffer = Buffer.from(attachment.content, 'base64');
res.setHeader('Content-Type', attachment.content_type);
res.setHeader('Content-Disposition', `attachment; filename="${attachment.filename}"`);
res.setHeader('Content-Length', buffer.length);
res.send(buffer);
}
catch (error)
{
console.error('Error fetching Mantis attachment:', error.message);
res.status(500).json({ error: 'Failed to fetch Mantis attachment' });
}
});
router.get('/msg-extract/:ticketId/:attachmentId', async(req, res) =>
{
const { url, headers } = await getMantisSettings();
const { ticketId, attachmentId } = req.params;
const attachmentUrl = `${url}/issues/${ticketId}/files/${attachmentId}`;
console.log('Fetching Mantis attachment from URL:', attachmentUrl);
try
{
const response = await axios.get(attachmentUrl, { headers });
const attachment = response.data.files[0];
if (!attachment)
{
return res.status(404).json({ error: 'Attachment not found' });
}
const buffer = Buffer.from(attachment.content, 'base64');
console.log(MsgReader);
const reader = new MsgReader(buffer);
const msg = reader.getFileData();
res.status(200).json(msg);
}
catch (error)
{
console.error('Error fetching Mantis attachment:', error.message);
res.status(500).json({ error: 'Failed to fetch Mantis attachment' });
}
});
router.get('/msg-extract/:ticketId/:attachmentId/:innerAttachmentId', async(req, res) =>
{
const { url, headers } = await getMantisSettings();
const { ticketId, attachmentId, innerAttachmentId } = req.params;
const attachmentUrl = `${url}/issues/${ticketId}/files/${attachmentId}`;
console.log('Fetching Mantis attachment from URL:', attachmentUrl);
try
{
const response = await axios.get(attachmentUrl, { headers });
const attachment = response.data.files[0];
if (!attachment)
{
return res.status(404).json({ error: 'Attachment not found' });
}
const buffer = Buffer.from(attachment.content, 'base64');
const reader = new MsgReader(buffer);
const msg = reader.getFileData();
// Find the inner attachment
const innerAttachment = msg.attachments[innerAttachmentId];
if (!innerAttachment)
{
return res.status(404).json({ error: 'Inner attachment not found' });
}
const attachmentData = reader.getAttachment(innerAttachment);
const innerBuffer = Buffer.from(attachmentData.content, 'base64');
res.setHeader('Content-Disposition', `attachment; filename="${innerAttachment.fileName}"`);
res.status(200).send(innerBuffer);
}
catch (error)
{
console.error('Error fetching Mantis attachment:', error.message);
res.status(500).json({ error: 'Failed to fetch Mantis attachment' });
}
});
export default router;