diff --git a/src/common/DTO/param.dto.ts b/src/common/DTO/param.dto.ts index 41554eb..53153de 100755 --- a/src/common/DTO/param.dto.ts +++ b/src/common/DTO/param.dto.ts @@ -17,3 +17,10 @@ export class ParamNumberIdDto { @ApiProperty({ description: "Id of the entity", example: "20" }) id: string; } + +export class SettingParamDto { + @IsNotEmpty({ message: CommonMessage.ID_REQUIRED }) + @IsUUID("all", { message: CommonMessage.ID_SHOULD_BE_UUID }) + @ApiProperty({ description: "Id of the entity", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" }) + id: string; +} diff --git a/src/modules/auth/services/auth.service.ts b/src/modules/auth/services/auth.service.ts index b1a3171..136ee02 100644 --- a/src/modules/auth/services/auth.service.ts +++ b/src/modules/auth/services/auth.service.ts @@ -10,14 +10,11 @@ import { LoginDto } from "../DTO/login.dto"; @Injectable() export class AuthService { - // private readonly logger = new Logger(AuthService.name); - constructor( private readonly notificationQueue: NotificationQueue, private readonly userRepository: UserRepository, private readonly tokensService: TokensService, private readonly passwordService: PasswordService, - // private readonly mailServerService: MailServerService, ) {} //============================================== diff --git a/src/modules/email/services/email-notification.service.ts b/src/modules/email/services/email-notification.service.ts index 2250d4c..0e6b088 100644 --- a/src/modules/email/services/email-notification.service.ts +++ b/src/modules/email/services/email-notification.service.ts @@ -61,20 +61,33 @@ export class EmailNotificationService { //************************************************************************ */ async notifyEmailRead(params: EmailStatusNotificationParams) { try { + // Find the user to get the correct User entity ID for websocket notifications + const em = this.em.fork(); + const user = await em.findOne(User, { + wildduckUserId: params.userId, + emailEnabled: true, + deletedAt: null, + }); + + if (!user) { + this.logger.warn(`User not found with wildduckUserId: ${params.userId}`); + return; + } + const payload: EmailStatusPayload = { - userId: params.userId, + userId: user.id, // Use User entity ID for websocket messageId: params.messageId, mailboxId: params.mailboxId, timestamp: new Date().toISOString(), }; - const success = await this.emailGateway.notifyEmailRead(params.userId, payload); - await this.updateUnreadCount(params.userId); + const success = await this.emailGateway.notifyEmailRead(user.id, payload); + await this.updateUnreadCount(params.userId); // Pass wildduckUserId to updateUnreadCount if (success) { - this.logger.log(`Email read notification dispatched for user ${params.userId}: message ${params.messageId}`); + this.logger.log(`Email read notification dispatched for user ${user.id}: message ${params.messageId}`); } else { - this.logger.warn(`Failed to dispatch email read notification for user ${params.userId}: user not connected`); + this.logger.warn(`Failed to dispatch email read notification for user ${user.id}: user not connected`); } } catch (error) { this.logger.error(`Failed to notify email read for user ${params.userId}:`, error); @@ -84,20 +97,33 @@ export class EmailNotificationService { //************************************************************************ */ async notifyEmailDeleted(params: EmailStatusNotificationParams) { try { + // Find the user to get the correct User entity ID for websocket notifications + const em = this.em.fork(); + const user = await em.findOne(User, { + wildduckUserId: params.userId, + emailEnabled: true, + deletedAt: null, + }); + + if (!user) { + this.logger.warn(`User not found with wildduckUserId: ${params.userId}`); + return; + } + const payload: EmailDeletePayload = { - userId: params.userId, + userId: user.id, // Use User entity ID for websocket messageId: params.messageId, mailboxId: params.mailboxId, timestamp: new Date().toISOString(), }; - const success = await this.emailGateway.notifyEmailDeleted(params.userId, payload); - await this.updateUnreadCount(params.userId); + const success = await this.emailGateway.notifyEmailDeleted(user.id, payload); + await this.updateUnreadCount(params.userId); // Pass wildduckUserId to updateUnreadCount if (success) { - this.logger.log(`Email deleted notification dispatched for user ${params.userId}: message ${params.messageId}`); + this.logger.log(`Email deleted notification dispatched for user ${user.id}: message ${params.messageId}`); } else { - this.logger.warn(`Failed to dispatch email deleted notification for user ${params.userId}: user not connected`); + this.logger.warn(`Failed to dispatch email deleted notification for user ${user.id}: user not connected`); } } catch (error) { this.logger.error(`Failed to notify email deleted for user ${params.userId}:`, error); @@ -134,7 +160,7 @@ export class EmailNotificationService { const em = this.em.fork(); const user = await em.findOne(User, { - id: userId, + wildduckUserId: userId, emailEnabled: true, deletedAt: null, }); @@ -155,7 +181,7 @@ export class EmailNotificationService { const unreadCount = results.length; const payload: UnreadCountPayload = { - userId, + userId: user.id, // Use the actual User entity ID for the notification payload count: unreadCount, timestamp: new Date().toISOString(), totalUnread: unreadCount, @@ -164,10 +190,10 @@ export class EmailNotificationService { }, }; - const success = await this.emailGateway.notifyUnreadCountUpdate(userId, payload); + const success = await this.emailGateway.notifyUnreadCountUpdate(user.id, payload); // Use User entity ID here too if (!success) { - this.logger.warn(`Failed to update unread count for user ${userId}: user not connected`); + this.logger.warn(`Failed to update unread count for user ${user.id}: user not connected`); } } catch (error) { this.logger.error(`Failed to update unread count for user ${userId}:`, error); diff --git a/src/modules/settings/entities/user-setting.entity.ts b/src/modules/settings/entities/user-setting.entity.ts index 26c4f5b..3ee8595 100755 --- a/src/modules/settings/entities/user-setting.entity.ts +++ b/src/modules/settings/entities/user-setting.entity.ts @@ -1,4 +1,4 @@ -import { Entity, EntityRepositoryType, ManyToOne, Property, Ref } from "@mikro-orm/core"; +import { Entity, EntityRepositoryType, ManyToOne, Property } from "@mikro-orm/core"; import { NotificationSetting } from "./notification-setting.entity"; import { BaseEntity } from "../../../common/entities/base.entity"; @@ -11,7 +11,7 @@ export class UserSetting extends BaseEntity { isActive!: boolean; @ManyToOne(() => NotificationSetting, { nullable: false }) - notificationSetting!: Ref; + notificationSetting!: NotificationSetting; @ManyToOne(() => User, { nullable: false, deleteRule: "cascade" }) user!: User; diff --git a/src/modules/settings/services/user-settings.service.ts b/src/modules/settings/services/user-settings.service.ts index 5c5e25b..c9bb9f2 100755 --- a/src/modules/settings/services/user-settings.service.ts +++ b/src/modules/settings/services/user-settings.service.ts @@ -81,13 +81,13 @@ export class UserSettingsService { //*+******************************************* async toggleUserNotificationSetting(settingId: string) { - const setting = await this.userSettingsRepository.findOne({ id: settingId, deletedAt: null }); + const setting = await this.userSettingsRepository.findOne({ id: settingId, deletedAt: null }, { orderBy: { createdAt: "DESC" } }); if (!setting) throw new BadRequestException(SettingMessageEnum.NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED); setting.isActive = !setting.isActive; - await this.em.persistAndFlush(setting); + await this.em.flush(); return { message: CommonMessage.UPDATE_SUCCESS, setting }; } diff --git a/src/modules/settings/settings.controller.ts b/src/modules/settings/settings.controller.ts index a6d66e3..a1b89e4 100755 --- a/src/modules/settings/settings.controller.ts +++ b/src/modules/settings/settings.controller.ts @@ -4,7 +4,7 @@ import { ApiOperation, ApiTags } from "@nestjs/swagger"; import { UserSettingsService } from "./services/user-settings.service"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; import { UserDec } from "../../common/decorators/user.decorator"; -import { ParamDto } from "../../common/DTO/param.dto"; +import { SettingParamDto } from "../../common/DTO/param.dto"; @Controller("settings") @ApiTags("Settings") @@ -22,7 +22,7 @@ export class SettingsController { @ApiOperation({ summary: "update status of setting" }) @HttpCode(HttpStatus.OK) @Patch(":id/toggle") - updateStatus(@Param() paramDto: ParamDto) { + updateStatus(@Param() paramDto: SettingParamDto) { return this.userSettingsService.toggleUserNotificationSetting(paramDto.id); } }