- migration 062: mimecast_tenants table (company_id, client_id/secret, account_code) - Seed Wulf (CUSA13A95) + Seubert (CUSA96A181) tenants - MimecastClient.getHeldMessages(): full pagination via meta.pagination.next cursor (API always returns 10/page regardless of pageSize param, totalCount in meta) - getMimecastClientForTenant() factory for per-tenant instantiation - GET /api/mimecast/held?tenantId=&recipient= — fetches all tenants in parallel, merges + sorts by date, returns per-tenant counts + combined messages[] - Held Mail tab on /admin/sync/mimecast (on-demand load, recipient filter, tenant badges, policy filter dropdown, DMARC/impersonation highlighted red)
91 lines
3.1 KiB
TypeScript
91 lines
3.1 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { postgresClient } from '@/lib/services/postgres-client';
|
|
import { getMimecastClientForTenant } from '@/lib/services/mimecast-client';
|
|
|
|
export async function GET(req: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(req.url);
|
|
const tenantId = searchParams.get('tenantId');
|
|
const recipient = searchParams.get('recipient') ?? undefined;
|
|
|
|
// Build query — filter by tenant if provided, else all enabled tenants
|
|
let tenants: any[];
|
|
if (tenantId) {
|
|
const r = await postgresClient.query(
|
|
`SELECT mt.*, c.company_name FROM mimecast_tenants mt
|
|
LEFT JOIN companies c ON c.id = mt.company_id
|
|
WHERE mt.id = $1 AND mt.enabled = true`,
|
|
[tenantId]
|
|
);
|
|
tenants = r.rows;
|
|
} else {
|
|
const r = await postgresClient.query(
|
|
`SELECT mt.*, c.company_name FROM mimecast_tenants mt
|
|
LEFT JOIN companies c ON c.id = mt.company_id
|
|
WHERE mt.enabled = true
|
|
ORDER BY mt.account_name`
|
|
);
|
|
tenants = r.rows;
|
|
}
|
|
|
|
if (!tenants.length) {
|
|
return NextResponse.json({ error: 'No configured Mimecast tenants found' }, { status: 404 });
|
|
}
|
|
|
|
// Fetch held messages for each tenant in parallel
|
|
const results = await Promise.allSettled(
|
|
tenants.map(async (tenant) => {
|
|
const client = getMimecastClientForTenant(tenant);
|
|
const { messages, totalCount } = await client.getHeldMessages({ recipient, maxMessages: 500 });
|
|
return {
|
|
tenantId: tenant.id,
|
|
accountCode: tenant.account_code,
|
|
accountName: tenant.account_name,
|
|
companyName: tenant.company_name ?? tenant.account_name,
|
|
companyId: tenant.company_id,
|
|
messages,
|
|
totalCount,
|
|
error: null,
|
|
};
|
|
})
|
|
);
|
|
|
|
const tenantResults = results.map((r, i) => {
|
|
if (r.status === 'fulfilled') return r.value;
|
|
return {
|
|
tenantId: tenants[i].id,
|
|
accountCode: tenants[i].account_code,
|
|
accountName: tenants[i].account_name,
|
|
companyName: tenants[i].company_name ?? tenants[i].account_name,
|
|
companyId: tenants[i].company_id,
|
|
messages: [],
|
|
totalCount: 0,
|
|
error: r.reason?.message ?? 'Failed to fetch',
|
|
};
|
|
});
|
|
|
|
const allMessages = tenantResults.flatMap(t =>
|
|
t.messages.map((m: any) => ({ ...m, tenantId: t.tenantId, accountName: t.accountName, companyName: t.companyName }))
|
|
);
|
|
|
|
// Sort all messages newest first
|
|
allMessages.sort((a, b) => new Date(b.dateReceived).getTime() - new Date(a.dateReceived).getTime());
|
|
|
|
return NextResponse.json({
|
|
tenants: tenantResults.map(t => ({
|
|
tenantId: t.tenantId,
|
|
accountName: t.accountName,
|
|
companyName: t.companyName,
|
|
companyId: t.companyId,
|
|
count: t.messages.length,
|
|
totalCount: t.totalCount,
|
|
error: t.error,
|
|
})),
|
|
messages: allMessages,
|
|
totalCount: allMessages.length,
|
|
});
|
|
} catch (error: any) {
|
|
console.error('[Mimecast] held messages error:', error);
|
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
}
|
|
}
|