chore: complete the email signuture

This commit is contained in:
mahyargdz
2025-07-13 15:15:03 +03:30
parent 00dd77377d
commit 76037f3472
8 changed files with 62 additions and 75 deletions
+2
View File
@@ -21,6 +21,7 @@ import { EmailModule } from "./modules/email/email.module";
import { MailServerModule } from "./modules/mail-server/mail-server.module"; import { MailServerModule } from "./modules/mail-server/mail-server.module";
import { MailboxModule } from "./modules/mailbox/mailbox.module"; import { MailboxModule } from "./modules/mailbox/mailbox.module";
import { QuotaSyncModule } from "./modules/quota-sync/quota-sync.module"; import { QuotaSyncModule } from "./modules/quota-sync/quota-sync.module";
import { EmailSignaturesModule } from "./modules/signatures/email-signatures.module";
import { UsersModule } from "./modules/users/users.module"; import { UsersModule } from "./modules/users/users.module";
import { UtilsModule } from "./modules/utils/utils.module"; import { UtilsModule } from "./modules/utils/utils.module";
@@ -42,6 +43,7 @@ import { UtilsModule } from "./modules/utils/utils.module";
MailboxModule, MailboxModule,
MailServerModule, MailServerModule,
QuotaSyncModule, QuotaSyncModule,
EmailSignaturesModule,
], ],
}) })
export class AppModule implements NestModule { export class AppModule implements NestModule {
@@ -3,6 +3,7 @@ import { Cascade, Collection, Entity, EntityRepositoryType, OneToMany, OneToOne,
import { BusinessStaff } from "./business-staff.entity"; import { BusinessStaff } from "./business-staff.entity";
import { BaseEntity } from "../../../common/entities/base.entity"; import { BaseEntity } from "../../../common/entities/base.entity";
import { Domain } from "../../domains/entities/domain.entity"; import { Domain } from "../../domains/entities/domain.entity";
import { EmailSignature } from "../../signatures/entities/email-signature.entity";
import { BusinessRepository } from "../repositories/business.repository"; import { BusinessRepository } from "../repositories/business.repository";
@Entity({ repository: () => BusinessRepository }) @Entity({ repository: () => BusinessRepository })
@@ -36,6 +37,10 @@ export class Business extends BaseEntity {
//========================= //=========================
@OneToOne(() => EmailSignature, (signature) => signature.business, { nullable: true, deleteRule: "cascade" })
emailSignature?: EmailSignature;
//=========================
// @OneToMany(() => User, (user) => user.business) // @OneToMany(() => User, (user) => user.business)
// users = new Collection<User>(this); // users = new Collection<User>(this);
@@ -1,63 +1,58 @@
import { Body, Controller, Delete, Get, Param, Patch, Post, Put } from "@nestjs/common"; import { Body, Controller, Delete, Get, Param, Patch, Post } from "@nestjs/common";
import { UseInterceptors } from "@nestjs/common";
import { ApiOperation, ApiResponse } from "@nestjs/swagger"; import { ApiOperation, ApiResponse } from "@nestjs/swagger";
import { CreateEmailSignatureDto } from "./DTO/create-email-signature.dto"; import { CreateEmailSignatureDto } from "./DTO/create-email-signature.dto";
import { UpdateEmailSignatureDto } from "./DTO/update-email-signature.dto"; import { UpdateEmailSignatureDto } from "./DTO/update-email-signature.dto";
import { EmailSignature } from "./entities/email-signature.entity";
import { EmailSignaturesService } from "./services/email-signatures.service"; import { EmailSignaturesService } from "./services/email-signatures.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { UserDec } from "../../common/decorators/user.decorator"; import { BusinessDec } from "../../common/decorators/business.decorator";
import { User } from "../users/entities/user.entity"; import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
import { Business } from "../businesses/entities/business.entity";
@Controller("email-signatures") @Controller("email-signatures")
@UseInterceptors(BusinessInterceptor)
@AuthGuards() @AuthGuards()
export class EmailSignaturesController { export class EmailSignaturesController {
constructor(private readonly emailSignaturesService: EmailSignaturesService) {} constructor(private readonly emailSignaturesService: EmailSignaturesService) {}
@Post() @Post()
@ApiOperation({ summary: "Create a new email signature" }) @ApiOperation({ summary: "Create a new email signature" })
@ApiResponse({ status: 201, description: "Email signature created successfully", type: EmailSignature }) @ApiResponse({ status: 201, description: "Email signature created successfully" })
@ApiResponse({ status: 400, description: "Bad request" }) @ApiResponse({ status: 400, description: "Bad request" })
create(@UserDec() user: User, @Body() createEmailSignatureDto: CreateEmailSignatureDto) { create(@BusinessDec() business: Business, @Body() createEmailSignatureDto: CreateEmailSignatureDto) {
return this.emailSignaturesService.create(user.id, createEmailSignatureDto); return this.emailSignaturesService.create(business, createEmailSignatureDto);
} }
@Get("active") @Get()
@ApiOperation({ summary: "Get all active email signatures for the user" })
@ApiResponse({ status: 200, description: "Active email signatures retrieved successfully", type: [EmailSignature] })
findActive(@UserDec() user: User) {
return this.emailSignaturesService.findActive(user.id);
}
@Get(":id")
@ApiOperation({ summary: "Get a specific email signature" }) @ApiOperation({ summary: "Get a specific email signature" })
@ApiResponse({ status: 200, description: "Email signature retrieved successfully", type: EmailSignature }) @ApiResponse({ status: 200, description: "Email signature retrieved successfully" })
@ApiResponse({ status: 404, description: "Email signature not found" }) @ApiResponse({ status: 404, description: "Email signature not found" })
findOne(@Param("id") id: string, @UserDec() user: User) { findOne(@BusinessDec() business: Business) {
return this.emailSignaturesService.findOne(id, user.id); return this.emailSignaturesService.getBusinessSignature(business);
} }
@Patch(":id") @Patch(":id")
@ApiOperation({ summary: "Update an email signature" }) @ApiOperation({ summary: "Update an email signature" })
@ApiResponse({ status: 200, description: "Email signature updated successfully", type: EmailSignature }) @ApiResponse({ status: 200, description: "Email signature updated successfully" })
@ApiResponse({ status: 404, description: "Email signature not found" }) @ApiResponse({ status: 404, description: "Email signature not found" })
update(@Param("id") id: string, @UserDec() user: User, @Body() updateEmailSignatureDto: UpdateEmailSignatureDto) { update(@Param("id") id: string, @BusinessDec() business: Business, @Body() updateEmailSignatureDto: UpdateEmailSignatureDto) {
return this.emailSignaturesService.update(id, user.id, updateEmailSignatureDto); return this.emailSignaturesService.update(id, business, updateEmailSignatureDto);
} }
@Put(":id/toggle-active") @Patch(":id/toggle-active")
@ApiOperation({ summary: "Activate an email signature" }) @ApiOperation({ summary: "Activate an email signature" })
@ApiResponse({ status: 200, description: "Email signature activated successfully", type: EmailSignature }) @ApiResponse({ status: 200, description: "Email signature activated successfully" })
@ApiResponse({ status: 404, description: "Email signature not found" }) @ApiResponse({ status: 404, description: "Email signature not found" })
toggleActive(@Param("id") id: string, @UserDec() user: User) { toggleActive(@Param("id") id: string, @BusinessDec() business: Business) {
return this.emailSignaturesService.toggleActive(id, user.id); return this.emailSignaturesService.toggleActive(id, business);
} }
@Delete(":id") @Delete(":id")
@ApiOperation({ summary: "Delete an email signature" }) @ApiOperation({ summary: "Delete an email signature" })
@ApiResponse({ status: 200, description: "Email signature deleted successfully" }) @ApiResponse({ status: 200, description: "Email signature deleted successfully" })
@ApiResponse({ status: 404, description: "Email signature not found" }) @ApiResponse({ status: 404, description: "Email signature not found" })
remove(@Param("id") id: string, @UserDec() user: User) { remove(@Param("id") id: string, @BusinessDec() business: Business) {
return this.emailSignaturesService.remove(id, user.id); return this.emailSignaturesService.remove(id, business);
} }
} }
@@ -3,13 +3,13 @@ import { Module } from "@nestjs/common";
import { EmailSignaturesController } from "./email-signatures.controller"; import { EmailSignaturesController } from "./email-signatures.controller";
import { EmailSignature } from "./entities/email-signature.entity"; import { EmailSignature } from "./entities/email-signature.entity";
import { EmailSignatureRepository } from "./repositories/email-signature.repository";
import { EmailSignaturesService } from "./services/email-signatures.service"; import { EmailSignaturesService } from "./services/email-signatures.service";
import { BusinessesModule } from "../businesses/businesses.module";
@Module({ @Module({
imports: [MikroOrmModule.forFeature([EmailSignature])], imports: [MikroOrmModule.forFeature([EmailSignature]), BusinessesModule],
controllers: [EmailSignaturesController], controllers: [EmailSignaturesController],
providers: [EmailSignaturesService, EmailSignatureRepository], providers: [EmailSignaturesService],
exports: [EmailSignaturesService], exports: [EmailSignaturesService],
}) })
export class EmailSignaturesModule {} export class EmailSignaturesModule {}
@@ -1,14 +1,14 @@
import { Entity, EntityRepositoryType, Index, OneToOne, Opt, Property } from "@mikro-orm/core"; import { Entity, EntityRepositoryType, Index, OneToOne, Opt, Property } from "@mikro-orm/core";
import { BaseEntity } from "../../../common/entities/base.entity"; import { BaseEntity } from "../../../common/entities/base.entity";
import { User } from "../../users/entities/user.entity"; import { Business } from "../../businesses/entities/business.entity";
import { EmailSignatureRepository } from "../repositories/email-signature.repository"; import { EmailSignatureRepository } from "../repositories/email-signature.repository";
@Entity({ repository: () => EmailSignatureRepository }) @Entity({ repository: () => EmailSignatureRepository })
@Index({ properties: ["user", "isActive"] }) @Index({ properties: ["business", "isActive"] })
export class EmailSignature extends BaseEntity { export class EmailSignature extends BaseEntity {
@OneToOne(() => User, (user) => user.emailSignature, { owner: true, deleteRule: "cascade" }) @OneToOne(() => Business, (business) => business.emailSignature, { owner: true, deleteRule: "cascade" })
user!: User; business!: Business;
@Property({ type: "varchar", length: 100 }) @Property({ type: "varchar", length: 100 })
name!: string; name!: string;
@@ -16,9 +16,6 @@ export class EmailSignature extends BaseEntity {
@Property({ type: "text", nullable: true }) @Property({ type: "text", nullable: true })
textContent?: string; textContent?: string;
// @Property({ type: "text", nullable: true })
// htmlContent?: string;
@Property({ type: "boolean", default: true }) @Property({ type: "boolean", default: true })
isActive!: boolean & Opt; isActive!: boolean & Opt;
@@ -3,15 +3,15 @@ import { EntityRepository } from "@mikro-orm/postgresql";
import { EmailSignature } from "../entities/email-signature.entity"; import { EmailSignature } from "../entities/email-signature.entity";
export class EmailSignatureRepository extends EntityRepository<EmailSignature> { export class EmailSignatureRepository extends EntityRepository<EmailSignature> {
async findByUserId(userId: string): Promise<EmailSignature[]> { async findByBusinessId(businessId: string): Promise<EmailSignature | null> {
return this.find({ user: userId }, { orderBy: { createdAt: "DESC" } }); return this.findOne({ business: { id: businessId } }, { orderBy: { createdAt: "DESC" } });
} }
async findActiveByUserId(userId: string): Promise<EmailSignature[]> { async findActiveByBusinessId(businessId: string): Promise<EmailSignature[]> {
return this.find({ user: userId, isActive: true }, { orderBy: { createdAt: "DESC" } }); return this.find({ business: { id: businessId }, isActive: true }, { orderBy: { createdAt: "DESC" } });
} }
async findByIdAndUserId(id: string, userId: string): Promise<EmailSignature | null> { async findByIdAndBusinessId(id: string, businessId: string): Promise<EmailSignature | null> {
return this.findOne({ id, user: userId }); return this.findOne({ id, business: { id: businessId } });
} }
} }
@@ -1,8 +1,8 @@
import { EntityManager } from "@mikro-orm/core"; import { EntityManager } from "@mikro-orm/postgresql";
import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; import { BadRequestException, Injectable } from "@nestjs/common";
import { SignatureMessage, UserMessage } from "../../../common/enums/message.enum"; import { SignatureMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity"; import { Business } from "../../businesses/entities/business.entity";
import { CreateEmailSignatureDto } from "../DTO/create-email-signature.dto"; import { CreateEmailSignatureDto } from "../DTO/create-email-signature.dto";
import { UpdateEmailSignatureDto } from "../DTO/update-email-signature.dto"; import { UpdateEmailSignatureDto } from "../DTO/update-email-signature.dto";
import { EmailSignatureRepository } from "../repositories/email-signature.repository"; import { EmailSignatureRepository } from "../repositories/email-signature.repository";
@@ -14,13 +14,10 @@ export class EmailSignaturesService {
private readonly em: EntityManager, private readonly em: EntityManager,
) {} ) {}
//######################### //#########################
async create(userId: string, createDto: CreateEmailSignatureDto) { async create(business: Business, createDto: CreateEmailSignatureDto) {
const user = await this.em.findOne(User, { id: userId, deletedAt: null });
if (!user) throw new NotFoundException(UserMessage.USER_NOT_FOUND);
const signature = this.emailSignatureRepository.create({ const signature = this.emailSignatureRepository.create({
...createDto, ...createDto,
user, business,
}); });
await this.em.persistAndFlush(signature); await this.em.persistAndFlush(signature);
@@ -29,19 +26,11 @@ export class EmailSignaturesService {
signature, signature,
}; };
} }
//#########################
async findActive(userId: string) {
const signatures = await this.emailSignatureRepository.findActiveByUserId(userId);
return {
signatures,
};
}
//######################### //#########################
async update(id: string, userId: string, updateDto: UpdateEmailSignatureDto) { async update(id: string, business: Business, updateDto: UpdateEmailSignatureDto) {
const { signature } = await this.findOne(id, userId); const { signature } = await this.findOne(id, business);
this.emailSignatureRepository.assign(signature, updateDto); this.emailSignatureRepository.assign(signature, updateDto);
await this.em.flush(); await this.em.flush();
@@ -49,15 +38,15 @@ export class EmailSignaturesService {
} }
//######################### //#########################
async remove(id: string, userId: string) { async remove(id: string, business: Business) {
const { signature } = await this.findOne(id, userId); const { signature } = await this.findOne(id, business);
await this.em.removeAndFlush(signature); await this.em.removeAndFlush(signature);
return { message: SignatureMessage.DELETED }; return { message: SignatureMessage.DELETED };
} }
//######################### //#########################
async toggleActive(id: string, userId: string) { async toggleActive(id: string, business: Business) {
const { signature } = await this.findOne(id, userId); const { signature } = await this.findOne(id, business);
signature.isActive = !signature.isActive; signature.isActive = !signature.isActive;
await this.em.flush(); await this.em.flush();
@@ -69,8 +58,13 @@ export class EmailSignaturesService {
} }
//######################### //#########################
async findOne(id: string, userId: string) { async getBusinessSignature(business: Business) {
const signature = await this.emailSignatureRepository.findByIdAndUserId(id, userId); const signature = await this.emailSignatureRepository.findByBusinessId(business.id);
return { signature };
}
async findOne(id: string, business: Business) {
const signature = await this.emailSignatureRepository.findByIdAndBusinessId(id, business.id);
if (!signature) throw new BadRequestException(SignatureMessage.NOT_FOUND); if (!signature) throw new BadRequestException(SignatureMessage.NOT_FOUND);
return { signature }; return { signature };
+1 -7
View File
@@ -1,11 +1,10 @@
import { Collection, Entity, EntityRepositoryType, ManyToOne, OneToMany, OneToOne, Opt, Property, Unique } from "@mikro-orm/core"; import { Collection, Entity, EntityRepositoryType, ManyToOne, OneToMany, Opt, Property, Unique } from "@mikro-orm/core";
import { RefreshToken } from "./refresh-token.entity"; import { RefreshToken } from "./refresh-token.entity";
import { Role } from "./role.entity"; import { Role } from "./role.entity";
import { BaseEntity } from "../../../common/entities/base.entity"; import { BaseEntity } from "../../../common/entities/base.entity";
import { Business } from "../../businesses/entities/business.entity"; import { Business } from "../../businesses/entities/business.entity";
import { Domain } from "../../domains/entities/domain.entity"; import { Domain } from "../../domains/entities/domain.entity";
import { EmailSignature } from "../../signatures/entities/email-signature.entity";
import { UserRepository } from "../repositories/user.repository"; import { UserRepository } from "../repositories/user.repository";
@Entity({ repository: () => UserRepository }) @Entity({ repository: () => UserRepository })
@@ -47,11 +46,6 @@ export class User extends BaseEntity {
//========================= //=========================
@OneToOne(() => EmailSignature, (signature) => signature.user, { nullable: true, deleteRule: "cascade" })
emailSignature?: EmailSignature;
//=========================
@OneToMany(() => RefreshToken, (token) => token.user) @OneToMany(() => RefreshToken, (token) => token.user)
refreshTokens = new Collection<RefreshToken>(this); refreshTokens = new Collection<RefreshToken>(this);