chore: add new route
This commit is contained in:
@@ -11,6 +11,7 @@ import { DomainsService } from "../../domains/services/domains.service";
|
||||
import { UpdateUserDto } from "../../mail-server/DTO";
|
||||
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
||||
import { QuotaSyncService } from "../../quota-sync/services/quota-sync.service";
|
||||
import { UserSettingsService } from "../../settings/services/user-settings.service";
|
||||
import { Template } from "../../templates/entities/template.entity";
|
||||
import { PasswordService } from "../../utils/services/password.service";
|
||||
import { CreateEmailUserDto } from "../DTO/create-email-user.dto";
|
||||
@@ -33,6 +34,7 @@ export class UsersService {
|
||||
private readonly domainsService: DomainsService,
|
||||
private readonly domainAutomationService: DomainAutomationService,
|
||||
private readonly quotaSyncService: QuotaSyncService,
|
||||
private readonly userSettingsService: UserSettingsService,
|
||||
) {}
|
||||
|
||||
async getUserEmailIdFromId(userId: string) {
|
||||
@@ -57,21 +59,24 @@ export class UsersService {
|
||||
const user = await this.userRepository.findOne({ id: userId }, { exclude: ["password"], populate: ["role"] });
|
||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
|
||||
const totalQuota = Number(user.emailQuota);
|
||||
const usedQuota = Number(user.emailQuotaUsed);
|
||||
const remainingQuota = totalQuota - usedQuota;
|
||||
|
||||
return {
|
||||
user,
|
||||
quota: {
|
||||
total: Number(user.emailQuota),
|
||||
used: Number(user.emailQuotaUsed),
|
||||
remaining: Number(user.emailQuota - user.emailQuotaUsed),
|
||||
totalInMB: Math.round(Number(user.emailQuota) / (1024 * 1024)),
|
||||
totalInGB: Math.round(Number(user.emailQuota) / (1024 * 1024 * 1024)),
|
||||
usedInMB: Math.round(Number(user.emailQuotaUsed) / (1024 * 1024)),
|
||||
usedInGB: Math.round(Number(user.emailQuotaUsed) / (1024 * 1024 * 1024)),
|
||||
remainingInMB: Math.round(Number(user.emailQuota - user.emailQuotaUsed) / (1024 * 1024)),
|
||||
remainingInGB: Math.round(Number(user.emailQuota - user.emailQuotaUsed) / (1024 * 1024 * 1024)),
|
||||
usagePercentage: Math.round((Number(user.emailQuotaUsed) / Number(user.emailQuota)) * 100),
|
||||
total: totalQuota,
|
||||
used: usedQuota,
|
||||
remaining: remainingQuota,
|
||||
totalInMB: Math.round(totalQuota / (1024 * 1024)),
|
||||
totalInGB: Math.round(totalQuota / (1024 * 1024 * 1024)),
|
||||
usedInMB: Math.round(usedQuota / (1024 * 1024)),
|
||||
usedInGB: Math.round(usedQuota / (1024 * 1024 * 1024)),
|
||||
remainingInMB: Math.round(remainingQuota / (1024 * 1024)),
|
||||
remainingInGB: Math.round(remainingQuota / (1024 * 1024 * 1024)),
|
||||
usagePercentage: totalQuota > 0 ? Math.round((usedQuota / totalQuota) * 100) : 0,
|
||||
},
|
||||
forwarders: user.forwarders || [],
|
||||
};
|
||||
}
|
||||
/*******************************/
|
||||
@@ -84,36 +89,39 @@ export class UsersService {
|
||||
|
||||
/*******************************/
|
||||
async createEmailUser(createEmailUserDto: CreateEmailUserDto, businessId: string) {
|
||||
const { username, password, domainId, displayName, quota, aliases, title, templateId, forwarders } = createEmailUserDto;
|
||||
|
||||
const business = await this.em.findOne(Business, { id: businessId });
|
||||
if (!business) throw new BadRequestException(BusinessMessage.NOT_FOUND);
|
||||
|
||||
// Check if business has enough quota
|
||||
const remainingQuota = Number(business.remainingQuota || 0);
|
||||
if (remainingQuota < QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION) {
|
||||
throw new BadRequestException("Insufficient quota to create user. Please upgrade your plan.");
|
||||
}
|
||||
|
||||
const domain = await this.domainsService.getDomainById(domainId, businessId);
|
||||
|
||||
if (domain.business.id !== businessId) throw new BadRequestException(DomainMessage.NOT_BELONG_TO_BUSINESS);
|
||||
|
||||
if (domain.status !== DomainStatus.VERIFIED) throw new BadRequestException(DomainMessage.NOT_VERIFIED);
|
||||
|
||||
const emailAddress = `${username}@${domain.name}`;
|
||||
const finalUserName = `${username}-${domain.name}`;
|
||||
const finalDisplayName = `${username}`;
|
||||
|
||||
const existingUser = await this.userRepository.findOne({ emailAddress });
|
||||
if (existingUser) throw new BadRequestException(UserMessage.EMAIL_ADDRESS_ALREADY_EXISTS);
|
||||
|
||||
const hashedPassword = await this.passwordService.hashPassword(password);
|
||||
|
||||
const userRole = await this.em.findOne(Role, { name: RoleEnum.USER });
|
||||
if (!userRole) throw new BadRequestException(RoleMessage.NOT_FOUND);
|
||||
const em = this.em.fork();
|
||||
|
||||
try {
|
||||
em.begin();
|
||||
const { username, password, domainId, displayName, quota, aliases, title, templateId, forwarders } = createEmailUserDto;
|
||||
|
||||
const business = await em.findOne(Business, { id: businessId });
|
||||
if (!business) throw new BadRequestException(BusinessMessage.NOT_FOUND);
|
||||
|
||||
// Check if business has enough quota
|
||||
const remainingQuota = Number(business.remainingQuota || 0);
|
||||
if (remainingQuota < QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION) {
|
||||
throw new BadRequestException("Insufficient quota to create user. Please upgrade your plan.");
|
||||
}
|
||||
|
||||
const domain = await this.domainsService.getDomainById(domainId, businessId);
|
||||
|
||||
if (domain.business.id !== businessId) throw new BadRequestException(DomainMessage.NOT_BELONG_TO_BUSINESS);
|
||||
|
||||
if (domain.status !== DomainStatus.VERIFIED) throw new BadRequestException(DomainMessage.NOT_VERIFIED);
|
||||
|
||||
const emailAddress = `${username}@${domain.name}`;
|
||||
const finalUserName = `${username}-${domain.name}`;
|
||||
const finalDisplayName = `${username}`;
|
||||
|
||||
const existingUser = await em.findOne(User, { emailAddress });
|
||||
if (existingUser) throw new BadRequestException(UserMessage.EMAIL_ADDRESS_ALREADY_EXISTS);
|
||||
|
||||
const hashedPassword = await this.passwordService.hashPassword(password);
|
||||
|
||||
const userRole = await em.findOne(Role, { name: RoleEnum.USER });
|
||||
if (!userRole) throw new BadRequestException(RoleMessage.NOT_FOUND);
|
||||
|
||||
const userQuota = quota || QUOTA_CONSTANTS.DEFAULT_EMAIL_QUOTA_BYTES;
|
||||
|
||||
const mailServerUser = await firstValueFrom(
|
||||
@@ -129,7 +137,7 @@ export class UsersService {
|
||||
|
||||
if (!mailServerUser.success) throw new BadRequestException(MailServerMessage.FAILED_TO_CREATE_ACCOUNT);
|
||||
|
||||
const user = this.userRepository.create({
|
||||
const user = em.create(User, {
|
||||
title: title || displayName || username,
|
||||
userName: finalUserName,
|
||||
password: hashedPassword,
|
||||
@@ -145,14 +153,15 @@ export class UsersService {
|
||||
forwarders: forwarders || [],
|
||||
});
|
||||
|
||||
// Update business quota after successful user creation
|
||||
await this.userSettingsService.createUserSettings(user.id, em);
|
||||
|
||||
business.usedQuota = Number(business.usedQuota) + QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION;
|
||||
business.remainingQuota = Number(business.quota) - Number(business.usedQuota);
|
||||
|
||||
await this.em.persistAndFlush([user, business]);
|
||||
await em.persistAndFlush([user, business]);
|
||||
|
||||
if (templateId) {
|
||||
const template = await this.em.findOne(Template, { id: templateId, business: { id: businessId } });
|
||||
const template = await em.findOne(Template, { id: templateId, business: { id: businessId } });
|
||||
if (!template) throw new BadRequestException(TemplateMessage.TEMPLATE_NOT_FOUND);
|
||||
user.template = template;
|
||||
}
|
||||
@@ -172,34 +181,27 @@ export class UsersService {
|
||||
}
|
||||
}
|
||||
|
||||
await this.em.flush();
|
||||
await em.flush();
|
||||
|
||||
//sync quota
|
||||
await this.quotaSyncService.scheduleUserQuotaSync(user.id, businessId, mailServerUser.id);
|
||||
//sync business quota
|
||||
await this.quotaSyncService.scheduleBusinessQuotaSync(businessId, business.name);
|
||||
|
||||
this.logger.log(`Email user created: ${emailAddress} for business ${businessId}`);
|
||||
|
||||
await this.domainAutomationService.createDefaultMailboxes(mailServerUser.id);
|
||||
|
||||
await em.commit();
|
||||
|
||||
return {
|
||||
message: UserMessage.EMAIL_USER_CREATED_SUCCESSFULLY,
|
||||
user: {
|
||||
id: user.id,
|
||||
emailAddress: user.emailAddress!,
|
||||
displayName: user.displayName!,
|
||||
wildduckUserId: user.wildduckUserId!,
|
||||
emailQuota: user.emailQuota!,
|
||||
emailEnabled: user.emailEnabled,
|
||||
domain: domain.name,
|
||||
forwarders: user.forwarders || [],
|
||||
createdAt: user.createdAt,
|
||||
isActive: user.isActive,
|
||||
},
|
||||
message: UserMessage.EMAIL_USER_CREATED_SUCCESSFULLY,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to create email user ${emailAddress}:`, error);
|
||||
await em.rollback();
|
||||
this.logger.error(`Failed to create email user ${createEmailUserDto.username}@${createEmailUserDto.domainId}:`, error);
|
||||
throw new BadRequestException(MailServerMessage.FAILED_TO_CREATE_ACCOUNT);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user