chore: add danak services and admin login

This commit is contained in:
mahyargdz
2025-01-25 16:52:54 +03:30
parent 8af72264e7
commit 6da4b5114c
35 changed files with 505 additions and 34 deletions
+25
View File
@@ -0,0 +1,25 @@
import { join } from "path";
import { config } from "dotenv";
import { DataSource } from "typeorm";
config();
const { DB_HOST, DB_NAME, DB_PASS, DB_PORT, DB_USER, NODE_ENV } = process.env;
const IS_PROD = NODE_ENV === "production";
const PATH = IS_PROD ? "dist" : "src";
export const connectionSource = new DataSource({
type: "postgres",
host: DB_HOST as string,
port: parseInt(DB_PORT as string),
username: DB_USER,
password: DB_PASS,
database: DB_NAME,
logging: true,
entities: [join(process.cwd(), PATH, "modules/**/*.entity{.ts,.js}")],
migrations: [join(process.cwd(), "database/migrations/*{.ts,.js}")],
synchronize: false,
migrationsTableName: "typeorm_migrations",
migrationsRun: false,
});
console.log(join(process.cwd(), PATH, "modules/**/*.entity{.ts,.js}"));
+19
View File
@@ -0,0 +1,19 @@
import { Logger } from "@nestjs/common";
import { connectionSource } from "./connection";
import { seedAdmin } from "./seeders/admin.seeder";
import { seedRole } from "./seeders/role.seeder";
const logger = new Logger("Seeder");
export const runSeeder = async () => {
await connectionSource.initialize();
logger.log("start seeding database");
await seedRole(connectionSource, logger);
await seedAdmin(connectionSource, logger);
logger.log("seeding completed");
process.exit(0);
};
runSeeder();
+33
View File
@@ -0,0 +1,33 @@
import { Logger } from "@nestjs/common";
import { DataSource, DeepPartial } from "typeorm";
import { Role } from "../../src/modules/users/entities/role.entity";
import { User } from "../../src/modules/users/entities/user.entity";
import { RoleEnum } from "../../src/modules/users/enums/role.enum";
const defaultAdmin: DeepPartial<User> = {
email: "admin-dsc@gmail.com",
phone: "09922320740",
userName: "admin-default",
password: "admin123",
firstName: "DSC",
lastName: "Admin",
nationalCode: "1234567890",
};
export const seedAdmin = async (dataSource: DataSource, logger: Logger) => {
try {
const roleRepo = dataSource.getRepository(Role);
const userRepo = dataSource.getRepository(User);
const adminRole = await roleRepo.findOneBy({ name: RoleEnum.ADMIN });
if (!adminRole) throw new Error("Role not found");
const admin = userRepo.create({ ...defaultAdmin, role: adminRole });
await userRepo.save(admin);
logger.log("admin created successfully");
} catch (error) {
logger.error("Error in seeding admin", error);
process.exit(1);
}
};
+19 -1
View File
@@ -1,3 +1,21 @@
import { Logger } from "@nestjs/common";
import { DataSource } from "typeorm";
import { Role } from "../../src/modules/users/entities/role.entity";
import { RoleEnum } from "../../src/modules/users/enums/role.enum";
export const roles = [{ name: RoleEnum.SUPER_ADMIN }, { name: RoleEnum.ADMIN }, { name: RoleEnum.VISITOR }, { name: RoleEnum.USER }];
const roles = [{ name: RoleEnum.SUPER_ADMIN }, { name: RoleEnum.ADMIN }, { name: RoleEnum.VISITOR }, { name: RoleEnum.USER }];
export const seedRole = async (dataSource: DataSource, logger: Logger) => {
try {
const roleRepo = dataSource.getRepository(Role);
for (const role of roles) {
const newRole = roleRepo.create(role);
await roleRepo.save(newRole);
}
logger.log("Role seeded successfully");
} catch (error) {
logger.error("Error in seeding role", error);
process.exit(1);
}
};
+1 -1
View File
@@ -6,7 +6,7 @@ services:
restart: always
container_name: postgres_dsc
ports:
- 54320:5432
- ${DB_PORT}:5432
# networks:
# - app_network
volumes:
+6 -3
View File
@@ -8,10 +8,10 @@
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:nest": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "NODE_ENV=production node --trace-warnings dist/main",
"start": "NODE_ENV=production node --trace-warnings dist/main",
"lint:fix": "eslint . --ext .ts --fix",
"test": "jest",
"test:watch": "jest --watch",
@@ -19,12 +19,14 @@
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"typeorm": "node -r ts-node/register ./node_modules/typeorm/cli",
"schema:drop": "npx typeorm-ts-node-commonjs schema:drop -d ./database/connection.ts",
"migration:run": "npx typeorm-ts-node-commonjs migration:run -d ./database/connection.ts",
"migration:generate": "npx typeorm-ts-node-commonjs migration:generate -d ./database/connection.ts ./database/migrations/$npm_config_name",
"migration:create": "npx typeorm-ts-node-commonjs migration:create ./database/migrations/$npm_config_name",
"migration:revert": "npx typeorm-ts-node-commonjs migration:revert -d ./database/connection.ts",
"migration:show": "npx typeorm-ts-node-commonjs migration:show -d ./database/connection.ts ",
"prepare": "husky"
"seed:ts": "npx ts-node -r tsconfig-paths/register ./database/seeder.runner.ts",
"prepare": "husky || true"
},
"dependencies": {
"@fastify/static": "^7.0.4",
@@ -48,6 +50,7 @@
"cache-manager": "^6.3.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.4.7",
"fastify": "^5.2.1",
"handlebars": "^4.7.8",
"nodemailer": "^6.9.16",
+3
View File
@@ -71,6 +71,9 @@ importers:
class-validator:
specifier: ^0.14.1
version: 0.14.1
dotenv:
specifier: ^16.4.7
version: 16.4.7
fastify:
specifier: ^5.2.1
version: 5.2.1
+2
View File
@@ -9,6 +9,7 @@ import { rateLimitConfig } from "./configs/rateLimit.config";
import { databaseConfigs } from "./configs/typeorm.config";
import { HTTPLogger } from "./core/middlewares/logger.middleware";
import { AuthModule } from "./modules/auth/auth.module";
import { DanakServicesModule } from "./modules/danak-services/danak-services.module";
import { TicketsModule } from "./modules/tickets/tickets.module";
import { UsersModule } from "./modules/users/users.module";
@@ -21,6 +22,7 @@ import { UsersModule } from "./modules/users/users.module";
UsersModule,
TicketsModule,
AuthModule,
DanakServicesModule,
],
controllers: [],
providers: [],
+13
View File
@@ -49,6 +49,7 @@ export const enum AuthMessage {
NATIONAL_NOT_EMPTY = "کد ملی نمی‌تواند خالی باشد",
OTP_ALREADY_SENT = "کد یکبار مصرف قبلا ارسال شده است",
TOO_MANY_REQUESTS = "تعداد درخواست های شما بیش از حد مجاز است",
NOT_ADMIN = "شما دسترسی به بخش ادمین ندارید",
}
export const enum UserMessage {
@@ -66,4 +67,16 @@ export const enum CommonMessage {
THIS_FILED_IS_REQUIRED = "این فیلد الزامی است",
VALID_FOR_CHOOSE = "معتبر برای انتخاب",
UPDATE_SUCCESS = "با موفقیت به روز رسانی شد",
CREATED = "با موفقیت ایجاد شد",
}
export const enum CategoryMessage {
TITLE_REQUIRED = "نام دسته بندی مورد نیاز است",
TITLE_STRING = "نام دسته بندی باید یک رشته باشد",
TITLE_LENGTH = "نام دسته بندی باید بین ۳ تا ۵۰ کاراکتر باشد",
ICON_REQUIRED = "آیکون دسته بندی مورد نیاز است",
ICON_SHOULD_BE_URL = "آیکون باید یک آدرس یو آر ال باشد",
PARENT_ID_REQUIRED = "شناسه والد دسته بندی مورد نیاز است",
PARENT_ID_SHOULD_BE_UUID = "شناسه والد باید یک یو یو آی دی باشد",
TITLE_EXIST = "دسته بندی با این نام قبلا ثبت شده است",
}
+16
View File
@@ -57,6 +57,22 @@ export class AuthController {
return this.authService.loginWithPassword(loginPasswordDto);
}
//***************************** */
@ApiOperation({ summary: "login with password ==> admin" })
@HttpCode(HttpStatus.OK)
@Post("login/password/admin")
adminLoginWithPassword(@Body() loginPasswordDto: LoginPasswordDTO) {
return this.authService.adminLoginWithPassword(loginPasswordDto);
}
@ApiOperation({ summary: "verify otp for login" })
@HttpCode(HttpStatus.OK)
@Post("otp/verify/admin")
adminVerifyOtp(@Body() verifyOtpDto: VerifyOtpDto) {
return this.authService.adminVerifyLoginOtp(verifyOtpDto);
}
//***************************** */
// @Post("forgot-password")
// async forgotPassword(@Body() forgotPasswordDto: ForgotPasswordDto) {
// return this.authService.forgotPassword(forgotPasswordDto);
+56 -11
View File
@@ -2,6 +2,7 @@ import { BadRequestException, Injectable, Logger } from "@nestjs/common";
import { TokensService } from "./tokens.service";
import { AuthMessage, UserMessage } from "../../../common/enums/message.enum";
import { RoleEnum } from "../../users/enums/role.enum";
import { UsersService } from "../../users/providers/users.service";
import { OTPService } from "../../utils/providers/otp.service";
import { PasswordService } from "../../utils/providers/password.service";
@@ -64,11 +65,7 @@ export class AuthService {
async loginWithPassword(loginDto: LoginPasswordDTO) {
const { email, password } = loginDto;
const user = await this.usersService.findOneWithEmail(email);
if (!user) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
const passCompare = await this.passwordService.comparePassword(password, user.password);
if (!passCompare) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
const user = await this.checkUserLoginCredentialWithEmail(email, password);
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
@@ -79,6 +76,21 @@ export class AuthService {
}
//****************** */
async adminLoginWithPassword(loginDto: LoginPasswordDTO) {
const { email, password } = loginDto;
const user = await this.checkUserLoginCredentialWithEmail(email, password);
if (user.role.name !== RoleEnum.ADMIN) throw new BadRequestException(AuthMessage.NOT_ADMIN);
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
return {
message: AuthMessage.PASSWORD_LOGIN_SUCCESS,
...tokens,
};
}
//****************** */
async checkUserExist(checkUserExistDto: CheckUserExistDto) {
const user = await this.usersService.findOneWithEmail(checkUserExistDto.email);
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
@@ -86,7 +98,6 @@ export class AuthService {
}
//****************** */
async requestLoginOtp(requestOtpDto: RequestOtpDto) {
const { phone } = requestOtpDto;
const user = await this.usersService.findOneWithPhone(phone);
@@ -114,13 +125,22 @@ export class AuthService {
async verifyLoginOtp(verifyOtpDto: VerifyOtpDto) {
const { code, phone } = verifyOtpDto;
const isValid = await this.otpService.verifyOtp(phone, code, "LOGIN");
if (!isValid) throw new BadRequestException(AuthMessage.INVALID_OTP);
const user = await this.checkUserLoginCredentialWithPhone(phone, code);
await this.otpService.delOtpFormCache(phone, "LOGIN");
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
return {
message: AuthMessage.LOGIN_SUCCESS,
...tokens,
};
}
const user = await this.usersService.findOneWithPhone(phone);
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
//****************** */
async adminVerifyLoginOtp(verifyOtpDto: VerifyOtpDto) {
const { code, phone } = verifyOtpDto;
const user = await this.checkUserLoginCredentialWithPhone(phone, code);
if (user.role.name !== RoleEnum.ADMIN) throw new BadRequestException(AuthMessage.NOT_ADMIN);
const tokens = this.tokensService.generateAccessAndRefreshToken({ sub: user.id, role: user.role.name });
return {
@@ -129,4 +149,29 @@ export class AuthService {
};
}
//****************** */
//****************** */
private async checkUserLoginCredentialWithEmail(email: string, password: string) {
const user = await this.usersService.findOneWithEmail(email);
if (!user) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
const passCompare = await this.passwordService.comparePassword(password, user.password);
if (!passCompare) throw new BadRequestException(AuthMessage.INVALID_PASSWORD);
return user;
}
//****************** */
//****************** */
private async checkUserLoginCredentialWithPhone(phone: string, otpCode: string) {
const isValid = await this.otpService.verifyOtp(phone, otpCode, "LOGIN");
if (!isValid) throw new BadRequestException(AuthMessage.INVALID_OTP);
await this.otpService.delOtpFormCache(phone, "LOGIN");
const user = await this.usersService.findOneWithPhone(phone);
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
return user;
}
}
@@ -0,0 +1,23 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length } from "class-validator";
import { CategoryMessage } from "../../../common/enums/message.enum";
export class CreateCategoryDto {
@IsNotEmpty({ message: CategoryMessage.TITLE_REQUIRED })
@IsString({ message: CategoryMessage.TITLE_STRING })
@Length(3, 50, { message: CategoryMessage.TITLE_LENGTH })
@ApiProperty({ description: "Category title", example: "business" })
title: string;
@IsNotEmpty({ message: CategoryMessage.ICON_REQUIRED })
@IsUrl({ protocols: ["http", "https"], require_protocol: true }, { message: CategoryMessage.ICON_SHOULD_BE_URL })
@ApiProperty({ description: "Category icon", example: "https://example.com/icon.png" })
icon: string;
@IsOptional()
@IsNotEmpty({ message: CategoryMessage.PARENT_ID_REQUIRED })
@IsUUID("4", { message: CategoryMessage.PARENT_ID_SHOULD_BE_UUID })
@ApiPropertyOptional({ description: "Parent category id", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" })
parentId?: string;
}
@@ -0,0 +1,18 @@
import { Body, Controller, Post } from "@nestjs/common";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { CreateCategoryDto } from "./DTO/create-category.dto";
import { DanakServicesService } from "./providers/danak-services.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
@Controller("services")
@ApiTags("Danak-Services")
export class DanakServicesController {
constructor(private readonly danakServicesService: DanakServicesService) {}
@AuthGuards()
@ApiOperation({ summary: "Create a new service category" })
@Post("category")
createCategory(@Body() createDto: CreateCategoryDto) {
return this.danakServicesService.createCategory(createDto);
}
}
@@ -0,0 +1,19 @@
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { DanakServicesController } from "./danak-services.controller";
import { DanakServiceCategory } from "./entities/danak-service-category.entity";
import { DanakServiceImage } from "./entities/danak-service-image.entity";
import { DanakService } from "./entities/danak-service.entity";
import { DanakServicesService } from "./providers/danak-services.service";
import { DanakServicesCategoryRepository } from "./repositories/danak-services-category.repository";
import { DanakServicesImageRepository } from "./repositories/danak-services-image.repository";
import { DanakServicesRepository } from "./repositories/danak-services.repository";
@Module({
imports: [TypeOrmModule.forFeature([DanakService, DanakServiceImage, DanakServiceCategory])],
providers: [DanakServicesService, DanakServicesRepository, DanakServicesCategoryRepository, DanakServicesImageRepository],
controllers: [DanakServicesController],
exports: [DanakServicesService, TypeOrmModule],
})
export class DanakServicesModule {}
@@ -0,0 +1,26 @@
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from "typeorm";
import { DanakService } from "./danak-service.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
@Entity()
export class DanakServiceCategory extends BaseEntity {
@Column({ type: "varchar", length: 100, nullable: false, unique: true })
title: string;
@Column({ type: "varchar", length: 150, nullable: false })
icon: string;
@ManyToOne(() => DanakServiceCategory, (category) => category.children)
@JoinColumn({ name: "parentId" })
parent: DanakServiceCategory;
@OneToMany(() => DanakServiceCategory, (category) => category.parent)
children: DanakServiceCategory[];
@Column({ nullable: true })
parentId: string;
@OneToMany(() => DanakService, (danakService) => danakService.category)
danakService: DanakService[];
}
@@ -0,0 +1,13 @@
import { Column, Entity, ManyToOne } from "typeorm";
import { DanakService } from "./danak-service.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
@Entity()
export class DanakServiceImage extends BaseEntity {
@Column({ type: "varchar", length: 255, nullable: false })
imageUrl: string;
@ManyToOne(() => DanakService, (danakService) => danakService.images, { nullable: false, onDelete: "CASCADE" })
danakService: DanakService;
}
@@ -0,0 +1,52 @@
import { Column, Entity, ManyToOne, OneToMany } from "typeorm";
import { DanakServiceCategory } from "./danak-service-category.entity";
import { DanakServiceImage } from "./danak-service-image.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { ServiceStatus } from "../enums/service-status.enum";
import { ServicesLanguage } from "../enums/services-language.enum";
@Entity()
export class DanakService extends BaseEntity {
@Column({ type: "varchar", length: 255, nullable: false })
name: string;
@Column({ type: "text", nullable: false })
description: string;
@Column({ type: "varchar", length: 255, nullable: false })
author: string;
@Column({ type: "timestamp", nullable: false, default: () => "CURRENT_TIMESTAMP" })
createDate: Date;
@Column({ type: "int", nullable: false, default: 0 })
userCount: number;
@Column({ type: "enum", enum: ServicesLanguage, nullable: false })
serviceLanguage: ServicesLanguage;
@Column({ type: "varchar", length: 150, nullable: false })
softwareLanguage: string;
@Column({ type: "text", nullable: false })
metaDescription: string;
@Column({ type: "enum", enum: ServiceStatus, nullable: false, default: ServiceStatus.IN_ACTIVE })
status: ServiceStatus;
@Column({ type: "varchar", length: 255, nullable: false })
link: string;
@Column({ type: "varchar", length: 255, nullable: false })
icon: string;
@OneToMany(() => DanakServiceImage, (danakServiceImage) => danakServiceImage.danakService, { eager: true })
images: DanakServiceImage[];
@ManyToOne(() => DanakServiceCategory, (danakServiceCategory) => danakServiceCategory.danakService, {
nullable: false,
onDelete: "RESTRICT",
})
category: DanakServiceCategory;
}
@@ -0,0 +1,4 @@
export enum ServiceStatus {
ACTIVE = "ACTIVE",
IN_ACTIVE = "IN_ACTIVE",
}
@@ -0,0 +1,5 @@
export enum ServicesLanguage {
ENGLISH = "en",
GERMAN = "de",
PERSIAN = "fa",
}
@@ -0,0 +1,24 @@
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
import { CategoryMessage, CommonMessage } from "../../../common/enums/message.enum";
import { CreateCategoryDto } from "../DTO/create-category.dto";
import { DanakServicesCategoryRepository } from "../repositories/danak-services-category.repository";
@Injectable()
export class DanakServicesService {
private readonly logger = new Logger(DanakServicesService.name);
constructor(private readonly danakServicesCategoryRepository: DanakServicesCategoryRepository) {}
/********** */
async createCategory(createDto: CreateCategoryDto) {
this.logger.log(`Creating a new category with title: ${createDto.title}`);
const existCategory = await this.danakServicesCategoryRepository.findOneBy({ title: createDto.title });
if (existCategory) throw new BadRequestException(CategoryMessage.TITLE_EXIST);
const category = this.danakServicesCategoryRepository.create(createDto);
await this.danakServicesCategoryRepository.save(category);
return {
message: CommonMessage.CREATED,
category,
};
}
/********** */
}
@@ -0,0 +1,12 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { DanakServiceCategory } from "../entities/danak-service-category.entity";
@Injectable()
export class DanakServicesCategoryRepository extends Repository<DanakServiceCategory> {
constructor(@InjectRepository(DanakServiceCategory) danakServicesCategoryRepository: Repository<DanakServiceCategory>) {
super(danakServicesCategoryRepository.target, danakServicesCategoryRepository.manager, danakServicesCategoryRepository.queryRunner);
}
}
@@ -0,0 +1,12 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { DanakServiceImage } from "../entities/danak-service-image.entity";
@Injectable()
export class DanakServicesImageRepository extends Repository<DanakServiceImage> {
constructor(@InjectRepository(DanakServiceImage) danakServicesImageRepository: Repository<DanakServiceImage>) {
super(danakServicesImageRepository.target, danakServicesImageRepository.manager, danakServicesImageRepository.queryRunner);
}
}
@@ -0,0 +1,12 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { DanakService } from "../entities/danak-service.entity";
@Injectable()
export class DanakServicesRepository extends Repository<DanakService> {
constructor(@InjectRepository(DanakService) danakServicesRepository: Repository<DanakService>) {
super(danakServicesRepository.target, danakServicesRepository.manager, danakServicesRepository.queryRunner);
}
}
@@ -0,0 +1,21 @@
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
import { BaseEntity } from "../../../common/entities/base.entity";
import { Ticket } from "./ticket.entity";
import { User } from "../../users/entities/user.entity";
@Entity()
export class TicketMessage extends BaseEntity {
@Column({ type: "text", nullable: false })
content: string;
@Column({ type: "varchar", length: 150, nullable: true, default: null })
attachmentUrl: string;
@JoinColumn()
@ManyToOne(() => Ticket, (ticket) => ticket.messages, { onDelete: "CASCADE", nullable: false })
ticket: Ticket;
@ManyToOne(() => User, (user) => user.ticketMessage, { onDelete: "SET NULL", nullable: true })
@JoinColumn()
author: User;
}
@@ -1,13 +1,17 @@
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from "typeorm";
import { TicketCategory } from "./ticket-category.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { User } from "../../users/entities/user.entity";
import { TicketPriority } from "../enums/ticket-priority.enum";
import { TicketStatus } from "../enums/ticket-status.enum";
import { TicketMessage } from "./ticket-message.entity";
@Entity()
export class Ticket extends BaseEntity {
@Column({ type: "int", generated: "identity", insert: false })
numericId: number;
@Column({ type: "varchar", length: 150, nullable: false })
title: string;
@@ -33,4 +37,7 @@ export class Ticket extends BaseEntity {
@JoinColumn()
@ManyToOne(() => TicketCategory, (category) => category.tickets, { onDelete: "RESTRICT", nullable: false })
category: TicketCategory;
@OneToMany(() => TicketMessage, (message) => message.ticket)
messages: TicketMessage[];
}
@@ -0,0 +1,11 @@
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { TicketCategory } from "../entities/ticket-category.entity";
import { Injectable } from "@nestjs/common";
@Injectable()
export class TicketCategoryRepository extends Repository<TicketCategory> {
constructor(@InjectRepository(TicketCategory) ticketCategoryRepository: Repository<TicketCategory>) {
super(ticketCategoryRepository.target, ticketCategoryRepository.manager, ticketCategoryRepository.queryRunner);
}
}
@@ -0,0 +1,11 @@
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { TicketMessage } from "../entities/ticket-message.entity";
import { Injectable } from "@nestjs/common";
@Injectable()
export class TicketMessagesRepository extends Repository<TicketMessage> {
constructor(@InjectRepository(TicketMessage) ticketMessagesRepository: Repository<TicketMessage>) {
super(ticketMessagesRepository.target, ticketMessagesRepository.manager, ticketMessagesRepository.queryRunner);
}
}
@@ -0,0 +1,11 @@
import { Repository } from "typeorm";
import { Ticket } from "../entities/ticket.entity";
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
@Injectable()
export class TicketsRepository extends Repository<Ticket> {
constructor(@InjectRepository(Ticket) ticketsRepository: Repository<Ticket>) {
super(ticketsRepository.target, ticketsRepository.manager, ticketsRepository.queryRunner);
}
}
+6 -2
View File
@@ -1,6 +1,10 @@
import { Controller } from "@nestjs/common";
import { ApiTags } from "@nestjs/swagger";
// import { TicketsService } from "./providers/tickets.service";
@Controller("tickets")
@ApiTags("users")
export class TicketsController {}
@ApiTags("Tickets")
export class TicketsController {
// constructor(private readonly ticketsService: TicketsService) {}
}
+8 -3
View File
@@ -4,11 +4,16 @@ import { TypeOrmModule } from "@nestjs/typeorm";
import { TicketCategory } from "./entities/ticket-category.entity";
import { Ticket } from "./entities/ticket.entity";
import { TicketsController } from "./tickets.controller";
import { TicketsService } from "./tickets.service";
import { TicketsService } from "./providers/tickets.service";
import { TicketMessage } from "./entities/ticket-message.entity";
import { TicketsRepository } from "./repositories/tickets.repository";
import { TicketCategoryRepository } from "./repositories/tickets-category.repository";
import { TicketMessagesRepository } from "./repositories/tickets-message.repository";
@Module({
imports: [TypeOrmModule.forFeature([Ticket, TicketCategory])],
providers: [TicketsService],
imports: [TypeOrmModule.forFeature([Ticket, TicketCategory, TicketMessage])],
providers: [TicketsService, TicketsRepository, TicketCategoryRepository, TicketMessagesRepository],
controllers: [TicketsController],
exports: [TypeOrmModule, TicketsService, TicketsRepository, TicketCategoryRepository, TicketMessagesRepository],
})
export class TicketsModule {}
+5 -2
View File
@@ -1,7 +1,8 @@
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from "typeorm";
import { Column, Entity, ManyToOne, OneToMany } from "typeorm";
import { Role } from "./role.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { TicketMessage } from "../../tickets/entities/ticket-message.entity";
import { Ticket } from "../../tickets/entities/ticket.entity";
@Entity()
@@ -30,10 +31,12 @@ export class User extends BaseEntity {
@Column({ type: "varchar", length: 100, unique: true, nullable: false })
nationalCode: string;
@JoinColumn()
@ManyToOne(() => Role, { eager: true, onDelete: "RESTRICT", nullable: false })
role: Role;
@OneToMany(() => Ticket, (ticket) => ticket.user)
tickets: Ticket[];
@OneToMany(() => TicketMessage, (ticketMessage) => ticketMessage.author)
ticketMessage: TicketMessage[];
}
+10 -9
View File
@@ -3,8 +3,8 @@ import slugify from "slugify";
import { Not } from "typeorm";
import { RoleRepository } from "./roles.repository";
import { UserRepository } from "./users.repository";
import { roles } from "../../../../database/seeders/role.seeder";
import { UserRepository } from "../repositories/users.repository";
// import { roles } from "../../../../database/seeders/role.seeder";
import { CommonMessage, UserMessage } from "../../../common/enums/message.enum";
import { CompleteRegistrationDto } from "../../auth/DTO/complete-register.dto";
import { CheckValidityDTO } from "../DTO/check-validity.dto";
@@ -38,6 +38,7 @@ export class UsersService {
/************************************************************ */
async getMe(userId: string) {
this.logger.debug("sss");
const user = await this.userRepository.findOne({ where: { id: userId }, select: this.userSelect });
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
return { user };
@@ -105,11 +106,11 @@ export class UsersService {
}
///****************************************************** */
async roleSeeder() {
const countRole = await this.roleRepository.count();
if (countRole > 0) return;
const createdRoles = await this.roleRepository.insert(roles);
this.logger.log({ createdRoles });
return createdRoles;
}
// async roleSeeder() {
// const countRole = await this.roleRepository.count();
// if (countRole > 0) return;
// const createdRoles = await this.roleRepository.insert(roles);
// this.logger.log({ createdRoles });
// return createdRoles;
// }
}
+1 -1
View File
@@ -4,8 +4,8 @@ import { TypeOrmModule } from "@nestjs/typeorm";
import { Role } from "./entities/role.entity";
import { User } from "./entities/user.entity";
import { RoleRepository } from "./providers/roles.repository";
import { UserRepository } from "./providers/users.repository";
import { UsersService } from "./providers/users.service";
import { UserRepository } from "./repositories/users.repository";
import { UsersController } from "./users.controller";
@Module({