update auth
This commit is contained in:
@@ -27,7 +27,6 @@ export class TokensService {
|
|||||||
slug: string,
|
slug: string,
|
||||||
em?: EntityManager,
|
em?: EntityManager,
|
||||||
) {
|
) {
|
||||||
const entityManager = em || this.em;
|
|
||||||
const refreshExpire = this.configService.getOrThrow<number>('REFRESH_TOKEN_EXPIRE');
|
const refreshExpire = this.configService.getOrThrow<number>('REFRESH_TOKEN_EXPIRE');
|
||||||
const accessExpire = this.configService.getOrThrow<number>('JWT_EXPIRATION_TIME');
|
const accessExpire = this.configService.getOrThrow<number>('JWT_EXPIRATION_TIME');
|
||||||
|
|
||||||
@@ -39,7 +38,8 @@ export class TokensService {
|
|||||||
const refreshToken = this.generateRefreshToken();
|
const refreshToken = this.generateRefreshToken();
|
||||||
const type = isAdmin ? RefreshTokenType.ADMIN : RefreshTokenType.USER;
|
const type = isAdmin ? RefreshTokenType.ADMIN : RefreshTokenType.USER;
|
||||||
|
|
||||||
await this.storeRefreshToken(ownerId, restaurantId, refreshToken, type, entityManager);
|
// Only pass em if it's a transaction manager (not this.em), otherwise pass undefined to trigger flush
|
||||||
|
await this.storeRefreshToken(ownerId, restaurantId, refreshToken, type, em);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accessToken: { token: accessToken, expire: dayjs().add(accessExpire, 'seconds').valueOf() },
|
accessToken: { token: accessToken, expire: dayjs().add(accessExpire, 'seconds').valueOf() },
|
||||||
@@ -79,8 +79,8 @@ export class TokensService {
|
|||||||
// Within transaction, just persist (flush will be called by transaction)
|
// Within transaction, just persist (flush will be called by transaction)
|
||||||
entityManager.persist(token);
|
entityManager.persist(token);
|
||||||
} else {
|
} else {
|
||||||
// Outside transaction, persist and flush
|
// Outside transaction, persist and flush immediately
|
||||||
return entityManager.persistAndFlush(token);
|
await entityManager.persistAndFlush(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
} from '@nestjs/websockets';
|
} from '@nestjs/websockets';
|
||||||
import { Server, Socket } from 'socket.io';
|
import { Server, Socket } from 'socket.io';
|
||||||
import { Logger, UseGuards, Inject, forwardRef } from '@nestjs/common';
|
import { Logger, UseGuards, Inject, forwardRef } from '@nestjs/common';
|
||||||
// import { WsRestId } from './decorators/ws-rest-id.decorator';
|
import { NotificationService } from './services/notification.service';
|
||||||
import { NotificationService } from './services/notification.service';
|
|
||||||
import { WsAdminAuthGuard, type AuthenticatedSocket } from './guards/ws-admin-auth.guard';
|
import { WsAdminAuthGuard, type AuthenticatedSocket } from './guards/ws-admin-auth.guard';
|
||||||
import { ModuleRef } from '@nestjs/core';
|
import { ModuleRef } from '@nestjs/core';
|
||||||
import { ExecutionContext } from '@nestjs/common';
|
import { ExecutionContext } from '@nestjs/common';
|
||||||
@@ -46,6 +45,7 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco
|
|||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Connection authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
`Connection authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||||
);
|
);
|
||||||
|
void client.emit('error', { message: 'Authentication failed' });
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,7 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco
|
|||||||
|
|
||||||
const canActivate = await guard.canActivate(context);
|
const canActivate = await guard.canActivate(context);
|
||||||
if (!canActivate) {
|
if (!canActivate) {
|
||||||
throw new Error('Authentication failed');
|
throw new Error('Authentication failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,6 +249,17 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -370,9 +381,34 @@
|
|||||||
addEvent('ERROR', `Connection error: ${error.message}`);
|
addEvent('ERROR', `Connection error: ${error.message}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('joined', data => {
|
||||||
|
addEvent('SUCCESS', `Joined room: ${data.room || 'unknown'}`, data);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle notifications event - can be either:
|
||||||
|
// 1. List response: { notifications: [...] }
|
||||||
|
// 2. Real-time notification: { subject: string, body: string }
|
||||||
socket.on('notifications', data => {
|
socket.on('notifications', data => {
|
||||||
addEvent('SUCCESS', `Received ${data.notifications?.length || 0} notifications`, data);
|
if (Array.isArray(data.notifications)) {
|
||||||
displayNotifications(data.notifications || []);
|
// List of notifications response
|
||||||
|
addEvent('SUCCESS', `Received ${data.notifications.length} notifications`, data);
|
||||||
|
displayNotifications(data.notifications);
|
||||||
|
} else if (data.subject || data.body) {
|
||||||
|
// Real-time single notification
|
||||||
|
addEvent('NOTIFICATION', 'New notification received', data);
|
||||||
|
addRealTimeNotification(data);
|
||||||
|
} else if (Array.isArray(data)) {
|
||||||
|
// Direct array response
|
||||||
|
addEvent('SUCCESS', `Received ${data.length} notifications`, data);
|
||||||
|
displayNotifications(data);
|
||||||
|
} else {
|
||||||
|
// Unknown format, try to extract notifications from various possible structures
|
||||||
|
addEvent('INFO', 'Received notifications data', data);
|
||||||
|
const notifications = data.notifications || data.data || (Array.isArray(data) ? data : [data]);
|
||||||
|
if (Array.isArray(notifications) && notifications.length > 0) {
|
||||||
|
displayNotifications(notifications);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('error', data => {
|
socket.on('error', data => {
|
||||||
@@ -423,14 +459,28 @@
|
|||||||
|
|
||||||
let html = '';
|
let html = '';
|
||||||
notifications.forEach(notification => {
|
notifications.forEach(notification => {
|
||||||
const date = notification.createdAt ? new Date(notification.createdAt).toLocaleString() : 'N/A';
|
// Handle both full notification objects and simple payloads
|
||||||
|
const title = notification.title || notification.subject || 'N/A';
|
||||||
|
const content = notification.content || notification.body || 'No content';
|
||||||
|
const id = notification.id || 'N/A';
|
||||||
|
const date = notification.createdAt
|
||||||
|
? new Date(notification.createdAt).toLocaleString()
|
||||||
|
: notification.created_at
|
||||||
|
? new Date(notification.created_at).toLocaleString()
|
||||||
|
: 'N/A';
|
||||||
|
|
||||||
|
const userName = notification.user
|
||||||
|
? `${notification.user.firstName || ''} ${notification.user.lastName || ''}`.trim()
|
||||||
|
: notification.userName || '';
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="notification-item">
|
<div class="notification-item">
|
||||||
<div class="notification-title">${notification.title || 'N/A'}</div>
|
<div class="notification-title">${escapeHtml(title)}</div>
|
||||||
<div class="notification-content">${notification.content || 'No content'}</div>
|
<div class="notification-content">${escapeHtml(content)}</div>
|
||||||
<div class="notification-meta">
|
<div class="notification-meta">
|
||||||
ID: ${notification.id} | Created: ${date}
|
ID: ${id} | Created: ${date}
|
||||||
${notification.user ? ` | User: ${notification.user.firstName || ''} ${notification.user.lastName || ''}` : ''}
|
${userName ? ` | User: ${escapeHtml(userName)}` : ''}
|
||||||
|
${notification.admin ? ` | Admin: ${notification.admin.firstName || ''} ${notification.admin.lastName || ''}` : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -439,6 +489,37 @@
|
|||||||
listDiv.innerHTML = html;
|
listDiv.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addRealTimeNotification(notification) {
|
||||||
|
const listDiv = document.getElementById('notificationsList');
|
||||||
|
const title = notification.subject || notification.title || 'New Notification';
|
||||||
|
const content = notification.body || notification.content || 'No content';
|
||||||
|
const currentTime = new Date().toLocaleString();
|
||||||
|
|
||||||
|
const notificationHtml = `
|
||||||
|
<div class="notification-item" style="animation: slideIn 0.3s ease-out;">
|
||||||
|
<div class="notification-title">${escapeHtml(title)}</div>
|
||||||
|
<div class="notification-content">${escapeHtml(content)}</div>
|
||||||
|
<div class="notification-meta">
|
||||||
|
Received: ${currentTime}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Add to the top of the list
|
||||||
|
if (listDiv.children.length === 1 && listDiv.children[0].textContent.includes('No notifications')) {
|
||||||
|
listDiv.innerHTML = notificationHtml;
|
||||||
|
} else {
|
||||||
|
listDiv.insertAdjacentHTML('afterbegin', notificationHtml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
function updateStatus(status, message) {
|
function updateStatus(status, message) {
|
||||||
const statusEl = document.getElementById('connectionStatus');
|
const statusEl = document.getElementById('connectionStatus');
|
||||||
statusEl.className = `status ${status}`;
|
statusEl.className = `status ${status}`;
|
||||||
@@ -457,6 +538,7 @@
|
|||||||
WARNING: '#dcdcaa',
|
WARNING: '#dcdcaa',
|
||||||
ERROR: '#f48771',
|
ERROR: '#f48771',
|
||||||
NOTIFICATIONS_LIST: '#4fc1ff',
|
NOTIFICATIONS_LIST: '#4fc1ff',
|
||||||
|
NOTIFICATION: '#9cdcfe',
|
||||||
};
|
};
|
||||||
|
|
||||||
eventItem.innerHTML = `
|
eventItem.innerHTML = `
|
||||||
|
|||||||
Reference in New Issue
Block a user