first commit
هذا الالتزام موجود في:
71
src/modules/notifications/notifications.gateway.ts
Normal file
71
src/modules/notifications/notifications.gateway.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
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}`;
|
||||
}
|
||||
}
|
||||
المرجع في مشكلة جديدة
حظر مستخدم