diff --git a/.env.development b/.env.development index 4ab1ee7..3114ae8 100644 --- a/.env.development +++ b/.env.development @@ -4,3 +4,4 @@ SERVER_URL=http://localhost:3000/ PORT=4000 JWT_KEY='MXvTnOhWYMYgYiFnBFRfX4Fnd4ZkXLK8qYU' IS_COOKIE_AUTH=false +IS_EMAIL=false diff --git a/README.md b/README.md index a633190..c31c0cb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Prettier](https://img.shields.io/badge/Code%20style-prettier-informational?logo=prettier&logoColor=white) [![GPL v3 License](https://img.shields.io/badge/License-GPLv3-green.svg)](./LICENSE) -[![HitCount](https://hits.dwyl.com/anilahir/nestjs-authentication-and-authorization.svg)](https://hits.dwyl.com/vinodnextcoder/nestjs-jwt-auth-cookie-mongoose) +[![HitCount](https://hits.dwyl.com/vinodnextcoder/nestjs-jwt-auth-cookie-mongoose.svg)](https://hits.dwyl.com/vinodnextcoder/nestjs-jwt-auth-cookie-mongoose) ## Description diff --git a/node-boilerplate.postman_collection.json b/node-boilerplate.postman_collection.json new file mode 100644 index 0000000..1592eff --- /dev/null +++ b/node-boilerplate.postman_collection.json @@ -0,0 +1,133 @@ +{ + "info": { + "_postman_id": "1c4f13b4-625a-43b8-b4ba-27fb10056118", + "name": "node-boilerplate", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "30399582" + }, + "item": [ + { + "name": "user login", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"password\":\"Password1@\",\r\n \"email\":\"te@test.com\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:4000/auth/login", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "4000", + "path": [ + "auth", + "login" + ] + } + }, + "response": [] + }, + { + "name": "user create", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"username\":\"11\",\r\n \"first_name\":\"test\",\r\n \"last_name\":\"test\",\r\n \"password\":\"Password1@\",\r\n \"password_reset_code\":\"1\",\r\n \"email\":\"te@test.com\",\r\n \"email_code\":\"eee\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:4000/v1/users", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "4000", + "path": [ + "v1", + "users" + ] + } + }, + "response": [] + }, + { + "name": "getUserid", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:4000/v1/users/getuser", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "4000", + "path": [ + "v1", + "users", + "getuser" + ] + } + }, + "response": [] + }, + { + "name": "getUser", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:4000/v1/users", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "4000", + "path": [ + "v1", + "users" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index 2a38978..71642b6 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,7 +6,9 @@ import { LoggerService } from './common/service/logger.service'; import { LoggerMiddleware } from './common/service/loggermiddleware.service'; import { DatabaseModule } from './config/database.module'; import { helloModule } from './hello/hello.module'; -// import { EmailService } from './common/service/mail.service'; +import { roleModule } from './roles/roles.module'; +import { app_Module } from './app_module/module.module'; + console.log(`${process.cwd()}/.env.${process.env.NODE_ENV}`) @Module({ @@ -19,7 +21,9 @@ console.log(`${process.cwd()}/.env.${process.env.NODE_ENV}`) DatabaseModule, UserModule, AuthModule, - helloModule + helloModule, + roleModule, + app_Module ], providers: [ LoggerService diff --git a/src/app_module/module.controller.spec.ts b/src/app_module/module.controller.spec.ts new file mode 100644 index 0000000..32a7da0 --- /dev/null +++ b/src/app_module/module.controller.spec.ts @@ -0,0 +1,27 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ModulesController } from './module.controller'; +import { LoggerService } from '../common/service/logger.service'; + +describe('RolesController', () => { + let controller: ModulesController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ModulesController], + providers: [ + { + provide: LoggerService, + useValue: { + log: jest.fn(), + }, + } + ], + }).compile(); + + controller = module.get(ModulesController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/app_module/module.controller.ts b/src/app_module/module.controller.ts new file mode 100644 index 0000000..10937d3 --- /dev/null +++ b/src/app_module/module.controller.ts @@ -0,0 +1,69 @@ +import { Body, Controller, Get, HttpStatus, Injectable, Post, Res, UseFilters, UsePipes, ValidationPipe, Version } from '@nestjs/common'; +import { Public } from "../common/decorators"; +import { HttpCode } from '@nestjs/common'; +import { LoggerService } from '../common/service/logger.service'; +import { v4 as uuid } from 'uuid'; +import { HttpExceptionFilter } from 'src/utils/http-exception.filter'; +import { statusMessage } from '../constant/statusMessage'; +import { sendResponse } from '../utils/index'; +import { ModulesService } from './module.service'; + + + +@Injectable() +@Controller('v1/modules') +export class ModulesController { + constructor( + private readonly modulesService :ModulesService, + private readonly logger: LoggerService + ) { } + + @Public() + @HttpCode(200) + @Get() + async helloWorld(): Promise { + const id: string = uuid(); + this.logger.log('modules controller called', id, 'modules.controler.ts', 'GET', '/', 'modules'); + return 'Hello World!'; + } + + @Public() + @HttpCode(200) + @UseFilters(new HttpExceptionFilter()) + @UsePipes(new ValidationPipe({ transform: true })) + @Version('1') + @Post('/add') + async addRole(@Body() productDto: any, @Res() res: Response): Promise { + console.log(productDto) + const id: string = uuid(); + this.logger.log('modules controller called', id, 'modules.controler.ts', 'POST', '/', 'roles'); + const prod = await this.modulesService.create(productDto); + return sendResponse( + res, + HttpStatus.OK, + statusMessage[HttpStatus.OK], + true, + null + ); + } + + + @Public() + @HttpCode(200) + @UseFilters(new HttpExceptionFilter()) + @UsePipes(new ValidationPipe({ transform: true })) + @Version('1') + @Get('/list') + async getRoles(@Res() res: Response): Promise { + const id: string = uuid(); + this.logger.log('modules controller called', id, 'modules.controler.ts', 'POST', '/', 'modules'); + const rolesList = await this.modulesService.findAll(); + return sendResponse( + res, + HttpStatus.OK, + statusMessage[HttpStatus.OK], + true, + rolesList + ); + } +} diff --git a/src/app_module/module.module.ts b/src/app_module/module.module.ts new file mode 100644 index 0000000..a043bae --- /dev/null +++ b/src/app_module/module.module.ts @@ -0,0 +1,22 @@ + +import { Module } from "@nestjs/common"; +import { LoggerService } from "../common/service/logger.service"; +import { MongooseModule } from "@nestjs/mongoose"; +import { ModulesService } from "./module.service"; +import { ModulesController } from "./module.controller"; +import { Modules, ModulesSchema } from "./schemas/modules.schema"; + + +@Module({ + imports: [ + MongooseModule.forFeature([ + { name: Modules.name, schema: ModulesSchema } + ]), + ], + providers: [ + LoggerService, + ModulesService + ], + controllers: [ModulesController] +}) +export class app_Module { } diff --git a/src/app_module/module.service.ts b/src/app_module/module.service.ts new file mode 100644 index 0000000..3ed7736 --- /dev/null +++ b/src/app_module/module.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from "@nestjs/common"; +import { LoggerService } from '../common/service/logger.service'; +import { InjectModel } from "@nestjs/mongoose"; +import { Model, Types } from "mongoose"; +import { Modules } from "./schemas/modules.schema"; +import { v4 as uuid } from 'uuid'; + +@Injectable() +export class ModulesService { + constructor( + @InjectModel(Modules.name) private readonly appModel: Model, + private readonly logger: LoggerService + ) { } + + async create(product: any): Promise { + const id: string = uuid(); + this.logger.log('modules service create called', id, 'modules.service.ts', '', '', 'create-service'); + + const createProduct = await this.appModel.create(product); + return createProduct; + } + + async findAll(): Promise { + const id: string = uuid(); + this.logger.log('modules service findall called', id, 'modules.service.ts', '', '', 'findAll-service'); + return this.appModel.find().exec(); + } + +} diff --git a/src/app_module/schemas/modules.schema.ts b/src/app_module/schemas/modules.schema.ts new file mode 100644 index 0000000..f014dd3 --- /dev/null +++ b/src/app_module/schemas/modules.schema.ts @@ -0,0 +1,23 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { HydratedDocument,now } from 'mongoose'; + +export type ModuleDocument = HydratedDocument; + +@Schema({ timestamps: true }) +export class Modules { + @Prop({ required: true, unique: true }) + moduleName: string; + @Prop({ default: null }) + description: string; + @Prop({ default: false }) + read: boolean; + @Prop({ default: false }) + write: boolean; + @Prop({ default: false }) + edit: boolean; + createdAt: Date; + @Prop({ default: now() }) + updatedAt: Date; +} + +export const ModulesSchema = SchemaFactory.createForClass(Modules); \ No newline at end of file diff --git a/src/auth/auth.controller.spec.ts b/src/auth/auth.controller.spec.ts index dfd51c8..125c31c 100644 --- a/src/auth/auth.controller.spec.ts +++ b/src/auth/auth.controller.spec.ts @@ -53,32 +53,12 @@ describe("Auth Controller", () => { message: "SUCCESS", isSuccess: true, statusCode: 200, - data: null, + data: { + "access_token": "eyJhbGciOiJIUzI1NiJ9.sss.aaaaa", + "refresh_token": "eyJhbGciOiJIUzI1NiJ9.sss.aaaaa", + } }); - expect(mockResponse.cookie).toHaveBeenCalledWith( - 'access_token', - 'eyJhbGciOiJIUzI1NiJ9.sss.aaaaa', - expect.objectContaining({ - httpOnly: false, - expires: expect.any(Date), - path: '/', - sameSite: 'none', - secure: false, - }) - ); - - expect(mockResponse.cookie).toHaveBeenCalledWith( - 'refresh_token', - 'eyJhbGciOiJIUzI1NiJ9.sss.aaaaa', - expect.objectContaining({ - httpOnly: false, - expires: expect.any(Date), - path: '/', - sameSite: 'none', - secure: false, - }) - ); }); it("should call the service's signIn method", async () => { diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index ef3c38b..6c01f35 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -60,21 +60,22 @@ export class AuthController { signInDto.email, signInDto.password ); + console.log(token) + console.log(signInDto.email, + signInDto.password) res.cookie("access_token", token.access_token, { - httpOnly: false, - expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000), - path: "/", - sameSite: "none", + httpOnly: true, secure: false, + sameSite: 'lax', + expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000), }); res.cookie("refresh_token", token.refresh_token, { - httpOnly: false, - expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000), - path: "/", - sameSite: "none", + httpOnly: true, secure: false, + sameSite: 'lax', + expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000) }); return sendResponse( @@ -82,7 +83,7 @@ export class AuthController { HttpStatus.OK, statusMessage[HttpStatus.OK], true, - null + token ); } @@ -100,7 +101,7 @@ export class AuthController { @GetCurrentUser("user") userId: string, @Res() res: Response ) { - const tokens = await this.authService.getTokens(payload); + const token = await this.authService.getTokens(payload); const id: string = uuid(); this.logger.log( "User refresh api called", @@ -110,20 +111,19 @@ export class AuthController { "/refresh", "refreshTokens" ); - res.cookie("access_token", tokens.access_token, { - httpOnly: false, + res.cookie("access_token", token.access_token, { + httpOnly: true, expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000), path: "/", - sameSite: "none", - secure: false, + secure: true, }); - res.cookie("refresh_token", tokens.refresh_token, { - httpOnly: false, + res.cookie("refresh_token", token.refresh_token, { + httpOnly: true, expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000), path: "/", - sameSite: "none", - secure: false, + + secure: true, }); return sendResponse( @@ -131,7 +131,7 @@ export class AuthController { HttpStatus.OK, statusMessage[HttpStatus.OK], true, - null + token ); } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 879b122..ca4e364 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -20,17 +20,21 @@ export class AuthService { const id: string = uuid(); this.logger.log('auth service api called', id, 'auth.service.ts', '', '', 'signIn-service'); const user = await this.usersService.findOneUser(email); + console.log(user) if (!user) { throw new UnauthorizedException('Username and password wrong.'); } const match = await bcrypt.compare(pass, user?.password); + console.log(match) if (match) { const payload = { email: user.email, userId: user._id.toString(), username: user.username }; const tokens = await this.getTokens(payload); return { ...tokens }; + } else { + throw new UnauthorizedException('Username and password wrong.'); } } diff --git a/src/common/guards/at.guard.ts b/src/common/guards/at.guard.ts index ee72a4e..3e7f8d4 100644 --- a/src/common/guards/at.guard.ts +++ b/src/common/guards/at.guard.ts @@ -49,7 +49,7 @@ export class AuthGuard implements CanActivate { let isCookieAuth = `${process.env.IS_COOKIE_AUTH}`; let token = undefined; if (isCookieAuth === "true") { - token = request?.cookies?.refresh_token ?? null; + token = request?.cookies?.access_token ?? null; } else { const [type, tokenValue] = request.headers.authorization?.split(" ") ?? []; diff --git a/src/interface/common.ts b/src/interface/common.ts index 55720ce..556b2b5 100644 --- a/src/interface/common.ts +++ b/src/interface/common.ts @@ -5,9 +5,9 @@ export interface responseData { path?: String; data?: [] | null; message: String, - isSuccess : Boolean, - error: string | null |[] - + isSuccess: Boolean, + error: string | null | [] + } export interface userData { @@ -18,9 +18,12 @@ export interface userData { email?: String; email_code?: String; password?: String; - password_reset_code? :String - _id? : Types.ObjectId | String| null - hashdRt? :String | null + password_reset_code?: String + _id?: Types.ObjectId | String | null + hashdRt?: String | null +} +export interface UserRequest extends Request { + user: any } diff --git a/src/main.ts b/src/main.ts index 881aef2..6016bf8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -40,7 +40,19 @@ async function bootstrap() { SwaggerModule.setup("api", app, document); app.use(helmet()); app.use(cookieParser()); - app.enableCors(); + app.enableCors({ + origin: [ + 'http://localhost:3000', + 'http://example.com', + 'http://www.example.com', + 'http://app.example.com', + 'https://example.com', + 'https://www.example.com', + 'https://app.example.com', + ], + methods: ["GET", "POST"], + credentials: true + }); await app.listen(Number(process.env.PORT) || 3000); console.log(`Application is running on: ${await app.getUrl()}`); } diff --git a/src/roles/roles.controller.spec.ts b/src/roles/roles.controller.spec.ts new file mode 100644 index 0000000..77d1bb2 --- /dev/null +++ b/src/roles/roles.controller.spec.ts @@ -0,0 +1,27 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RolesController } from './roles.controller'; +import { LoggerService } from '../common/service/logger.service'; + +describe('RolesController', () => { + let controller: RolesController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [RolesController], + providers: [ + { + provide: LoggerService, + useValue: { + log: jest.fn(), + }, + } + ], + }).compile(); + + controller = module.get(RolesController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/roles/roles.controller.ts b/src/roles/roles.controller.ts new file mode 100644 index 0000000..d868f26 --- /dev/null +++ b/src/roles/roles.controller.ts @@ -0,0 +1,68 @@ +import { Body, Controller, Get, HttpStatus, Injectable, Post, Res, UseFilters, UsePipes, ValidationPipe, Version } from '@nestjs/common'; +import { Public } from "../common/decorators"; +import { HttpCode } from '@nestjs/common'; +import { LoggerService } from '../common/service/logger.service'; +import { v4 as uuid } from 'uuid'; +import { HttpExceptionFilter } from 'src/utils/http-exception.filter'; +import { statusMessage } from '../constant/statusMessage'; +import { sendResponse } from '../utils/index'; +import { RolesService } from './roles.service'; + + +@Injectable() +@Controller('v1/roles') +export class RolesController { + constructor( + private readonly rolesService :RolesService, + private readonly logger: LoggerService + ) { } + + @Public() + @HttpCode(200) + @Get() + async helloWorld(): Promise { + const id: string = uuid(); + this.logger.log('roles controller called', id, 'roles.controler.ts', 'GET', '/', 'roles'); + return 'Hello World!'; + } + + @Public() + @HttpCode(200) + @UseFilters(new HttpExceptionFilter()) + @UsePipes(new ValidationPipe({ transform: true })) + @Version('1') + @Post('/add') + async addRole(@Body() productDto: any, @Res() res: Response): Promise { + console.log(productDto) + const id: string = uuid(); + this.logger.log('roles controller called', id, 'roles.controler.ts', 'POST', '/', 'roles'); + const prod = await this.rolesService.create(productDto); + return sendResponse( + res, + HttpStatus.OK, + statusMessage[HttpStatus.OK], + true, + null + ); + } + + + @Public() + @HttpCode(200) + @UseFilters(new HttpExceptionFilter()) + @UsePipes(new ValidationPipe({ transform: true })) + @Version('1') + @Get('/list') + async getRoles(@Res() res: Response): Promise { + const id: string = uuid(); + this.logger.log('roles controller called', id, 'roles.controler.ts', 'POST', '/', 'roles'); + const rolesList = await this.rolesService.findAll(); + return sendResponse( + res, + HttpStatus.OK, + statusMessage[HttpStatus.OK], + true, + rolesList + ); + } +} diff --git a/src/roles/roles.module.ts b/src/roles/roles.module.ts new file mode 100644 index 0000000..45277e2 --- /dev/null +++ b/src/roles/roles.module.ts @@ -0,0 +1,22 @@ + +import { Module } from "@nestjs/common"; +import { RolesController } from "./roles.controller"; +import { LoggerService } from "../common/service/logger.service"; +import { RolesService } from "./roles.service"; +import { MongooseModule } from "@nestjs/mongoose"; +import { Roles, RolesSchema } from "./schemas/roles.schema"; + + +@Module({ + imports: [ + MongooseModule.forFeature([ + { name: Roles.name, schema: RolesSchema } + ]), + ], + providers: [ + LoggerService, + RolesService + ], + controllers: [RolesController] +}) +export class roleModule { } diff --git a/src/roles/roles.service.ts b/src/roles/roles.service.ts new file mode 100644 index 0000000..e9de909 --- /dev/null +++ b/src/roles/roles.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from "@nestjs/common"; +import { LoggerService } from '../common/service/logger.service'; +import { InjectModel } from "@nestjs/mongoose"; +import { Model, Types } from "mongoose"; +import { Roles } from "./schemas/roles.schema"; +import { v4 as uuid } from 'uuid'; + +@Injectable() +export class RolesService { + constructor( + @InjectModel(Roles.name) private readonly roleModel: Model, + private readonly logger: LoggerService + ) { } + + async create(product: any): Promise { + const id: string = uuid(); + this.logger.log('Roles service create called', id, 'Roles.service.ts', '', '', 'create-service'); + + const createProduct = await this.roleModel.create(product); + return createProduct; + } + + async findAll(): Promise { + const id: string = uuid(); + this.logger.log('Roles service findall called', id, 'roles.service.ts', '', '', 'findAll-service'); + return this.roleModel.find().exec(); + } + +} diff --git a/src/roles/schemas/roles.schema.ts b/src/roles/schemas/roles.schema.ts new file mode 100644 index 0000000..7e59997 --- /dev/null +++ b/src/roles/schemas/roles.schema.ts @@ -0,0 +1,22 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { HydratedDocument, now } from 'mongoose'; + +export type RolesDocument = HydratedDocument; + +@Schema({ timestamps: true }) +export class Roles { + @Prop({ type: String }) + role_name: string; + @Prop({ type: String }) + description: string; + @Prop({ type: String }) + status: string; + @Prop({ type: Boolean }) + is_admin: { type: Boolean, default: false } + @Prop({ default: now() }) + createdAt: Date; + @Prop({ default: now() }) + updatedAt: Date; +} + +export const RolesSchema = SchemaFactory.createForClass(Roles); \ No newline at end of file diff --git a/src/users/dto/create-user.dto.ts b/src/users/dto/create-user.dto.ts index 618ed08..4ba57ee 100644 --- a/src/users/dto/create-user.dto.ts +++ b/src/users/dto/create-user.dto.ts @@ -5,6 +5,8 @@ import { IsOptional, IsStrongPassword, } from "class-validator"; +import { Modules } from '../../app_module/schemas/modules.schema' +import { Roles } from "../../roles/schemas/roles.schema"; export class CreateUserDto { @ApiProperty({ example: 'testname', description: 'username of the user' }) @@ -39,4 +41,11 @@ export class CreateUserDto { updatedAt?: Date; @ApiProperty({ description: 'Email verification status' }) isEmailVerify?: Boolean; + + @ApiPropertyOptional({ example: 'iiiisskjkjakk', description: 'Roleid ' }) + roles?: Roles + + @ApiPropertyOptional({ example: 'iiiisskjkjakk', description: 'Moduleid ' }) + modules?: Modules + } diff --git a/src/users/schemas/user.schema.ts b/src/users/schemas/user.schema.ts index c5427f4..ba6e665 100644 --- a/src/users/schemas/user.schema.ts +++ b/src/users/schemas/user.schema.ts @@ -1,6 +1,7 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; -import { HydratedDocument, now } from 'mongoose'; - +import mongoose, { HydratedDocument, ObjectId, now } from 'mongoose'; +import { Roles } from '../../roles/schemas/roles.schema'; +import { Modules } from '../../app_module/schemas/modules.schema' export type UserDocument = HydratedDocument; @Schema({ timestamps: true }) @@ -27,6 +28,10 @@ export class User { updatedAt: Date; @Prop({ default: false }) isEmailVerify: Boolean; + @Prop({ type: mongoose.Schema.Types.ObjectId, ref: Roles.name }) + roles: Roles; + @Prop({ type: mongoose.Schema.Types.ObjectId, ref: Modules.name }) + module: Modules; } export const UserSchema = SchemaFactory.createForClass(User); \ No newline at end of file diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 8bfc7e4..b668b97 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -3,7 +3,10 @@ import { Controller, Get, HttpStatus, + Param, Post, + Query, + Req, Res, UseFilters, UseGuards, @@ -14,7 +17,7 @@ import { Public } from "../common/decorators"; import { LoggerService } from '../common/service/logger.service'; import { UserService } from "./users.service"; import { CreateUserDto } from "./dto/create-user.dto"; -import { Response } from "express"; +import { Request, Response } from "express"; import { sendResponse, userErrorResponse, @@ -23,11 +26,12 @@ import { } from "../utils"; import { statusMessage } from "../constant/statusMessage"; import { HttpExceptionFilter } from "../utils/http-exception.filter"; -import { responseData, userData } from "../interface/common"; +import { UserRequest, responseData, userData } from "../interface/common"; import { AuthGuard } from "../common/guards/at.guard"; import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; import { v4 as uuid } from 'uuid'; import { EmailService } from '../common/service/mail.service'; +import mongoose from "mongoose"; @ApiTags("users") @Controller("v1/users") @@ -47,13 +51,18 @@ export class UserController { @UseFilters(new HttpExceptionFilter()) @UsePipes(new ValidationPipe({ transform: true })) async create( - @Body() createCatDto: CreateUserDto, + @Body() createUserDto: CreateUserDto, @Res() res: Response ): Promise { const id: string = uuid(); this.logger.log('User create api called', id, 'users.controler.ts', 'POST', '/users', 'create'); - const user = await this.userService.create(createCatDto); - await this.mailer.sendEmailVerification(user.email, user.email_code) + + const user = await this.userService.create(createUserDto); + const isMAil = process.env.IS_EMAIL + + if (isMAil === "true") { + await this.mailer.sendEmailVerification(user.email, user.email_code) + } return sendResponse( res, HttpStatus.CREATED, @@ -68,6 +77,7 @@ export class UserController { summary: "User List", description: "Get User List", }) + @Public() @ApiResponse(userListSuccessResponse) @ApiResponse({ status: 403, description: "Forbidden." }) @UseGuards(AuthGuard) @@ -85,4 +95,40 @@ export class UserController { userList ); } + + + // get user + @ApiOperation({ + summary: "User List", + description: "Get User List", + }) + @ApiResponse(userListSuccessResponse) + @ApiResponse({ status: 403, description: "Forbidden." }) + @UseGuards(AuthGuard) + @Get('getuser') + @UseFilters(new HttpExceptionFilter()) + async findUser(@Query('userid') name: string, @Req() req: UserRequest, @Res() res: Response): Promise { + const id: string = uuid(); + console.log('=============================================================IN FUNCTION') + this.logger.log('find User api called', id, 'users.controler.ts', 'GET', '/getuser', 'findUser'); + + let userid: string = null; + if (userid) { + userid = userid; + } else { + userid = req.user.sub + } + userid = req.user.sub + let projection = { _id: 1, first_name: 1, last_name: 1, email: 1 } + const userList = await this.userService.findOne(userid, projection); + return sendResponse( + res, + HttpStatus.OK, + statusMessage[HttpStatus.OK], + true, + userList + ); + } + } +// "role_name": "admin", diff --git a/src/users/users.service.ts b/src/users/users.service.ts index ecb01fd..baa7a36 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -35,15 +35,15 @@ export class UserService { async findAll(): Promise { const id: string = uuid(); this.logger.log('User service findall called', id, 'users.service.ts', '', '', 'findAll-service'); - return this.userModel.find().exec(); + return this.userModel.find().populate('roles','role_name').exec(); } - async findOne(id: string): Promise { - return this.userModel.findOne({ _id: id }).exec(); + async findOne(id: string, projection = {}): Promise { + return this.userModel.findOne({ _id: id }, projection).populate('roles','role_name').exec(); } async findOneUser(email: string): Promise { - return this.userModel.findOne({ email: email }).exec(); + return this.userModel.findOne({ email: email }).populate('roles','role_name').exec(); } async delete(id: string) { const deletedUser = await this.userModel