├── .env ├── .env.test ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── README.md ├── docker-compose.yml ├── nest-cli.json ├── package-lock.json ├── package.json ├── prisma ├── migrations │ ├── 20230903131351_ │ │ └── migration.sql │ ├── 20230904120642_ │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma ├── src ├── app.module.ts ├── auth │ ├── auth.controller.ts │ ├── auth.module.ts │ ├── auth.service.ts │ ├── decorator │ │ └── request.decorator.ts │ ├── dist │ │ ├── auth.controller.js │ │ ├── auth.module.js │ │ ├── auth.service.js │ │ └── dist │ │ │ ├── auth.controller.dev.js │ │ │ ├── auth.module.dev.js │ │ │ └── auth.service.dev.js │ ├── dto │ │ ├── auth.dto.ts │ │ ├── dist │ │ │ ├── auth.dto.js │ │ │ ├── dist │ │ │ │ ├── auth.dto.dev.js │ │ │ │ └── index.dev.js │ │ │ └── index.js │ │ └── index.ts │ ├── guard │ │ └── auth.guard.ts │ └── strategy │ │ ├── dist │ │ ├── index.js │ │ └── jwt.strategy.js │ │ ├── index.ts │ │ └── jwt.strategy.ts ├── bookmark │ ├── bookmark.controller.ts │ ├── bookmark.module.ts │ └── bookmark.service.ts ├── main.ts ├── prisma │ ├── prisma.module.ts │ └── prisma.service.ts └── user │ ├── dto │ ├── edit.user.ts │ └── index.ts │ ├── user.controller.ts │ ├── user.module.ts │ └── user.service.ts ├── test ├── app.e2e-spec.ts └── jest-e2e.json ├── tsconfig.build.json └── tsconfig.json /.env: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="postgresql://postgres:sadra35289546@localhost:5434/nest?schema=public" -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="postgresql://postgres:sadra35289546@localhost:5435/nest?schema=public" -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir: __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 6 | [circleci-url]: https://circleci.com/gh/nestjs/nest 7 | 8 |

A progressive Node.js framework for building efficient and scalable server-side applications.

9 |

10 | NPM Version 11 | Package License 12 | NPM Downloads 13 | CircleCI 14 | Coverage 15 | Discord 16 | Backers on Open Collective 17 | Sponsors on Open Collective 18 | 19 | Support us 20 | 21 |

22 | 24 | 25 | ## Description 26 | 27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 28 | 29 | ## Installation 30 | 31 | ```bash 32 | $ npm install 33 | ``` 34 | 35 | ## Running the app 36 | 37 | ```bash 38 | # development 39 | $ npm run start 40 | 41 | # watch mode 42 | $ npm run start:dev 43 | 44 | # production mode 45 | $ npm run start:prod 46 | ``` 47 | 48 | ## Test 49 | 50 | ```bash 51 | # unit tests 52 | $ npm run test 53 | 54 | # e2e tests 55 | $ npm run test:e2e 56 | 57 | # test coverage 58 | $ npm run test:cov 59 | ``` 60 | 61 | ## Support 62 | 63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 64 | 65 | ## Stay in touch 66 | 67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 68 | - Website - [https://nestjs.com](https://nestjs.com/) 69 | - Twitter - [@nestframework](https://twitter.com/nestframework) 70 | 71 | ## License 72 | 73 | Nest is [MIT licensed](LICENSE). 74 | # nest-restapi 75 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | dev-db: 4 | image: postgres:13 5 | ports: 6 | - 5434:5432 7 | environment: 8 | POSTGRES_USER: postgres 9 | POSTGRES_PASSWORD: sadra35289546 10 | POSTGRES_DB: nest 11 | test-db: 12 | image: postgres:13 13 | ports: 14 | - 5435:5432 15 | environment: 16 | POSTGRES_USER: postgres 17 | POSTGRES_PASSWORD: sadra35289546 18 | POSTGRES_DB: nest 19 | -------------------------------------------------------------------------------- /nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rest-api", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "prisma:dev:deploy": " prisma migrate deploy", 10 | "db:dev:up": "sudo docker compose up dev-db -d", 11 | "db:dev:rm": "sudo docker compose rm -s -f -v", 12 | "db:dev:restart": "npm run db:dev:rm && npm run db:dev:up && sleep 1 && run prisma:dev:deploy", 13 | "prisma:test:deploy": "dotenv -e .env.test -- prisma deploy", 14 | "db:test:up": "sudo docker compose up test-db -d", 15 | "db:test:rm": "sudo docker compose rm -s -f -v", 16 | "db:test:restart": "npm run db:test:rm && npm run db:test:up && sleep 1 && run prisma:test:deploy", 17 | "build": "nest build", 18 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 19 | "start": "nest start", 20 | "start:dev": "nest start --watch", 21 | "start:debug": "nest start --debug --watch", 22 | "start:prod": "node dist/main", 23 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 24 | "test": "jest", 25 | "test:watch": "jest --watch", 26 | "test:cov": "jest --coverage", 27 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 28 | "test:e2e": "dotenv -e .env.test -- jest --watch --no--cache --config ./test/jest-e2e.json" 29 | }, 30 | "dependencies": { 31 | "@nestjs/common": "^10.0.0", 32 | "@nestjs/config": "^3.0.1", 33 | "@nestjs/core": "^10.0.0", 34 | "@nestjs/jwt": "^10.1.1", 35 | "@nestjs/passport": "^10.0.1", 36 | "@nestjs/platform-express": "^10.0.0", 37 | "@nestjs/swagger": "^7.1.10", 38 | "@prisma/client": "^5.2.0", 39 | "argon2": "^0.31.1", 40 | "class-transformer": "^0.5.1", 41 | "class-validator": "^0.14.0", 42 | "config": "^3.3.9", 43 | "dotenv-cli": "^7.3.0", 44 | "passport": "^0.6.0", 45 | "passport-jwt": "^4.0.1", 46 | "reflect-metadata": "^0.1.13", 47 | "rxjs": "^7.8.1" 48 | }, 49 | "devDependencies": { 50 | "@nestjs/cli": "^10.0.0", 51 | "@nestjs/schematics": "^10.0.0", 52 | "@nestjs/testing": "^10.0.0", 53 | "@types/express": "^4.17.17", 54 | "@types/jest": "^29.5.2", 55 | "@types/node": "^20.3.1", 56 | "@types/passport-jwt": "^3.0.9", 57 | "@types/supertest": "^2.0.12", 58 | "@typescript-eslint/eslint-plugin": "^6.0.0", 59 | "@typescript-eslint/parser": "^6.0.0", 60 | "eslint": "^8.42.0", 61 | "eslint-config-prettier": "^9.0.0", 62 | "eslint-plugin-prettier": "^5.0.0", 63 | "jest": "^29.5.0", 64 | "nodemon": "^3.0.1", 65 | "prettier": "^3.0.0", 66 | "prisma": "^5.2.0", 67 | "source-map-support": "^0.5.21", 68 | "supertest": "^6.3.3", 69 | "ts-jest": "^29.1.0", 70 | "ts-loader": "^9.4.3", 71 | "ts-node": "^10.9.1", 72 | "tsconfig-paths": "^4.2.0", 73 | "typescript": "^5.1.3" 74 | }, 75 | "jest": { 76 | "moduleFileExtensions": [ 77 | "js", 78 | "json", 79 | "ts" 80 | ], 81 | "rootDir": "src", 82 | "testRegex": ".*\\.spec\\.ts$", 83 | "transform": { 84 | "^.+\\.(t|j)s$": "ts-jest" 85 | }, 86 | "collectCoverageFrom": [ 87 | "**/*.(t|j)s" 88 | ], 89 | "coverageDirectory": "../coverage", 90 | "testEnvironment": "node" 91 | } 92 | } -------------------------------------------------------------------------------- /prisma/migrations/20230903131351_/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "User" ( 3 | "id" SERIAL NOT NULL, 4 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 5 | "updatedAt" TIMESTAMP(3) NOT NULL, 6 | "email" TEXT NOT NULL, 7 | "password" TEXT NOT NULL, 8 | "first_name" TEXT, 9 | "last_name" TEXT, 10 | 11 | CONSTRAINT "User_pkey" PRIMARY KEY ("id") 12 | ); 13 | 14 | -- CreateTable 15 | CREATE TABLE "Bookmark" ( 16 | "id" SERIAL NOT NULL, 17 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 18 | "updatedAt" TIMESTAMP(3) NOT NULL, 19 | "title" TEXT NOT NULL, 20 | "description" TEXT NOT NULL, 21 | "link" TEXT NOT NULL, 22 | 23 | CONSTRAINT "Bookmark_pkey" PRIMARY KEY ("id") 24 | ); 25 | -------------------------------------------------------------------------------- /prisma/migrations/20230904120642_/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[id]` on the table `Bookmark` will be added. If there are existing duplicate values, this will fail. 5 | - A unique constraint covering the columns `[id]` on the table `User` will be added. If there are existing duplicate values, this will fail. 6 | - A unique constraint covering the columns `[email]` on the table `User` will be added. If there are existing duplicate values, this will fail. 7 | - Added the required column `userID` to the `Bookmark` table without a default value. This is not possible if the table is not empty. 8 | 9 | */ 10 | -- AlterTable 11 | ALTER TABLE "Bookmark" ADD COLUMN "userID" INTEGER NOT NULL; 12 | 13 | -- CreateIndex 14 | CREATE UNIQUE INDEX "Bookmark_id_key" ON "Bookmark"("id"); 15 | 16 | -- CreateIndex 17 | CREATE UNIQUE INDEX "User_id_key" ON "User"("id"); 18 | 19 | -- CreateIndex 20 | CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); 21 | 22 | -- AddForeignKey 23 | ALTER TABLE "Bookmark" ADD CONSTRAINT "Bookmark_userID_fkey" FOREIGN KEY ("userID") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 24 | -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "postgresql" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model User { 14 | id Int @id @unique @default(autoincrement()) 15 | createdAt DateTime @default(now()) 16 | updatedAt DateTime @updatedAt 17 | email String @unique 18 | password String 19 | first_name String? 20 | last_name String? 21 | Bookmark Bookmark[] 22 | } 23 | 24 | model Bookmark { 25 | id Int @id @unique @default(autoincrement()) 26 | createdAt DateTime @default(now()) 27 | updatedAt DateTime @updatedAt 28 | title String 29 | description String 30 | link String 31 | userID Int 32 | userDetail User @relation(fields: [userID], references: [id]) 33 | } 34 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AuthModule } from './auth/auth.module'; 3 | import { UserModule } from './user/user.module'; 4 | import { BookmarkModule } from './bookmark/bookmark.module'; 5 | import { PrismaModule } from './prisma/prisma.module'; 6 | import { ConfigModule } from '@nestjs/config'; 7 | 8 | @Module({ 9 | imports: [ 10 | ConfigModule.forRoot({ isGlobal: true }), 11 | AuthModule, 12 | UserModule, 13 | BookmarkModule, 14 | PrismaModule], 15 | }) 16 | export class AppModule { } 17 | -------------------------------------------------------------------------------- /src/auth/auth.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, HttpCode, Post } from "@nestjs/common"; 2 | import { AuthService } from "./auth.service"; 3 | import { AuthDto } from "./dto"; 4 | import { singinDecorator, singupDecorator } from './decorator/request.decorator'; 5 | 6 | @Controller('auth') 7 | export class AuthController { 8 | constructor(private authservice: AuthService) { } 9 | 10 | @singinDecorator() 11 | signup(@Body() dto: AuthDto) { 12 | return this.authservice.signin(dto); 13 | } 14 | 15 | @singupDecorator() 16 | signin(@Body() dto: AuthDto) { 17 | return this.authservice.signup(dto); 18 | } 19 | } -------------------------------------------------------------------------------- /src/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from "@nestjs/common"; 2 | import { AuthController } from "./auth.controller"; 3 | import { AuthService } from "./auth.service"; 4 | import { JwtModule } from "@nestjs/jwt"; 5 | import { JwtStrategy } from './strategy'; 6 | 7 | @Module({ 8 | imports: [JwtModule.register({ secret: "secret_key" })], 9 | controllers: [AuthController], 10 | providers: [AuthService, JwtStrategy] 11 | }) 12 | export class AuthModule { 13 | 14 | } -------------------------------------------------------------------------------- /src/auth/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; 2 | import { PrismaService } from "../prisma/prisma.service"; 3 | import { AuthDto } from "./dto"; 4 | import * as argon from "argon2" 5 | import { PrismaClientKnownRequestError, } from "@prisma/client/runtime/library"; 6 | import { JwtService } from "@nestjs/jwt"; 7 | @Injectable({}) 8 | 9 | export class AuthService { 10 | constructor(private prisma: PrismaService, private jwt: JwtService) { } 11 | async signin(dto: AuthDto): Promise<{ msg: string }> { 12 | try { 13 | const hashPassword = await argon.hash(dto.password); 14 | const userData = { 15 | email: dto.email, 16 | password: hashPassword 17 | } 18 | await this.prisma.user.create({ data: userData }); 19 | return { msg: "user created successfully" }; 20 | } catch (error) { 21 | if (error instanceof PrismaClientKnownRequestError) 22 | if (error.code == "P2002") { 23 | throw new ForbiddenException("email has been already registered") 24 | } 25 | throw error 26 | } 27 | } 28 | async signup(dto: AuthDto): Promise { 29 | const user = await this.prisma.user.findFirst({ where: { email: dto.email } }); 30 | if (!user) throw new NotFoundException({ msg: "user not found" }); 31 | const pwCompare = await argon.verify(user.password, dto.password); 32 | if (!pwCompare) throw new ForbiddenException("email or password is invalid"); 33 | return this.singToken(user.id, user.email); 34 | } 35 | async singToken(userId: number, userEmail: string) { 36 | const payload = { 37 | sub: userId, 38 | email: userEmail 39 | }; 40 | const token = await this.jwt.signAsync(payload, { 41 | expiresIn: "1h" 42 | }); 43 | return token 44 | } 45 | } -------------------------------------------------------------------------------- /src/auth/decorator/request.decorator.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext, HttpCode, Post, applyDecorators, createParamDecorator, Request } from '@nestjs/common'; 2 | import { ApiResponse, ApiTags } from "@nestjs/swagger" 3 | 4 | export function singinDecorator() { 5 | return applyDecorators( 6 | ApiTags("auth"), 7 | ApiResponse({ status: 201, description: "user created successfully" }), 8 | ApiResponse({ status: 403, description: "internal server error" }), 9 | Post('signup'), 10 | HttpCode(201), 11 | ) 12 | } 13 | export function singupDecorator() { 14 | return applyDecorators( 15 | ApiTags("auth"), 16 | ApiResponse({ status: 201, description: "user created successfully" }), 17 | ApiResponse({ status: 403, description: "internal server error" }), 18 | Post('signin'), 19 | HttpCode(200) 20 | ) 21 | } 22 | export const GetUser = createParamDecorator( 23 | ( 24 | data: string | undefined, 25 | ctx: ExecutionContext 26 | ) => { 27 | const request: Express.Request = ctx.switchToHttp().getRequest(); 28 | if (data) { 29 | return request.user[data]; 30 | } 31 | return request.user; 32 | 33 | }) -------------------------------------------------------------------------------- /src/auth/dist/auth.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __param = (this && this.__param) || function (paramIndex, decorator) { 9 | return function (target, key) { decorator(target, key, paramIndex); } 10 | }; 11 | exports.__esModule = true; 12 | exports.AuthController = void 0; 13 | var common_1 = require("@nestjs/common"); 14 | var swagger_1 = require("@nestjs/swagger"); 15 | var AuthController = /** @class */ (function () { 16 | function AuthController(authservice) { 17 | this.authservice = authservice; 18 | } 19 | AuthController.prototype.signup = function (dto) { 20 | return this.authservice.signin(dto); 21 | }; 22 | AuthController.prototype.signin = function (dto) { 23 | return this.authservice.signup(dto); 24 | }; 25 | __decorate([ 26 | swagger_1.ApiTags("auth"), 27 | swagger_1.ApiResponse({ status: 201, description: "user created successfully" }), 28 | swagger_1.ApiResponse({ status: 403, description: "internal server error" }), 29 | common_1.Post('signup'), 30 | common_1.HttpCode(201), 31 | __param(0, common_1.Body()) 32 | ], AuthController.prototype, "signup"); 33 | __decorate([ 34 | common_1.Post('signin'), 35 | common_1.HttpCode(200), 36 | __param(0, common_1.Body()) 37 | ], AuthController.prototype, "signin"); 38 | AuthController = __decorate([ 39 | common_1.Controller('auth') 40 | ], AuthController); 41 | return AuthController; 42 | }()); 43 | exports.AuthController = AuthController; 44 | -------------------------------------------------------------------------------- /src/auth/dist/auth.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | exports.__esModule = true; 9 | exports.AuthModule = void 0; 10 | var common_1 = require("@nestjs/common"); 11 | var auth_controller_1 = require("./auth.controller"); 12 | var auth_service_1 = require("./auth.service"); 13 | var jwt_1 = require("@nestjs/jwt"); 14 | var strategy_1 = require("./strategy"); 15 | var AuthModule = /** @class */ (function () { 16 | function AuthModule() { 17 | } 18 | AuthModule = __decorate([ 19 | common_1.Module({ 20 | imports: [jwt_1.JwtModule.register({ secret: "secret_key" })], 21 | controllers: [auth_controller_1.AuthController], 22 | providers: [auth_service_1.AuthService, strategy_1.JwtStrategy] 23 | }) 24 | ], AuthModule); 25 | return AuthModule; 26 | }()); 27 | exports.AuthModule = AuthModule; 28 | -------------------------------------------------------------------------------- /src/auth/dist/auth.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 9 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 10 | return new (P || (P = Promise))(function (resolve, reject) { 11 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 12 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 13 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 14 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 15 | }); 16 | }; 17 | var __generator = (this && this.__generator) || function (thisArg, body) { 18 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 19 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 20 | function verb(n) { return function (v) { return step([n, v]); }; } 21 | function step(op) { 22 | if (f) throw new TypeError("Generator is already executing."); 23 | while (_) try { 24 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 25 | if (y = 0, t) op = [op[0] & 2, t.value]; 26 | switch (op[0]) { 27 | case 0: case 1: t = op; break; 28 | case 4: _.label++; return { value: op[1], done: false }; 29 | case 5: _.label++; y = op[1]; op = [0]; continue; 30 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 31 | default: 32 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 33 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 34 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 35 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 36 | if (t[2]) _.ops.pop(); 37 | _.trys.pop(); continue; 38 | } 39 | op = body.call(thisArg, _); 40 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 41 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 42 | } 43 | }; 44 | exports.__esModule = true; 45 | exports.AuthService = void 0; 46 | var common_1 = require("@nestjs/common"); 47 | var argon = require("argon2"); 48 | var library_1 = require("@prisma/client/runtime/library"); 49 | var AuthService = /** @class */ (function () { 50 | function AuthService(prisma, jwt) { 51 | this.prisma = prisma; 52 | this.jwt = jwt; 53 | } 54 | AuthService.prototype.signin = function (dto) { 55 | return __awaiter(this, void 0, Promise, function () { 56 | var hashPassword, userData, error_1; 57 | return __generator(this, function (_a) { 58 | switch (_a.label) { 59 | case 0: 60 | _a.trys.push([0, 3, , 4]); 61 | return [4 /*yield*/, argon.hash(dto.password)]; 62 | case 1: 63 | hashPassword = _a.sent(); 64 | userData = { 65 | email: dto.email, 66 | password: hashPassword 67 | }; 68 | return [4 /*yield*/, this.prisma.user.create({ data: userData })]; 69 | case 2: 70 | _a.sent(); 71 | return [2 /*return*/, { msg: "user created successfully" }]; 72 | case 3: 73 | error_1 = _a.sent(); 74 | if (error_1 instanceof library_1.PrismaClientKnownRequestError) 75 | if (error_1.code == "P2002") { 76 | throw new common_1.ForbiddenException("email has been already registered"); 77 | } 78 | throw error_1; 79 | case 4: return [2 /*return*/]; 80 | } 81 | }); 82 | }); 83 | }; 84 | AuthService.prototype.signup = function (dto) { 85 | return __awaiter(this, void 0, Promise, function () { 86 | var user, pwCompare; 87 | return __generator(this, function (_a) { 88 | switch (_a.label) { 89 | case 0: return [4 /*yield*/, this.prisma.user.findFirst({ where: { email: dto.email } })]; 90 | case 1: 91 | user = _a.sent(); 92 | if (!user) 93 | throw new common_1.NotFoundException({ msg: "user not found" }); 94 | return [4 /*yield*/, argon.verify(user.password, dto.password)]; 95 | case 2: 96 | pwCompare = _a.sent(); 97 | if (!pwCompare) 98 | throw new common_1.ForbiddenException("email or password is invalid"); 99 | return [2 /*return*/, this.singToken(user.id, user.email)]; 100 | } 101 | }); 102 | }); 103 | }; 104 | AuthService.prototype.singToken = function (userId, userEmail) { 105 | return __awaiter(this, void 0, void 0, function () { 106 | var payload, token; 107 | return __generator(this, function (_a) { 108 | switch (_a.label) { 109 | case 0: 110 | payload = { 111 | sub: userId, 112 | username: userEmail 113 | }; 114 | return [4 /*yield*/, this.jwt.signAsync(payload, { 115 | secret: "secret", 116 | expiresIn: "1h" 117 | })]; 118 | case 1: 119 | token = _a.sent(); 120 | return [2 /*return*/, token]; 121 | } 122 | }); 123 | }); 124 | }; 125 | AuthService = __decorate([ 126 | common_1.Injectable({}) 127 | ], AuthService); 128 | return AuthService; 129 | }()); 130 | exports.AuthService = AuthService; 131 | -------------------------------------------------------------------------------- /src/auth/dist/dist/auth.controller.dev.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | var __decorate = void 0 && (void 0).__decorate || function (decorators, target, key, desc) { 6 | var c = arguments.length, 7 | r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, 8 | d; 9 | if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) { 10 | if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 11 | } 12 | return c > 3 && r && Object.defineProperty(target, key, r), r; 13 | }; 14 | 15 | var __param = void 0 && (void 0).__param || function (paramIndex, decorator) { 16 | return function (target, key) { 17 | decorator(target, key, paramIndex); 18 | }; 19 | }; 20 | 21 | exports.__esModule = true; 22 | exports.AuthController = void 0; 23 | 24 | var common_1 = require("@nestjs/common"); 25 | 26 | var AuthController = 27 | /** @class */ 28 | function () { 29 | function AuthController(authservice) { 30 | this.authservice = authservice; 31 | } 32 | 33 | AuthController.prototype.signup = function (dto) { 34 | return this.authservice.signin(dto); 35 | }; 36 | 37 | AuthController.prototype.signin = function (dto) { 38 | return this.authservice.signup(dto); 39 | }; 40 | 41 | __decorate([common_1.Post('signup'), common_1.HttpCode(201), __param(0, common_1.Body())], AuthController.prototype, "signup"); 42 | 43 | __decorate([common_1.Post('signin'), common_1.HttpCode(200), __param(0, common_1.Body())], AuthController.prototype, "signin"); 44 | 45 | AuthController = __decorate([common_1.Controller('auth')], AuthController); 46 | return AuthController; 47 | }(); 48 | 49 | exports.AuthController = AuthController; -------------------------------------------------------------------------------- /src/auth/dist/dist/auth.module.dev.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | var __decorate = void 0 && (void 0).__decorate || function (decorators, target, key, desc) { 6 | var c = arguments.length, 7 | r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, 8 | d; 9 | if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) { 10 | if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 11 | } 12 | return c > 3 && r && Object.defineProperty(target, key, r), r; 13 | }; 14 | 15 | exports.__esModule = true; 16 | exports.AuthModule = void 0; 17 | 18 | var common_1 = require("@nestjs/common"); 19 | 20 | var auth_controller_1 = require("./auth.controller"); 21 | 22 | var auth_service_1 = require("./auth.service"); 23 | 24 | var jwt_1 = require("@nestjs/jwt"); 25 | 26 | var AuthModule = 27 | /** @class */ 28 | function () { 29 | function AuthModule() {} 30 | 31 | AuthModule = __decorate([common_1.Module({ 32 | controllers: [auth_controller_1.AuthController], 33 | providers: [auth_service_1.AuthService], 34 | exports: [jwt_1.JwtModule.register({ 35 | secret: "secret_key" 36 | })] 37 | })], AuthModule); 38 | return AuthModule; 39 | }(); 40 | 41 | exports.AuthModule = AuthModule; -------------------------------------------------------------------------------- /src/auth/dist/dist/auth.service.dev.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | var __decorate = void 0 && (void 0).__decorate || function (decorators, target, key, desc) { 6 | var c = arguments.length, 7 | r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, 8 | d; 9 | if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) { 10 | if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 11 | } 12 | return c > 3 && r && Object.defineProperty(target, key, r), r; 13 | }; 14 | 15 | var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) { 16 | function adopt(value) { 17 | return value instanceof P ? value : new P(function (resolve) { 18 | resolve(value); 19 | }); 20 | } 21 | 22 | return new (P || (P = Promise))(function (resolve, reject) { 23 | function fulfilled(value) { 24 | try { 25 | step(generator.next(value)); 26 | } catch (e) { 27 | reject(e); 28 | } 29 | } 30 | 31 | function rejected(value) { 32 | try { 33 | step(generator["throw"](value)); 34 | } catch (e) { 35 | reject(e); 36 | } 37 | } 38 | 39 | function step(result) { 40 | result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); 41 | } 42 | 43 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 44 | }); 45 | }; 46 | 47 | var __generator = void 0 && (void 0).__generator || function (thisArg, body) { 48 | var _ = { 49 | label: 0, 50 | sent: function sent() { 51 | if (t[0] & 1) throw t[1]; 52 | return t[1]; 53 | }, 54 | trys: [], 55 | ops: [] 56 | }, 57 | f, 58 | y, 59 | t, 60 | g; 61 | return g = { 62 | next: verb(0), 63 | "throw": verb(1), 64 | "return": verb(2) 65 | }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { 66 | return this; 67 | }), g; 68 | 69 | function verb(n) { 70 | return function (v) { 71 | return step([n, v]); 72 | }; 73 | } 74 | 75 | function step(op) { 76 | if (f) throw new TypeError("Generator is already executing."); 77 | 78 | while (_) { 79 | try { 80 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 81 | if (y = 0, t) op = [op[0] & 2, t.value]; 82 | 83 | switch (op[0]) { 84 | case 0: 85 | case 1: 86 | t = op; 87 | break; 88 | 89 | case 4: 90 | _.label++; 91 | return { 92 | value: op[1], 93 | done: false 94 | }; 95 | 96 | case 5: 97 | _.label++; 98 | y = op[1]; 99 | op = [0]; 100 | continue; 101 | 102 | case 7: 103 | op = _.ops.pop(); 104 | 105 | _.trys.pop(); 106 | 107 | continue; 108 | 109 | default: 110 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { 111 | _ = 0; 112 | continue; 113 | } 114 | 115 | if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { 116 | _.label = op[1]; 117 | break; 118 | } 119 | 120 | if (op[0] === 6 && _.label < t[1]) { 121 | _.label = t[1]; 122 | t = op; 123 | break; 124 | } 125 | 126 | if (t && _.label < t[2]) { 127 | _.label = t[2]; 128 | 129 | _.ops.push(op); 130 | 131 | break; 132 | } 133 | 134 | if (t[2]) _.ops.pop(); 135 | 136 | _.trys.pop(); 137 | 138 | continue; 139 | } 140 | 141 | op = body.call(thisArg, _); 142 | } catch (e) { 143 | op = [6, e]; 144 | y = 0; 145 | } finally { 146 | f = t = 0; 147 | } 148 | } 149 | 150 | if (op[0] & 5) throw op[1]; 151 | return { 152 | value: op[0] ? op[1] : void 0, 153 | done: true 154 | }; 155 | } 156 | }; 157 | 158 | exports.__esModule = true; 159 | exports.AuthService = void 0; 160 | 161 | var common_1 = require("@nestjs/common"); 162 | 163 | var argon = require("argon2"); 164 | 165 | var library_1 = require("@prisma/client/runtime/library"); 166 | 167 | var AuthService = 168 | /** @class */ 169 | function () { 170 | function AuthService(prisma, jwt) { 171 | this.prisma = prisma; 172 | this.jwt = jwt; 173 | } 174 | 175 | AuthService.prototype.signin = function (dto) { 176 | return __awaiter(this, void 0, Promise, function () { 177 | var hashPassword, userData, error_1; 178 | return __generator(this, function (_a) { 179 | switch (_a.label) { 180 | case 0: 181 | _a.trys.push([0, 3,, 4]); 182 | 183 | return [4 184 | /*yield*/ 185 | , argon.hash(dto.password)]; 186 | 187 | case 1: 188 | hashPassword = _a.sent(); 189 | userData = { 190 | email: dto.email, 191 | password: hashPassword 192 | }; 193 | return [4 194 | /*yield*/ 195 | , this.prisma.user.create({ 196 | data: userData 197 | })]; 198 | 199 | case 2: 200 | _a.sent(); 201 | 202 | return [2 203 | /*return*/ 204 | , { 205 | msg: "user created successfully" 206 | }]; 207 | 208 | case 3: 209 | error_1 = _a.sent(); 210 | if (error_1 instanceof library_1.PrismaClientKnownRequestError) if (error_1.code == "P2002") { 211 | throw new common_1.ForbiddenException("email has been already registered"); 212 | } 213 | throw error_1; 214 | 215 | case 4: 216 | return [2 217 | /*return*/ 218 | ]; 219 | } 220 | }); 221 | }); 222 | }; 223 | 224 | AuthService.prototype.signup = function (dto) { 225 | return __awaiter(this, void 0, Promise, function () { 226 | var user, pwCompare; 227 | return __generator(this, function (_a) { 228 | switch (_a.label) { 229 | case 0: 230 | return [4 231 | /*yield*/ 232 | , this.prisma.user.findFirst({ 233 | where: { 234 | email: dto.email 235 | } 236 | })]; 237 | 238 | case 1: 239 | user = _a.sent(); 240 | if (!user) throw new common_1.NotFoundException({ 241 | msg: "user not found" 242 | }); 243 | return [4 244 | /*yield*/ 245 | , argon.verify(user.password, dto.password)]; 246 | 247 | case 2: 248 | pwCompare = _a.sent(); 249 | if (!pwCompare) throw new common_1.ForbiddenException("email or password is invalid"); 250 | return [2 251 | /*return*/ 252 | , this.singToken(user.id, user.email)]; 253 | } 254 | }); 255 | }); 256 | }; 257 | 258 | AuthService.prototype.singToken = function (userId, userEmail) { 259 | return __awaiter(this, void 0, void 0, function () { 260 | var payload, token; 261 | return __generator(this, function (_a) { 262 | switch (_a.label) { 263 | case 0: 264 | payload = { 265 | sub: userId, 266 | username: userEmail 267 | }; 268 | return [4 269 | /*yield*/ 270 | , this.jwt.signAsync(payload, { 271 | secret: "secret", 272 | expiresIn: "1h" 273 | })]; 274 | 275 | case 1: 276 | token = _a.sent(); 277 | return [2 278 | /*return*/ 279 | , token]; 280 | } 281 | }); 282 | }); 283 | }; 284 | 285 | AuthService = __decorate([common_1.Injectable({})], AuthService); 286 | return AuthService; 287 | }(); 288 | 289 | exports.AuthService = AuthService; -------------------------------------------------------------------------------- /src/auth/dto/auth.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from "@nestjs/swagger"; 2 | import { IsEmail, IsNotEmpty, IsString } from "class-validator"; 3 | 4 | export class AuthDto { 5 | @ApiProperty({ example: "email@email.com" }) 6 | @IsNotEmpty() 7 | @IsEmail() 8 | email: string; 9 | 10 | @ApiProperty({ example: "myPassword" }) 11 | @IsString() 12 | @IsNotEmpty() 13 | password: string 14 | 15 | } -------------------------------------------------------------------------------- /src/auth/dto/dist/auth.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | exports.__esModule = true; 9 | exports.AuthDto = void 0; 10 | var swagger_1 = require("@nestjs/swagger"); 11 | var class_validator_1 = require("class-validator"); 12 | var AuthDto = /** @class */ (function () { 13 | function AuthDto() { 14 | } 15 | __decorate([ 16 | swagger_1.ApiProperty({ example: "email@email.com" }), 17 | class_validator_1.IsNotEmpty(), 18 | class_validator_1.IsEmail() 19 | ], AuthDto.prototype, "email"); 20 | __decorate([ 21 | swagger_1.ApiProperty({ example: "myPassword" }), 22 | class_validator_1.IsString(), 23 | class_validator_1.IsNotEmpty() 24 | ], AuthDto.prototype, "password"); 25 | return AuthDto; 26 | }()); 27 | exports.AuthDto = AuthDto; 28 | -------------------------------------------------------------------------------- /src/auth/dto/dist/dist/auth.dto.dev.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | var __decorate = void 0 && (void 0).__decorate || function (decorators, target, key, desc) { 6 | var c = arguments.length, 7 | r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, 8 | d; 9 | if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) { 10 | if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 11 | } 12 | return c > 3 && r && Object.defineProperty(target, key, r), r; 13 | }; 14 | 15 | exports.__esModule = true; 16 | exports.AuthDto = void 0; 17 | 18 | var class_validator_1 = require("class-validator"); 19 | 20 | var AuthDto = 21 | /** @class */ 22 | function () { 23 | function AuthDto() {} 24 | 25 | __decorate([class_validator_1.IsNotEmpty(), class_validator_1.IsEmail()], AuthDto.prototype, "email"); 26 | 27 | __decorate([class_validator_1.IsString(), class_validator_1.IsNotEmpty()], AuthDto.prototype, "password"); 28 | 29 | return AuthDto; 30 | }(); 31 | 32 | exports.AuthDto = AuthDto; -------------------------------------------------------------------------------- /src/auth/dto/dist/dist/index.dev.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { 4 | if (k2 === undefined) k2 = k; 5 | Object.defineProperty(o, k2, { 6 | enumerable: true, 7 | get: function get() { 8 | return m[k]; 9 | } 10 | }); 11 | } : function (o, m, k, k2) { 12 | if (k2 === undefined) k2 = k; 13 | o[k2] = m[k]; 14 | }); 15 | 16 | var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { 17 | for (var p in m) { 18 | if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); 19 | } 20 | }; 21 | 22 | exports.__esModule = true; 23 | 24 | __exportStar(require("./auth.dto"), exports); -------------------------------------------------------------------------------- /src/auth/dto/dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 10 | for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); 11 | }; 12 | exports.__esModule = true; 13 | __exportStar(require("./auth.dto"), exports); 14 | -------------------------------------------------------------------------------- /src/auth/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./auth.dto" -------------------------------------------------------------------------------- /src/auth/guard/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Injectable, 3 | } from '@nestjs/common'; 4 | import { AuthGuard } from '@nestjs/passport'; 5 | 6 | 7 | @Injectable() 8 | export class JwtGuard extends AuthGuard('jwt') { 9 | constructor() { 10 | super(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/auth/strategy/dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 5 | }) : (function(o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | o[k2] = m[k]; 8 | })); 9 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 10 | for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); 11 | }; 12 | exports.__esModule = true; 13 | __exportStar(require("./jwt.strategy"), exports); 14 | -------------------------------------------------------------------------------- /src/auth/strategy/dist/jwt.strategy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 16 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 17 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 18 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 19 | return c > 3 && r && Object.defineProperty(target, key, r), r; 20 | }; 21 | exports.__esModule = true; 22 | exports.JwtStrategy = void 0; 23 | var common_1 = require("@nestjs/common"); 24 | var passport_1 = require("@nestjs/passport"); 25 | var passport_jwt_1 = require("passport-jwt"); 26 | var JwtStrategy = /** @class */ (function (_super) { 27 | __extends(JwtStrategy, _super); 28 | function JwtStrategy() { 29 | return _super.call(this, { 30 | jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(), 31 | secretOrKey: 'JWT_SECRET' 32 | }) || this; 33 | } 34 | JwtStrategy.prototype.validation = function (payload) { 35 | console.log(payload); 36 | }; 37 | JwtStrategy = __decorate([ 38 | common_1.Injectable() 39 | ], JwtStrategy); 40 | return JwtStrategy; 41 | }(passport_1.PassportStrategy(passport_jwt_1.Strategy, 'jwt'))); 42 | exports.JwtStrategy = JwtStrategy; 43 | -------------------------------------------------------------------------------- /src/auth/strategy/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./jwt.strategy" -------------------------------------------------------------------------------- /src/auth/strategy/jwt.strategy.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@nestjs/common"; 2 | import { PassportStrategy } from "@nestjs/passport"; 3 | import { ExtractJwt, Strategy } from "passport-jwt"; 4 | import { PrismaService } from "../../prisma/prisma.service"; 5 | 6 | @Injectable() 7 | export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { 8 | constructor(private prisma: PrismaService) { 9 | super({ 10 | jwtFromRequest: 11 | ExtractJwt.fromAuthHeaderAsBearerToken(), 12 | secretOrKey: 'secret_key' 13 | }) 14 | } 15 | async validate(payload: { 16 | sub: number; 17 | email: string; 18 | }) { 19 | const user = await this.prisma.user.findMany( 20 | { 21 | where: 22 | { email: payload.email, id: payload.sub }, 23 | select: 24 | { id: true, email: true, first_name: true, last_name: true, Bookmark: true } 25 | }) 26 | return user; 27 | } 28 | } -------------------------------------------------------------------------------- /src/bookmark/bookmark.controller.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sadrax4/nest-restapi/dee9b156453ccb6f949a80bd83b5e38b36f631b8/src/bookmark/bookmark.controller.ts -------------------------------------------------------------------------------- /src/bookmark/bookmark.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | @Module({}) 4 | export class BookmarkModule {} 5 | -------------------------------------------------------------------------------- /src/bookmark/bookmark.service.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sadrax4/nest-restapi/dee9b156453ccb6f949a80bd83b5e38b36f631b8/src/bookmark/bookmark.service.ts -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | import { ValidationPipe } from '@nestjs/common'; 4 | import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; 5 | 6 | async function app() { 7 | const app = await NestFactory.create(AppModule); 8 | const config = new DocumentBuilder() 9 | .addBearerAuth() 10 | .setTitle('CRUD Api') 11 | .setDescription('the documentation of crud api') 12 | .setVersion('1.0') 13 | .addTag("auth") 14 | .addTag("user") 15 | .build(); 16 | const document = SwaggerModule.createDocument(app, config); 17 | SwaggerModule.setup('api', app, document); 18 | app.useGlobalPipes(new ValidationPipe({ 19 | whitelist: true 20 | })) 21 | await app.listen(3000); 22 | } 23 | app(); 24 | -------------------------------------------------------------------------------- /src/prisma/prisma.module.ts: -------------------------------------------------------------------------------- 1 | import { Global, Module } from '@nestjs/common'; 2 | import { PrismaService } from './prisma.service'; 3 | import { PrismaClient } from '@prisma/client'; 4 | 5 | @Global() 6 | @Module({ 7 | providers: [PrismaService], 8 | exports: [PrismaService] 9 | }) 10 | export class PrismaModule extends PrismaClient { 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/prisma/prisma.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { ConfigService } from '@nestjs/config'; 3 | import { PrismaClient } from '@prisma/client'; 4 | 5 | @Injectable() 6 | export class PrismaService extends PrismaClient { 7 | constructor(config: ConfigService) { 8 | super({ 9 | datasources: { 10 | db: { 11 | url: config.get("DATABASE_URL") 12 | } 13 | } 14 | } 15 | ) 16 | } 17 | cleanDb() { 18 | return this.$transaction([ 19 | this.user.deleteMany(), 20 | this.bookmark.deleteMany(), 21 | ]) 22 | } 23 | } -------------------------------------------------------------------------------- /src/user/dto/edit.user.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString, Max, MaxLength, Min, MinLength } from "class-validator"; 2 | 3 | export class EditUser { 4 | 5 | @IsString() 6 | @MinLength(2) 7 | @MaxLength(10) 8 | @IsNotEmpty() 9 | first_name: string 10 | 11 | 12 | @IsString() 13 | @MinLength(2) 14 | @MaxLength(10) 15 | @IsNotEmpty() 16 | last_name: string 17 | } 18 | -------------------------------------------------------------------------------- /src/user/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./edit.user" -------------------------------------------------------------------------------- /src/user/user.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, Get, Post, Res, Response, UseGuards } from "@nestjs/common"; 2 | import { JwtGuard } from "../auth/guard/auth.guard"; 3 | import { UserService } from './user.service'; 4 | import { GetUser } from "src/auth/decorator/request.decorator"; 5 | import { User } from "@prisma/client"; 6 | import { EditUser } from "./dto"; 7 | 8 | @UseGuards(JwtGuard) 9 | @Controller("user") 10 | export class UserController { 11 | constructor(private userService: UserService) { } 12 | @Get("profile") 13 | profile(@GetUser() user: User): User { 14 | return user; 15 | } 16 | 17 | @Post("edit") 18 | editProfile(@Body() dto: EditUser, @GetUser() user: User) { 19 | return this.userService.editUser(dto, user.id); 20 | } 21 | 22 | @Get("list") 23 | getUserList() { 24 | return this.userService.getUserList() 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { UserService } from './user.service'; 3 | import { UserController } from './user.controller'; 4 | import { JwtModule } from '@nestjs/jwt'; 5 | 6 | @Module({ 7 | imports: [JwtModule.register({ secret: "secret_key" })], 8 | controllers: [UserController], 9 | providers: [UserService] 10 | }) 11 | export class UserModule { } 12 | -------------------------------------------------------------------------------- /src/user/user.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, InternalServerErrorException } from "@nestjs/common"; 2 | import { PrismaService } from "src/prisma/prisma.service"; 3 | import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library"; 4 | import { User } from "@prisma/client"; 5 | import { EditUser } from "./dto"; 6 | 7 | @Injectable() 8 | export class UserService { 9 | constructor(private prisma: PrismaService) { } 10 | async editUser(dto: EditUser, userID: number): Promise<{ msg: string }> { 11 | try { 12 | await this.prisma.user.update({ 13 | where: { 14 | id: userID 15 | }, 16 | data: { 17 | first_name: dto.first_name, 18 | last_name: dto.last_name 19 | } 20 | }) 21 | return { msg: "user updated successfully" } 22 | } catch (error) { 23 | if (error instanceof PrismaClientKnownRequestError) 24 | if (error.code === 'P2025') 25 | throw new InternalServerErrorException("Update failed"); 26 | } 27 | } 28 | async getUserList(): Promise { 29 | const users = await this.prisma.user.findMany(); 30 | users.map(user => { 31 | delete user.password; 32 | }) 33 | return users; 34 | } 35 | } -------------------------------------------------------------------------------- /test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test } from '@nestjs/testing'; 2 | import { AppModule } from '../src/app.module'; 3 | import { INestApplication, ValidationPipe } from '@nestjs/common'; 4 | import { PrismaService } from '../src/prisma/prisma.service'; 5 | 6 | describe("app e2e", () => { 7 | let app: INestApplication; 8 | let prisma: PrismaService; 9 | beforeAll(async () => { 10 | const moduleRef = await Test.createTestingModule( 11 | { 12 | imports: [AppModule] 13 | }).compile(); 14 | app = moduleRef.createNestApplication(); 15 | app.useGlobalPipes(new ValidationPipe({ 16 | whitelist: true 17 | })) 18 | await app.init(); 19 | prisma = app.get(PrismaService); 20 | await prisma.cleanDb(); 21 | }) 22 | afterAll(() => { 23 | app.close(); 24 | }) 25 | it.todo("should be pass") 26 | }) -------------------------------------------------------------------------------- /test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "ES2021", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | --------------------------------------------------------------------------------