chore: new feture for quato
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { Type } from "class-transformer";
|
||||
import { IsIn, IsOptional, IsString } from "class-validator";
|
||||
|
||||
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||
import { CommonMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
export class UserListQueryDto extends PaginationDto {
|
||||
@IsOptional()
|
||||
@IsString({ message: CommonMessage.SEARCH_QUERY_STRING })
|
||||
@ApiPropertyOptional({ description: "Search query", example: "search query" })
|
||||
q?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsIn([1, 0], { message: CommonMessage.IS_ACTIVE_SHOULD_BE_1_0 })
|
||||
@ApiPropertyOptional({ description: "User status", example: 1 })
|
||||
isActive?: number;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Collection, Entity, EntityRepositoryType, ManyToOne, OneToMany, Property } from "@mikro-orm/core";
|
||||
import { Collection, Entity, EntityRepositoryType, ManyToOne, OneToMany, OneToOne, Property } 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 "../../email-signatures/entities/email-signature.entity";
|
||||
import { UserRepository } from "../repositories/user.repository";
|
||||
|
||||
@Entity({ repository: () => UserRepository })
|
||||
@@ -27,18 +28,29 @@ export class User extends BaseEntity {
|
||||
@Property({ type: "bigint", nullable: true, default: 1073741824 }) // 1GB default
|
||||
emailQuota?: number; // Email quota in bytes
|
||||
|
||||
@Property({ type: "bigint", nullable: true, default: 0 })
|
||||
emailQuotaUsed?: number; // Email quota used in bytes
|
||||
|
||||
// Email account integration fields
|
||||
@Property({ type: "varchar", length: 255, nullable: true })
|
||||
emailAccountId?: string; // WildDuck user ID
|
||||
wildduckUserId?: string; // WildDuck user ID
|
||||
|
||||
@Property({ type: "varchar", length: 255, nullable: true })
|
||||
displayName?: string; // Display name for email
|
||||
|
||||
@Property({ type: "timestamptz", nullable: true })
|
||||
lastQuotaSync?: Date; // Last time quota was synced with WildDuck
|
||||
|
||||
@Property({ default: true, nullable: false })
|
||||
isActive: boolean = true;
|
||||
|
||||
//=========================
|
||||
|
||||
@OneToOne(() => EmailSignature, (signature) => signature.user, { nullable: true, deleteRule: "cascade" })
|
||||
emailSignature?: EmailSignature;
|
||||
|
||||
//=========================
|
||||
|
||||
@OneToMany(() => RefreshToken, (token) => token.user)
|
||||
refreshTokens = new Collection<RefreshToken>(this);
|
||||
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||
import { EntityRepository, FilterQuery } from "@mikro-orm/postgresql";
|
||||
|
||||
import { PaginationUtils } from "../../utils/services/pagination.utils";
|
||||
import { UserListQueryDto } from "../DTO/user-list-query.dto";
|
||||
import { User } from "../entities/user.entity";
|
||||
|
||||
export class UserRepository extends EntityRepository<User> {}
|
||||
export class UserRepository extends EntityRepository<User> {
|
||||
async getUserListForAdmin(businessId: string, queryDto: UserListQueryDto) {
|
||||
const { limit, skip } = PaginationUtils(queryDto);
|
||||
|
||||
const whereClause: FilterQuery<User> = {
|
||||
business: { id: businessId },
|
||||
emailEnabled: true,
|
||||
deletedAt: null,
|
||||
};
|
||||
|
||||
if (queryDto.q) {
|
||||
whereClause.$or = [
|
||||
{ userName: { $like: `%${queryDto.q}%` } },
|
||||
{ emailAddress: { $like: `%${queryDto.q}%` } },
|
||||
{ displayName: { $like: `%${queryDto.q}%` } },
|
||||
];
|
||||
}
|
||||
|
||||
if (queryDto.isActive) {
|
||||
console.log(queryDto.isActive);
|
||||
|
||||
whereClause.isActive = queryDto.isActive === 1;
|
||||
}
|
||||
|
||||
return this.findAndCount(whereClause, {
|
||||
populate: ["domain", "business"],
|
||||
limit,
|
||||
offset: skip,
|
||||
orderBy: { createdAt: "DESC" },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EntityManager, FilterQuery } from "@mikro-orm/postgresql";
|
||||
import { EntityManager } from "@mikro-orm/postgresql";
|
||||
import { BadRequestException, Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
@@ -17,6 +17,7 @@ import { DomainsService } from "../../domains/services/domains.service";
|
||||
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
||||
import { PasswordService } from "../../utils/services/password.service";
|
||||
import { CreateEmailUserDto } from "../DTO/create-email-user.dto";
|
||||
import { UserListQueryDto } from "../DTO/user-list-query.dto";
|
||||
import { Role } from "../entities/role.entity";
|
||||
import { User } from "../entities/user.entity";
|
||||
import { RoleEnum } from "../enums/role.enum";
|
||||
@@ -103,7 +104,7 @@ export class UsersService {
|
||||
emailAddress,
|
||||
emailEnabled: true,
|
||||
emailQuota: quota || 1073741824,
|
||||
emailAccountId: mailServerUser.id,
|
||||
wildduckUserId: mailServerUser.id,
|
||||
displayName: displayName || username,
|
||||
isActive: true,
|
||||
business,
|
||||
@@ -135,7 +136,7 @@ export class UsersService {
|
||||
id: user.id,
|
||||
emailAddress: user.emailAddress!,
|
||||
displayName: user.displayName!,
|
||||
emailAccountId: user.emailAccountId!,
|
||||
wildduckUserId: user.wildduckUserId!,
|
||||
emailQuota: user.emailQuota!,
|
||||
emailEnabled: user.emailEnabled,
|
||||
domain: domain.name,
|
||||
@@ -164,21 +165,10 @@ export class UsersService {
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
async getEmailUsers(businessId: string, domainId?: string) {
|
||||
const whereClause: FilterQuery<User> = {
|
||||
business: { id: businessId },
|
||||
emailEnabled: true,
|
||||
deletedAt: null,
|
||||
};
|
||||
async getEmailUsers(businessId: string, queryDto: UserListQueryDto) {
|
||||
const [users, count] = await this.userRepository.getUserListForAdmin(businessId, queryDto);
|
||||
|
||||
if (domainId) whereClause.domain = { id: domainId };
|
||||
|
||||
const users = await this.userRepository.find(whereClause, {
|
||||
populate: ["domain", "business"],
|
||||
orderBy: { createdAt: "DESC" },
|
||||
});
|
||||
|
||||
return { users };
|
||||
return { users, count, paginate: true };
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
@@ -192,8 +182,8 @@ export class UsersService {
|
||||
if (!user) throw new NotFoundException(UserMessage.EMAIL_USER_NOT_FOUND);
|
||||
|
||||
try {
|
||||
if (user.emailAccountId) {
|
||||
await firstValueFrom(this.mailServerService.users.deleteUser(user.emailAccountId));
|
||||
if (user.wildduckUserId) {
|
||||
await firstValueFrom(this.mailServerService.users.deleteUser(user.wildduckUserId));
|
||||
}
|
||||
|
||||
user.deletedAt = new Date();
|
||||
@@ -224,9 +214,9 @@ export class UsersService {
|
||||
if (!user) throw new NotFoundException(UserMessage.EMAIL_USER_NOT_FOUND);
|
||||
|
||||
try {
|
||||
if (user.emailAccountId) {
|
||||
if (user.wildduckUserId) {
|
||||
await firstValueFrom(
|
||||
this.mailServerService.users.updateUser(user.emailAccountId, {
|
||||
this.mailServerService.users.updateUser(user.wildduckUserId, {
|
||||
quota: newQuota,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common";
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseInterceptors } from "@nestjs/common";
|
||||
import { ApiHeader, ApiOperation, ApiResponse } from "@nestjs/swagger";
|
||||
|
||||
import { CreateEmailUserDto } from "./DTO/create-email-user.dto";
|
||||
import { UserListQueryDto } from "./DTO/user-list-query.dto";
|
||||
import { UsersService } from "./services/users.service";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { BusinessDec } from "../../common/decorators/business.decorator";
|
||||
import { ParamDto } from "../../common/DTO/param.dto";
|
||||
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
|
||||
|
||||
@Controller("users")
|
||||
@ApiHeader({ name: "x-business-id", description: "Business ID" })
|
||||
@UseInterceptors(BusinessInterceptor)
|
||||
@AuthGuards()
|
||||
export class UsersController {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
@@ -23,8 +26,8 @@ export class UsersController {
|
||||
@Get()
|
||||
@ApiOperation({ summary: "Get email users for business" })
|
||||
@ApiResponse({ status: 200, description: "Email users retrieved successfully" })
|
||||
getEmailUsers(@BusinessDec("id") businessId: string, @Query("domainId") domainId?: string) {
|
||||
return this.usersService.getEmailUsers(businessId, domainId);
|
||||
getEmailUsers(@BusinessDec("id") businessId: string, @Query() queryDto: UserListQueryDto) {
|
||||
return this.usersService.getEmailUsers(businessId, queryDto);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
|
||||
@@ -6,12 +6,13 @@ import { Role } from "./entities/role.entity";
|
||||
import { User } from "./entities/user.entity";
|
||||
import { UsersService } from "./services/users.service";
|
||||
import { UsersController } from "./users.controller";
|
||||
import { BusinessesModule } from "../businesses/businesses.module";
|
||||
import { DomainsModule } from "../domains/domains.module";
|
||||
import { MailServerModule } from "../mail-server/mail-server.module";
|
||||
import { UtilsModule } from "../utils/utils.module";
|
||||
|
||||
@Module({
|
||||
imports: [MikroOrmModule.forFeature([User, RefreshToken, Role]), UtilsModule, MailServerModule, DomainsModule],
|
||||
imports: [MikroOrmModule.forFeature([User, RefreshToken, Role]), UtilsModule, MailServerModule, DomainsModule, BusinessesModule],
|
||||
controllers: [UsersController],
|
||||
providers: [UsersService],
|
||||
exports: [UsersService],
|
||||
|
||||
Reference in New Issue
Block a user