72 أسطر
2.1 KiB
TypeScript
72 أسطر
2.1 KiB
TypeScript
import { ConfigService } from '@nestjs/config';
|
|
import { JwtService } from '@nestjs/jwt';
|
|
import {
|
|
OnGatewayConnection,
|
|
WebSocketGateway,
|
|
WebSocketServer,
|
|
} from '@nestjs/websockets';
|
|
import { Server, Socket } from 'socket.io';
|
|
|
|
type SocketWithUser = Socket & { data: { userId?: string } };
|
|
|
|
@WebSocketGateway({ cors: { origin: '*' }, namespace: 'notifications' })
|
|
export class NotificationsGateway implements OnGatewayConnection {
|
|
@WebSocketServer()
|
|
server!: Server;
|
|
|
|
constructor(
|
|
private readonly jwtService: JwtService,
|
|
private readonly configService: ConfigService,
|
|
) {}
|
|
|
|
async handleConnection(client: SocketWithUser) {
|
|
const token = this.extractToken(client);
|
|
if (!token) {
|
|
client.disconnect(true);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const payload = this.jwtService.verify<{ sub: string; tokenType: string }>(token, {
|
|
secret: this.configService.get<string>('jwt.accessSecret', { infer: true }),
|
|
});
|
|
if (payload.tokenType !== 'access') {
|
|
client.disconnect(true);
|
|
return;
|
|
}
|
|
|
|
client.data.userId = payload.sub;
|
|
await client.join(this.userRoom(payload.sub));
|
|
} catch {
|
|
client.disconnect(true);
|
|
}
|
|
}
|
|
|
|
emitCreated(recipientId: string, notification: unknown, unreadCount: number): void {
|
|
this.server.to(this.userRoom(recipientId)).emit('notification_created', notification);
|
|
this.server.to(this.userRoom(recipientId)).emit('notifications_unread_count', { unreadCount });
|
|
}
|
|
|
|
emitUnreadCount(recipientId: string, unreadCount: number): void {
|
|
this.server.to(this.userRoom(recipientId)).emit('notifications_unread_count', { unreadCount });
|
|
}
|
|
|
|
private extractToken(client: Socket): string | null {
|
|
const authToken = client.handshake.auth?.token;
|
|
if (typeof authToken === 'string' && authToken.trim()) {
|
|
return authToken.replace(/^Bearer\s+/i, '').trim();
|
|
}
|
|
|
|
const headerAuth = client.handshake.headers.authorization;
|
|
if (typeof headerAuth === 'string' && headerAuth.trim()) {
|
|
return headerAuth.replace(/^Bearer\s+/i, '').trim();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private userRoom(userId: string): string {
|
|
return `user:${userId}`;
|
|
}
|
|
}
|