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 { MailboxModule } from "./modules/mailbox/mailbox.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 { UtilsModule } from "./modules/utils/utils.module";
@@ -42,6 +43,7 @@ import { UtilsModule } from "./modules/utils/utils.module";
MailboxModule,
MailServerModule,
QuotaSyncModule,
EmailSignaturesModule,
],
})
export class AppModule implements NestModule {
@@ -3,6 +3,7 @@ import { Cascade, Collection, Entity, EntityRepositoryType, OneToMany, OneToOne,
import { BusinessStaff } from "./business-staff.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { Domain } from "../../domains/entities/domain.entity";
import { EmailSignature } from "../../signatures/entities/email-signature.entity";
import { BusinessRepository } from "../repositories/business.repository";
@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)
// 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 { CreateEmailSignatureDto } from "./DTO/create-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 { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
import { User } from "../users/entities/user.entity";
import { BusinessDec } from "../../common/decorators/business.decorator";
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
import { Business } from "../businesses/entities/business.entity";
@Controller("email-signatures")
@UseInterceptors(BusinessInterceptor)
@AuthGuards()
export class EmailSignaturesController {
constructor(private readonly emailSignaturesService: EmailSignaturesService) {}
@Post()
@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" })
create(@UserDec() user: User, @Body() createEmailSignatureDto: CreateEmailSignatureDto) {
return this.emailSignaturesService.create(user.id, createEmailSignatureDto);
create(@BusinessDec() business: Business, @Body() createEmailSignatureDto: CreateEmailSignatureDto) {
return this.emailSignaturesService.create(business, createEmailSignatureDto);
}
@Get("active")
@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")
@Get()
@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" })
findOne(@Param("id") id: string, @UserDec() user: User) {
return this.emailSignaturesService.findOne(id, user.id);
findOne(@BusinessDec() business: Business) {
return this.emailSignaturesService.getBusinessSignature(business);
}
@Patch(":id")
@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" })
update(@Param("id") id: string, @UserDec() user: User, @Body() updateEmailSignatureDto: UpdateEmailSignatureDto) {
return this.emailSignaturesService.update(id, user.id, updateEmailSignatureDto);
update(@Param("id") id: string, @BusinessDec() business: Business, @Body() updateEmailSignatureDto: UpdateEmailSignatureDto) {
return this.emailSignaturesService.update(id, business, updateEmailSignatureDto);
}
@Put(":id/toggle-active")
@Patch(":id/toggle-active")
@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" })
toggleActive(@Param("id") id: string, @UserDec() user: User) {
return this.emailSignaturesService.toggleActive(id, user.id);
toggleActive(@Param("id") id: string, @BusinessDec() business: Business) {
return this.emailSignaturesService.toggleActive(id, business);
}
@Delete(":id")
@ApiOperation({ summary: "Delete an email signature" })
@ApiResponse({ status: 200, description: "Email signature deleted successfully" })
@ApiResponse({ status: 404, description: "Email signature not found" })
remove(@Param("id") id: string, @UserDec() user: User) {
return this.emailSignaturesService.remove(id, user.id);
remove(@Param("id") id: string, @BusinessDec() business: Business) {
return this.emailSignaturesService.remove(id, business);
}
}
@@ -3,13 +3,13 @@ import { Module } from "@nestjs/common";
import { EmailSignaturesController } from "./email-signatures.controller";
import { EmailSignature } from "./entities/email-signature.entity";
import { EmailSignatureRepository } from "./repositories/email-signature.repository";
import { EmailSignaturesService } from "./services/email-signatures.service";
import { BusinessesModule } from "../businesses/businesses.module";
@Module({
imports: [MikroOrmModule.forFeature([EmailSignature])],
imports: [MikroOrmModule.forFeature([EmailSignature]), BusinessesModule],
controllers: [EmailSignaturesController],
providers: [EmailSignaturesService, EmailSignatureRepository],
providers: [EmailSignaturesService],
exports: [EmailSignaturesService],
})
export class EmailSignaturesModule {}
@@ -1,14 +1,14 @@
import { Entity, EntityRepositoryType, Index, OneToOne, Opt, Property } from "@mikro-orm/core";
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";
@Entity({ repository: () => EmailSignatureRepository })
@Index({ properties: ["user", "isActive"] })
@Index({ properties: ["business", "isActive"] })
export class EmailSignature extends BaseEntity {
@OneToOne(() => User, (user) => user.emailSignature, { owner: true, deleteRule: "cascade" })
user!: User;
@OneToOne(() => Business, (business) => business.emailSignature, { owner: true, deleteRule: "cascade" })
business!: Business;
@Property({ type: "varchar", length: 100 })
name!: string;
@@ -16,9 +16,6 @@ export class EmailSignature extends BaseEntity {
@Property({ type: "text", nullable: true })
textContent?: string;
// @Property({ type: "text", nullable: true })
// htmlContent?: string;
@Property({ type: "boolean", default: true })
isActive!: boolean & Opt;
@@ -3,15 +3,15 @@ import { EntityRepository } from "@mikro-orm/postgresql";
import { EmailSignature } from "../entities/email-signature.entity";
export class EmailSignatureRepository extends EntityRepository<EmailSignature> {
async findByUserId(userId: string): Promise<EmailSignature[]> {
return this.find({ user: userId }, { orderBy: { createdAt: "DESC" } });
async findByBusinessId(businessId: string): Promise<EmailSignature | null> {
return this.findOne({ business: { id: businessId } }, { orderBy: { createdAt: "DESC" } });
}
async findActiveByUserId(userId: string): Promise<EmailSignature[]> {
return this.find({ user: userId, isActive: true }, { orderBy: { createdAt: "DESC" } });
async findActiveByBusinessId(businessId: string): Promise<EmailSignature[]> {
return this.find({ business: { id: businessId }, isActive: true }, { orderBy: { createdAt: "DESC" } });
}
async findByIdAndUserId(id: string, userId: string): Promise<EmailSignature | null> {
return this.findOne({ id, user: userId });
async findByIdAndBusinessId(id: string, businessId: string): Promise<EmailSignature | null> {
return this.findOne({ id, business: { id: businessId } });
}
}
@@ -1,8 +1,8 @@
import { EntityManager } from "@mikro-orm/core";
import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
import { EntityManager } from "@mikro-orm/postgresql";
import { BadRequestException, Injectable } from "@nestjs/common";
import { SignatureMessage, UserMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity";
import { SignatureMessage } from "../../../common/enums/message.enum";
import { Business } from "../../businesses/entities/business.entity";
import { CreateEmailSignatureDto } from "../DTO/create-email-signature.dto";
import { UpdateEmailSignatureDto } from "../DTO/update-email-signature.dto";
import { EmailSignatureRepository } from "../repositories/email-signature.repository";
@@ -14,13 +14,10 @@ export class EmailSignaturesService {
private readonly em: EntityManager,
) {}
//#########################
async create(userId: string, createDto: CreateEmailSignatureDto) {
const user = await this.em.findOne(User, { id: userId, deletedAt: null });
if (!user) throw new NotFoundException(UserMessage.USER_NOT_FOUND);
async create(business: Business, createDto: CreateEmailSignatureDto) {
const signature = this.emailSignatureRepository.create({
...createDto,
user,
business,
});
await this.em.persistAndFlush(signature);
@@ -29,19 +26,11 @@ export class EmailSignaturesService {
signature,
};
}
//#########################
async findActive(userId: string) {
const signatures = await this.emailSignatureRepository.findActiveByUserId(userId);
return {
signatures,
};
}
//#########################
async update(id: string, userId: string, updateDto: UpdateEmailSignatureDto) {
const { signature } = await this.findOne(id, userId);
async update(id: string, business: Business, updateDto: UpdateEmailSignatureDto) {
const { signature } = await this.findOne(id, business);
this.emailSignatureRepository.assign(signature, updateDto);
await this.em.flush();
@@ -49,15 +38,15 @@ export class EmailSignaturesService {
}
//#########################
async remove(id: string, userId: string) {
const { signature } = await this.findOne(id, userId);
async remove(id: string, business: Business) {
const { signature } = await this.findOne(id, business);
await this.em.removeAndFlush(signature);
return { message: SignatureMessage.DELETED };
}
//#########################
async toggleActive(id: string, userId: string) {
const { signature } = await this.findOne(id, userId);
async toggleActive(id: string, business: Business) {
const { signature } = await this.findOne(id, business);
signature.isActive = !signature.isActive;
await this.em.flush();
@@ -69,8 +58,13 @@ export class EmailSignaturesService {
}
//#########################
async findOne(id: string, userId: string) {
const signature = await this.emailSignatureRepository.findByIdAndUserId(id, userId);
async getBusinessSignature(business: Business) {
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);
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 { Role } from "./role.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { Business } from "../../businesses/entities/business.entity";
import { Domain } from "../../domains/entities/domain.entity";
import { EmailSignature } from "../../signatures/entities/email-signature.entity";
import { UserRepository } from "../repositories/user.repository";
@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)
refreshTokens = new Collection<RefreshToken>(this);