diff --git a/server/private/lib/alerts/processTestAlerts.ts b/server/private/lib/alerts/processTestAlerts.ts index acbd6fa5e..f598dc633 100644 --- a/server/private/lib/alerts/processTestAlerts.ts +++ b/server/private/lib/alerts/processTestAlerts.ts @@ -1,6 +1,11 @@ import logger from "@server/logger"; -import type { TestAlertContext } from "@server/routers/alertRule/types"; +import type { + EmailAlertAction, + TestAlertContext +} from "@server/routers/alertRule/types"; import { sendAlertEmail } from "./sendAlertEmail"; +import type { db, alertEmailRecipients, users, userOrgRoles } from "@server/db"; +import type { eq } from "drizzle-orm"; export async function processTestAlerts(context: TestAlertContext) { const emailActions = context.actions.filter( @@ -9,9 +14,7 @@ export async function processTestAlerts(context: TestAlertContext) { // Process email actions for (const action of emailActions) { try { - const recipients = await resolveEmailRecipients( - action.emailActionId - ); + const recipients = await resolveEmailRecipients(action); if (recipients.length > 0) { await sendAlertEmail(recipients, context); } @@ -20,3 +23,51 @@ export async function processTestAlerts(context: TestAlertContext) { } } } + +/** + * Resolves all email addresses for a given `emailActionId`. + * + * Recipients may be: + * - Direct users (by `userId`) + * - All users in a role (by `roleId`, resolved via `userOrgRoles`) + * - Direct external email addresses + */ +async function resolveEmailRecipients( + action: EmailAlertAction +): Promise { + const emailSet = new Set(); + + // for (const row of rows) { + // if (row.email) { + // emailSet.add(row.email); + // } + + // if (row.userId) { + // const [user] = await db + // .select({ email: users.email }) + // .from(users) + // .where(eq(users.userId, row.userId)) + // .limit(1); + // if (user?.email) { + // emailSet.add(user.email); + // } + // } + + // if (row.roleId) { + // // Find all users with this role via userOrgRoles + // const roleUsers = await db + // .select({ email: users.email }) + // .from(userOrgRoles) + // .innerJoin(users, eq(userOrgRoles.userId, users.userId)) + // .where(eq(userOrgRoles.roleId, Number(row.roleId))); + + // for (const u of roleUsers) { + // if (u.email) { + // emailSet.add(u.email); + // } + // } + // } + // } + + return Array.from(emailSet); +} diff --git a/server/routers/alertRule/types.ts b/server/routers/alertRule/types.ts index 90c4e3163..99057b312 100644 --- a/server/routers/alertRule/types.ts +++ b/server/routers/alertRule/types.ts @@ -125,14 +125,14 @@ export interface AlertContext { data: Record; } -type EmailAlertAction = { +export type EmailAlertAction = { type: "email"; userIds?: string[]; roleIds?: string[]; emails?: string[]; }; -type WebhookAlertAction = { +export type WebhookAlertAction = { type: "webhook"; webhookUrl: string; enabled: boolean; @@ -143,6 +143,7 @@ type AlertAction = EmailAlertAction | WebhookAlertAction; export interface TestAlertContext { eventType: AlertEventType; actions: AlertAction[]; + orgId: string; /** Human-readable context data included in emails and webhook payloads */ data: Record; }