mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 19:58:11 +00:00
refactor( iam ): remove prisma.user references from passenger-side services
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { InjectDataSource } from '@nestjs/typeorm';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { PrismaService } from '../../common/prisma.service';
|
||||
import { SendNotificationDto, NotificationCategoryEnum } from './notifications.dto';
|
||||
import { EmailAdapter, SmsAdapter, PushAdapter, NotificationChannel } from './notification.adapters';
|
||||
|
||||
export type NotificationChannelType = 'EMAIL' | 'SMS' | 'PUSH' | 'IN_APP';
|
||||
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
@Injectable()
|
||||
export class NotificationsService {
|
||||
private readonly logger = new Logger(NotificationsService.name);
|
||||
@@ -13,6 +17,7 @@ export class NotificationsService {
|
||||
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
@InjectDataSource() private readonly dataSource: DataSource,
|
||||
private emailAdapter: EmailAdapter,
|
||||
private smsAdapter: SmsAdapter,
|
||||
private pushAdapter: PushAdapter,
|
||||
@@ -98,15 +103,17 @@ export class NotificationsService {
|
||||
|
||||
const passenger = await this.prisma.passenger.findUnique({
|
||||
where: { id: dto.passengerId },
|
||||
include: { user: true },
|
||||
});
|
||||
|
||||
if (passenger?.user) {
|
||||
await this.emailAdapter.send(
|
||||
passenger.user.email,
|
||||
this.sanitize(dto.title),
|
||||
this.sanitize(dto.body),
|
||||
);
|
||||
if (passenger?.iamUserId) {
|
||||
const contact = await this.resolveContactInfo(passenger.iamUserId);
|
||||
if (contact.email) {
|
||||
await this.emailAdapter.send(
|
||||
contact.email,
|
||||
this.sanitize(dto.title),
|
||||
this.sanitize(dto.body),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return notification;
|
||||
@@ -118,22 +125,20 @@ export class NotificationsService {
|
||||
body: string,
|
||||
context: Record<string, unknown>,
|
||||
): Promise<void> {
|
||||
// Try to find passenger by ID or email
|
||||
let passengerId = recipient;
|
||||
|
||||
if (!recipient.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)) {
|
||||
const user = await this.prisma.user.findFirst({
|
||||
where: {
|
||||
OR: [{ email: recipient }, { phone: recipient }],
|
||||
},
|
||||
include: { passenger: true },
|
||||
});
|
||||
if (user?.passenger) {
|
||||
passengerId = user.passenger.id;
|
||||
} else {
|
||||
if (!UUID_RE.test(recipient)) {
|
||||
const iamUserId = await this.resolveIamUserId(recipient);
|
||||
if (!iamUserId) {
|
||||
this.logger.warn(`Could not find passenger for recipient: ${recipient}`);
|
||||
return;
|
||||
}
|
||||
const passenger = await this.prisma.passenger.findUnique({ where: { iamUserId } });
|
||||
if (!passenger) {
|
||||
this.logger.warn(`Could not find passenger for recipient: ${recipient}`);
|
||||
return;
|
||||
}
|
||||
passengerId = passenger.id;
|
||||
}
|
||||
|
||||
await this.prisma.notification.create({
|
||||
@@ -165,13 +170,10 @@ export class NotificationsService {
|
||||
}
|
||||
|
||||
private async getUserPreferredChannels(recipient: string): Promise<NotificationChannelType[]> {
|
||||
const user = await this.prisma.user.findFirst({
|
||||
where: { OR: [{ id: recipient }, { email: recipient }, { phone: recipient }] },
|
||||
include: { passenger: { select: { iamUserId: true } } },
|
||||
});
|
||||
|
||||
const iamUserId = user?.passenger?.iamUserId ?? recipient;
|
||||
const preferences = await this.prisma.userPreferences.findUnique({ where: { iamUserId } });
|
||||
const iamUserId = await this.resolveIamUserId(recipient);
|
||||
const preferences = iamUserId
|
||||
? await this.prisma.userPreferences.findUnique({ where: { iamUserId } })
|
||||
: null;
|
||||
|
||||
if (!preferences) {
|
||||
return ['IN_APP', 'EMAIL'];
|
||||
@@ -189,27 +191,38 @@ export class NotificationsService {
|
||||
recipient: string,
|
||||
channel: NotificationChannelType,
|
||||
): Promise<string | null> {
|
||||
const user = await this.prisma.user.findFirst({
|
||||
where: {
|
||||
OR: [{ id: recipient }, { email: recipient }, { phone: recipient }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) return null;
|
||||
const iamUserId = await this.resolveIamUserId(recipient);
|
||||
if (!iamUserId) return null;
|
||||
const contact = await this.resolveContactInfo(iamUserId);
|
||||
|
||||
switch (channel) {
|
||||
case 'EMAIL':
|
||||
return user.email;
|
||||
case 'SMS':
|
||||
return user.phone;
|
||||
case 'PUSH':
|
||||
// Would need to fetch device push token
|
||||
return user.id;
|
||||
default:
|
||||
return null;
|
||||
case 'EMAIL': return contact.email;
|
||||
case 'SMS': return contact.phone;
|
||||
case 'PUSH': return iamUserId;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async resolveIamUserId(recipient: string): Promise<string | null> {
|
||||
if (UUID_RE.test(recipient)) {
|
||||
const passenger = await this.prisma.passenger.findUnique({ where: { id: recipient } });
|
||||
return passenger?.iamUserId ?? recipient;
|
||||
}
|
||||
const rows = await this.dataSource.query<{ id: string }[]>(
|
||||
`SELECT id FROM iam.users WHERE email = $1 OR phone_number = $1 LIMIT 1`,
|
||||
[recipient],
|
||||
);
|
||||
return rows[0]?.id ?? null;
|
||||
}
|
||||
|
||||
private async resolveContactInfo(iamUserId: string): Promise<{ email: string | null; phone: string | null }> {
|
||||
const rows = await this.dataSource.query<{ email: string; phone_number: string | null }[]>(
|
||||
`SELECT email, phone_number FROM iam.users WHERE id = $1 LIMIT 1`,
|
||||
[iamUserId],
|
||||
);
|
||||
return { email: rows[0]?.email ?? null, phone: rows[0]?.phone_number ?? null };
|
||||
}
|
||||
|
||||
private sanitize(value: string): string {
|
||||
return value
|
||||
.replace(/[\r\n]/g, ' ')
|
||||
|
||||
Reference in New Issue
Block a user