├── .editorconfig ├── .env.example ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .gitkeep ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── inspectionProfiles │ └── Project_Default.xml ├── modules.xml ├── talent.iml └── vcs.xml ├── .lintstagedrc.json ├── .prettierrc ├── .vscode ├── launch.json └── settings.json ├── Makefile ├── README.md ├── dist ├── app.d.ts ├── app.js ├── app.js.map ├── configs │ ├── development.json │ ├── env │ │ ├── dev.env.json │ │ └── prod.env.json │ ├── index.d.ts │ ├── index.js │ ├── index.js.map │ ├── production.json │ └── test.json ├── controllers │ ├── auth.controller.d.ts │ ├── auth.controller.js │ ├── auth.controller.js.map │ ├── index.controller.d.ts │ ├── index.controller.js │ ├── index.controller.js.map │ ├── users.controller.d.ts │ ├── users.controller.js │ └── users.controller.js.map ├── dtos │ ├── users.dto.d.ts │ ├── users.dto.js │ └── users.dto.js.map ├── exceptions │ ├── HttpException.d.ts │ ├── HttpException.js │ └── HttpException.js.map ├── interfaces │ ├── auth.interface.d.ts │ ├── auth.interface.js │ ├── auth.interface.js.map │ ├── routes.interface.d.ts │ ├── routes.interface.js │ └── routes.interface.js.map ├── logs │ ├── debug │ │ ├── .0fdd8272eea6e3a3e30364131bac1064b6ee2ba6-audit.json │ │ └── 2021-06-08.log │ └── error │ │ ├── .f794145503009200c1d8831dcc5d151993851e5a-audit.json │ │ └── 2021-06-08.log ├── middlewares │ ├── auth.middleware.d.ts │ ├── auth.middleware.js │ ├── auth.middleware.js.map │ ├── error.middleware.d.ts │ ├── error.middleware.js │ ├── error.middleware.js.map │ ├── validation.middleware.d.ts │ ├── validation.middleware.js │ └── validation.middleware.js.map ├── routes │ ├── auth.route.d.ts │ ├── auth.route.js │ ├── auth.route.js.map │ ├── index.route.d.ts │ ├── index.route.js │ ├── index.route.js.map │ ├── users.route.d.ts │ ├── users.route.js │ └── users.route.js.map ├── server.d.ts ├── server.js ├── server.js.map ├── services │ ├── auth.service.d.ts │ ├── auth.service.js │ ├── auth.service.js.map │ ├── mail.service.d.ts │ ├── mail.service.js │ ├── mail.service.js.map │ ├── users.service.d.ts │ ├── users.service.js │ └── users.service.js.map ├── tests │ ├── auth.test.d.ts │ ├── auth.test.js │ ├── auth.test.js.map │ ├── index.test.d.ts │ ├── index.test.js │ ├── index.test.js.map │ ├── users.test.d.ts │ ├── users.test.js │ └── users.test.js.map └── utils │ ├── logger.d.ts │ ├── logger.js │ ├── logger.js.map │ ├── util.d.ts │ ├── util.js │ ├── util.js.map │ ├── validateEnv.d.ts │ ├── validateEnv.js │ └── validateEnv.js.map ├── jest.config.js ├── nodemon.json ├── package-lock.json ├── package.json ├── prisma ├── .gitignore ├── migrations │ └── migration_lock.toml └── schema.prisma ├── src ├── app.ts ├── configs │ ├── development.json │ ├── production.json │ └── test.json ├── controllers │ ├── auth.controller.ts │ ├── index.controller.ts │ ├── post.controller.ts │ └── users.controller.ts ├── dtos │ ├── post.dto.ts │ └── users.dto.ts ├── exceptions │ └── HttpException.ts ├── interfaces │ ├── auth.interface.ts │ └── routes.interface.ts ├── logs │ ├── debug │ │ ├── .97c8ad83eeb58d63df9ef18134f1cead3fa43941-audit.json │ │ └── 2021-06-08.log │ └── error │ │ ├── .2b1b4f2f1d0bbd27a23e3aee5c4dd77c3dfabd17-audit.json │ │ └── 2021-06-08.log ├── middlewares │ ├── auth.middleware.ts │ ├── error.middleware.ts │ ├── multer.middleware.ts │ └── validation.middleware.ts ├── routes │ ├── auth.route.ts │ ├── index.route.ts │ ├── post.route.ts │ └── users.route.ts ├── server.ts ├── services │ ├── auth.service.ts │ ├── mail.service.ts │ ├── post.service.ts │ └── users.service.ts ├── tests │ ├── auth.test.ts │ ├── index.test.ts │ ├── post.test.ts │ └── users.test.ts └── utils │ ├── logger.ts │ ├── match.decorator.ts │ ├── multer.ts │ ├── util.ts │ └── validateEnv.ts ├── swagger.yaml ├── tsconfig.json └── uploads └── .gitignore /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # This text is inserted by `prisma init`: 2 | # Environment variables declared in this file are automatically made available to Prisma. 3 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables 4 | 5 | # Prisma supports the native connection string format for PostgreSQL, MySQL and SQLite. 6 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 7 | # Please kindly supply the missing parameters 8 | 9 | PORT= 10 | DATABASE_URL = '://:@localhost:/' 11 | NODE_ENV= 12 | 13 | CLIENT_URL= 14 | 15 | MAIL_HOST= 16 | MAIL_USERNAME= 17 | MAIL_PASSWORD= 18 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "extends": ["prettier", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"], 4 | "parserOptions": { 5 | "ecmaVersion": 2018, 6 | "sourceType": "module" 7 | }, 8 | "rules": { 9 | "@typescript-eslint/explicit-member-accessibility": 0, 10 | "@typescript-eslint/explicit-function-return-type": 0, 11 | "@typescript-eslint/no-parameter-properties": 0, 12 | "@typescript-eslint/interface-name-prefix": 0, 13 | "@typescript-eslint/explicit-module-boundary-types": 0, 14 | "@typescript-eslint/no-explicit-any": "off", 15 | "@typescript-eslint/ban-types": "off", 16 | "@typescript-eslint/no-var-requires": "off" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | 4 | src/logs 5 | # production env files 6 | .env 7 | src/configs/env/prod.env.json 8 | 9 | -------------------------------------------------------------------------------- /.gitkeep: -------------------------------------------------------------------------------- 1 | # exclude everything 2 | uploads/* 3 | 4 | # exception to the rule 5 | !uploads/.gitkeep -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 15 | 16 | 23 | 24 | 27 | 28 | 35 | 36 | 43 | 44 | 51 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/talent.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.ts": ["npm run lint"] 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 150, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "semi": true, 7 | "arrowParens": "avoid" 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node-terminal", 6 | "request": "launch", 7 | "name": "Dev typescript-express-starter", 8 | "command": "npm run dev" 9 | }, 10 | { 11 | "type": "node-terminal", 12 | "request": "launch", 13 | "name": "Start typescript-express-starter", 14 | "command": "npm run start" 15 | }, 16 | { 17 | "type": "node-terminal", 18 | "request": "launch", 19 | "name": "Test typescript-express-starter", 20 | "command": "npm run test" 21 | }, 22 | { 23 | "type": "node-terminal", 24 | "request": "launch", 25 | "name": "Lint typescript-express-starter", 26 | "command": "npm run lint" 27 | }, 28 | { 29 | "type": "node-terminal", 30 | "request": "launch", 31 | "name": "Lint:Fix typescript-express-starter", 32 | "command": "npm run lint:fix" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": true 4 | }, 5 | "editor.formatOnSave": false 6 | } 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | docker build -t ${tag} . 3 | clean: 4 | docker rmi -f ${tag} 5 | run: 6 | docker run -d -p ${port}:${port} --name ${name} ${tag} 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoderByte Task 2 | 3 | This project was generated with ❤. 4 | 5 | ## Installation 6 | 7 | 1. Clone repository - `$ git clone https://github.com/Fn-studyo/talentQL-task.git` 8 | 9 | 2. Install dependencies - `$ cd talent` 10 | 11 | 3. Install dependencies - `$ npm install` 12 | 13 | 4. Create a new file `.env` if it doesn't exist and copy the contents of `.env.example` into it to be able to run your server on production environment. 14 | 15 | ## Setting up db 16 | 17 | Make sure you have mysql or postgresql installed, you could use any database of your choice 18 | 19 | 1. Initialize Prisma - `$ npx prisma init` 20 | 21 | 2. Connect to your db by providing the appropriate credentials, check .env.example for a similar example 22 | 23 | 3. Migrate the Database - `$ prisma migrate dev --name init` 24 | 25 | ## Viewing your database 26 | 27 | 1. Start up prisma studio - Run `$ npx prisma studio` 28 | 29 | ## Running the server locally 30 | 31 | 1. Start up the server - Run `$ npm start` | `$ npm run dev` 32 | 33 | 2. Server should be running on http://localhost:2020/ by default 34 | 35 | ## e2e Tests 36 | 37 | 1. Start up `$ npm run test` 38 | 39 | 40 | ## Testing the api 41 | 42 | 1. Via Postman Collection (https://documenter.getpostman.com/view/11039127/TzeTJpNs) 43 | 44 | 2. Via Swagger, viewing the api locally (http://localhost:3000/api-docs) 45 | 46 | ## Routes 47 | 48 | | Routes | Description | Auth roles | 49 | | -------------------------------------------------- | ------------------------------ | ---------- | 50 | | [POST]   /api/auth/signup | Create a new account | none | 51 | | [POST]   /api/auth/login | User sign in | none | 52 | | [POST]   /api/auth/logout | Logout a user | User | 53 | | [POST]   /api/auth/request-email-verification | Resend verfication email | none | 54 | | [POST]   /api/auth/verify-email | Email verification | none | 55 | | [POST]   /api/auth/request-password-reset | Sends a request password email | none | 56 | | [POST]   /api/auth/reset-password | Reset password form handler | none | 57 | | [PUT]   /api/users | Update a user | User | 58 | | [GET]   /api/posts/create | Create a post | User | 59 | | [GET]   /api/posts/publish/:bookId | Publish a book | User | 60 | | [GET]   /api/user | Get users details | User | 61 | | [DELETE]   /api/user | Delete a user | User | 62 | -------------------------------------------------------------------------------- /dist/app.d.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import Routes from './interfaces/routes.interface'; 3 | declare class App { 4 | app: express.Application; 5 | port: string | number; 6 | env: string; 7 | constructor(routes: Routes[]); 8 | listen(): void; 9 | getServer(): express.Application; 10 | private initializeMiddlewares; 11 | private initializeRoutes; 12 | private initializeSwagger; 13 | private initializeErrorHandling; 14 | } 15 | export default App; 16 | -------------------------------------------------------------------------------- /dist/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | process.env['NODE_CONFIG_DIR'] = __dirname + '/configs'; 5 | const compression_1 = tslib_1.__importDefault(require('compression')); 6 | const cookie_parser_1 = tslib_1.__importDefault(require('cookie-parser')); 7 | const express_1 = tslib_1.__importDefault(require('express')); 8 | const helmet_1 = tslib_1.__importDefault(require('helmet')); 9 | const hpp_1 = tslib_1.__importDefault(require('hpp')); 10 | const morgan_1 = tslib_1.__importDefault(require('morgan')); 11 | const swagger_jsdoc_1 = tslib_1.__importDefault(require('swagger-jsdoc')); 12 | const swagger_ui_express_1 = tslib_1.__importDefault(require('swagger-ui-express')); 13 | const error_middleware_1 = tslib_1.__importDefault(require('./middlewares/error.middleware')); 14 | const logger_1 = require('./utils/logger'); 15 | class App { 16 | constructor(routes) { 17 | this.app = express_1.default(); 18 | this.port = process.env.PORT || 3000; 19 | this.env = process.env.NODE_ENV || 'development'; 20 | this.initializeMiddlewares(); 21 | this.initializeRoutes(routes); 22 | this.initializeSwagger(); 23 | this.initializeErrorHandling(); 24 | } 25 | listen() { 26 | this.app.listen(this.port, () => { 27 | logger_1.logger.info(`=================================`); 28 | logger_1.logger.info(`======= ENV: ${this.env} =======`); 29 | logger_1.logger.info(`🚀 App listening on the port ${this.port}`); 30 | logger_1.logger.info(`=================================`); 31 | }); 32 | } 33 | getServer() { 34 | return this.app; 35 | } 36 | initializeMiddlewares() { 37 | if (this.env === 'production') { 38 | this.app.use(morgan_1.default('combined', { stream: logger_1.stream })); 39 | } else { 40 | this.app.use(morgan_1.default('dev', { stream: logger_1.stream })); 41 | } 42 | this.app.use(hpp_1.default()); 43 | this.app.use(helmet_1.default()); 44 | this.app.use(compression_1.default()); 45 | this.app.use(express_1.default.json()); 46 | this.app.use(express_1.default.urlencoded({ extended: true })); 47 | this.app.use(cookie_parser_1.default()); 48 | } 49 | initializeRoutes(routes) { 50 | routes.forEach(route => { 51 | this.app.use('/', route.router); 52 | }); 53 | } 54 | initializeSwagger() { 55 | const options = { 56 | swaggerDefinition: { 57 | info: { 58 | title: 'REST API', 59 | version: '1.0.0', 60 | description: 'Example docs', 61 | }, 62 | }, 63 | apis: ['swagger.yaml'], 64 | }; 65 | const specs = swagger_jsdoc_1.default(options); 66 | this.app.use('/api-docs', swagger_ui_express_1.default.serve, swagger_ui_express_1.default.setup(specs)); 67 | } 68 | initializeErrorHandling() { 69 | this.app.use(error_middleware_1.default); 70 | } 71 | } 72 | exports.default = App; 73 | //# sourceMappingURL=app.js.map 74 | -------------------------------------------------------------------------------- /dist/app.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/configs/development.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "development", 3 | "secretKey": "secretKey" 4 | } 5 | -------------------------------------------------------------------------------- /dist/configs/env/dev.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "APP_NAME": "talent banga", 3 | "JWT_SECRET": "XXXX-XXXX-XXXX", 4 | "BCRYPT_SALT": 10, 5 | "url": { 6 | "BASE_URL": "http://localhost:8080" 7 | }, 8 | "mailer": { 9 | "FROM": "Muritala David", 10 | "HOST": "", 11 | "USER": "", 12 | "PASSWORD": "", 13 | "PORT": "", 14 | "SECURE": "", 15 | "DOMAIN": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dist/configs/env/prod.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "APP_NAME": "talent banga", 3 | "JWT_SECRET": "XXXX-XXXX-XXXX", 4 | "BCRYPT_SALT": 10, 5 | "url": { 6 | "BASE_URL": "http://localhost:8080" 7 | }, 8 | "mailer": { 9 | "HOST": "", 10 | "USER": "", 11 | "PASSWORD": "", 12 | "PORT": "", 13 | "SECURE": "", 14 | "DOMAIN": "" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dist/configs/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: any; 2 | export default _default; 3 | -------------------------------------------------------------------------------- /dist/configs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const env = process.env.NODE_ENV; 4 | const environments = { 5 | development: require('./env/dev.env.json'), 6 | production: require('./env/prod.env.json'), 7 | }; 8 | // export config for the current environment 9 | exports.default = environments[env] || environments['production']; 10 | //# sourceMappingURL=index.js.map 11 | -------------------------------------------------------------------------------- /dist/configs/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/configs/index.ts"],"names":[],"mappings":";;AAAA,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEjC,MAAM,YAAY,GAAG;IACnB,WAAW,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAC1C,UAAU,EAAE,OAAO,CAAC,qBAAqB,CAAC;CAC3C,CAAC;AAEF,4CAA4C;AAC5C,kBAAe,YAAY,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,YAAY,CAAC,CAAC"} -------------------------------------------------------------------------------- /dist/configs/production.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "production", 3 | "secretKey": "secretKey" 4 | } 5 | -------------------------------------------------------------------------------- /dist/configs/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "test", 3 | "secretKey": "secretKey" 4 | } 5 | -------------------------------------------------------------------------------- /dist/controllers/auth.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { RequestWithUser } from '../interfaces/auth.interface'; 3 | import AuthService from '../services/auth.service'; 4 | declare class AuthController { 5 | authService: AuthService; 6 | signUp: (req: Request, res: Response, next: NextFunction) => Promise; 7 | logIn: (req: Request, res: Response, next: NextFunction) => Promise; 8 | logOut: (req: RequestWithUser, res: Response, next: NextFunction) => Promise; 9 | } 10 | export default AuthController; 11 | -------------------------------------------------------------------------------- /dist/controllers/auth.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const auth_service_1 = tslib_1.__importDefault(require('../services/auth.service')); 5 | class AuthController { 6 | constructor() { 7 | this.authService = new auth_service_1.default(); 8 | this.signUp = async (req, res, next) => { 9 | try { 10 | const userData = req.body; 11 | const signUpUserData = await this.authService.signup(userData); 12 | res.status(201).json({ data: signUpUserData, message: 'signup' }); 13 | } catch (error) { 14 | next(error); 15 | } 16 | }; 17 | this.logIn = async (req, res, next) => { 18 | try { 19 | const userData = req.body; 20 | const { cookie, findUser } = await this.authService.login(userData); 21 | res.setHeader('Set-Cookie', [cookie]); 22 | res.status(200).json({ data: findUser, message: 'login' }); 23 | } catch (error) { 24 | next(error); 25 | } 26 | }; 27 | this.logOut = async (req, res, next) => { 28 | try { 29 | const userData = req.user; 30 | const logOutUserData = await this.authService.logout(userData); 31 | res.setHeader('Set-Cookie', ['Authorization=; Max-age=0']); 32 | res.status(200).json({ data: logOutUserData, message: 'logout' }); 33 | } catch (error) { 34 | next(error); 35 | } 36 | }; 37 | } 38 | } 39 | exports.default = AuthController; 40 | //# sourceMappingURL=auth.controller.js.map 41 | -------------------------------------------------------------------------------- /dist/controllers/auth.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../src/controllers/auth.controller.ts"],"names":[],"mappings":";;;AAIA,kFAAiD;AAEjD,MAAM,cAAc;IAApB;QACS,gBAAW,GAAG,IAAI,sBAAW,EAAE,CAAC;QAEhC,WAAM,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAiB,EAAE;YACvF,IAAI;gBACF,MAAM,QAAQ,GAAkB,GAAG,CAAC,IAAI,CAAC;gBACzC,MAAM,cAAc,GAAS,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAErE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;aACnE;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,KAAK,CAAC,CAAC;aACb;QACH,CAAC,CAAC;QAEK,UAAK,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAiB,EAAE;YACtF,IAAI;gBACF,MAAM,QAAQ,GAAkB,GAAG,CAAC,IAAI,CAAC;gBACzC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAEpE,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;gBACtC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;aAC5D;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,KAAK,CAAC,CAAC;aACb;QACH,CAAC,CAAC;QAEK,WAAM,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAa,EAAE,IAAkB,EAAiB,EAAE;YAC/F,IAAI;gBACF,MAAM,QAAQ,GAAS,GAAG,CAAC,IAAI,CAAC;gBAChC,MAAM,cAAc,GAAS,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAErE,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,2BAA2B,CAAC,CAAC,CAAC;gBAC3D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;aACnE;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,KAAK,CAAC,CAAC;aACb;QACH,CAAC,CAAC;IACJ,CAAC;CAAA;AAED,kBAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/controllers/index.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | declare class IndexController { 3 | index: (req: Request, res: Response, next: NextFunction) => Response; 4 | } 5 | export default IndexController; 6 | -------------------------------------------------------------------------------- /dist/controllers/index.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | class IndexController { 4 | constructor() { 5 | this.index = (req, res, next) => { 6 | try { 7 | return res.status(200).send({ 8 | message: 'Application Live ❤', 9 | author: 'Muritala David', 10 | github: 'https://github.com/Fn-studyo', 11 | }); 12 | } catch (error) { 13 | next(error); 14 | } 15 | }; 16 | } 17 | } 18 | exports.default = IndexController; 19 | //# sourceMappingURL=index.controller.js.map 20 | -------------------------------------------------------------------------------- /dist/controllers/index.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.controller.js","sourceRoot":"","sources":["../../src/controllers/index.controller.ts"],"names":[],"mappings":";;AAEA,MAAM,eAAe;IAArB;QACS,UAAK,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAY,EAAE;YAC3E,IAAI;gBACF,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBAC1B,OAAO,EAAE,oBAAoB;oBAC7B,MAAM,EAAE,gBAAgB;oBACxB,MAAM,EAAE,8BAA8B;iBACvC,CAAC,CAAC;aACJ;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,KAAK,CAAC,CAAC;aACb;QACH,CAAC,CAAC;IACJ,CAAC;CAAA;AAED,kBAAe,eAAe,CAAC"} -------------------------------------------------------------------------------- /dist/controllers/users.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import userService from '../services/users.service'; 3 | declare class UsersController { 4 | userService: userService; 5 | getUsers: (req: Request, res: Response, next: NextFunction) => Promise; 6 | getUserById: (req: Request, res: Response, next: NextFunction) => Promise; 7 | createUser: (req: Request, res: Response, next: NextFunction) => Promise; 8 | updateUser: (req: Request, res: Response, next: NextFunction) => Promise; 9 | deleteUser: (req: Request, res: Response, next: NextFunction) => Promise; 10 | } 11 | export default UsersController; 12 | -------------------------------------------------------------------------------- /dist/controllers/users.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const users_service_1 = tslib_1.__importDefault(require('../services/users.service')); 5 | class UsersController { 6 | constructor() { 7 | this.userService = new users_service_1.default(); 8 | this.getUsers = async (req, res, next) => { 9 | try { 10 | const findAllUsersData = await this.userService.findAllUser(); 11 | res.status(200).json({ data: findAllUsersData, message: 'findAll' }); 12 | } catch (error) { 13 | next(error); 14 | } 15 | }; 16 | this.getUserById = async (req, res, next) => { 17 | try { 18 | const userId = Number(req.params.id); 19 | const findOneUserData = await this.userService.findUserById(userId); 20 | res.status(200).json({ data: findOneUserData, message: 'findOne' }); 21 | } catch (error) { 22 | next(error); 23 | } 24 | }; 25 | this.createUser = async (req, res, next) => { 26 | try { 27 | const userData = req.body; 28 | const createUserData = await this.userService.createUser(userData); 29 | res.status(201).json({ data: createUserData, message: 'created' }); 30 | } catch (error) { 31 | next(error); 32 | } 33 | }; 34 | this.updateUser = async (req, res, next) => { 35 | try { 36 | const userId = Number(req.params.id); 37 | const userData = req.body; 38 | const updateUserData = await this.userService.updateUser(userId, userData); 39 | res.status(200).json({ data: updateUserData, message: 'updated' }); 40 | } catch (error) { 41 | next(error); 42 | } 43 | }; 44 | this.deleteUser = async (req, res, next) => { 45 | try { 46 | const userId = Number(req.params.id); 47 | const deleteUserData = await this.userService.deleteUser(userId); 48 | res.status(200).json({ data: deleteUserData, message: 'deleted' }); 49 | } catch (error) { 50 | next(error); 51 | } 52 | }; 53 | } 54 | } 55 | exports.default = UsersController; 56 | //# sourceMappingURL=users.controller.js.map 57 | -------------------------------------------------------------------------------- /dist/controllers/users.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.controller.js","sourceRoot":"","sources":["../../src/controllers/users.controller.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/dtos/users.dto.d.ts: -------------------------------------------------------------------------------- 1 | declare class CreateUserDto { 2 | name: string; 3 | email: string; 4 | password: string; 5 | } 6 | declare class UserLoginDto { 7 | email: string; 8 | password: string; 9 | } 10 | declare class UserMailDto { 11 | name: string; 12 | email: string; 13 | } 14 | export { CreateUserDto, UserLoginDto, UserMailDto }; 15 | -------------------------------------------------------------------------------- /dist/dtos/users.dto.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.UserMailDto = exports.UserLoginDto = exports.CreateUserDto = void 0; 4 | const tslib_1 = require('tslib'); 5 | const class_validator_1 = require('class-validator'); 6 | class CreateUserDto {} 7 | tslib_1.__decorate( 8 | [class_validator_1.IsNotEmpty({ message: 'Name is required' }), class_validator_1.IsString(), tslib_1.__metadata('design:type', String)], 9 | CreateUserDto.prototype, 10 | 'name', 11 | void 0, 12 | ); 13 | tslib_1.__decorate( 14 | [class_validator_1.IsNotEmpty({ message: 'Email address is required' }), class_validator_1.IsEmail(), tslib_1.__metadata('design:type', String)], 15 | CreateUserDto.prototype, 16 | 'email', 17 | void 0, 18 | ); 19 | tslib_1.__decorate( 20 | [ 21 | class_validator_1.IsNotEmpty({ message: 'Password is required' }), 22 | class_validator_1.MinLength(7), 23 | class_validator_1.IsString(), 24 | tslib_1.__metadata('design:type', String), 25 | ], 26 | CreateUserDto.prototype, 27 | 'password', 28 | void 0, 29 | ); 30 | exports.CreateUserDto = CreateUserDto; 31 | class UserLoginDto {} 32 | tslib_1.__decorate([class_validator_1.IsEmail(), tslib_1.__metadata('design:type', String)], UserLoginDto.prototype, 'email', void 0); 33 | tslib_1.__decorate([class_validator_1.IsString(), tslib_1.__metadata('design:type', String)], UserLoginDto.prototype, 'password', void 0); 34 | exports.UserLoginDto = UserLoginDto; 35 | class UserMailDto {} 36 | exports.UserMailDto = UserMailDto; 37 | //# sourceMappingURL=users.dto.js.map 38 | -------------------------------------------------------------------------------- /dist/dtos/users.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.dto.js","sourceRoot":"","sources":["../../src/dtos/users.dto.ts"],"names":[],"mappings":";;;;AAAA,qDAA2E;AAE3E,MAAM,aAAa;CAalB;AAVC;IAFC,4BAAU,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC3C,0BAAQ,EAAE;;2CACS;AAIpB;IAFC,4BAAU,CAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;IACpD,yBAAO,EAAE;;4CACW;AAKrB;IAHC,4BAAU,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAC/C,2BAAS,CAAC,CAAC,CAAC;IACZ,0BAAQ,EAAE;;+CACa;AAejB,sCAAa;AAZtB,MAAM,YAAY;CAMjB;AAJC;IADC,yBAAO,EAAE;;2CACW;AAGrB;IADC,0BAAQ,EAAE;;8CACa;AAOF,oCAAY;AAJpC,MAAM,WAAW;CAGhB;AACqC,kCAAW"} -------------------------------------------------------------------------------- /dist/exceptions/HttpException.d.ts: -------------------------------------------------------------------------------- 1 | declare class HttpException extends Error { 2 | status: number; 3 | message: string; 4 | constructor(status: number, message: string); 5 | } 6 | export default HttpException; 7 | -------------------------------------------------------------------------------- /dist/exceptions/HttpException.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | class HttpException extends Error { 4 | constructor(status, message) { 5 | super(message); 6 | this.status = status; 7 | this.message = message; 8 | } 9 | } 10 | exports.default = HttpException; 11 | //# sourceMappingURL=HttpException.js.map 12 | -------------------------------------------------------------------------------- /dist/exceptions/HttpException.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"HttpException.js","sourceRoot":"","sources":["../../src/exceptions/HttpException.ts"],"names":[],"mappings":";;AAAA,MAAM,aAAc,SAAQ,KAAK;IAI/B,YAAY,MAAc,EAAE,OAAe;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,kBAAe,aAAa,CAAC"} -------------------------------------------------------------------------------- /dist/interfaces/auth.interface.d.ts: -------------------------------------------------------------------------------- 1 | import { Request } from 'express'; 2 | import { User } from '@prisma/client'; 3 | export interface DataStoredInToken { 4 | id: number; 5 | } 6 | export interface TokenData { 7 | token: string; 8 | expiresIn: number; 9 | } 10 | export interface RequestWithUser extends Request { 11 | user: User; 12 | } 13 | -------------------------------------------------------------------------------- /dist/interfaces/auth.interface.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | //# sourceMappingURL=auth.interface.js.map 4 | -------------------------------------------------------------------------------- /dist/interfaces/auth.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.interface.js","sourceRoot":"","sources":["../../src/interfaces/auth.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/interfaces/routes.interface.d.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | interface Route { 3 | path?: string; 4 | router: Router; 5 | } 6 | export default Route; 7 | -------------------------------------------------------------------------------- /dist/interfaces/routes.interface.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | //# sourceMappingURL=routes.interface.js.map 4 | -------------------------------------------------------------------------------- /dist/interfaces/routes.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"routes.interface.js","sourceRoot":"","sources":["../../src/interfaces/routes.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/logs/debug/.0fdd8272eea6e3a3e30364131bac1064b6ee2ba6-audit.json: -------------------------------------------------------------------------------- 1 | { 2 | "keep": { 3 | "days": false, 4 | "amount": 30 5 | }, 6 | "auditLog": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\dist\\logs\\debug\\.0fdd8272eea6e3a3e30364131bac1064b6ee2ba6-audit.json", 7 | "files": [ 8 | { 9 | "date": 1623208578401, 10 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\dist\\logs\\debug\\2021-06-08.log", 11 | "hash": "8664b8833a5414c63d45d92902d640ec" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /dist/logs/debug/2021-06-08.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipethedev/typescript-starter/733b4db48f60ead1f5e307d04dee1a049c19fcec/dist/logs/debug/2021-06-08.log -------------------------------------------------------------------------------- /dist/logs/error/.f794145503009200c1d8831dcc5d151993851e5a-audit.json: -------------------------------------------------------------------------------- 1 | { 2 | "keep": { 3 | "days": false, 4 | "amount": 30 5 | }, 6 | "auditLog": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\dist\\logs\\error\\.f794145503009200c1d8831dcc5d151993851e5a-audit.json", 7 | "files": [ 8 | { 9 | "date": 1623208578439, 10 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\dist\\logs\\error\\2021-06-08.log", 11 | "hash": "d4cf2349dd3682b200e24e8e90833a3f" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /dist/logs/error/2021-06-08.log: -------------------------------------------------------------------------------- 1 | 2021-06-08 20:16:31 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 2 | Error: listen EADDRINUSE: address already in use :::3000 3 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 4 | at listenInCluster (net.js:1366:12) 5 | at Server.listen (net.js:1452:7) 6 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 7 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\dist\app.js:26:18) 8 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\dist\server.js:13:5) 9 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 10 | at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 11 | at Module.load (internal/modules/cjs/loader.js:933:32) 12 | at Function.Module._load (internal/modules/cjs/loader.js:774:14) 13 | -------------------------------------------------------------------------------- /dist/middlewares/auth.middleware.d.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Response } from 'express'; 2 | import { RequestWithUser } from '../interfaces/auth.interface'; 3 | declare const authMiddleware: (req: RequestWithUser, res: Response, next: NextFunction) => Promise; 4 | export default authMiddleware; 5 | -------------------------------------------------------------------------------- /dist/middlewares/auth.middleware.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const config_1 = tslib_1.__importDefault(require('config')); 5 | const jsonwebtoken_1 = tslib_1.__importDefault(require('jsonwebtoken')); 6 | const client_1 = require('@prisma/client'); 7 | const HttpException_1 = tslib_1.__importDefault(require('../exceptions/HttpException')); 8 | const authMiddleware = async (req, res, next) => { 9 | try { 10 | const Authorization = req.cookies['Authorization'] || req.header('Authorization').split('Bearer ')[1] || null; 11 | if (Authorization) { 12 | const secretKey = config_1.default.get('secretKey'); 13 | const verificationResponse = await jsonwebtoken_1.default.verify(Authorization, secretKey); 14 | const userId = verificationResponse.id; 15 | const users = new client_1.PrismaClient().user; 16 | const findUser = await users.findUnique({ where: { id: Number(userId) } }); 17 | if (findUser) { 18 | req.user = findUser; 19 | next(); 20 | } else { 21 | next(new HttpException_1.default(401, 'Wrong authentication token')); 22 | } 23 | } else { 24 | next(new HttpException_1.default(404, 'Authentication token missing')); 25 | } 26 | } catch (error) { 27 | next(new HttpException_1.default(401, 'Wrong authentication token')); 28 | } 29 | }; 30 | exports.default = authMiddleware; 31 | //# sourceMappingURL=auth.middleware.js.map 32 | -------------------------------------------------------------------------------- /dist/middlewares/auth.middleware.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.middleware.js","sourceRoot":"","sources":["../../src/middlewares/auth.middleware.ts"],"names":[],"mappings":";;;AACA,4DAA4B;AAC5B,wEAA+B;AAC/B,2CAA8C;AAC9C,sFAAsD;AAGtD,MAAM,cAAc,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACvF,IAAI;QACF,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAE9G,IAAI,aAAa,EAAE;YACjB,MAAM,SAAS,GAAW,gBAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAClD,MAAM,oBAAoB,GAAG,CAAC,MAAM,sBAAG,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAAsB,CAAC;YAC/F,MAAM,MAAM,GAAG,oBAAoB,CAAC,EAAE,CAAC;YAEvC,MAAM,KAAK,GAAG,IAAI,qBAAY,EAAE,CAAC,IAAI,CAAC;YACtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;YAE3E,IAAI,QAAQ,EAAE;gBACZ,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;gBACpB,IAAI,EAAE,CAAC;aACR;iBAAM;gBACL,IAAI,CAAC,IAAI,uBAAa,CAAC,GAAG,EAAE,4BAA4B,CAAC,CAAC,CAAC;aAC5D;SACF;aAAM;YACL,IAAI,CAAC,IAAI,uBAAa,CAAC,GAAG,EAAE,8BAA8B,CAAC,CAAC,CAAC;SAC9D;KACF;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,IAAI,uBAAa,CAAC,GAAG,EAAE,4BAA4B,CAAC,CAAC,CAAC;KAC5D;AACH,CAAC,CAAC;AAEF,kBAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/middlewares/error.middleware.d.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import HttpException from '../exceptions/HttpException'; 3 | declare const errorMiddleware: (error: HttpException, req: Request, res: Response, next: NextFunction) => void; 4 | export default errorMiddleware; 5 | -------------------------------------------------------------------------------- /dist/middlewares/error.middleware.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const logger_1 = require('../utils/logger'); 4 | const errorMiddleware = (error, req, res, next) => { 5 | try { 6 | const status = error.status || 500; 7 | const message = error.message || 'Something went wrong'; 8 | logger_1.logger.error(`[${req.method}] ${req.path} >> StatusCode:: ${status}, Message:: ${message}`); 9 | res.status(status).json({ message }); 10 | } catch (error) { 11 | next(error); 12 | } 13 | }; 14 | exports.default = errorMiddleware; 15 | //# sourceMappingURL=error.middleware.js.map 16 | -------------------------------------------------------------------------------- /dist/middlewares/error.middleware.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"error.middleware.js","sourceRoot":"","sources":["../../src/middlewares/error.middleware.ts"],"names":[],"mappings":";;AAEA,0CAAuC;AAEvC,MAAM,eAAe,GAAG,CAAC,KAAoB,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IAChG,IAAI;QACF,MAAM,MAAM,GAAW,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC;QAC3C,MAAM,OAAO,GAAW,KAAK,CAAC,OAAO,IAAI,sBAAsB,CAAC;QAEhE,eAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,oBAAoB,MAAM,eAAe,OAAO,EAAE,CAAC,CAAC;QAC5F,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;KACtC;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,KAAK,CAAC,CAAC;KACb;AACH,CAAC,CAAC;AAEF,kBAAe,eAAe,CAAC"} -------------------------------------------------------------------------------- /dist/middlewares/validation.middleware.d.ts: -------------------------------------------------------------------------------- 1 | import { RequestHandler } from 'express'; 2 | declare const validationMiddleware: ( 3 | type: any, 4 | value?: string | 'body' | 'query' | 'params', 5 | skipMissingProperties?: boolean, 6 | whitelist?: boolean, 7 | forbidNonWhitelisted?: boolean, 8 | ) => RequestHandler; 9 | export default validationMiddleware; 10 | -------------------------------------------------------------------------------- /dist/middlewares/validation.middleware.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const class_transformer_1 = require('class-transformer'); 5 | const class_validator_1 = require('class-validator'); 6 | const HttpException_1 = tslib_1.__importDefault(require('../exceptions/HttpException')); 7 | const validationMiddleware = (type, value = 'body', skipMissingProperties = false, whitelist = true, forbidNonWhitelisted = true) => { 8 | return (req, res, next) => { 9 | class_validator_1 10 | .validate(class_transformer_1.plainToClass(type, req[value]), { skipMissingProperties, whitelist, forbidNonWhitelisted }) 11 | .then(errors => { 12 | if (errors.length > 0) { 13 | const message = errors.map(error => Object.values(error.constraints)).join(', '); 14 | next(new HttpException_1.default(400, message)); 15 | } else { 16 | next(); 17 | } 18 | }); 19 | }; 20 | }; 21 | exports.default = validationMiddleware; 22 | //# sourceMappingURL=validation.middleware.js.map 23 | -------------------------------------------------------------------------------- /dist/middlewares/validation.middleware.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"validation.middleware.js","sourceRoot":"","sources":["../../src/middlewares/validation.middleware.ts"],"names":[],"mappings":";;;AAAA,yDAAiD;AACjD,qDAA4D;AAE5D,sFAAsD;AAEtD,MAAM,oBAAoB,GAAG,CAC3B,IAAS,EACT,QAA8C,MAAM,EACpD,qBAAqB,GAAG,KAAK,EAC7B,SAAS,GAAG,IAAI,EAChB,oBAAoB,GAAG,IAAI,EACX,EAAE;IAClB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,0BAAQ,CAAC,gCAAY,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,qBAAqB,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAyB,EAAE,EAAE;YACtI,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;gBACrB,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpG,IAAI,CAAC,IAAI,uBAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;aACvC;iBAAM;gBACL,IAAI,EAAE,CAAC;aACR;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,oBAAoB,CAAC"} -------------------------------------------------------------------------------- /dist/routes/auth.route.d.ts: -------------------------------------------------------------------------------- 1 | import AuthController from '../controllers/auth.controller'; 2 | import Route from '../interfaces/routes.interface'; 3 | declare class AuthRoute implements Route { 4 | path: string; 5 | router: import('express-serve-static-core').Router; 6 | authController: AuthController; 7 | constructor(); 8 | private initializeRoutes; 9 | } 10 | export default AuthRoute; 11 | -------------------------------------------------------------------------------- /dist/routes/auth.route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const express_1 = require('express'); 5 | const auth_controller_1 = tslib_1.__importDefault(require('../controllers/auth.controller')); 6 | const users_dto_1 = require('../dtos/users.dto'); 7 | const auth_middleware_1 = tslib_1.__importDefault(require('../middlewares/auth.middleware')); 8 | const validation_middleware_1 = tslib_1.__importDefault(require('../middlewares/validation.middleware')); 9 | class AuthRoute { 10 | constructor() { 11 | this.path = '/auth'; 12 | this.router = express_1.Router(); 13 | this.authController = new auth_controller_1.default(); 14 | this.initializeRoutes(); 15 | } 16 | initializeRoutes() { 17 | this.router.post(`${this.path}/signup`, validation_middleware_1.default(users_dto_1.CreateUserDto, 'body'), this.authController.signUp); 18 | this.router.post(`${this.path}/login`, validation_middleware_1.default(users_dto_1.CreateUserDto, 'body'), this.authController.logIn); 19 | this.router.post(`${this.path}/logout`, auth_middleware_1.default, this.authController.logOut); 20 | } 21 | } 22 | exports.default = AuthRoute; 23 | //# sourceMappingURL=auth.route.js.map 24 | -------------------------------------------------------------------------------- /dist/routes/auth.route.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.route.js","sourceRoot":"","sources":["../../src/routes/auth.route.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AACjC,2FAA0D;AAC1D,+CAAgD;AAEhD,2FAA0D;AAC1D,uGAAsE;AAEtE,MAAM,SAAS;IAKb;QAJO,SAAI,GAAG,OAAO,CAAC;QACf,WAAM,GAAG,gBAAM,EAAE,CAAC;QAClB,mBAAc,GAAG,IAAI,yBAAc,EAAE,CAAC;QAG3C,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,SAAS,EAAE,+BAAoB,CAAC,yBAAa,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACjH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,QAAQ,EAAE,+BAAoB,CAAC,yBAAa,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/G,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,SAAS,EAAE,yBAAc,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACtF,CAAC;CACF;AAED,kBAAe,SAAS,CAAC"} -------------------------------------------------------------------------------- /dist/routes/index.route.d.ts: -------------------------------------------------------------------------------- 1 | import IndexController from '../controllers/index.controller'; 2 | import Route from '../interfaces/routes.interface'; 3 | declare class IndexRoute implements Route { 4 | path: string; 5 | router: import('express-serve-static-core').Router; 6 | indexController: IndexController; 7 | constructor(); 8 | private initializeRoutes; 9 | } 10 | export default IndexRoute; 11 | -------------------------------------------------------------------------------- /dist/routes/index.route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const express_1 = require('express'); 5 | const index_controller_1 = tslib_1.__importDefault(require('../controllers/index.controller')); 6 | class IndexRoute { 7 | constructor() { 8 | this.path = '/'; 9 | this.router = express_1.Router(); 10 | this.indexController = new index_controller_1.default(); 11 | this.initializeRoutes(); 12 | } 13 | initializeRoutes() { 14 | this.router.get(`${this.path}`, this.indexController.index); 15 | } 16 | } 17 | exports.default = IndexRoute; 18 | //# sourceMappingURL=index.route.js.map 19 | -------------------------------------------------------------------------------- /dist/routes/index.route.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.route.js","sourceRoot":"","sources":["../../src/routes/index.route.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AACjC,6FAA4D;AAG5D,MAAM,UAAU;IAKd;QAJO,SAAI,GAAG,GAAG,CAAC;QACX,WAAM,GAAG,gBAAM,EAAE,CAAC;QAClB,oBAAe,GAAG,IAAI,0BAAe,EAAE,CAAC;QAG7C,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC;CACF;AAED,kBAAe,UAAU,CAAC"} -------------------------------------------------------------------------------- /dist/routes/users.route.d.ts: -------------------------------------------------------------------------------- 1 | import UsersController from '../controllers/users.controller'; 2 | import Route from '../interfaces/routes.interface'; 3 | declare class UsersRoute implements Route { 4 | path: string; 5 | router: import('express-serve-static-core').Router; 6 | usersController: UsersController; 7 | constructor(); 8 | private initializeRoutes; 9 | } 10 | export default UsersRoute; 11 | -------------------------------------------------------------------------------- /dist/routes/users.route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const express_1 = require('express'); 5 | const users_controller_1 = tslib_1.__importDefault(require('../controllers/users.controller')); 6 | const users_dto_1 = require('../dtos/users.dto'); 7 | const validation_middleware_1 = tslib_1.__importDefault(require('../middlewares/validation.middleware')); 8 | class UsersRoute { 9 | constructor() { 10 | this.path = '/users'; 11 | this.router = express_1.Router(); 12 | this.usersController = new users_controller_1.default(); 13 | this.initializeRoutes(); 14 | } 15 | initializeRoutes() { 16 | this.router.get(`${this.path}`, this.usersController.getUsers); 17 | this.router.get(`${this.path}/:id(\\d+)`, this.usersController.getUserById); 18 | this.router.post(`${this.path}`, validation_middleware_1.default(users_dto_1.CreateUserDto, 'body'), this.usersController.createUser); 19 | this.router.put( 20 | `${this.path}/:id(\\d+)`, 21 | validation_middleware_1.default(users_dto_1.CreateUserDto, 'body', true), 22 | this.usersController.updateUser, 23 | ); 24 | this.router.delete(`${this.path}/:id(\\d+)`, this.usersController.deleteUser); 25 | } 26 | } 27 | exports.default = UsersRoute; 28 | //# sourceMappingURL=users.route.js.map 29 | -------------------------------------------------------------------------------- /dist/routes/users.route.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.route.js","sourceRoot":"","sources":["../../src/routes/users.route.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AACjC,6FAA4D;AAC5D,+CAAgD;AAEhD,uGAAsE;AAEtE,MAAM,UAAU;IAKd;QAJO,SAAI,GAAG,QAAQ,CAAC;QAChB,WAAM,GAAG,gBAAM,EAAE,CAAC;QAClB,oBAAe,GAAG,IAAI,0BAAe,EAAE,CAAC;QAG7C,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAC5E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,+BAAoB,CAAC,yBAAa,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAC/G,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,YAAY,EAAE,+BAAoB,CAAC,yBAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAC9H,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAChF,CAAC;CACF;AAED,kBAAe,UAAU,CAAC"} -------------------------------------------------------------------------------- /dist/server.d.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | -------------------------------------------------------------------------------- /dist/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | process.env['NODE_CONFIG_DIR'] = __dirname + '/configs'; 5 | require('dotenv/config'); 6 | const app_1 = tslib_1.__importDefault(require('./app')); 7 | const auth_route_1 = tslib_1.__importDefault(require('./routes/auth.route')); 8 | const index_route_1 = tslib_1.__importDefault(require('./routes/index.route')); 9 | const users_route_1 = tslib_1.__importDefault(require('./routes/users.route')); 10 | const validateEnv_1 = tslib_1.__importDefault(require('./utils/validateEnv')); 11 | validateEnv_1.default(); 12 | const app = new app_1.default([new index_route_1.default(), new users_route_1.default(), new auth_route_1.default()]); 13 | app.listen(); 14 | //# sourceMappingURL=server.js.map 15 | -------------------------------------------------------------------------------- /dist/server.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;AAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,SAAS,GAAG,UAAU,CAAC;AAExD,yBAAuB;AACvB,wDAAwB;AACxB,4EAA2C;AAC3C,8EAA6C;AAC7C,8EAA6C;AAC7C,6EAA6C;AAE7C,qBAAW,EAAE,CAAC;AAEd,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,CAAC,IAAI,qBAAU,EAAE,EAAE,IAAI,qBAAU,EAAE,EAAE,IAAI,oBAAS,EAAE,CAAC,CAAC,CAAC;AAE3E,GAAG,CAAC,MAAM,EAAE,CAAC"} -------------------------------------------------------------------------------- /dist/services/auth.service.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { CreateUserDto, UserLoginDto } from '../dtos/users.dto'; 3 | import { TokenData } from '../interfaces/auth.interface'; 4 | declare class AuthService { 5 | users: import('.prisma/client').Prisma.UserDelegate< 6 | import('.prisma/client').Prisma.RejectOnNotFound | import('.prisma/client').Prisma.RejectPerOperation 7 | >; 8 | token: import('.prisma/client').Prisma.TokenDelegate< 9 | import('.prisma/client').Prisma.RejectOnNotFound | import('.prisma/client').Prisma.RejectPerOperation 10 | >; 11 | signup(userData: CreateUserDto): Promise; 12 | login(userData: UserLoginDto): Promise<{ 13 | cookie: string; 14 | findUser: User; 15 | }>; 16 | logout(userData: User): Promise; 17 | createToken(user: User): TokenData; 18 | createCookie(tokenData: TokenData): string; 19 | RequestEmailVerification(email: string): Promise; 20 | } 21 | export default AuthService; 22 | -------------------------------------------------------------------------------- /dist/services/auth.service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const bcrypt_1 = tslib_1.__importDefault(require('bcrypt')); 5 | const config_1 = tslib_1.__importDefault(require('config')); 6 | const jsonwebtoken_1 = tslib_1.__importDefault(require('jsonwebtoken')); 7 | const client_1 = require('@prisma/client'); 8 | const HttpException_1 = tslib_1.__importDefault(require('../exceptions/HttpException')); 9 | const util_1 = require('../utils/util'); 10 | const configs_1 = tslib_1.__importDefault(require('./../configs')); 11 | const configs_2 = tslib_1.__importDefault(require('./../configs')); 12 | const mail_service_1 = tslib_1.__importDefault(require('./mail.service')); 13 | const crypto_1 = tslib_1.__importDefault(require('crypto')); 14 | class AuthService { 15 | constructor() { 16 | this.users = new client_1.PrismaClient().user; 17 | this.token = new client_1.PrismaClient().token; 18 | } 19 | async signup(userData) { 20 | if (util_1.isEmpty(userData)) throw new HttpException_1.default(400, "You're not userData"); 21 | const findUser = await this.users.findUnique({ where: { email: userData.email } }); 22 | if (findUser) throw new HttpException_1.default(409, `You're email ${userData.email} already exists`); 23 | const hashedPassword = await bcrypt_1.default.hash(userData.password, 10); 24 | const createUserData = this.users.create({ data: Object.assign(Object.assign({}, userData), { password: hashedPassword }) }); 25 | // Request email verification 26 | await this.RequestEmailVerification(userData.email); 27 | return createUserData; 28 | } 29 | async login(userData) { 30 | if (util_1.isEmpty(userData)) throw new HttpException_1.default(400, "You're not userData"); 31 | const findUser = await this.users.findUnique({ where: { email: userData.email } }); 32 | if (!findUser) throw new HttpException_1.default(409, `You're email ${userData.email} not found`); 33 | const isPasswordMatching = await bcrypt_1.default.compare(userData.password, findUser.password); 34 | if (!isPasswordMatching) throw new HttpException_1.default(409, "You're password not matching"); 35 | const tokenData = this.createToken(findUser); 36 | const cookie = this.createCookie(tokenData); 37 | return { cookie, findUser }; 38 | } 39 | async logout(userData) { 40 | if (util_1.isEmpty(userData)) throw new HttpException_1.default(400, "You're not userData"); 41 | const findUser = await this.users.findFirst({ where: { email: userData.email, password: userData.password } }); 42 | if (!findUser) throw new HttpException_1.default(409, "You're not user"); 43 | return findUser; 44 | } 45 | createToken(user) { 46 | const dataStoredInToken = { id: user.id }; 47 | const secretKey = config_1.default.get('secretKey'); 48 | const expiresIn = 60 * 60; 49 | return { expiresIn, token: jsonwebtoken_1.default.sign(dataStoredInToken, secretKey, { expiresIn }) }; 50 | } 51 | createCookie(tokenData) { 52 | return `Authorization=${tokenData.token}; HttpOnly; Max-Age=${tokenData.expiresIn};`; 53 | } 54 | //Send Verification to user 55 | async RequestEmailVerification(email) { 56 | const user = await this.users.findFirst({ 57 | where: { 58 | email, 59 | }, 60 | }); 61 | if (!user) throw new HttpException_1.default(404, 'Email does not exist'); 62 | if (user.isVerified) throw new HttpException_1.default(409, 'Email is already verified'); 63 | const token = await this.token.findFirst({ 64 | where: { 65 | userId: user.id, 66 | }, 67 | }); 68 | if (token) 69 | await this.token.delete({ 70 | where: { 71 | id: token.id, 72 | }, 73 | }); 74 | const verifyToken = crypto_1.default.randomBytes(32).toString('hex'); 75 | const hash = await bcrypt_1.default.hash(verifyToken, configs_1.default); 76 | await this.token.create({ 77 | data: { 78 | userId: user.id, 79 | token: hash, 80 | }, 81 | }); 82 | const link = `${configs_2.default.CLIENT_URL}/email-verification?uid=${user.id}&verifyToken=${verifyToken}`; 83 | // Send Mail 84 | await new mail_service_1.default(user).sendEmailVerificationMail(link); 85 | return; 86 | } 87 | } 88 | exports.default = AuthService; 89 | //# sourceMappingURL=auth.service.js.map 90 | -------------------------------------------------------------------------------- /dist/services/auth.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":";;;AAAA,4DAA4B;AAC5B,4DAA4B;AAC5B,wEAA+B;AAC/B,2CAA2D;AAE3D,sFAAsD;AAEtD,sCAAsC;AACtC,mEAAuC;AACvC,mEAA+B;AAC/B,0EAAyC;AACzC,4DAA4B;AAE5B,MAAM,WAAW;IAAjB;QACS,UAAK,GAAG,IAAI,qBAAY,EAAE,CAAC,IAAI,CAAC;QAChC,UAAK,GAAG,IAAI,qBAAY,EAAE,CAAC,KAAK,CAAC;IA4F1C,CAAC;IA1FQ,KAAK,CAAC,MAAM,CAAC,QAAuB;QACzC,IAAI,cAAO,CAAC,QAAQ,CAAC;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAE3E,MAAM,QAAQ,GAAS,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzF,IAAI,QAAQ;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,gBAAgB,QAAQ,CAAC,KAAK,iBAAiB,CAAC,CAAC;QAE5F,MAAM,cAAc,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEhE,MAAM,cAAc,GAAkB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,kCAAO,QAAQ,KAAE,QAAQ,EAAE,cAAc,GAAE,EAAE,CAAC,CAAC;QAE7G,6BAA6B;QAC7B,MAAM,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEpD,OAAO,cAAc,CAAC;IACxB,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,QAAsB;QACvC,IAAI,cAAO,CAAC,QAAQ,CAAC;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAE3E,MAAM,QAAQ,GAAS,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzF,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,gBAAgB,QAAQ,CAAC,KAAK,YAAY,CAAC,CAAC;QAExF,MAAM,kBAAkB,GAAY,MAAM,gBAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC/F,IAAI,CAAC,kBAAkB;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,8BAA8B,CAAC,CAAC;QAEtF,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAE5C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,QAAc;QAChC,IAAI,cAAO,CAAC,QAAQ,CAAC;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAE3E,MAAM,QAAQ,GAAS,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACrH,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QAE/D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,WAAW,CAAC,IAAU;QAC3B,MAAM,iBAAiB,GAAsB,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAW,gBAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,SAAS,GAAW,EAAE,GAAG,EAAE,CAAC;QAElC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,sBAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC;IAEM,YAAY,CAAC,SAAoB;QACtC,OAAO,iBAAiB,SAAS,CAAC,KAAK,uBAAuB,SAAS,CAAC,SAAS,GAAG,CAAC;IACvF,CAAC;IAED,2BAA2B;IAC3B,KAAK,CAAC,wBAAwB,CAAC,KAAa;QAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YACtC,KAAK,EAAE;gBACL,KAAK;aACN;SACF,CAAC,CAAC;QACH,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QAChE,IAAI,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,2BAA2B,CAAC,CAAC;QAE/E,MAAM,KAAK,GAAU,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAC9C,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI,CAAC,EAAE;aAChB;SACF,CAAC,CAAC;QACH,IAAI,KAAK;YACP,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;gBACtB,KAAK,EAAE;oBACL,EAAE,EAAE,KAAK,CAAC,EAAE;iBACb;aACF,CAAC,CAAC;QAEL,MAAM,WAAW,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,MAAM,gBAAM,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAW,CAAC,CAAC;QAEzD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YACtB,IAAI,EAAE;gBACJ,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,KAAK,EAAE,IAAI;aACZ;SACF,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,iBAAG,CAAC,UAAU,2BAA2B,IAAI,CAAC,EAAE,gBAAgB,WAAW,EAAE,CAAC;QAE9F,YAAY;QACZ,MAAM,IAAI,sBAAW,CAAC,IAAI,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAE5D,OAAO;IACT,CAAC;CACF;AAED,kBAAe,WAAW,CAAC"} -------------------------------------------------------------------------------- /dist/services/mail.service.d.ts: -------------------------------------------------------------------------------- 1 | import SMTPTransport from 'nodemailer/lib/smtp-transport'; 2 | import { UserMailDto } from '../dtos/users.dto'; 3 | declare class MailService { 4 | user: UserMailDto; 5 | constructor(user: UserMailDto); 6 | send(subject: any, content: any, recipient: any, from: any): Promise; 7 | sendEmailVerificationMail(link: any): Promise; 8 | sendPasswordResetMail(link: any): Promise; 9 | } 10 | export default MailService; 11 | -------------------------------------------------------------------------------- /dist/services/mail.service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const nodemailer_1 = tslib_1.__importDefault(require('nodemailer')); 5 | const HttpException_1 = tslib_1.__importDefault(require('../exceptions/HttpException')); 6 | const configs_1 = tslib_1.__importDefault(require('./../configs')); 7 | const configs_2 = tslib_1.__importDefault(require('./../configs')); 8 | class MailService { 9 | constructor(user) { 10 | this.user = user; 11 | } 12 | async send(subject, content, recipient, from) { 13 | from = from || `${configs_1.default} `; 14 | content = content || ' '; 15 | if (!recipient || recipient.length < 1) throw new HttpException_1.default(400, 'Recipient is required'); 16 | if (!subject) throw new HttpException_1.default(400, 'Subject is required'); 17 | // Nodemailer transporter 18 | const transporter = nodemailer_1.default.createTransport({ 19 | host: configs_2.default.HOST, 20 | port: configs_2.default.PORT, 21 | secure: configs_2.default.SECURE, 22 | auth: { 23 | user: configs_2.default.USER, 24 | pass: configs_2.default.PASSWORD, 25 | }, 26 | }); 27 | const result = await transporter.sendMail({ 28 | from, 29 | to: Array.isArray(recipient) ? recipient.join() : recipient, 30 | subject, 31 | text: content, 32 | }); 33 | if (!result) throw new HttpException_1.default(500, 'Unable to send mail'); 34 | return result; 35 | } 36 | async sendEmailVerificationMail(link) { 37 | const subject = 'Email Verification'; 38 | const content = `Hey ${this.user.name}, Please click on the link to verify your email ${link}`; 39 | const recipient = this.user.email; 40 | return await this.send(subject, content, recipient, configs_2.default.FROM); 41 | } 42 | async sendPasswordResetMail(link) { 43 | const subject = 'Reset password'; 44 | const content = `Hey ${this.user.name}, Please click on the link to reset your password ${link}`; 45 | const recipient = this.user.email; 46 | return await this.send(subject, content, recipient, configs_2.default.FROM); 47 | } 48 | } 49 | exports.default = MailService; 50 | //# sourceMappingURL=mail.service.js.map 51 | -------------------------------------------------------------------------------- /dist/services/mail.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"mail.service.js","sourceRoot":"","sources":["../../src/services/mail.service.ts"],"names":[],"mappings":";;;AAAA,oEAAoC;AAEpC,sFAAsD;AACtD,mEAAoC;AACpC,mEAAkC;AAGlC,MAAM,WAAW;IAEf,YAAY,IAAiB;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI;QAC1C,IAAI,GAAG,IAAI,IAAI,GAAG,iBAAQ,aAAa,iBAAM,CAAC,MAAM,GAAG,CAAC;QACxD,OAAO,GAAG,OAAO,IAAI,GAAG,CAAC;QAEzB,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;QAC9F,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAElE,yBAAyB;QACzB,MAAM,WAAW,GAAG,oBAAU,CAAC,eAAe,CAAC;YAC7C,IAAI,EAAE,iBAAM,CAAC,IAAI;YACjB,IAAI,EAAE,iBAAM,CAAC,IAAI;YACjB,MAAM,EAAE,iBAAM,CAAC,MAAM;YACrB,IAAI,EAAE;gBACJ,IAAI,EAAE,iBAAM,CAAC,IAAI;gBACjB,IAAI,EAAE,iBAAM,CAAC,QAAQ;aACtB;SACuB,CAAC,CAAC;QAE5B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC;YACxC,IAAI;YACJ,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;YAC3D,OAAO;YACP,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,uBAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAEjE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,IAAI;QAClC,MAAM,OAAO,GAAG,oBAAoB,CAAC;QACrC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,mDAAmD,IAAI,EAAE,CAAC;QAC/F,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAElC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAM,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,IAAI;QAC9B,MAAM,OAAO,GAAG,gBAAgB,CAAC;QACjC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,qDAAqD,IAAI,EAAE,CAAC;QACjG,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAElC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAM,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;CACF;AAED,kBAAe,WAAW,CAAC"} -------------------------------------------------------------------------------- /dist/services/users.service.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { CreateUserDto } from '../dtos/users.dto'; 3 | declare class UserService { 4 | users: import('.prisma/client').Prisma.UserDelegate< 5 | import('.prisma/client').Prisma.RejectOnNotFound | import('.prisma/client').Prisma.RejectPerOperation 6 | >; 7 | findAllUser(): Promise; 8 | findUserById(userId: number): Promise; 9 | createUser(userData: CreateUserDto): Promise; 10 | updateUser(userId: number, userData: CreateUserDto): Promise; 11 | deleteUser(userId: number): Promise; 12 | } 13 | export default UserService; 14 | -------------------------------------------------------------------------------- /dist/services/users.service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const bcrypt_1 = tslib_1.__importDefault(require('bcrypt')); 5 | const client_1 = require('@prisma/client'); 6 | const HttpException_1 = tslib_1.__importDefault(require('../exceptions/HttpException')); 7 | const util_1 = require('../utils/util'); 8 | class UserService { 9 | constructor() { 10 | this.users = new client_1.PrismaClient().user; 11 | } 12 | async findAllUser() { 13 | return await this.users.findMany(); 14 | } 15 | async findUserById(userId) { 16 | if (util_1.isEmpty(userId)) throw new HttpException_1.default(400, "You're not userId"); 17 | const findUser = await this.users.findUnique({ where: { id: userId } }); 18 | if (!findUser) throw new HttpException_1.default(409, "You're not user"); 19 | return findUser; 20 | } 21 | async createUser(userData) { 22 | if (util_1.isEmpty(userData)) throw new HttpException_1.default(400, "You're not userData"); 23 | const findUser = await this.users.findUnique({ where: { email: userData.email } }); 24 | if (findUser) throw new HttpException_1.default(409, `You're email ${userData.email} already exists`); 25 | const hashedPassword = await bcrypt_1.default.hash(userData.password, 10); 26 | return await this.users.create({ data: Object.assign(Object.assign({}, userData), { password: hashedPassword }) }); 27 | } 28 | async updateUser(userId, userData) { 29 | if (util_1.isEmpty(userData)) throw new HttpException_1.default(400, "You're not userData"); 30 | const findUser = await this.users.findUnique({ where: { id: userId } }); 31 | if (!findUser) throw new HttpException_1.default(409, "You're not user"); 32 | const hashedPassword = await bcrypt_1.default.hash(userData.password, 10); 33 | return await this.users.update({ where: { id: userId }, data: Object.assign(Object.assign({}, userData), { password: hashedPassword }) }); 34 | } 35 | async deleteUser(userId) { 36 | if (util_1.isEmpty(userId)) throw new HttpException_1.default(400, "You're not userId"); 37 | const findUser = await this.users.findUnique({ where: { id: userId } }); 38 | if (!findUser) throw new HttpException_1.default(409, "You're not user"); 39 | return await this.users.delete({ where: { id: userId } }); 40 | } 41 | } 42 | exports.default = UserService; 43 | //# sourceMappingURL=users.service.js.map 44 | -------------------------------------------------------------------------------- /dist/services/users.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.service.js","sourceRoot":"","sources":["../../src/services/users.service.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/tests/auth.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/tests/auth.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const bcrypt_1 = tslib_1.__importDefault(require('bcrypt')); 5 | const supertest_1 = tslib_1.__importDefault(require('supertest')); 6 | const app_1 = tslib_1.__importDefault(require('../app')); 7 | const auth_route_1 = tslib_1.__importDefault(require('../routes/auth.route')); 8 | afterAll(async () => { 9 | await new Promise(resolve => setTimeout(() => resolve(), 500)); 10 | }); 11 | describe('Testing Auth', () => { 12 | describe('[POST] /signup', () => { 13 | it('response should have the Create userData', async () => { 14 | const userData = { 15 | name: 'Random Dev', 16 | email: 'test@email.com', 17 | password: 'q1w2e3r4', 18 | }; 19 | const authRoute = new auth_route_1.default(); 20 | const users = authRoute.authController.authService.users; 21 | users.findUnique = jest.fn().mockReturnValue(null); 22 | users.create = jest.fn().mockReturnValue({ 23 | id: 1, 24 | email: userData.email, 25 | password: await bcrypt_1.default.hash(userData.password, 10), 26 | }); 27 | const app = new app_1.default([authRoute]); 28 | return supertest_1.default(app.getServer()).post(`${authRoute.path}signup`).send(userData).expect(201); 29 | }); 30 | }); 31 | describe('[POST] /login', () => { 32 | it('response should have the Set-Cookie header with the Authorization token', async () => { 33 | const userData = { 34 | email: 'test@email.com', 35 | password: 'q1w2e3r4', 36 | }; 37 | const authRoute = new auth_route_1.default(); 38 | const users = authRoute.authController.authService.users; 39 | users.findUnique = jest.fn().mockReturnValue({ 40 | id: 1, 41 | email: userData.email, 42 | password: await bcrypt_1.default.hash(userData.password, 10), 43 | }); 44 | const app = new app_1.default([authRoute]); 45 | return supertest_1 46 | .default(app.getServer()) 47 | .post(`${authRoute.path}login`) 48 | .send(userData) 49 | .expect('Set-Cookie', /^Authorization=.+/); 50 | }); 51 | }); 52 | describe('[POST] /logout', () => { 53 | it('logout Set-Cookie Authorization=; Max-age=0', async () => { 54 | const user = { 55 | id: 1, 56 | name: 'Random Dev', 57 | img: '', 58 | email: 'test@email.com', 59 | isVerified: true, 60 | password: 'q1w2e3r4', 61 | }; 62 | const authRoute = new auth_route_1.default(); 63 | const users = authRoute.authController.authService.users; 64 | users.findFirst = jest 65 | .fn() 66 | .mockReturnValue(Object.assign(Object.assign({}, user), { password: await bcrypt_1.default.hash(user.password, 10) })); 67 | const app = new app_1.default([authRoute]); 68 | return supertest_1 69 | .default(app.getServer()) 70 | .post(`${authRoute.path}logout`) 71 | .expect('Set-Cookie', /^Authorization=;/); 72 | }); 73 | }); 74 | }); 75 | //# sourceMappingURL=auth.test.js.map 76 | -------------------------------------------------------------------------------- /dist/tests/auth.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../src/tests/auth.test.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/tests/index.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/tests/index.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const supertest_1 = tslib_1.__importDefault(require('supertest')); 5 | const app_1 = tslib_1.__importDefault(require('../app')); 6 | const index_route_1 = tslib_1.__importDefault(require('../routes/index.route')); 7 | afterAll(async () => { 8 | await new Promise(resolve => setTimeout(() => resolve(), 500)); 9 | }); 10 | describe('Testing Index', () => { 11 | describe('[GET] /', () => { 12 | it('response statusCode 200', () => { 13 | const indexRoute = new index_route_1.default(); 14 | const app = new app_1.default([indexRoute]); 15 | return supertest_1.default(app.getServer()).get(`${indexRoute.path}`).expect(200); 16 | }); 17 | }); 18 | }); 19 | //# sourceMappingURL=index.test.js.map 20 | -------------------------------------------------------------------------------- /dist/tests/index.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/tests/index.test.ts"],"names":[],"mappings":";;;AAAA,kEAAgC;AAChC,wDAAwB;AACxB,8EAA6C;AAE7C,QAAQ,CAAC,KAAK,IAAI,EAAE;IAClB,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,UAAU,GAAG,IAAI,qBAAU,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YAElC,OAAO,mBAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /dist/tests/users.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/tests/users.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const tslib_1 = require('tslib'); 4 | const bcrypt_1 = tslib_1.__importDefault(require('bcrypt')); 5 | const supertest_1 = tslib_1.__importDefault(require('supertest')); 6 | const app_1 = tslib_1.__importDefault(require('../app')); 7 | const users_route_1 = tslib_1.__importDefault(require('../routes/users.route')); 8 | afterAll(async () => { 9 | await new Promise(resolve => setTimeout(() => resolve(), 500)); 10 | }); 11 | describe('Testing Users', () => { 12 | describe('[GET] /users', () => { 13 | it('response findAll users', async () => { 14 | const usersRoute = new users_route_1.default(); 15 | const users = usersRoute.usersController.userService.users; 16 | users.findMany = jest.fn().mockReturnValue([ 17 | { 18 | id: 1, 19 | email: 'a@email.com', 20 | password: await bcrypt_1.default.hash('q1w2e3r4!', 10), 21 | }, 22 | { 23 | id: 2, 24 | email: 'b@email.com', 25 | password: await bcrypt_1.default.hash('a1s2d3f4!', 10), 26 | }, 27 | { 28 | id: 3, 29 | email: 'c@email.com', 30 | password: await bcrypt_1.default.hash('z1x2c3v4!', 10), 31 | }, 32 | ]); 33 | const app = new app_1.default([usersRoute]); 34 | return supertest_1.default(app.getServer()).get(`${usersRoute.path}`).expect(200); 35 | }); 36 | }); 37 | describe('[GET] /users/:id', () => { 38 | it('response findOne user', async () => { 39 | const userId = 1; 40 | const usersRoute = new users_route_1.default(); 41 | const users = usersRoute.usersController.userService.users; 42 | users.findUnique = jest.fn().mockReturnValue({ 43 | id: 1, 44 | email: 'a@email.com', 45 | password: await bcrypt_1.default.hash('q1w2e3r4!', 10), 46 | }); 47 | const app = new app_1.default([usersRoute]); 48 | return supertest_1.default(app.getServer()).get(`${usersRoute.path}/${userId}`).expect(200); 49 | }); 50 | }); 51 | describe('[POST] /users', () => { 52 | it('response Create user', async () => { 53 | const userData = { 54 | name: 'Random Dev', 55 | email: 'test@email.com', 56 | password: 'q1w2e3r4', 57 | }; 58 | const usersRoute = new users_route_1.default(); 59 | const users = usersRoute.usersController.userService.users; 60 | users.findUnique = jest.fn().mockReturnValue(null); 61 | users.create = jest.fn().mockReturnValue({ 62 | id: 1, 63 | email: userData.email, 64 | password: await bcrypt_1.default.hash(userData.password, 10), 65 | }); 66 | const app = new app_1.default([usersRoute]); 67 | return supertest_1.default(app.getServer()).post(`${usersRoute.path}`).send(userData).expect(201); 68 | }); 69 | }); 70 | describe('[PUT] /users/:id', () => { 71 | it('response Update user', async () => { 72 | const userId = 1; 73 | const userData = { 74 | name: 'James pipe', 75 | email: 'test@email.com', 76 | password: 'q1w2e3r4', 77 | }; 78 | const usersRoute = new users_route_1.default(); 79 | const users = usersRoute.usersController.userService.users; 80 | users.findUnique = jest.fn().mockReturnValue({ 81 | id: userId, 82 | email: userData.email, 83 | password: await bcrypt_1.default.hash(userData.password, 10), 84 | }); 85 | users.update = jest.fn().mockReturnValue({ 86 | id: userId, 87 | email: userData.email, 88 | password: await bcrypt_1.default.hash(userData.password, 10), 89 | }); 90 | const app = new app_1.default([usersRoute]); 91 | return supertest_1.default(app.getServer()).put(`${usersRoute.path}/${userId}`).send(userData).expect(200); 92 | }); 93 | }); 94 | describe('[DELETE] /users/:id', () => { 95 | it('response Delete user', async () => { 96 | const userId = 1; 97 | const userData = { 98 | name: 'Random Dev', 99 | email: 'test@email.com', 100 | password: 'q1w2e3r4', 101 | }; 102 | const usersRoute = new users_route_1.default(); 103 | const users = usersRoute.usersController.userService.users; 104 | users.findUnique = jest.fn().mockReturnValue({ 105 | id: userId, 106 | email: userData.email, 107 | password: await bcrypt_1.default.hash(userData.password, 10), 108 | }); 109 | users.delete = jest.fn().mockReturnValue({ 110 | id: userId, 111 | email: userData.email, 112 | password: await bcrypt_1.default.hash(userData.password, 10), 113 | }); 114 | const app = new app_1.default([usersRoute]); 115 | return supertest_1.default(app.getServer()).delete(`${usersRoute.path}/${userId}`).expect(200); 116 | }); 117 | }); 118 | }); 119 | //# sourceMappingURL=users.test.js.map 120 | -------------------------------------------------------------------------------- /dist/tests/users.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.test.js","sourceRoot":"","sources":["../../src/tests/users.test.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/utils/logger.d.ts: -------------------------------------------------------------------------------- 1 | import winston from 'winston'; 2 | declare const logger: winston.Logger; 3 | declare const stream: { 4 | write: (message: string) => void; 5 | }; 6 | export { logger, stream }; 7 | -------------------------------------------------------------------------------- /dist/utils/logger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.stream = exports.logger = void 0; 4 | const tslib_1 = require('tslib'); 5 | const fs_1 = tslib_1.__importDefault(require('fs')); 6 | const winston_1 = tslib_1.__importDefault(require('winston')); 7 | const winston_daily_rotate_file_1 = tslib_1.__importDefault(require('winston-daily-rotate-file')); 8 | // logs dir 9 | const logDir = __dirname + '/../logs'; 10 | if (!fs_1.default.existsSync(logDir)) { 11 | fs_1.default.mkdirSync(logDir); 12 | } 13 | // Define log format 14 | const logFormat = winston_1.default.format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`); 15 | /* 16 | * Log Level 17 | * error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6 18 | */ 19 | const logger = winston_1.default.createLogger({ 20 | format: winston_1.default.format.combine( 21 | winston_1.default.format.timestamp({ 22 | format: 'YYYY-MM-DD HH:mm:ss', 23 | }), 24 | logFormat, 25 | ), 26 | transports: [ 27 | // debug log setting 28 | new winston_daily_rotate_file_1.default({ 29 | level: 'debug', 30 | datePattern: 'YYYY-MM-DD', 31 | dirname: logDir + '/debug', 32 | filename: `%DATE%.log`, 33 | maxFiles: 30, 34 | json: false, 35 | zippedArchive: true, 36 | }), 37 | // error log setting 38 | new winston_daily_rotate_file_1.default({ 39 | level: 'error', 40 | datePattern: 'YYYY-MM-DD', 41 | dirname: logDir + '/error', 42 | filename: `%DATE%.log`, 43 | maxFiles: 30, 44 | handleExceptions: true, 45 | json: false, 46 | zippedArchive: true, 47 | }), 48 | ], 49 | }); 50 | exports.logger = logger; 51 | logger.add( 52 | new winston_1.default.transports.Console({ 53 | format: winston_1.default.format.combine(winston_1.default.format.splat(), winston_1.default.format.colorize()), 54 | }), 55 | ); 56 | const stream = { 57 | write: message => { 58 | logger.info(message.substring(0, message.lastIndexOf('\n'))); 59 | }, 60 | }; 61 | exports.stream = stream; 62 | //# sourceMappingURL=logger.js.map 63 | -------------------------------------------------------------------------------- /dist/utils/logger.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;;AAAA,oDAAoB;AACpB,8DAA8B;AAC9B,kGAAqD;AAErD,WAAW;AACX,MAAM,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAEtC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;IAC1B,YAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,oBAAoB;AACpB,MAAM,SAAS,GAAG,iBAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,SAAS,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;AAEhH;;;GAGG;AACH,MAAM,MAAM,GAAG,iBAAO,CAAC,YAAY,CAAC;IAClC,MAAM,EAAE,iBAAO,CAAC,MAAM,CAAC,OAAO,CAC5B,iBAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QACvB,MAAM,EAAE,qBAAqB;KAC9B,CAAC,EACF,SAAS,CACV;IACD,UAAU,EAAE;QACV,oBAAoB;QACpB,IAAI,mCAAY,CAAC;YACf,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,YAAY;YACzB,OAAO,EAAE,MAAM,GAAG,QAAQ;YAC1B,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,KAAK;YACX,aAAa,EAAE,IAAI;SACpB,CAAC;QACF,oBAAoB;QACpB,IAAI,mCAAY,CAAC;YACf,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,YAAY;YACzB,OAAO,EAAE,MAAM,GAAG,QAAQ;YAC1B,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,EAAE;YACZ,gBAAgB,EAAE,IAAI;YACtB,IAAI,EAAE,KAAK;YACX,aAAa,EAAE,IAAI;SACpB,CAAC;KACH;CACF,CAAC,CAAC;AAcM,wBAAM;AAZf,MAAM,CAAC,GAAG,CACR,IAAI,iBAAO,CAAC,UAAU,CAAC,OAAO,CAAC;IAC7B,MAAM,EAAE,iBAAO,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,iBAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;CAClF,CAAC,CACH,CAAC;AAEF,MAAM,MAAM,GAAG;IACb,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE;QACzB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF,CAAC;AAEe,wBAAM"} -------------------------------------------------------------------------------- /dist/utils/util.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @method isEmpty 3 | * @param {String | Number | Object} value 4 | * @returns {Boolean} true & false 5 | * @description this value is Empty Check 6 | */ 7 | export declare const isEmpty: (value: string | number | object) => boolean; 8 | -------------------------------------------------------------------------------- /dist/utils/util.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.isEmpty = void 0; 4 | /** 5 | * @method isEmpty 6 | * @param {String | Number | Object} value 7 | * @returns {Boolean} true & false 8 | * @description this value is Empty Check 9 | */ 10 | const isEmpty = value => { 11 | if (value === null) { 12 | return true; 13 | } else if (typeof value !== 'number' && value === '') { 14 | return true; 15 | } else if (value === 'undefined' || value === undefined) { 16 | return true; 17 | } else if (value !== null && typeof value === 'object' && !Object.keys(value).length) { 18 | return true; 19 | } else { 20 | return false; 21 | } 22 | }; 23 | exports.isEmpty = isEmpty; 24 | //# sourceMappingURL=util.js.map 25 | -------------------------------------------------------------------------------- /dist/utils/util.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/utils/util.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACI,MAAM,OAAO,GAAG,CAAC,KAA+B,EAAW,EAAE;IAClE,IAAI,KAAK,KAAK,IAAI,EAAE;QAClB,OAAO,IAAI,CAAC;KACb;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE;QACpD,OAAO,IAAI,CAAC;KACb;SAAM,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,SAAS,EAAE;QACvD,OAAO,IAAI,CAAC;KACb;SAAM,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;QACpF,OAAO,IAAI,CAAC;KACb;SAAM;QACL,OAAO,KAAK,CAAC;KACd;AACH,CAAC,CAAC;AAZW,QAAA,OAAO,WAYlB"} -------------------------------------------------------------------------------- /dist/utils/validateEnv.d.ts: -------------------------------------------------------------------------------- 1 | declare const validateEnv: () => void; 2 | export default validateEnv; 3 | -------------------------------------------------------------------------------- /dist/utils/validateEnv.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | const envalid_1 = require('envalid'); 4 | const validateEnv = () => { 5 | envalid_1.cleanEnv(process.env, { 6 | NODE_ENV: envalid_1.str(), 7 | PORT: envalid_1.port(), 8 | }); 9 | }; 10 | exports.default = validateEnv; 11 | //# sourceMappingURL=validateEnv.js.map 12 | -------------------------------------------------------------------------------- /dist/utils/validateEnv.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"validateEnv.js","sourceRoot":"","sources":["../../src/utils/validateEnv.ts"],"names":[],"mappings":";;AAAA,qCAA8C;AAE9C,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,kBAAQ,CAAC,OAAO,CAAC,GAAG,EAAE;QACpB,QAAQ,EAAE,aAAG,EAAE;QACf,IAAI,EAAE,cAAI,EAAE;KACb,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,kBAAe,WAAW,CAAC"} -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { pathsToModuleNameMapper } = require('ts-jest/utils'); 2 | const { compilerOptions } = require('./tsconfig.json'); 3 | 4 | module.exports = { 5 | preset: 'ts-jest', 6 | testEnvironment: 'node', 7 | roots: ['/src'], 8 | transform: { 9 | '^.+\\.tsx?$': 'ts-jest', 10 | }, 11 | moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/src' }), 12 | }; 13 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src", ".env"], 3 | "ext": "js,ts,json", 4 | "ignore": ["src/**/*.spec.ts", "src/**/*.test.ts"], 5 | "exec": "ts-node -r tsconfig-paths/register --transpile-only src/server.ts" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "talent", 3 | "version": "0.0.0", 4 | "description": "TypeScript + Prisma + MySQL + Express API Server", 5 | "author": "Muritala David", 6 | "license": "ISC", 7 | "scripts": { 8 | "start": "npm run build && cross-env NODE_ENV=production node dist/server.js", 9 | "dev": "cross-env NODE_ENV=development nodemon", 10 | "build": "tsc && npx tsc-alias", 11 | "test": "jest --forceExit --detectOpenHandles", 12 | "lint": "eslint --ignore-path .gitignore --ext .ts src/", 13 | "lint:fix": "npm run lint -- --fix", 14 | "prisma:init": "prisma init", 15 | "prisma:migrate": "prisma migrate dev --preview-feature", 16 | "prisma:generate": "prisma generate" 17 | }, 18 | "prisma": { 19 | "schema": "./prisma/schema.prisma" 20 | }, 21 | "dependencies": { 22 | "@prisma/client": "^2.24.1", 23 | "@types/nodemailer": "^6.4.2", 24 | "@types/shortid": "^0.0.29", 25 | "bcrypt": "^5.0.1", 26 | "class-transformer": "^0.4.0", 27 | "class-validator": "^0.13.1", 28 | "compression": "^1.7.4", 29 | "config": "^3.3.6", 30 | "cookie-parser": "^1.4.5", 31 | "cors": "^2.8.5", 32 | "cross-env": "^7.0.3", 33 | "crypto": "^1.0.1", 34 | "dotenv": "^10.0.0", 35 | "envalid": "^7.1.0", 36 | "express": "^4.17.1", 37 | "helmet": "^4.6.0", 38 | "hpp": "^0.2.3", 39 | "jest": "^27.0.4", 40 | "jsonwebtoken": "^8.5.1", 41 | "morgan": "^1.10.0", 42 | "multer": "^1.4.2", 43 | "nodemailer": "^6.6.1", 44 | "shortid": "^2.2.16", 45 | "swagger-jsdoc": "^6.0.0", 46 | "swagger-ui-express": "^4.1.6", 47 | "ts-jest": "^27.0.3", 48 | "winston": "^3.3.3", 49 | "winston-daily-rotate-file": "^4.5.5" 50 | }, 51 | "devDependencies": { 52 | "@types/bcrypt": "^5.0.0", 53 | "@types/compression": "^1.7.0", 54 | "@types/config": "^0.0.38", 55 | "@types/cookie-parser": "^1.4.2", 56 | "@types/cors": "^2.8.10", 57 | "@types/dotenv": "^8.2.0", 58 | "@types/express": "^4.17.12", 59 | "@types/helmet": "^4.0.0", 60 | "@types/hpp": "^0.2.1", 61 | "@types/jest": "^26.0.23", 62 | "@types/jsonwebtoken": "^8.5.1", 63 | "@types/morgan": "^1.9.2", 64 | "@types/multer": "^1.4.5", 65 | "@types/node": "^15.12.2", 66 | "@types/supertest": "^2.0.11", 67 | "@types/swagger-jsdoc": "^6.0.0", 68 | "@types/swagger-ui-express": "^4.1.2", 69 | "@types/winston": "^2.4.4", 70 | "@typescript-eslint/eslint-plugin": "^4.26.1", 71 | "@typescript-eslint/parser": "^4.26.1", 72 | "eslint": "^7.28.0", 73 | "eslint-config-prettier": "^8.3.0", 74 | "eslint-plugin-prettier": "^3.4.0", 75 | "husky": "^6.0.0", 76 | "lint-staged": "^11.0.0", 77 | "node-config": "^0.0.2", 78 | "node-gyp": "^8.1.0", 79 | "nodemon": "^2.0.7", 80 | "prettier": "^2.3.1", 81 | "prisma": "^2.24.1", 82 | "supertest": "^6.1.3", 83 | "ts-node": "^10.0.0", 84 | "tsconfig-paths": "^3.9.0", 85 | "typescript": "^4.3.2" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /prisma/.gitignore: -------------------------------------------------------------------------------- 1 | migrations -------------------------------------------------------------------------------- /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 = "mysql" -------------------------------------------------------------------------------- /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 | datasource db { 5 | provider = "mysql" 6 | url = env("DATABASE_URL") 7 | } 8 | 9 | generator client { 10 | provider = "prisma-client-js" 11 | } 12 | 13 | model Post { 14 | id Int @default(autoincrement()) @id 15 | createdAt DateTime @default(now()) 16 | updatedAt DateTime @updatedAt 17 | title String @db.VarChar(255) 18 | content String? @db.Text 19 | img Json? @db.Json 20 | published Boolean @default(false) 21 | author User @relation(fields: [authorId], references: [id]) 22 | authorId Int 23 | } 24 | 25 | model User { 26 | id Int @default(autoincrement()) @id 27 | email String @unique 28 | name String 29 | img String 30 | password String 31 | isVerified Boolean @default(false) 32 | posts Post[] 33 | tokens Token[] 34 | } 35 | 36 | model Token { 37 | id Int @default(autoincrement()) @id 38 | user User @relation(fields: [userId], references: [id]) 39 | userId Int 40 | token String 41 | createdAt DateTime @default(now()) 42 | updatedAt DateTime @default(now()) 43 | 44 | @@map("tokens") 45 | } 46 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | process.env['NODE_CONFIG_DIR'] = __dirname + '/configs'; 2 | 3 | import compression from 'compression'; 4 | import cookieParser from 'cookie-parser'; 5 | import express from 'express'; 6 | import helmet from 'helmet'; 7 | import hpp from 'hpp'; 8 | import morgan from 'morgan'; 9 | import swaggerJSDoc from 'swagger-jsdoc'; 10 | import swaggerUi from 'swagger-ui-express'; 11 | import Routes from '@interfaces/routes.interface'; 12 | import errorMiddleware from '@middlewares/error.middleware'; 13 | import { logger, stream } from '@utils/logger'; 14 | 15 | class App { 16 | public app: express.Application; 17 | public port: string | number; 18 | public env: string; 19 | 20 | constructor(routes: Routes[]) { 21 | this.app = express(); 22 | this.port = process.env.PORT || 3000; 23 | this.env = process.env.NODE_ENV || 'development'; 24 | 25 | this.initializeMiddlewares(); 26 | this.initializeRoutes(routes); 27 | this.initializeSwagger(); 28 | this.initializeErrorHandling(); 29 | } 30 | 31 | public listen() { 32 | this.app.listen(this.port, () => { 33 | logger.info(`=================================`); 34 | logger.info(`======= ENV: ${this.env} =======`); 35 | logger.info(`🚀 App listening on the port ${this.port}`); 36 | logger.info(`=================================`); 37 | }); 38 | } 39 | 40 | public getServer() { 41 | return this.app; 42 | } 43 | 44 | private initializeMiddlewares() { 45 | if (this.env === 'production') { 46 | this.app.use(morgan('combined', { stream })); 47 | } else { 48 | this.app.use(morgan('dev', { stream })); 49 | } 50 | 51 | this.app.use(hpp()); 52 | this.app.use(helmet()); 53 | this.app.use(compression()); 54 | this.app.use(express.json()); 55 | this.app.use(express.urlencoded({ extended: true })); 56 | this.app.use(cookieParser()); 57 | } 58 | 59 | private initializeRoutes(routes: Routes[]) { 60 | routes.forEach(route => { 61 | this.app.use('/api', route.router); 62 | }); 63 | } 64 | 65 | private initializeSwagger() { 66 | const options = { 67 | swaggerDefinition: { 68 | info: { 69 | openapi: '3.0.0', 70 | title: 'CoderByte Task', 71 | version: '1.0.0', 72 | description: 'Api playgroud for api coderbyte task', 73 | }, 74 | }, 75 | apis: ['swagger.yaml'], 76 | }; 77 | 78 | const specs = swaggerJSDoc(options); 79 | this.app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs)); 80 | } 81 | 82 | private initializeErrorHandling() { 83 | this.app.use(errorMiddleware); 84 | } 85 | } 86 | 87 | export default App; 88 | -------------------------------------------------------------------------------- /src/configs/development.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "development", 3 | "secretKey": "secretKey" 4 | } 5 | -------------------------------------------------------------------------------- /src/configs/production.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "production", 3 | "secretKey": "secretKey" 4 | } 5 | -------------------------------------------------------------------------------- /src/configs/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "test", 3 | "secretKey": "secretKey" 4 | } 5 | -------------------------------------------------------------------------------- /src/controllers/auth.controller.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { User } from '@prisma/client'; 3 | import { CreateUserDto, ResetPasswordDto, UserLoginDto, VerifyToken } from '@dtos/users.dto'; 4 | import { RequestWithUser } from '@interfaces/auth.interface'; 5 | import AuthService from '@services/auth.service'; 6 | 7 | class AuthController { 8 | public authService = new AuthService(); 9 | 10 | public signUp = async (req: Request, res: Response, next: NextFunction): Promise => { 11 | try { 12 | const userData: CreateUserDto = req.body; 13 | userData.img = String(req.file.path); 14 | const signUpUserData: User = await this.authService.signup(userData, userData.img); 15 | 16 | res.status(201).json({ data: signUpUserData, message: 'signup' }); 17 | } catch (error) { 18 | next(error); 19 | } 20 | }; 21 | 22 | public logIn = async (req: Request, res: Response, next: NextFunction): Promise => { 23 | try { 24 | const userData: UserLoginDto = req.body; 25 | const { cookie, findUser, tokenData } = await this.authService.login(userData); 26 | 27 | res.setHeader('Set-Cookie', [cookie]); 28 | res.status(200).json({ token: tokenData, data: findUser, message: 'login successful' }); 29 | } catch (error) { 30 | next(error); 31 | } 32 | }; 33 | 34 | public logOut = async (req: RequestWithUser, res: Response, next: NextFunction): Promise => { 35 | try { 36 | const userData: User = req.user; 37 | const logOutUserData: User = await this.authService.logout(userData); 38 | 39 | res.setHeader('Set-Cookie', ['Authorization=; Max-age=0']); 40 | res.status(200).json({ data: logOutUserData, message: 'logout' }); 41 | } catch (error) { 42 | next(error); 43 | } 44 | }; 45 | 46 | public verify = async (req: RequestWithUser, res: Response, next: NextFunction): Promise => { 47 | try { 48 | const tokenData: VerifyToken = req.body; 49 | const result = await this.authService.VerifyEmail(tokenData); 50 | res.status(200).json({ data: result, message: 'Email verified successfully' }); 51 | } catch (error) { 52 | next(error); 53 | } 54 | }; 55 | 56 | public requestEmailVerification = async (req: RequestWithUser, res: Response, next: NextFunction): Promise => { 57 | try { 58 | const email = req.query.email; 59 | const result = await this.authService.RequestEmailVerification(email.toString()); 60 | res.status(200).json({ data: result, message: 'Email verfication link sent' }); 61 | } catch (error) { 62 | next(error); 63 | } 64 | }; 65 | 66 | public requestPasswordReset = async (req: RequestWithUser, res: Response, next: NextFunction): Promise => { 67 | try { 68 | const email = req.query.email; 69 | const result = await this.authService.RequestPasswordReset(email.toString()); 70 | res.status(200).json({ data: result, message: 'Password reset link sent' }); 71 | } catch (error) { 72 | next(error); 73 | } 74 | }; 75 | 76 | public resetPassword = async (req: RequestWithUser, res: Response, next: NextFunction): Promise => { 77 | try { 78 | const data: ResetPasswordDto = req.body; 79 | const result = await this.authService.ResetPassword(data); 80 | res.status(200).json({ data: result, message: 'Password updated' }); 81 | } catch (error) { 82 | next(error); 83 | } 84 | }; 85 | } 86 | 87 | export default AuthController; 88 | -------------------------------------------------------------------------------- /src/controllers/index.controller.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | 3 | class IndexController { 4 | public index = (req: Request, res: Response, next: NextFunction): Response => { 5 | try { 6 | return res.status(200).send({ 7 | message: 'Application Live ❤', 8 | author: 'Muritala David', 9 | github: 'https://github.com/Fn-studyo', 10 | }); 11 | } catch (error) { 12 | next(error); 13 | } 14 | }; 15 | } 16 | 17 | export default IndexController; 18 | -------------------------------------------------------------------------------- /src/controllers/post.controller.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { PrismaClient, Post } from '@prisma/client'; 3 | import { PostDTO, UpdatePostDto } from '@dtos/post.dto'; 4 | import PostService from '@services/post.service'; 5 | 6 | class PostController { 7 | public postService = new PostService(); 8 | public post = new PrismaClient().post; 9 | 10 | public create = async (req: Request, res: Response, next: NextFunction): Promise => { 11 | try { 12 | const postData: PostDTO = req.body; 13 | postData.authorId = req.user.id; 14 | postData.img = req.files; 15 | const post: Post = await this.postService.createPost(postData, postData.img); 16 | res.status(201).json({ data: post, message: 'Post draft saved successfully' }); 17 | } catch (error) { 18 | next(error); 19 | } 20 | }; 21 | 22 | public publish = async (req: Request, res: Response, next: NextFunction): Promise => { 23 | try { 24 | const post: Post = await this.postService.publishPost(Number(req.params.id)); 25 | 26 | res.status(201).json({ data: post, message: 'Your post is now live' }); 27 | } catch (error) { 28 | next(error); 29 | } 30 | }; 31 | 32 | public getById = async (req: Request, res: Response, next: NextFunction): Promise => { 33 | try { 34 | const post: Post = await this.postService.getPostById(Number(req.params.id)); 35 | 36 | res.status(201).json({ data: post, message: 'success' }); 37 | } catch (error) { 38 | next(error); 39 | } 40 | }; 41 | 42 | public get = async (req: Request, res: Response, next: NextFunction): Promise => { 43 | try { 44 | const { id } = req.user; 45 | const post: Post[] = await this.postService.getAllPost(Number(id)); 46 | 47 | res.status(201).json({ data: post, message: 'success' }); 48 | } catch (error) { 49 | next(error); 50 | } 51 | }; 52 | 53 | public update = async (req: Request, res: Response, next: NextFunction): Promise => { 54 | try { 55 | const data: UpdatePostDto = req.body; 56 | const post: Post = await this.postService.updateAPost(Number(req.params.id), data); 57 | 58 | res.status(201).json({ data: post, message: 'post updated succesfully' }); 59 | } catch (error) { 60 | next(error); 61 | } 62 | }; 63 | 64 | public delete = async (req: Request, res: Response, next: NextFunction): Promise => { 65 | try { 66 | const post: Post = await this.postService.deleteAPost(Number(req.params.id)); 67 | 68 | res.status(201).json({ data: post, message: 'post deleted succesfully' }); 69 | } catch (error) { 70 | next(error); 71 | } 72 | }; 73 | } 74 | 75 | export default PostController; 76 | -------------------------------------------------------------------------------- /src/controllers/users.controller.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { User } from '@prisma/client'; 3 | import { UpdateUserDto } from '@dtos/users.dto'; 4 | import userService from '@services/users.service'; 5 | 6 | class UsersController { 7 | public userService = new userService(); 8 | 9 | public getUsers = async (req: Request, res: Response, next: NextFunction): Promise => { 10 | try { 11 | const findAllUsersData: User[] = await this.userService.findAllUser(); 12 | 13 | res.status(200).json({ data: findAllUsersData, message: 'findAll' }); 14 | } catch (error) { 15 | next(error); 16 | } 17 | }; 18 | 19 | public getUserById = async (req: Request, res: Response, next: NextFunction): Promise => { 20 | try { 21 | const userId = Number(req.params.id); 22 | const findOneUserData: User = await this.userService.findUserById(userId); 23 | 24 | res.status(200).json({ data: findOneUserData, message: 'findOne' }); 25 | } catch (error) { 26 | next(error); 27 | } 28 | }; 29 | 30 | public updateUser = async (req: Request, res: Response, next: NextFunction): Promise => { 31 | try { 32 | const userId = 1; //Number(req.user.id); 33 | const userData: UpdateUserDto = req.body; 34 | const updateUserData: User = await this.userService.updateUser(userId, userData); 35 | 36 | res.status(200).json({ data: updateUserData, message: 'updated' }); 37 | } catch (error) { 38 | next(error); 39 | } 40 | }; 41 | 42 | public deleteUser = async (req: Request, res: Response, next: NextFunction): Promise => { 43 | try { 44 | const userId = Number(req.user.id); 45 | const deleteUserData: User = await this.userService.deleteUser(userId); 46 | 47 | res.status(200).json({ data: deleteUserData, message: 'deleted' }); 48 | } catch (error) { 49 | next(error); 50 | } 51 | }; 52 | } 53 | 54 | export default UsersController; 55 | -------------------------------------------------------------------------------- /src/dtos/post.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsOptional, IsString, IsNumber } from 'class-validator'; 2 | 3 | class PostDTO { 4 | @IsOptional() 5 | @IsNumber() 6 | authorId: number; 7 | 8 | @IsNotEmpty({ message: 'Title name is required' }) 9 | @IsString() 10 | title: string; 11 | 12 | @IsString() 13 | content: string; 14 | 15 | @IsOptional() 16 | img: string; 17 | } 18 | 19 | class UpdatePostDto { 20 | @IsOptional() 21 | @IsString() 22 | title?: string; 23 | 24 | @IsOptional() 25 | @IsString() 26 | content?: string; 27 | 28 | @IsOptional() 29 | img?: string; 30 | } 31 | 32 | export { PostDTO, UpdatePostDto }; 33 | -------------------------------------------------------------------------------- /src/dtos/users.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, IsNotEmpty, IsNumber, IsOptional, IsString, Matches, MinLength } from 'class-validator'; 2 | import { Match } from '@utils/match.decorator'; 3 | 4 | class CreateUserDto { 5 | @IsNotEmpty({ message: 'Name is required' }) 6 | @IsString() 7 | public name: string; 8 | 9 | @IsNotEmpty({ message: 'Email address is required' }) 10 | @IsEmail() 11 | public email: string; 12 | 13 | //@IsNotEmpty({ message: 'Image is required' }) 14 | @IsOptional() 15 | public img: string; 16 | 17 | @IsNotEmpty({ message: 'Password is required' }) 18 | @MinLength(7) 19 | //@Matches(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, { message: 'password too weak' }) 20 | @IsString() 21 | public password: string; 22 | 23 | // @IsString() 24 | // @MinLength(7) 25 | // @Match('password', { message: 'Password does not match'}) 26 | // passwordConfirm: string; 27 | } 28 | 29 | class UpdateUserDto { 30 | @IsOptional() 31 | @IsString() 32 | public name?: string; 33 | 34 | @IsOptional() 35 | @IsEmail() 36 | public email?: string; 37 | 38 | //@IsNotEmpty({ message: 'Image is required' }) 39 | @IsOptional() 40 | public img?: string; 41 | 42 | @IsOptional() 43 | @IsString() 44 | public password?: string; 45 | } 46 | 47 | class UserLoginDto { 48 | @IsEmail() 49 | public email: string; 50 | 51 | @IsString() 52 | public password: string; 53 | } 54 | 55 | class UserMailDto { 56 | name: string; 57 | email: string; 58 | } 59 | 60 | class VerifyToken { 61 | @IsNotEmpty({ message: 'Verification token is required' }) 62 | @IsString() 63 | token: string; 64 | 65 | @IsNotEmpty({ message: 'User id is required' }) 66 | @IsNumber() 67 | id: number; 68 | } 69 | 70 | class MailDto { 71 | @IsNotEmpty({ message: 'Email address is required' }) 72 | @IsString() 73 | @IsEmail() 74 | email: string; 75 | } 76 | 77 | class ResetPasswordDto { 78 | @IsNotEmpty({ message: 'User id is required' }) 79 | @IsNumber() 80 | userId: number; 81 | 82 | @IsNotEmpty({ message: 'Reset token is required' }) 83 | @IsString() 84 | resetToken: string; 85 | 86 | @IsNotEmpty({ message: 'Password is required' }) 87 | @Matches(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, { message: 'password too weak' }) 88 | @MinLength(7) 89 | @IsString() 90 | public password: string; 91 | 92 | @IsString() 93 | @MinLength(7) 94 | @Match('password', { message: 'Password does not match' }) 95 | passwordConfirm: string; 96 | } 97 | 98 | export { CreateUserDto, UserLoginDto, UserMailDto, VerifyToken, MailDto, ResetPasswordDto, UpdateUserDto }; 99 | -------------------------------------------------------------------------------- /src/exceptions/HttpException.ts: -------------------------------------------------------------------------------- 1 | class HttpException extends Error { 2 | public status: number; 3 | public message: string; 4 | 5 | constructor(status: number, message: string) { 6 | super(message); 7 | this.status = status; 8 | this.message = message; 9 | } 10 | } 11 | 12 | export default HttpException; 13 | -------------------------------------------------------------------------------- /src/interfaces/auth.interface.ts: -------------------------------------------------------------------------------- 1 | import { Request } from 'express'; 2 | import { User } from '@prisma/client'; 3 | 4 | export interface DataStoredInToken { 5 | id: number; 6 | } 7 | 8 | export interface TokenData { 9 | token: string; 10 | expiresIn: number; 11 | } 12 | 13 | export interface RequestWithUser extends Request { 14 | user: User; 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/routes.interface.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | 3 | interface Route { 4 | path?: string; 5 | router: Router; 6 | } 7 | 8 | export default Route; 9 | -------------------------------------------------------------------------------- /src/logs/debug/.97c8ad83eeb58d63df9ef18134f1cead3fa43941-audit.json: -------------------------------------------------------------------------------- 1 | { 2 | "keep": { 3 | "days": false, 4 | "amount": 30 5 | }, 6 | "auditLog": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\debug\\.97c8ad83eeb58d63df9ef18134f1cead3fa43941-audit.json", 7 | "files": [ 8 | { 9 | "date": 1623195889965, 10 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\debug\\2021-06-08.log", 11 | "hash": "16118ec24ed33963f7b1bc2975579f3e" 12 | }, 13 | { 14 | "date": 1623273495556, 15 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\debug\\2021-06-09.log", 16 | "hash": "7240a64b36ba4babe537812876105715" 17 | }, 18 | { 19 | "date": 1623378002828, 20 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\debug\\2021-06-10.log", 21 | "hash": "4a6ab79b6237783e577a08c50cb2d5d3" 22 | }, 23 | { 24 | "date": 1623394838829, 25 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\debug\\2021-06-11.log", 26 | "hash": "8d81736ee5575dc00546ddba7d9c700f" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /src/logs/error/.2b1b4f2f1d0bbd27a23e3aee5c4dd77c3dfabd17-audit.json: -------------------------------------------------------------------------------- 1 | { 2 | "keep": { 3 | "days": false, 4 | "amount": 30 5 | }, 6 | "auditLog": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\error\\.2b1b4f2f1d0bbd27a23e3aee5c4dd77c3dfabd17-audit.json", 7 | "files": [ 8 | { 9 | "date": 1623195889976, 10 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\error\\2021-06-08.log", 11 | "hash": "0137c32823d271357be0780e76b36006" 12 | }, 13 | { 14 | "date": 1623273495564, 15 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\error\\2021-06-09.log", 16 | "hash": "7e580234e31c40b1887d0ec3d8ff0651" 17 | }, 18 | { 19 | "date": 1623378002864, 20 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\error\\2021-06-10.log", 21 | "hash": "62e56415f17a36db583303dc2f417401" 22 | }, 23 | { 24 | "date": 1623394854359, 25 | "name": "C:\\Users\\HP\\OneDrive\\Desktop\\talent\\src\\logs\\error\\2021-06-11.log", 26 | "hash": "87d15c0c39c102bc930e138b6b48ab3c" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /src/logs/error/2021-06-08.log: -------------------------------------------------------------------------------- 1 | 2021-06-08 16:51:05 error: [POST] /users >> StatusCode:: 400, Message:: property id should not exist 2 | 2021-06-08 16:51:23 error: [POST] /users >> StatusCode:: 500, Message:: 3 | Invalid `prisma.user.create()` invocation: 4 | 5 | { 6 | data: { 7 | name: 'Muritala David', 8 | ~~~~ 9 | email: 'davmuri1414@gmail.com', 10 | password: '$2b$10$7FXvL0VJo/6NkIBkmXFg2.5ZzPqQKMXvYbGgOGblmlrOdoif3aQgG' 11 | } 12 | } 13 | 14 | Unknown arg `name` in data.name for type UserCreateInput. Did you mean `email`? Available args: 15 | type UserCreateInput { 16 | email: String 17 | password: String 18 | } 19 | 20 | 21 | 2021-06-08 17:01:05 error: [POST] /users >> StatusCode:: 409, Message:: You're email davmuri1414@gmail.com already exists 22 | 2021-06-08 19:32:48 error: [POST] /users >> StatusCode:: 400, Message:: property title should not exist, property note should not exist, property token should not exist, property started_at should not exist, property duration should not exist, property caller_id should not exist, property participants should not exist, name must be a string,Name is required, email must be an email,Email address is required, password must be a string,password must be longer than or equal to 7 characters,Password is required 23 | 2021-06-08 19:33:10 error: [POST] /users >> StatusCode:: 400, Message:: name must be a string,Name is required, email must be an email,Email address is required, password must be a string,password must be longer than or equal to 7 characters,Password is required 24 | 2021-06-08 19:41:29 error: [POST] /api/auth/signup >> StatusCode:: 400, Message:: name must be a string,Name is required, email must be an email,Email address is required, password must be a string,password must be longer than or equal to 7 characters,Password is required 25 | 2021-06-08 19:42:46 error: [POST] /api/auth/signup >> StatusCode:: 404, Message:: Email does not exist 26 | 2021-06-08 19:45:13 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 27 | Error: listen EADDRINUSE: address already in use :::3000 28 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 29 | at listenInCluster (net.js:1366:12) 30 | at Server.listen (net.js:1452:7) 31 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 32 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 33 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 34 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 35 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 36 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 37 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 38 | 2021-06-08 19:45:48 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 39 | Error: listen EADDRINUSE: address already in use :::3000 40 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 41 | at listenInCluster (net.js:1366:12) 42 | at Server.listen (net.js:1452:7) 43 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 44 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 45 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 46 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 47 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 48 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 49 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 50 | 2021-06-08 19:47:28 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 51 | Error: listen EADDRINUSE: address already in use :::3000 52 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 53 | at listenInCluster (net.js:1366:12) 54 | at Server.listen (net.js:1452:7) 55 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 56 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 57 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 58 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 59 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 60 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 61 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 62 | 2021-06-08 19:48:04 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 63 | Error: listen EADDRINUSE: address already in use :::3000 64 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 65 | at listenInCluster (net.js:1366:12) 66 | at Server.listen (net.js:1452:7) 67 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 68 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 69 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 70 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 71 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 72 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 73 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 74 | 2021-06-08 19:49:42 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 75 | Error: listen EADDRINUSE: address already in use :::3000 76 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 77 | at listenInCluster (net.js:1366:12) 78 | at Server.listen (net.js:1452:7) 79 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 80 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 81 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 82 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 83 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 84 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 85 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 86 | 2021-06-08 19:49:58 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 87 | Error: listen EADDRINUSE: address already in use :::3000 88 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 89 | at listenInCluster (net.js:1366:12) 90 | at Server.listen (net.js:1452:7) 91 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 92 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 93 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 94 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 95 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 96 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 97 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 98 | 2021-06-08 19:50:24 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 99 | Error: listen EADDRINUSE: address already in use :::3000 100 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 101 | at listenInCluster (net.js:1366:12) 102 | at Server.listen (net.js:1452:7) 103 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 104 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 105 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 106 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 107 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 108 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 109 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 110 | 2021-06-08 19:52:58 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 111 | Error: listen EADDRINUSE: address already in use :::3000 112 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 113 | at listenInCluster (net.js:1366:12) 114 | at Server.listen (net.js:1452:7) 115 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 116 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 117 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 118 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 119 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 120 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 121 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 122 | 2021-06-08 20:00:18 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 123 | Error: listen EADDRINUSE: address already in use :::3000 124 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 125 | at listenInCluster (net.js:1366:12) 126 | at Server.listen (net.js:1452:7) 127 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 128 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:33:14) 129 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 130 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 131 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 132 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 133 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 134 | 2021-06-08 20:13:49 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 135 | Error: listen EADDRINUSE: address already in use :::3000 136 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 137 | at listenInCluster (net.js:1366:12) 138 | at Server.listen (net.js:1452:7) 139 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 140 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:32:14) 141 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 142 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 143 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 144 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 145 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 146 | 2021-06-08 20:20:00 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 147 | Error: listen EADDRINUSE: address already in use :::3000 148 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 149 | at listenInCluster (net.js:1366:12) 150 | at Server.listen (net.js:1452:7) 151 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 152 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:32:14) 153 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 154 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 155 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 156 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 157 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 158 | 2021-06-08 20:35:48 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 159 | Error: listen EADDRINUSE: address already in use :::3000 160 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 161 | at listenInCluster (net.js:1366:12) 162 | at Server.listen (net.js:1452:7) 163 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 164 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:32:14) 165 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 166 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 167 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 168 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 169 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 170 | 2021-06-08 20:59:03 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 171 | Error: listen EADDRINUSE: address already in use :::3000 172 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 173 | at listenInCluster (net.js:1366:12) 174 | at Server.listen (net.js:1452:7) 175 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 176 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:32:14) 177 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 178 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 179 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 180 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 181 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 182 | 2021-06-08 21:00:52 error: uncaughtException: listen EADDRINUSE: address already in use :::3000 183 | Error: listen EADDRINUSE: address already in use :::3000 184 | at Server.setupListenHandle [as _listen2] (net.js:1318:16) 185 | at listenInCluster (net.js:1366:12) 186 | at Server.listen (net.js:1452:7) 187 | at Function.listen (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\application.js:618:24) 188 | at App.listen (C:\Users\HP\OneDrive\Desktop\talent\src\app.ts:32:14) 189 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:14:5) 190 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 191 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 192 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 193 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 194 | 2021-06-08 21:13:15 error: [POST] /api/auth/signup >> StatusCode:: 400, Message:: name must be a string,Name is required, email must be an email,Email address is required, password must be a string,password must be longer than or equal to 7 characters,Password is required 195 | 2021-06-08 21:13:52 error: [POST] /api/auth/signup >> StatusCode:: 404, Message:: Email does not exist 196 | 2021-06-08 21:15:13 error: [POST] /api/auth/signup >> StatusCode:: 500, Message:: data must be a string or Buffer and salt must either be a salt string or a number of rounds 197 | 2021-06-08 21:17:59 error: [POST] /api/auth/signup >> StatusCode:: 500, Message:: data must be a string or Buffer and salt must either be a salt string or a number of rounds 198 | 2021-06-08 21:18:48 error: [POST] /api/auth/signup >> StatusCode:: 409, Message:: You're email davmuri1414@gmail.com already exists 199 | 2021-06-08 21:19:19 error: [POST] /api/auth/signup >> StatusCode:: 500, Message:: connect ECONNREFUSED 127.0.0.1:587 200 | 2021-06-08 21:24:12 error: uncaughtException: Cannot find module './../configs' 201 | Require stack: 202 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 203 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 204 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 205 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 206 | Error: Cannot find module './../configs' 207 | Require stack: 208 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 209 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 210 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 211 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 212 | at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15) 213 | at Function.Module._resolveFilename (C:\Users\HP\OneDrive\Desktop\talent\node_modules\tsconfig-paths\lib\register.js:75:40) 214 | at Function.Module._load (internal/modules/cjs/loader.js:730:27) 215 | at Module.require (internal/modules/cjs/loader.js:957:19) 216 | at require (internal/modules/cjs/helpers.js:88:18) 217 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts:10:1) 218 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 219 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 220 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 221 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 222 | 2021-06-08 21:25:17 error: uncaughtException: Cannot find module './../configs' 223 | Require stack: 224 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 225 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 226 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 227 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 228 | Error: Cannot find module './../configs' 229 | Require stack: 230 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 231 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 232 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 233 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 234 | at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15) 235 | at Function.Module._resolveFilename (C:\Users\HP\OneDrive\Desktop\talent\node_modules\tsconfig-paths\lib\register.js:75:40) 236 | at Function.Module._load (internal/modules/cjs/loader.js:730:27) 237 | at Module.require (internal/modules/cjs/loader.js:957:19) 238 | at require (internal/modules/cjs/helpers.js:88:18) 239 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts:10:1) 240 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 241 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 242 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 243 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 244 | 2021-06-08 21:26:33 error: uncaughtException: Cannot find module './../configs' 245 | Require stack: 246 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 247 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 248 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 249 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 250 | Error: Cannot find module './../configs' 251 | Require stack: 252 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 253 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 254 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 255 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 256 | at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15) 257 | at Function.Module._resolveFilename (C:\Users\HP\OneDrive\Desktop\talent\node_modules\tsconfig-paths\lib\register.js:75:40) 258 | at Function.Module._load (internal/modules/cjs/loader.js:730:27) 259 | at Module.require (internal/modules/cjs/loader.js:957:19) 260 | at require (internal/modules/cjs/helpers.js:88:18) 261 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts:10:1) 262 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 263 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 264 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 265 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 266 | 2021-06-08 21:27:41 error: uncaughtException: Cannot find module './../configs' 267 | Require stack: 268 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 269 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 270 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 271 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 272 | Error: Cannot find module './../configs' 273 | Require stack: 274 | - C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts 275 | - C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts 276 | - C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts 277 | - C:\Users\HP\OneDrive\Desktop\talent\src\server.ts 278 | at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15) 279 | at Function.Module._resolveFilename (C:\Users\HP\OneDrive\Desktop\talent\node_modules\tsconfig-paths\lib\register.js:75:40) 280 | at Function.Module._load (internal/modules/cjs/loader.js:730:27) 281 | at Module.require (internal/modules/cjs/loader.js:957:19) 282 | at require (internal/modules/cjs/helpers.js:88:18) 283 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\services\auth.service.ts:10:1) 284 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 285 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 286 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 287 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 288 | 2021-06-08 21:48:52 error: [POST] /api/auth/signup >> StatusCode:: 500, Message:: 7224:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:c:\ws\deps\openssl\openssl\ssl\record\ssl3_record.c:332: 289 | 290 | 2021-06-08 21:55:13 error: [POST] /api/auth/signup >> StatusCode:: 409, Message:: You're email davmuri1414@gmail.com already exists 291 | 2021-06-08 22:01:07 error: uncaughtException: Route.post() requires a callback function but got a [object Undefined] 292 | Error: Route.post() requires a callback function but got a [object Undefined] 293 | at Route. [as post] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\router\route.js:202:15) 294 | at Function.proto. [as post] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\express\lib\router\index.js:510:19) 295 | at AuthRoute.initializeRoutes (C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts:20:17) 296 | at new AuthRoute (C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts:14:10) 297 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\server.ts:12:58) 298 | at Module._compile (internal/modules/cjs/loader.js:1068:30) 299 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 300 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 301 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 302 | at Module.load (internal/modules/cjs/loader.js:933:32) 303 | 2021-06-08 22:01:56 error: uncaughtException: ⨯ Unable to compile TypeScript: 304 | src/controllers/auth.controller.ts:48:13 - error TS1003: Identifier expected. 305 | 306 | 48 } catch() 307 |    ~ 308 | src/controllers/auth.controller.ts:49:3 - error TS1005: '{' expected. 309 | 310 | 49 } 311 |    ~ 312 | 313 | TSError: ⨯ Unable to compile TypeScript: 314 | src/controllers/auth.controller.ts:48:13 - error TS1003: Identifier expected. 315 | 316 | 48 } catch() 317 |    ~ 318 | src/controllers/auth.controller.ts:49:3 - error TS1005: '{' expected. 319 | 320 | 49 } 321 |    ~ 322 | 323 | at createTSError (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:587:12) 324 | at reportTSError (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:591:19) 325 | at getOutput (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1174:34) 326 | at Object.compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1189:32) 327 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:42) 328 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 329 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 330 | at Module.load (internal/modules/cjs/loader.js:933:32) 331 | at Function.Module._load (internal/modules/cjs/loader.js:774:14) 332 | at Module.require (internal/modules/cjs/loader.js:957:19) 333 | 2021-06-08 22:02:40 error: uncaughtException: Missing initializer in const declaration 334 | C:\Users\HP\OneDrive\Desktop\talent\src\controllers\auth.controller.ts:42 335 | const token; 336 | ^^^^^ 337 | 338 | SyntaxError: Missing initializer in const declaration 339 | at wrapSafe (internal/modules/cjs/loader.js:984:16) 340 | at Module._compile (internal/modules/cjs/loader.js:1032:27) 341 | at Module.m._compile (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1295:23) 342 | at Module._extensions..js (internal/modules/cjs/loader.js:1097:10) 343 | at Object.require.extensions. [as .ts] (C:\Users\HP\OneDrive\Desktop\talent\node_modules\ts-node\src\index.ts:1298:12) 344 | at Module.load (internal/modules/cjs/loader.js:933:32) 345 | at Function.Module._load (internal/modules/cjs/loader.js:774:14) 346 | at Module.require (internal/modules/cjs/loader.js:957:19) 347 | at require (internal/modules/cjs/helpers.js:88:18) 348 | at Object. (C:\Users\HP\OneDrive\Desktop\talent\src\routes\auth.route.ts:2:1) 349 | 2021-06-08 22:08:14 error: [POST] /api/auth/verify >> StatusCode:: 400, Message:: token must be a string,Verification token is required, id must be a string,User id is required 350 | 2021-06-08 22:27:00 error: [POST] /api/auth/verify >> StatusCode:: 400, Message:: Verification token is required, id must be a string 351 | 2021-06-08 22:27:08 error: [POST] /api/auth/verify >> StatusCode:: 400, Message:: Verification token is required, id must be a string 352 | 2021-06-08 22:28:17 error: [POST] /api/auth/verify >> StatusCode:: 400, Message:: id must be a string 353 | 2021-06-08 22:29:31 error: [POST] /api/auth/verify >> StatusCode:: 404, Message:: User does not exist 354 | 2021-06-08 22:29:51 error: [POST] /api/auth/verify >> StatusCode:: 401, Message:: Invalid or expired password reset token 355 | -------------------------------------------------------------------------------- /src/middlewares/auth.middleware.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Response } from 'express'; 2 | import config from 'config'; 3 | import jwt from 'jsonwebtoken'; 4 | import { PrismaClient } from '@prisma/client'; 5 | import HttpException from '@exceptions/HttpException'; 6 | import { DataStoredInToken, RequestWithUser } from '@interfaces/auth.interface'; 7 | 8 | const authMiddleware = async (req: RequestWithUser, res: Response, next: NextFunction) => { 9 | try { 10 | const Authorization = req.cookies['Authorization'] || req.header('Authorization').split('Bearer ')[1] || null; 11 | 12 | if (Authorization) { 13 | const secretKey: string = config.get('secretKey'); 14 | const verificationResponse = (await jwt.verify(Authorization, secretKey)) as DataStoredInToken; 15 | const userId = verificationResponse.id; 16 | 17 | const users = new PrismaClient().user; 18 | const findUser = await users.findUnique({ where: { id: Number(userId) } }); 19 | 20 | if (findUser) { 21 | req.user = findUser; 22 | next(); 23 | } else { 24 | next(new HttpException(401, 'Wrong authentication token')); 25 | } 26 | } else { 27 | next(new HttpException(404, 'Authentication token missing')); 28 | } 29 | } catch (error) { 30 | next(new HttpException(401, 'Wrong authentication token')); 31 | } 32 | }; 33 | 34 | export default authMiddleware; 35 | -------------------------------------------------------------------------------- /src/middlewares/error.middleware.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import HttpException from '@exceptions/HttpException'; 3 | import { logger } from '@utils/logger'; 4 | 5 | const errorMiddleware = (error: HttpException, req: Request, res: Response, next: NextFunction) => { 6 | try { 7 | const status: number = error.status || 500; 8 | const message: string = error.message || 'Something went wrong'; 9 | 10 | logger.error(`[${req.method}] ${req.path} >> StatusCode:: ${status}, Message:: ${message}`); 11 | res.status(status).json({ message }); 12 | } catch (error) { 13 | next(error); 14 | } 15 | }; 16 | 17 | export default errorMiddleware; 18 | -------------------------------------------------------------------------------- /src/middlewares/multer.middleware.ts: -------------------------------------------------------------------------------- 1 | import multer from 'multer'; 2 | import { Request } from 'express'; 3 | 4 | const storage = multer.diskStorage({ 5 | destination: (req: Request, file, cb) => { 6 | cb(null, './uploads'); 7 | }, 8 | filename: (req: Request, file, cb) => { 9 | cb(null, `${Date.now()}-${file.originalname}`); 10 | }, 11 | }); 12 | 13 | const options: multer.Options = { 14 | storage, 15 | limits: { 16 | fileSize: 2000000, 17 | }, 18 | fileFilter(req: Request, file, cb) { 19 | if (!file.originalname.match(/\.(jpg|png|JPG|PNG|JPEG|jpeg)$/)) return cb(new Error('file format incorrect')); 20 | cb(null, true); 21 | }, 22 | }; 23 | 24 | export const upload = multer(options); 25 | -------------------------------------------------------------------------------- /src/middlewares/validation.middleware.ts: -------------------------------------------------------------------------------- 1 | import { plainToClass } from 'class-transformer'; 2 | import { validate, ValidationError } from 'class-validator'; 3 | import { RequestHandler } from 'express'; 4 | import HttpException from '@exceptions/HttpException'; 5 | 6 | const validationMiddleware = ( 7 | type: any, 8 | value: string | 'body' | 'query' | 'params' = 'body', 9 | skipMissingProperties = false, 10 | whitelist = true, 11 | forbidNonWhitelisted = true, 12 | ): RequestHandler => { 13 | return (req, res, next) => { 14 | validate(plainToClass(type, req[value]), { skipMissingProperties, whitelist, forbidNonWhitelisted }).then((errors: ValidationError[]) => { 15 | if (errors.length > 0) { 16 | const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(', '); 17 | next(new HttpException(400, message)); 18 | } else { 19 | next(); 20 | } 21 | }); 22 | }; 23 | }; 24 | 25 | export default validationMiddleware; 26 | -------------------------------------------------------------------------------- /src/routes/auth.route.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import AuthController from '@controllers/auth.controller'; 3 | import { CreateUserDto, VerifyToken, MailDto, ResetPasswordDto, UserLoginDto } from '@dtos/users.dto'; 4 | import Route from '@interfaces/routes.interface'; 5 | import authMiddleware from '@middlewares/auth.middleware'; 6 | import validationMiddleware from '@middlewares/validation.middleware'; 7 | import { upload } from '@middlewares/multer.middleware'; 8 | 9 | class AuthRoute implements Route { 10 | public path = '/auth'; 11 | public router = Router(); 12 | public authController = new AuthController(); 13 | 14 | constructor() { 15 | this.initializeRoutes(); 16 | } 17 | 18 | private initializeRoutes() { 19 | this.router.post(`${this.path}/signup`, upload.single('img'), validationMiddleware(CreateUserDto, 'body'), this.authController.signUp); 20 | this.router.post(`${this.path}/login`, validationMiddleware(UserLoginDto, 'body'), this.authController.logIn); 21 | this.router.post(`${this.path}/verify`, validationMiddleware(VerifyToken, 'body'), this.authController.verify); 22 | this.router.post(`${this.path}/logout`, authMiddleware, this.authController.logOut); 23 | this.router.post(`${this.path}/request-email-verification`, validationMiddleware(MailDto, 'query'), this.authController.requestEmailVerification); 24 | this.router.post(`${this.path}/request-password-reset`, validationMiddleware(MailDto, 'query'), this.authController.requestPasswordReset); 25 | this.router.post( 26 | `${this.path}/reset-password`, 27 | authMiddleware, 28 | validationMiddleware(ResetPasswordDto, 'body'), 29 | this.authController.resetPassword, 30 | ); 31 | // 32 | } 33 | } 34 | 35 | export default AuthRoute; 36 | -------------------------------------------------------------------------------- /src/routes/index.route.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import IndexController from '@controllers/index.controller'; 3 | import Route from '@interfaces/routes.interface'; 4 | 5 | class IndexRoute implements Route { 6 | public path = '/'; 7 | public router = Router(); 8 | public indexController = new IndexController(); 9 | 10 | constructor() { 11 | this.initializeRoutes(); 12 | } 13 | 14 | private initializeRoutes() { 15 | this.router.get(`${this.path}`, this.indexController.index); 16 | } 17 | } 18 | 19 | export default IndexRoute; 20 | -------------------------------------------------------------------------------- /src/routes/post.route.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import PostController from '@controllers/post.controller'; 3 | import Route from '@interfaces/routes.interface'; 4 | import { PostDTO, UpdatePostDto } from '@dtos/post.dto'; 5 | import authMiddleware from '@middlewares/auth.middleware'; 6 | import validationMiddleware from '@middlewares/validation.middleware'; 7 | import { upload } from '@middlewares/multer.middleware'; 8 | 9 | class PostRoute implements Route { 10 | public path = '/posts'; 11 | public router = Router(); 12 | public postController = new PostController(); 13 | 14 | constructor() { 15 | this.initializeRoutes(); 16 | } 17 | 18 | private initializeRoutes() { 19 | //create a post 20 | this.router.post(`${this.path}/create`, authMiddleware, upload.array('img'), validationMiddleware(PostDTO, 'body'), this.postController.create); 21 | //publish a post 22 | this.router.put(`${this.path}/publish/:id(\\d+)`, authMiddleware, validationMiddleware(PostDTO, 'param', true), this.postController.publish); 23 | //get post by id 24 | this.router.get(`${this.path}/:id(\\d+)`, authMiddleware, this.postController.getById); 25 | //get all posts 26 | this.router.get(`${this.path}`, authMiddleware, this.postController.get); 27 | //delete a post 28 | this.router.delete(`${this.path}/delete/:id(\\d+)`, authMiddleware, this.postController.delete); 29 | //update a post 30 | this.router.put(`${this.path}/update/:id(\\d+)`, authMiddleware, validationMiddleware(UpdatePostDto, 'body'), this.postController.update); 31 | } 32 | } 33 | 34 | export default PostRoute; 35 | -------------------------------------------------------------------------------- /src/routes/users.route.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import UsersController from '@controllers/users.controller'; 3 | import { CreateUserDto } from '@dtos/users.dto'; 4 | import Route from '@interfaces/routes.interface'; 5 | import authMiddleware from '@middlewares/auth.middleware'; 6 | import validationMiddleware from '@middlewares/validation.middleware'; 7 | 8 | class UsersRoute implements Route { 9 | public path = '/users'; 10 | public router = Router(); 11 | public usersController = new UsersController(); 12 | 13 | constructor() { 14 | this.initializeRoutes(); 15 | } 16 | 17 | private initializeRoutes() { 18 | this.router.get(`${this.path}`, this.usersController.getUsers); 19 | this.router.get(`${this.path}/:id(\\d+)`, this.usersController.getUserById); 20 | this.router.put(`${this.path}`, authMiddleware, validationMiddleware(CreateUserDto, 'body', true), this.usersController.updateUser); 21 | this.router.delete(`${this.path}`, authMiddleware, this.usersController.deleteUser); 22 | } 23 | } 24 | 25 | export default UsersRoute; 26 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | process.env['NODE_CONFIG_DIR'] = __dirname + '/configs'; 2 | 3 | import 'dotenv/config'; 4 | import App from '@/app'; 5 | import AuthRoute from '@routes/auth.route'; 6 | import IndexRoute from '@routes/index.route'; 7 | import UsersRoute from '@routes/users.route'; 8 | import PostRoute from '@routes/post.route'; 9 | import validateEnv from '@utils/validateEnv'; 10 | 11 | validateEnv(); 12 | 13 | const app = new App([new IndexRoute(), new UsersRoute(), new AuthRoute(), new PostRoute()]); 14 | 15 | app.listen(); 16 | -------------------------------------------------------------------------------- /src/services/auth.service.ts: -------------------------------------------------------------------------------- 1 | import bcrypt from 'bcrypt'; 2 | import config from 'config'; 3 | import jwt from 'jsonwebtoken'; 4 | import { PrismaClient, User, Token } from '@prisma/client'; 5 | import { CreateUserDto, ResetPasswordDto, UserLoginDto, VerifyToken } from '@dtos/users.dto'; 6 | import HttpException from '@exceptions/HttpException'; 7 | import { DataStoredInToken, TokenData } from '@interfaces/auth.interface'; 8 | import { isEmpty } from '@utils/util'; 9 | import MailService from './mail.service'; 10 | import crypto from 'crypto'; 11 | 12 | class AuthService { 13 | public users = new PrismaClient().user; 14 | public token = new PrismaClient().token; 15 | 16 | public async signup(userData: CreateUserDto, buffed): Promise { 17 | if (isEmpty(userData)) throw new HttpException(400, "You're not userData"); 18 | 19 | const findUser: User = await this.users.findUnique({ where: { email: userData.email } }); 20 | if (findUser) throw new HttpException(409, `${userData.email} already exists`); 21 | 22 | const hashedPassword = await bcrypt.hash(userData.password, 10); 23 | 24 | const createUserData = await this.users.create({ data: { ...userData, img: buffed, password: hashedPassword } }); 25 | 26 | // Request email verification 27 | await this.RequestEmailVerification(userData.email); 28 | 29 | return createUserData; 30 | } 31 | 32 | public async login(userData: UserLoginDto): Promise<{ cookie: string; findUser: User; tokenData: TokenData }> { 33 | if (isEmpty(userData)) throw new HttpException(400, "You're not userData"); 34 | 35 | const findUser: User = await this.users.findUnique({ where: { email: userData.email } }); 36 | if (!findUser) throw new HttpException(409, `You're email ${userData.email} not found`); 37 | 38 | const isPasswordMatching: boolean = await bcrypt.compare(userData.password, findUser.password); 39 | if (!isPasswordMatching) throw new HttpException(401, 'Email or password may be incorrect'); 40 | 41 | const tokenData = this.createToken(findUser); 42 | const cookie = this.createCookie(tokenData); 43 | 44 | return { cookie, findUser, tokenData }; 45 | } 46 | 47 | public async logout(userData: User): Promise { 48 | if (isEmpty(userData)) throw new HttpException(400, "You're not userData"); 49 | 50 | const findUser: User = await this.users.findFirst({ where: { email: userData.email, password: userData.password } }); 51 | if (!findUser) throw new HttpException(409, "You're not user"); 52 | 53 | return findUser; 54 | } 55 | 56 | public createToken(user: User): TokenData { 57 | const dataStoredInToken: DataStoredInToken = { id: user.id }; 58 | const secretKey: string = config.get('secretKey'); 59 | const expiresIn: number = 60 * 60; 60 | 61 | return { expiresIn, token: jwt.sign(dataStoredInToken, secretKey, { expiresIn }) }; 62 | } 63 | 64 | public createCookie(tokenData: TokenData): string { 65 | return `Authorization=${tokenData.token}; HttpOnly; Max-Age=${tokenData.expiresIn};`; 66 | } 67 | 68 | //Send Verification to user 69 | async RequestEmailVerification(email: string) { 70 | const user = await this.users.findFirst({ 71 | where: { 72 | email, 73 | }, 74 | }); 75 | if (!user) throw new HttpException(404, 'Email does not exist'); 76 | if (user.isVerified) throw new HttpException(409, 'Email is already verified'); 77 | 78 | const token: Token = await this.token.findFirst({ 79 | where: { 80 | userId: user.id, 81 | }, 82 | }); 83 | if (token) 84 | await this.token.delete({ 85 | where: { 86 | id: token.id, 87 | }, 88 | }); 89 | 90 | const verifyToken = crypto.randomBytes(32).toString('hex'); 91 | const hash = await bcrypt.hash(verifyToken, 10); 92 | 93 | await this.token.create({ 94 | data: { 95 | userId: user.id, 96 | token: hash, 97 | }, 98 | }); 99 | const link = `${process.env.CLIENT_URL}/email-verification?uid=${user.id}&verifyToken=${verifyToken}`; 100 | console.log(link); 101 | 102 | // Send Mail 103 | await new MailService(user).sendEmailVerificationMail(link); 104 | 105 | return; 106 | } 107 | 108 | async VerifyEmail(tokenData: VerifyToken) { 109 | const user = await this.users.findFirst({ 110 | where: { 111 | id: tokenData.id, 112 | }, 113 | }); 114 | if (!user) throw new HttpException(404, 'User does not exist'); 115 | if (user.isVerified) throw new HttpException(409, 'Email is already verified'); 116 | 117 | const VToken = await this.token.findFirst({ 118 | where: { 119 | userId: user.id, 120 | }, 121 | }); 122 | if (!VToken) throw new HttpException(401, 'Invalid or expired password reset token'); 123 | 124 | const isValid = await bcrypt.compare(tokenData.token, VToken.token); 125 | if (!isValid) throw new HttpException(401, 'Invalid or expired password reset token'); 126 | 127 | await this.users.update({ 128 | where: { 129 | id: user.id, 130 | }, 131 | data: { 132 | isVerified: true, 133 | }, 134 | }); 135 | 136 | await this.token.delete({ 137 | where: { 138 | id: VToken.id, 139 | }, 140 | }); 141 | 142 | return; 143 | } 144 | 145 | async RequestPasswordReset(email: string) { 146 | const user = await this.users.findFirst({ 147 | where: { 148 | email, 149 | }, 150 | }); 151 | if (!user) throw new HttpException(404, 'Email does not exist'); 152 | 153 | const token: Token = await this.token.findFirst({ 154 | where: { 155 | userId: user.id, 156 | }, 157 | }); 158 | if (token) 159 | await this.token.delete({ 160 | where: { 161 | id: token.id, 162 | }, 163 | }); 164 | 165 | const resetToken = crypto.randomBytes(32).toString('hex'); 166 | const hash = await bcrypt.hash(resetToken, 10); 167 | 168 | await this.token.create({ 169 | data: { 170 | userId: user.id, 171 | token: hash, 172 | }, 173 | }); 174 | 175 | const link = `${process.env.CLIENT_URL}/reset-password?uid=${user.id}&resetToken=${resetToken}`; 176 | 177 | // Send Mail 178 | await new MailService(user).sendPasswordResetMail(link); 179 | 180 | return; 181 | } 182 | 183 | async ResetPassword(data: ResetPasswordDto) { 184 | const { userId, resetToken, password } = data; 185 | 186 | const token: Token = await this.token.findFirst({ 187 | where: { 188 | userId, 189 | }, 190 | }); 191 | if (!token) throw new HttpException(401, 'Invalid or expired password reset token'); 192 | 193 | const isValid = await bcrypt.compare(resetToken, token.token); 194 | if (!isValid) throw new HttpException(401, 'Invalid or expired password reset token'); 195 | 196 | const hash = await bcrypt.hash(password, 10); 197 | 198 | await this.users.update({ 199 | where: { 200 | id: userId, 201 | }, 202 | data: { 203 | password: hash, 204 | }, 205 | }); 206 | 207 | await this.token.delete({ 208 | where: { 209 | id: token.id, 210 | }, 211 | }); 212 | 213 | return; 214 | } 215 | } 216 | 217 | export default AuthService; 218 | -------------------------------------------------------------------------------- /src/services/mail.service.ts: -------------------------------------------------------------------------------- 1 | import nodemailer from 'nodemailer'; 2 | import SMTPTransport from 'nodemailer/lib/smtp-transport'; 3 | import HttpException from '@exceptions/HttpException'; 4 | import { UserMailDto } from '@/dtos/users.dto'; 5 | 6 | class MailService { 7 | user: UserMailDto; 8 | constructor(user: UserMailDto) { 9 | this.user = user; 10 | } 11 | 12 | async send(subject, content, recipient, from) { 13 | from = from || `My APP `; 14 | content = content || ' '; 15 | 16 | if (!recipient || recipient.length < 1) throw new HttpException(400, 'Recipient is required'); 17 | if (!subject) throw new HttpException(400, 'Subject is required'); 18 | 19 | // Nodemailer transporter 20 | const transporter = nodemailer.createTransport({ 21 | host: 'smtp.mailtrap.io', 22 | port: 2525, 23 | auth: { 24 | user: '4024b919401df6', 25 | pass: '15af4ca851e3ec', 26 | }, 27 | tls: { 28 | rejectUnauthorized: false, 29 | }, 30 | } as SMTPTransport.Options); 31 | 32 | const result = await transporter.sendMail({ 33 | from, 34 | to: Array.isArray(recipient) ? recipient.join() : recipient, 35 | subject, 36 | text: content, 37 | }); 38 | 39 | if (!result) throw new HttpException(500, 'Unable to send mail'); 40 | 41 | return result; 42 | } 43 | 44 | async sendEmailVerificationMail(link) { 45 | console.log(this.user.email); 46 | const subject = 'Email Verification'; 47 | const content = `Hey ${this.user.name}, Please click on the link to verify your email ${link}`; 48 | const recipient = this.user.email; 49 | 50 | return await this.send(subject, content, recipient, 'Muritala David'); 51 | } 52 | 53 | async sendPasswordResetMail(link) { 54 | const subject = 'Reset password'; 55 | const content = `Hey ${this.user.name}, Please click on the link to reset your password ${link}`; 56 | const recipient = this.user.email; 57 | 58 | return await this.send(subject, content, recipient, 'Muritala David'); 59 | } 60 | } 61 | 62 | export default MailService; 63 | -------------------------------------------------------------------------------- /src/services/post.service.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient, Post } from '@prisma/client'; 2 | import { PostDTO, UpdatePostDto } from '@dtos/post.dto'; 3 | import HttpException from '@exceptions/HttpException'; 4 | import { isEmpty } from '@utils/util'; 5 | 6 | class PostService { 7 | public post = new PrismaClient().post; 8 | 9 | public async createPost(postData: PostDTO, buffed): Promise { 10 | if (isEmpty(postData)) throw new HttpException(400, "You're not postData"); 11 | 12 | //get information from buffed 13 | const images = []; 14 | for (const i in buffed) { 15 | images.push(buffed[i].path); 16 | } 17 | 18 | const post = await this.post.create({ 19 | data: { 20 | ...postData, 21 | img: images, 22 | }, 23 | }); 24 | 25 | return post; 26 | } 27 | 28 | public async publishPost(id: number): Promise { 29 | return await this.post.update({ 30 | where: { 31 | id, 32 | }, 33 | data: { 34 | published: true, 35 | }, 36 | }); 37 | } 38 | 39 | public async getPostById(id: number): Promise { 40 | return await this.post.findFirst({ 41 | where: { 42 | id, 43 | }, 44 | }); 45 | } 46 | 47 | public async getAllPost(id: number): Promise { 48 | return await this.post.findMany({ 49 | where: { 50 | authorId: id, 51 | }, 52 | }); 53 | } 54 | 55 | public async deleteAPost(id: number): Promise { 56 | return await this.post.delete({ 57 | where: { 58 | id, 59 | }, 60 | }); 61 | } 62 | 63 | public async updateAPost(id: number, data: UpdatePostDto): Promise { 64 | return await this.post.update({ 65 | where: { 66 | id, 67 | }, 68 | data, 69 | }); 70 | } 71 | } 72 | 73 | export default PostService; 74 | -------------------------------------------------------------------------------- /src/services/users.service.ts: -------------------------------------------------------------------------------- 1 | import bcrypt from 'bcrypt'; 2 | import { PrismaClient, User } from '@prisma/client'; 3 | import { CreateUserDto, UpdateUserDto } from '@dtos/users.dto'; 4 | import HttpException from '@exceptions/HttpException'; 5 | import { isEmpty } from '@utils/util'; 6 | 7 | class UserService { 8 | public users = new PrismaClient().user; 9 | 10 | public async findAllUser(): Promise { 11 | return await this.users.findMany(); 12 | } 13 | 14 | public async findUserById(userId: number): Promise { 15 | if (isEmpty(userId)) throw new HttpException(400, "You're not userId"); 16 | 17 | const findUser: User = await this.users.findUnique({ where: { id: userId } }); 18 | if (!findUser) throw new HttpException(409, "You're not user"); 19 | 20 | return findUser; 21 | } 22 | 23 | public async createUser(userData: CreateUserDto): Promise { 24 | if (isEmpty(userData)) throw new HttpException(400, "You're not userData"); 25 | 26 | const findUser: User = await this.users.findUnique({ where: { email: userData.email } }); 27 | if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); 28 | const hashedPassword = await bcrypt.hash(userData.password, 10); 29 | return await this.users.create({ data: { ...userData, password: hashedPassword } }); 30 | } 31 | 32 | public async updateUser(userId: number, userData: UpdateUserDto): Promise { 33 | if (isEmpty(userData)) throw new HttpException(400, "You're not a updateData"); 34 | 35 | const findUser: User = await this.users.findUnique({ where: { id: userId } }); 36 | if (!findUser) throw new HttpException(404, 'User not found'); 37 | 38 | return await this.users.update({ where: { id: userId }, data: { ...userData } }); 39 | } 40 | 41 | public async deleteUser(userId: number): Promise { 42 | if (isEmpty(userId)) throw new HttpException(400, "You're not userId"); 43 | 44 | const findUser: User = await this.users.findUnique({ where: { id: userId } }); 45 | if (!findUser) throw new HttpException(409, "You're not user"); 46 | 47 | return await this.users.delete({ where: { id: userId } }); 48 | } 49 | } 50 | 51 | export default UserService; 52 | -------------------------------------------------------------------------------- /src/tests/auth.test.ts: -------------------------------------------------------------------------------- 1 | import bcrypt from 'bcrypt'; 2 | import request from 'supertest'; 3 | import { User } from '@prisma/client'; 4 | import App from '@/app'; 5 | import { CreateUserDto, UserLoginDto } from '@dtos/users.dto'; 6 | import AuthRoute from '@routes/auth.route'; 7 | 8 | afterAll(async () => { 9 | await new Promise(resolve => setTimeout(() => resolve(), 500)); 10 | }); 11 | 12 | describe('Testing Auth', () => { 13 | describe('[POST] /signup', () => { 14 | it('response should have the Create userData', async () => { 15 | const userData: CreateUserDto = { 16 | name: 'Random Dev', 17 | email: 'test@email.com', 18 | password: 'q1w2e3r4', 19 | img: '', 20 | }; 21 | 22 | const authRoute = new AuthRoute(); 23 | const users = authRoute.authController.authService.users; 24 | 25 | users.findUnique = jest.fn().mockReturnValue(null); 26 | users.create = jest.fn().mockReturnValue({ 27 | id: 1, 28 | email: userData.email, 29 | password: await bcrypt.hash(userData.password, 10), 30 | }); 31 | 32 | const app = new App([authRoute]); 33 | return request(app.getServer()).post(`${authRoute.path}signup`).send(userData).expect(201); 34 | }); 35 | }); 36 | 37 | describe('[POST] /login', () => { 38 | it('response should have the Set-Cookie header with the Authorization token', async () => { 39 | const userData: UserLoginDto = { 40 | email: 'test@email.com', 41 | password: 'q1w2e3r4', 42 | }; 43 | 44 | const authRoute = new AuthRoute(); 45 | const users = authRoute.authController.authService.users; 46 | 47 | users.findUnique = jest.fn().mockReturnValue({ 48 | id: 1, 49 | email: userData.email, 50 | password: await bcrypt.hash(userData.password, 10), 51 | }); 52 | 53 | const app = new App([authRoute]); 54 | return request(app.getServer()) 55 | .post(`${authRoute.path}login`) 56 | .send(userData) 57 | .expect('Set-Cookie', /^Authorization=.+/); 58 | }); 59 | }); 60 | 61 | describe('[POST] /logout', () => { 62 | it('logout Set-Cookie Authorization=; Max-age=0', async () => { 63 | const user: User = { 64 | id: 1, 65 | name: 'Random Dev', 66 | img: '', 67 | email: 'test@email.com', 68 | isVerified: true, 69 | password: 'q1w2e3r4', 70 | }; 71 | 72 | const authRoute = new AuthRoute(); 73 | const users = authRoute.authController.authService.users; 74 | 75 | users.findFirst = jest.fn().mockReturnValue({ 76 | ...user, 77 | password: await bcrypt.hash(user.password, 10), 78 | }); 79 | 80 | const app = new App([authRoute]); 81 | return request(app.getServer()) 82 | .post(`${authRoute.path}logout`) 83 | .expect('Set-Cookie', /^Authorization=;/); 84 | }); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import request from 'supertest'; 2 | import App from '@/app'; 3 | import IndexRoute from '@routes/index.route'; 4 | 5 | afterAll(async () => { 6 | await new Promise(resolve => setTimeout(() => resolve(), 500)); 7 | }); 8 | 9 | describe('Testing Index', () => { 10 | describe('[GET] /', () => { 11 | it('response statusCode 200', () => { 12 | const indexRoute = new IndexRoute(); 13 | const app = new App([indexRoute]); 14 | 15 | return request(app.getServer()).get(`${indexRoute.path}`).expect(200); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/tests/post.test.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipethedev/typescript-starter/733b4db48f60ead1f5e307d04dee1a049c19fcec/src/tests/post.test.ts -------------------------------------------------------------------------------- /src/tests/users.test.ts: -------------------------------------------------------------------------------- 1 | import bcrypt from 'bcrypt'; 2 | import request from 'supertest'; 3 | import App from '@/app'; 4 | import { CreateUserDto, UpdateUserDto } from '@dtos/users.dto'; 5 | import UserRoute from '@routes/users.route'; 6 | 7 | afterAll(async () => { 8 | await new Promise(resolve => setTimeout(() => resolve(), 500)); 9 | }); 10 | 11 | describe('Testing Users', () => { 12 | describe('[GET] /users', () => { 13 | it('response findAll users', async () => { 14 | const usersRoute = new UserRoute(); 15 | const users = usersRoute.usersController.userService.users; 16 | 17 | users.findMany = jest.fn().mockReturnValue([ 18 | { 19 | id: 1, 20 | email: 'a@email.com', 21 | password: await bcrypt.hash('q1w2e3r4!', 10), 22 | }, 23 | { 24 | id: 2, 25 | email: 'b@email.com', 26 | password: await bcrypt.hash('a1s2d3f4!', 10), 27 | }, 28 | { 29 | id: 3, 30 | email: 'c@email.com', 31 | password: await bcrypt.hash('z1x2c3v4!', 10), 32 | }, 33 | ]); 34 | 35 | const app = new App([usersRoute]); 36 | return request(app.getServer()).get(`${usersRoute.path}`).expect(200); 37 | }); 38 | }); 39 | 40 | describe('[GET] /users/:id', () => { 41 | it('response findOne user', async () => { 42 | const userId = 1; 43 | 44 | const usersRoute = new UserRoute(); 45 | const users = usersRoute.usersController.userService.users; 46 | 47 | users.findUnique = jest.fn().mockReturnValue({ 48 | id: 1, 49 | email: 'a@email.com', 50 | password: await bcrypt.hash('q1w2e3r4!', 10), 51 | }); 52 | 53 | const app = new App([usersRoute]); 54 | return request(app.getServer()).get(`${usersRoute.path}/${userId}`).expect(200); 55 | }); 56 | }); 57 | 58 | describe('[POST] /users', () => { 59 | it('response Create user', async () => { 60 | const userData: CreateUserDto = { 61 | name: 'Random Dev', 62 | email: 'test@email.com', 63 | password: 'q1w2e3r4', 64 | img: '', 65 | }; 66 | 67 | const usersRoute = new UserRoute(); 68 | const users = usersRoute.usersController.userService.users; 69 | 70 | users.findUnique = jest.fn().mockReturnValue(null); 71 | users.create = jest.fn().mockReturnValue({ 72 | id: 1, 73 | email: userData.email, 74 | password: await bcrypt.hash(userData.password, 10), 75 | }); 76 | 77 | const app = new App([usersRoute]); 78 | return request(app.getServer()).post(`${usersRoute.path}`).send(userData).expect(201); 79 | }); 80 | }); 81 | 82 | describe('[PUT] /users/:id', () => { 83 | it('response Update user', async () => { 84 | const userId = 1; 85 | const userData: UpdateUserDto = { 86 | name: 'James pipe', 87 | email: 'test@email.com', 88 | password: 'q1w2e3r4', 89 | }; 90 | 91 | const usersRoute = new UserRoute(); 92 | const users = usersRoute.usersController.userService.users; 93 | 94 | users.findUnique = jest.fn().mockReturnValue({ 95 | id: userId, 96 | email: userData.email, 97 | password: await bcrypt.hash(userData.password, 10), 98 | }); 99 | users.update = jest.fn().mockReturnValue({ 100 | id: userId, 101 | email: userData.email, 102 | password: await bcrypt.hash(userData.password, 10), 103 | }); 104 | 105 | const app = new App([usersRoute]); 106 | return request(app.getServer()).put(`${usersRoute.path}/${userId}`).send(userData).expect(200); 107 | }); 108 | }); 109 | 110 | describe('[DELETE] /users/:id', () => { 111 | it('response Delete user', async () => { 112 | const userId = 1; 113 | const userData: CreateUserDto = { 114 | name: 'Random Dev', 115 | email: 'test@email.com', 116 | password: 'q1w2e3r4', 117 | img: '', 118 | }; 119 | 120 | const usersRoute = new UserRoute(); 121 | const users = usersRoute.usersController.userService.users; 122 | 123 | users.findUnique = jest.fn().mockReturnValue({ 124 | id: userId, 125 | email: userData.email, 126 | password: await bcrypt.hash(userData.password, 10), 127 | }); 128 | users.delete = jest.fn().mockReturnValue({ 129 | id: userId, 130 | email: userData.email, 131 | password: await bcrypt.hash(userData.password, 10), 132 | }); 133 | 134 | const app = new App([usersRoute]); 135 | return request(app.getServer()).delete(`${usersRoute.path}/${userId}`).expect(200); 136 | }); 137 | }); 138 | }); 139 | -------------------------------------------------------------------------------- /src/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import winston from 'winston'; 3 | import winstonDaily from 'winston-daily-rotate-file'; 4 | 5 | // logs dir 6 | const logDir = __dirname + '/../logs'; 7 | 8 | if (!fs.existsSync(logDir)) { 9 | fs.mkdirSync(logDir); 10 | } 11 | 12 | // Define log format 13 | const logFormat = winston.format.printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`); 14 | 15 | /* 16 | * Log Level 17 | * error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6 18 | */ 19 | const logger = winston.createLogger({ 20 | format: winston.format.combine( 21 | winston.format.timestamp({ 22 | format: 'YYYY-MM-DD HH:mm:ss', 23 | }), 24 | logFormat, 25 | ), 26 | transports: [ 27 | // debug log setting 28 | new winstonDaily({ 29 | level: 'debug', 30 | datePattern: 'YYYY-MM-DD', 31 | dirname: logDir + '/debug', // log file /logs/debug/*.log in save 32 | filename: `%DATE%.log`, 33 | maxFiles: 30, // 30 Days saved 34 | json: false, 35 | zippedArchive: true, 36 | }), 37 | // error log setting 38 | new winstonDaily({ 39 | level: 'error', 40 | datePattern: 'YYYY-MM-DD', 41 | dirname: logDir + '/error', // log file /logs/error/*.log in save 42 | filename: `%DATE%.log`, 43 | maxFiles: 30, // 30 Days saved 44 | handleExceptions: true, 45 | json: false, 46 | zippedArchive: true, 47 | }), 48 | ], 49 | }); 50 | 51 | logger.add( 52 | new winston.transports.Console({ 53 | format: winston.format.combine(winston.format.splat(), winston.format.colorize()), 54 | }), 55 | ); 56 | 57 | const stream = { 58 | write: (message: string) => { 59 | logger.info(message.substring(0, message.lastIndexOf('\n'))); 60 | }, 61 | }; 62 | 63 | export { logger, stream }; 64 | -------------------------------------------------------------------------------- /src/utils/match.decorator.ts: -------------------------------------------------------------------------------- 1 | import { registerDecorator, ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'; 2 | 3 | export function Match(property: string, validationOptions?: ValidationOptions) { 4 | return (object: any, propertyName: string) => { 5 | registerDecorator({ 6 | target: object.constructor, 7 | propertyName, 8 | options: validationOptions, 9 | constraints: [property], 10 | validator: MatchConstraint, 11 | }); 12 | }; 13 | } 14 | 15 | @ValidatorConstraint({ name: 'Match' }) 16 | export class MatchConstraint implements ValidatorConstraintInterface { 17 | validate(value: any, args: ValidationArguments) { 18 | const [relatedPropertyName] = args.constraints; 19 | const relatedValue = (args.object as any)[relatedPropertyName]; 20 | return value === relatedValue; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/utils/multer.ts: -------------------------------------------------------------------------------- 1 | import HttpException from '@exceptions/HttpException'; 2 | import multer from 'multer'; 3 | import shortid from 'shortid'; 4 | 5 | const storage = multer.diskStorage({ 6 | destination: (req, file, cb) => { 7 | // Store files in "uploads" folder 8 | cb(null, 'uploads'); 9 | }, 10 | filename: (req, file, cb) => { 11 | // Generate unique filename form current date and shortid 12 | const fileExt = file.originalname.split('.').pop(); 13 | const filename = `${shortid.generate()}_${new Date().getTime()}.${fileExt}`; 14 | 15 | cb(null, filename); 16 | }, 17 | }); 18 | 19 | const limits = { 20 | // Maximum file size of 5mb 21 | fileSize: 5 * 1024 * 1024, 22 | }; 23 | 24 | const fileFilter = (req, file, cb) => { 25 | //Accepted file types 26 | const mimeTypes = ['image/jpeg', 'image/png']; 27 | 28 | // Check if file type is accepted 29 | if (mimeTypes.includes(file.mimetype)) { 30 | cb(null, true); 31 | } else { 32 | cb(new HttpException(400, 'Invalid file type'), false); 33 | } 34 | }; 35 | 36 | export default multer({ storage, limits, fileFilter }); 37 | -------------------------------------------------------------------------------- /src/utils/util.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @method isEmpty 3 | * @param {String | Number | Object} value 4 | * @returns {Boolean} true & false 5 | * @description this value is Empty Check 6 | */ 7 | export const isEmpty = (value: string | number | object): boolean => { 8 | if (value === null) { 9 | return true; 10 | } else if (typeof value !== 'number' && value === '') { 11 | return true; 12 | } else if (value === 'undefined' || value === undefined) { 13 | return true; 14 | } else if (value !== null && typeof value === 'object' && !Object.keys(value).length) { 15 | return true; 16 | } else { 17 | return false; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/utils/validateEnv.ts: -------------------------------------------------------------------------------- 1 | import { cleanEnv, port, str } from 'envalid'; 2 | 3 | const validateEnv = () => { 4 | cleanEnv(process.env, { 5 | NODE_ENV: str(), 6 | PORT: port(), 7 | }); 8 | }; 9 | 10 | export default validateEnv; 11 | -------------------------------------------------------------------------------- /swagger.yaml: -------------------------------------------------------------------------------- 1 | # servers: 2 | # - url: http://localhost:3000 3 | # components: 4 | # securitySchemes: 5 | # bearerAuth: 6 | # type: http 7 | # scheme: bearer 8 | # security: 9 | # - bearerAuth: [] 10 | paths: 11 | /api/auth/signup: 12 | post: 13 | tags: 14 | - default 15 | summary: Register a user 16 | requestBody: 17 | content: 18 | application/json: 19 | schema: 20 | type: object 21 | example: 22 | name: Muritala David 23 | email: davmuri1414@gmail.com 24 | password: Famzer22@ 25 | img: ok 26 | responses: 27 | '200': 28 | description: Successful response 29 | content: 30 | application/json: {} 31 | /api/auth/verify: 32 | post: 33 | tags: 34 | - default 35 | summary: Verify A User 36 | requestBody: 37 | content: 38 | application/json: 39 | schema: 40 | type: object 41 | example: 42 | token: >- 43 | 8aff3e468636878d22163d5122c38b87125bff813ec2d846a83f9cf03498d7a7 44 | id: 4 45 | responses: 46 | '200': 47 | description: Successful response 48 | content: 49 | application/json: {} 50 | /api/auth/request-email-verification: 51 | post: 52 | tags: 53 | - default 54 | summary: Request Email Verification 55 | requestBody: 56 | content: {} 57 | parameters: 58 | - name: email 59 | in: query 60 | schema: 61 | type: string 62 | example: davmuri1414@gmail.com 63 | responses: 64 | '200': 65 | description: Successful response 66 | content: 67 | application/json: {} 68 | /api/auth/request-password-reset: 69 | post: 70 | tags: 71 | - default 72 | summary: Request Reset Password 73 | requestBody: 74 | content: {} 75 | security: 76 | - bearerAuth: [] 77 | parameters: 78 | - name: email 79 | in: query 80 | schema: 81 | type: string 82 | example: davmuri1414@gmail.com 83 | responses: 84 | '200': 85 | description: Successful response 86 | content: 87 | application/json: {} 88 | /api/users: 89 | put: 90 | tags: 91 | - default 92 | summary: Update A User 93 | requestBody: 94 | content: 95 | application/json: 96 | schema: 97 | type: object 98 | example: 99 | name: Bode Thomas 100 | security: 101 | - bearerAuth: [] 102 | responses: 103 | '200': 104 | description: Successful response 105 | content: 106 | application/json: {} 107 | /api/auth/login: 108 | post: 109 | tags: 110 | - default 111 | summary: Login a user 112 | requestBody: 113 | content: 114 | application/json: 115 | schema: 116 | type: object 117 | example: 118 | email: davmuri1414@gmail.com 119 | password: Famzer22@ 120 | responses: 121 | '200': 122 | description: Successful response 123 | content: 124 | application/json: {} 125 | /api/auth/reset-password: 126 | post: 127 | tags: 128 | - default 129 | summary: Reset Password 130 | requestBody: 131 | content: 132 | application/json: 133 | schema: 134 | type: object 135 | example: 136 | userId: 1 137 | resetToken: >- 138 | 2db3c6ef4e116445ace1d8a5c582bd3098e4fc5a64b7bff33a47098a713908fa 139 | password: passerBy22@ 140 | passwordConfirm: passerBy22@ 141 | responses: 142 | '200': 143 | description: Successful response 144 | content: 145 | application/json: {} 146 | /api/posts/create: 147 | post: 148 | tags: 149 | - default 150 | summary: Create a post 151 | requestBody: 152 | content: 153 | application/json: 154 | schema: 155 | type: object 156 | example: 157 | authorId: 4 158 | title: Example 159 | content: A content 160 | security: 161 | - bearerAuth: [] 162 | responses: 163 | '200': 164 | description: Successful response 165 | content: 166 | application/json: {} 167 | /api/posts/publish/1: 168 | put: 169 | tags: 170 | - default 171 | summary: Publish Post 172 | requestBody: 173 | content: {} 174 | responses: 175 | '200': 176 | description: Successful response 177 | content: 178 | application/json: {} 179 | /api/posts/1: 180 | get: 181 | tags: 182 | - default 183 | summary: Get Post By Id 184 | security: 185 | - bearerAuth: [] 186 | responses: 187 | '200': 188 | description: Successful response 189 | content: 190 | application/json: {} 191 | /api/posts: 192 | get: 193 | tags: 194 | - default 195 | summary: Get all posts 196 | security: 197 | - bearerAuth: [] 198 | responses: 199 | '200': 200 | description: Successful response 201 | content: 202 | application/json: {} -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "lib": ["es2017", "esnext.asynciterable"], 6 | "typeRoots": ["node_modules/@types"], 7 | "allowSyntheticDefaultImports": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "moduleResolution": "node", 12 | "module": "commonjs", 13 | "pretty": true, 14 | "sourceMap": true, 15 | "declaration": true, 16 | "outDir": "./dist", 17 | "allowJs": true, 18 | "noEmit": false, 19 | "esModuleInterop": true, 20 | "resolveJsonModule": true, 21 | "importHelpers": true, 22 | "baseUrl": "src", 23 | "paths": { 24 | "@/*": ["*"], 25 | "@controllers/*": ["controllers/*"], 26 | "@dtos/*": ["dtos/*"], 27 | "@exceptions/*": ["exceptions/*"], 28 | "@interfaces/*": ["interfaces/*"], 29 | "@middlewares/*": ["middlewares/*"], 30 | "@routes/*": ["routes/*"], 31 | "@services/*": ["services/*"], 32 | "@utils/*": ["utils/*"] 33 | } 34 | }, 35 | "include": ["src/**/*.ts", "src/**/*.json", ".env"], 36 | "exclude": ["node_modules"] 37 | } 38 | -------------------------------------------------------------------------------- /uploads/.gitignore: -------------------------------------------------------------------------------- 1 | ./ --------------------------------------------------------------------------------