Files
dsc-api/src/modules/users/providers/admins.service.ts
T

230 lines
8.5 KiB
TypeScript
Executable File

import { BadRequestException, Injectable } from "@nestjs/common";
import slugify from "slugify";
import { DataSource, In, Not } from "typeorm";
import { AdminMessage, AdsMessage, UserMessage } from "../../../common/enums/message.enum";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
import { PasswordService } from "../../utils/providers/password.service";
import { CreateAdminDto } from "../DTO/create-admin.dto";
import { CreateRoleDto } from "../DTO/create-role.dto";
import { SearchAdminQueryDto } from "../DTO/search-admins-query.dto";
import { SearchRolesQueryDto } from "../DTO/search-roles.dto";
import { UpdateAdminDto } from "../DTO/update-admin.dto";
import { RoleEnum } from "../enums/role.enum";
import { PermissionsRepository } from "../repositories/permissions.repository";
import { RoleRepository } from "../repositories/roles.repository";
import { UserRepository } from "../repositories/users.repository";
@Injectable()
export class AdminsService {
constructor(
private readonly userRepository: UserRepository,
private readonly rolesRepository: RoleRepository,
private readonly permissionsRepository: PermissionsRepository,
private readonly passwordService: PasswordService,
private readonly dataSource: DataSource,
) {}
async createAdmin(createDto: CreateAdminDto) {
const queryRunner = this.dataSource.createQueryRunner();
try {
await queryRunner.connect();
await queryRunner.startTransaction();
const existEmail = await queryRunner.manager.findOneBy(this.userRepository.target, { email: createDto.email });
if (existEmail) throw new BadRequestException(UserMessage.EMAIL_EXIST);
const existPhone = await queryRunner.manager.findOneBy(this.userRepository.target, { phone: createDto.phone });
if (existPhone) throw new BadRequestException(UserMessage.PHONE_EXIST);
const role = await queryRunner.manager.findOne(this.rolesRepository.target, {
where: { id: createDto.roleId },
relations: { permissions: true },
});
if (!role) throw new BadRequestException(AdsMessage.ROLE_NOT_FOUND);
if (createDto.password !== createDto.repeatPassword) throw new BadRequestException(AdminMessage.PASSWORD_NOT_MATCH);
const hashedPassword = await this.passwordService.hashPassword(createDto.password);
const userName = slugify(`${createDto.firstName} ${Date.now().toString().slice(-5)}`, { lower: true, trim: true });
await queryRunner.manager.save(this.rolesRepository.target, role);
const adminUser = queryRunner.manager.create(this.userRepository.target, {
...createDto,
roles: [role],
password: hashedPassword,
userName,
});
await queryRunner.manager.save(this.userRepository.target, adminUser);
await queryRunner.commitTransaction();
return {
message: AdminMessage.ADMIN_CREATED,
adminUser,
};
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
}
/************************************************************ */
async updateAdmin(id: string, updateDto: UpdateAdminDto) {
const queryRunner = this.dataSource.createQueryRunner();
try {
await queryRunner.connect();
await queryRunner.startTransaction();
const admin = await queryRunner.manager.findOne(this.userRepository.target, {
where: { id, roles: { isAdmin: true } },
relations: { roles: true },
});
if (!admin) throw new BadRequestException(UserMessage.ADMIN_NOT_FOUND);
if (updateDto.email && updateDto.email !== admin.email) {
const existEmail = await queryRunner.manager.findOneBy(this.userRepository.target, { email: updateDto.email, id: Not(id) });
if (existEmail) throw new BadRequestException(UserMessage.EMAIL_EXIST);
}
if (updateDto.phone && updateDto.phone !== admin.phone) {
const existPhone = await queryRunner.manager.findOneBy(this.userRepository.target, { phone: updateDto.phone, id: Not(id) });
if (existPhone) throw new BadRequestException(UserMessage.PHONE_EXIST);
}
if (updateDto.roleId) {
const role = await queryRunner.manager.findOne(this.rolesRepository.target, {
where: { id: updateDto.roleId },
relations: { permissions: true },
});
if (!role) throw new BadRequestException(AdsMessage.ROLE_NOT_FOUND);
await queryRunner.manager.save(this.rolesRepository.target, role);
admin.roles = [role];
await queryRunner.manager.save(this.userRepository.target, admin);
}
if (updateDto.password) {
if (updateDto.password !== updateDto.repeatPassword) throw new BadRequestException(AdminMessage.PASSWORD_NOT_MATCH);
admin.password = await this.passwordService.hashPassword(updateDto.password);
}
await queryRunner.manager.save(this.userRepository.target, { ...admin, ...updateDto, password: admin.password });
await queryRunner.commitTransaction();
return {
message: AdminMessage.ADMIN_UPDATED,
};
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
}
/************************************************************ */
async deleteAdmin(id: string) {
const admin = await this.userRepository.findOne({ where: { id, roles: { isAdmin: true } } });
if (!admin) throw new BadRequestException(AdminMessage.ADMIN_NOT_FOUND);
await this.userRepository.softDelete(id);
return {
message: AdminMessage.ADMIN_DELETED,
};
}
/************************************************************ */
async createRole(createDto: CreateRoleDto) {
const existRole = await this.rolesRepository.findOne({ where: { name: createDto.name } });
if (existRole) throw new BadRequestException(AdminMessage.ROLE_EXIST);
const permissions = await this.permissionsRepository.findBy({ id: In(createDto.permissions) });
if (permissions.length !== createDto.permissions.length) throw new BadRequestException(AdminMessage.PERMISSIONS_NOT_FOUND);
const role = this.rolesRepository.create({ ...createDto, permissions, isAdmin: true });
await this.rolesRepository.save(role);
return {
message: AdminMessage.ROLE_CREATED,
role,
};
}
/************************************************************ */
async getAdmins(queryDto: SearchAdminQueryDto) {
const [users, count] = await this.userRepository.getAdmins(queryDto);
return {
users,
count,
paginate: true,
};
}
/************************************************************ */
async getAdminById(id: string) {
const admin = await this.userRepository.findOne({ where: { id, roles: { isAdmin: true } }, relations: { roles: true } });
if (!admin) throw new BadRequestException(AdminMessage.ADMIN_NOT_FOUND);
return { admin };
}
/************************************************************ */
async getPermissions() {
const permissions = await this.permissionsRepository.find({ select: { id: true, name: true } });
return {
permissions,
};
}
/************************************************************ */
async getAdminPermissions(userId: string) {
const user = await this.userRepository.findOne({ where: { id: userId }, relations: { roles: { permissions: true } } });
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
return {
permissions: user.roles[0].permissions,
};
}
/************************************************************ */
async getRoles(queryDto: SearchRolesQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
const queryBuilder = this.rolesRepository.createQueryBuilder("role");
queryBuilder
.where("role.isAdmin = :isAdmin", { isAdmin: true })
// .leftJoinAndSelect("role.permissions", "permissions")
.loadRelationCountAndMap("role.userCount", "role.users");
if (queryDto.q) {
queryBuilder.andWhere("role.name ILIKE :q", { q: `%${queryDto.q}%` });
}
queryBuilder.take(limit).skip(skip).orderBy("role.createdAt", "DESC");
const [roles, count] = await queryBuilder.getManyAndCount();
return {
roles,
count,
paginate: true,
};
}
/************************************************************ */
async getSuperAdmins() {
return this.userRepository.find({ where: { roles: { isAdmin: true, name: RoleEnum.SUPER_ADMIN } } });
}
}