Files
Nas-Notification/server/api/notifications/logs/index.get.js

234 lines
6.9 KiB
JavaScript

import prisma from '~/server/utils/prisma'
export default defineEventHandler(async (event) => {
try {
// Check authentication
const user = event.context.user;
if (!user || !user.userID) {
return {
statusCode: 401,
body: { success: false, message: 'Unauthorized' }
}
}
const query = getQuery(event)
let logs = [];
let totalLogs = 0;
let failedDeliveries = 0;
let successfulDeliveries = 0;
let total = 0;
try {
// Define filters
const filters = {}
// Date range filter
if (query.startDate) {
filters.created_at = {
...filters.created_at,
gte: new Date(query.startDate)
}
}
if (query.endDate) {
filters.created_at = {
...filters.created_at,
lte: new Date(query.endDate)
}
}
// Action filter
if (query.action) {
filters.action = query.action
}
// Channel filter
if (query.channel) {
filters.channel_type = query.channel
}
// Status filter
if (query.status) {
filters.status = query.status
}
// Actor/user filter
if (query.actor) {
filters.actor = {
contains: query.actor
}
}
// Notification ID filter
if (query.notificationId) {
filters.notification_id = query.notificationId
}
// Keyword search in details or error_message
if (query.keyword) {
filters.OR = [
{ details: { contains: query.keyword } },
{ error_message: { contains: query.keyword } }
]
}
// Pagination
const page = parseInt(query.page) || 1
const limit = parseInt(query.limit) || 10
const skip = (page - 1) * limit
try {
console.log("Attempting to query notification_logs table...");
// First check if the table exists
let tableExists = true;
try {
await prisma.$queryRaw`SELECT 1 FROM notification_logs LIMIT 1`;
console.log("notification_logs table exists!");
} catch (tableCheckError) {
console.error("Table check error:", tableCheckError.message);
console.error("Table likely doesn't exist - you need to run the migration!");
tableExists = false;
throw new Error("notification_logs table does not exist");
}
if (tableExists) {
// Get total count for pagination
total = await prisma.notification_logs.count({
where: filters
})
// Get logs with pagination and sorting
logs = await prisma.notification_logs.findMany({
where: filters,
orderBy: {
created_at: 'desc'
},
skip,
take: limit
})
// Get summary stats
totalLogs = await prisma.notification_logs.count()
failedDeliveries = await prisma.notification_logs.count({
where: {
status: 'Failed'
}
})
successfulDeliveries = await prisma.notification_logs.count({
where: {
status: 'Sent'
}
})
console.log(`Successfully fetched ${logs.length} logs from database`);
}
} catch (dbError) {
console.error("Database query error:", dbError.message);
console.error("Stack trace:", dbError.stack);
// Uncommenting the mock data code below will revert to using mock data
// If you want to see real errors, keep this commented out
/*
// If the database table doesn't exist or there's another error, use mock data
logs = generateMockLogs(limit);
total = 25; // Mock total count
totalLogs = 25;
failedDeliveries = 3;
successfulDeliveries = 20;
*/
throw dbError; // Re-throw to see actual error in response
}
} catch (prismaError) {
console.error("Prisma error:", prismaError.message);
console.error("Stack trace:", prismaError.stack);
// Uncommenting the mock data code below will revert to using mock data
// If you want to see real errors, keep this commented out
/*
// If there's an issue with Prisma itself, use mock data
logs = generateMockLogs(10);
total = 25; // Mock total count
totalLogs = 25;
failedDeliveries = 3;
successfulDeliveries = 20;
*/
throw prismaError; // Re-throw to see actual error in response
}
// Calculate success rate
const successRate = totalLogs > 0
? Math.round((successfulDeliveries / totalLogs) * 100)
: 0
const page = parseInt(query.page) || 1
const limit = parseInt(query.limit) || 10
return {
statusCode: 200,
body: {
success: true,
data: {
logs,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit)
},
summary: {
totalLogs,
failedDeliveries,
successfulDeliveries,
successRate
}
}
}
}
} catch (error) {
console.error('Error fetching notification logs:', error)
return {
statusCode: 500,
body: {
success: false,
message: 'Failed to fetch notification logs',
error: error.message,
stack: error.stack
}
}
}
})
// Helper function to generate mock logs for testing
function generateMockLogs(count = 10) {
const actions = ['Notification Created', 'Notification Sent', 'Delivery Attempted', 'Notification Opened'];
const statuses = ['Sent', 'Failed', 'Opened', 'Queued'];
const channels = ['Email', 'SMS', 'Push Notification', 'Webhook'];
const actors = ['System', 'Admin', 'API', 'Scheduler'];
return Array.from({ length: count }, (_, i) => {
const status = statuses[Math.floor(Math.random() * statuses.length)];
const action = actions[Math.floor(Math.random() * actions.length)];
const created_at = new Date();
created_at.setHours(created_at.getHours() - Math.floor(Math.random() * 72)); // Random time in last 72 hours
return {
id: `mock-${i+1}-${Date.now()}`.substring(0, 36),
notification_id: `notif-${i+1}-${Date.now()}`.substring(0, 36),
action,
actor: actors[Math.floor(Math.random() * actors.length)],
actor_id: `user-${i+1}`,
channel_type: channels[Math.floor(Math.random() * channels.length)],
status,
details: `${action} via ${channels[Math.floor(Math.random() * channels.length)]}`,
source_ip: `192.168.1.${i+1}`,
error_code: status === 'Failed' ? 'ERR_DELIVERY_FAILED' : null,
error_message: status === 'Failed' ? 'Failed to deliver notification' : null,
created_at
};
});
}