├── .DS_Store ├── .editorconfig ├── .env ├── .env.test ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── README.md ├── index.ts ├── package.json ├── src ├── .DS_Store ├── helpers │ ├── createSchema.ts │ ├── getIDfromToken.ts │ └── loadenv.ts ├── init │ ├── db.ts │ ├── locales │ │ ├── ar │ │ │ └── translation.json │ │ ├── en │ │ │ └── translation.json │ │ └── index.ts │ ├── localize.ts │ ├── routes.ts │ └── theApp.ts ├── interfaces │ ├── controllers.interface.ts │ ├── interface.ts │ └── types.d.ts └── mvc │ ├── .DS_Store │ ├── controllers │ ├── auth.controller.ts │ ├── index.ts │ └── user.controller.ts │ ├── middlewares │ ├── auth │ │ └── index.ts │ ├── index.ts │ └── userAuth │ │ └── index.ts │ ├── models │ ├── index.ts │ └── user.model.ts │ └── routes │ ├── auth.routes.ts │ ├── index.ts │ ├── routesStrings │ └── index.ts │ └── user.routes.ts └── tsconfig.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/.DS_Store -------------------------------------------------------------------------------- /.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: -------------------------------------------------------------------------------- 1 | DATABASE_URL = mongodb://localhost:27017/test 2 | JWT_KEY=secret -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | MORGAN_FORMAT=tiny 2 | SERVER_PORT=3000 -------------------------------------------------------------------------------- /.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 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | # .env 73 | # .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Package-lock json file 107 | package-lock.json 108 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 150, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "semi": true, 7 | "arrowParens": "avoid" 8 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # express-typescript-mongoose-boilerplate 2 | simple starter for newbies. 3 | 4 | My main goal with this project is a simple and easy starter for new learners. I like you to be focused on the correct learning path and not spending hours in choosing the right project structure. 5 | 6 | > Full Explanation available on Dev Community Post: [here](https://dev.to/nour_abdou/express-typescript-mongoose-boilerplate-2omp) 7 | 8 | ## Features 9 | - Beautiful Code as simple as possible. 10 | - Clear Structure inspired by MVC Model. 11 | - Localization implemention. 12 | - Authorization CRUD example. 13 | 14 | 15 | ## Scripts 16 | 17 | All script are defined in the package-scripts.js file, but the most important ones are listed here. 18 | 19 | ### Install 20 | Install node-ts `npm i -g node-ts` 21 | Install all dependencies with `npm i` 22 | 23 | ### Linting 24 | Run code quality analysis using `npm run lint` or `npm run lint:fix` to fix errors. 25 | 26 | 27 | 28 | 29 | ## Project Structure 30 | 31 | ``` 32 | src\ 33 | |--mvc 34 | |--models\ # Mongoose models (data layer) 35 | |--routes\ # Views routes 36 | |--controllers\ # Route controllers (controller layer) 37 | |--middlewares\ # Custom express middlewares 38 | |--helpers\ # Utility functions 39 | |--app.js # Express app 40 | |--init\ # Init Express app 41 | |--locales\ # translation maps 42 | |--db.ts # Init DB Connection 43 | |--localize.ts # Init localization 44 | |--routes.ts # Init Routes 45 | |--thApp.ts # Express app 46 | |--index.ts # App entry point 47 | ``` 48 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import express, { Express } from 'express'; 2 | import dotenv from 'dotenv'; 3 | import routes from './src/init/routes'; 4 | import localize from './src/init/localize'; 5 | import db from './src/init/db'; 6 | import theApp from './src/init/theApp'; 7 | 8 | dotenv.config(); 9 | const app: Express = express(); 10 | 11 | const cors = require('cors'); 12 | const corsOptions = { 13 | origin: 'http://localhost:8081', 14 | }; 15 | 16 | app.use(cors(corsOptions)); 17 | theApp(app); 18 | localize(app); 19 | db(); 20 | routes(app); 21 | 22 | app.listen(3000, () => { 23 | console.log(`⚡️ [server]: Server is running at https://localhost:${3000}`); 24 | }); 25 | export default app; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "small-business-backend", 3 | "version": "1.0.0", 4 | "main": "index.ts", 5 | "scripts": { 6 | "start": "npx nodemon", 7 | "dev": "npx nodemon --exec ts-node index.ts", 8 | "lint": "eslint --ignore-path .gitignore --ext .ts src/", 9 | "lint:fix": "npm run lint -- --fix", 10 | "in": "npm i --save", 11 | "ind": "npm i -D --save", 12 | "uin": "npm uninstall --save" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/NourAliAbdou/express-typescript-mongoose-boilerplate.git" 17 | }, 18 | "keywords": [ 19 | "node", 20 | "express", 21 | "mongodb", 22 | "typescript", 23 | "js", 24 | "ts" 25 | ], 26 | "author": "Nour Abdou", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/NourAliAbdou/express-typescript-mongoose-boilerplate/issues" 30 | }, 31 | "homepage": "https://github.com/NourAliAbdou/express-typescript-mongoose-boilerplate#readme", 32 | "description": "", 33 | "dependencies": { 34 | "bcryptjs": "^2.4.3", 35 | "body-parser": "^1.20.1", 36 | "cookie-parser": "^1.4.6", 37 | "cors": "^2.8.5", 38 | "dotenv": "^16.0.3", 39 | "eslint": "^8.28.0", 40 | "eslint-config-prettier": "^8.5.0", 41 | "eslint-plugin-prettier": "^4.2.1", 42 | "express": "^4.18.2", 43 | "http-errors": "^2.0.0", 44 | "i18next": "^22.0.6", 45 | "i18next-http-middleware": "^3.2.1", 46 | "i18next-node-fs-backend": "^2.1.3", 47 | "jest": "^29.1.2", 48 | "jsonwebtoken": "^8.5.1", 49 | "jwt-decode": "^3.1.2", 50 | "module-resolver": "^1.0.0", 51 | "mongoose": "^6.6.5", 52 | "morgan": "^1.10.0", 53 | "prettier": "2.7.1", 54 | "source-map-support": "^0.5.21" 55 | }, 56 | "devDependencies": { 57 | "@types/bcrypt": "^5.0.0", 58 | "@types/cookie-parser": "^1.4.3", 59 | "@types/cors": "^2.8.12", 60 | "@types/express": "^4.17.14", 61 | "@types/express-serve-static-core": "^4.17.31", 62 | "@types/i18n": "^0.13.5", 63 | "@types/mongoose": "^5.11.97", 64 | "@types/morgan": "^1.9.3", 65 | "@types/node": "^18.11.9", 66 | "@typescript-eslint/eslint-plugin": "^5.45.0", 67 | "@typescript-eslint/parser": "^5.45.0", 68 | "tsc-alias": "^1.8.1", 69 | "tsconfig-paths": "^4.1.1", 70 | "typescript": "^4.9.3" 71 | }, 72 | "jest": { 73 | "setupFiles": [ 74 | "./src/helpers/loadenv.ts" 75 | ], 76 | "testEnvironment": "node" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/src/.DS_Store -------------------------------------------------------------------------------- /src/helpers/createSchema.ts: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | import { ISchemaType } from '../interfaces/interface'; 3 | const Schema: ISchemaType = mongoose.Schema; 4 | 5 | const CreateSchema = (schema: any) => { 6 | const schem: any = new Schema(schema, { timestamps: true }); 7 | schem.method('toJSON', function () { 8 | const { _id, ...object } = this.toObject(); 9 | object.id = _id; 10 | return object; 11 | }); 12 | 13 | return schem; 14 | }; 15 | export { CreateSchema }; 16 | -------------------------------------------------------------------------------- /src/helpers/getIDfromToken.ts: -------------------------------------------------------------------------------- 1 | const jwt_decode = require('jwt-decode'); 2 | 3 | export const getIDfromToken = req => { 4 | const token = req.body.token; 5 | return jwt_decode(token).id; 6 | }; 7 | -------------------------------------------------------------------------------- /src/helpers/loadenv.ts: -------------------------------------------------------------------------------- 1 | import { config } from 'dotenv'; 2 | 3 | const { NODE_ENV } = process.env; 4 | const path = `.env${NODE_ENV ? `.${NODE_ENV}` : ''}`; 5 | 6 | export default config({ path }); 7 | -------------------------------------------------------------------------------- /src/init/db.ts: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | export default () => { 4 | const mongoString = 'mongodb://localhost:27017/test'; 5 | 6 | mongoose.connect(mongoString, {}, (error: any) => { 7 | if (error) { 8 | console.log(error); 9 | } else { 10 | console.log('Database Connected'); 11 | } 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /src/init/locales/ar/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "responseMessages": { 3 | "successMessages": { 4 | "registeredsuccessfully": "تم تسجيل {{name}} بنجاح", 5 | "profile updated successfuly": "تم تحديث المعل،مات بنجاح." 6 | }, 7 | "errorMessages": { 8 | "User already exists": "المستخدم موجود بالفعل." 9 | } 10 | }, 11 | "home": { 12 | "title": "متجر", 13 | "total": "يوجد لدينا {{counter}} كتب في القائمة", 14 | "buttonText": "إعادة التحميل", 15 | "buttonHTML": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/init/locales/en/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "responseMessages": { 3 | "successMessages": { 4 | "registeredsuccessfully": "{{name}} registered successfully", 5 | "profile updated successfuly": "Profile updated successfuly" 6 | }, 7 | "errorMessages": { 8 | "User already exists": "User already exists" 9 | } 10 | }, 11 | "home": { 12 | "title": "Book shop", 13 | "total": "There are {{counter}} books in the list", 14 | "buttonText": "Refresh button", 15 | "buttonHTML": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/init/locales/index.ts: -------------------------------------------------------------------------------- 1 | export const transStrings = { 2 | registeredsuccessfully: 'responseMessages.successMessages.registeredsuccessfully', 3 | useralreadyexists: 'responseMessages.errorMessages.User already exists', 4 | profileupdatedsuccessfuly: 'responseMessages.successMessages.profile updated successfuly', 5 | }; 6 | -------------------------------------------------------------------------------- /src/init/localize.ts: -------------------------------------------------------------------------------- 1 | import { Express } from 'express'; 2 | const i18next = require('i18next'); 3 | const Backend = require('i18next-node-fs-backend'); 4 | const i18nextMiddleware = require('i18next-http-middleware'); 5 | 6 | export default function (app: Express) { 7 | i18next 8 | .use(Backend) 9 | .use(i18nextMiddleware.LanguageDetector) 10 | .init( 11 | { 12 | backend: { 13 | loadPath: __dirname + '/locales/{{lng}}/translation.json', 14 | addPath: __dirname + '/locales/ar/{{ns}}.json', 15 | }, 16 | fallbackLng: 'ar', 17 | preload: ['en', 'ar'], 18 | supportedLngs: ['en', 'ar'], 19 | cleanCode: true, 20 | }, 21 | (err, t) => { 22 | if (err) return console.log('something went wrong loading', err); 23 | console.log(t('home.title')); 24 | }, 25 | ); 26 | 27 | app.use( 28 | i18nextMiddleware.handle(i18next, { 29 | }), 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/init/routes.ts: -------------------------------------------------------------------------------- 1 | import { Express } from 'express'; 2 | 3 | import { authRouter, userRouter } from '../mvc/routes'; 4 | import { Routes } from '../mvc/routes/routesStrings'; 5 | 6 | export default (app: Express) => { 7 | app.use('/', authRouter); 8 | app.use(Routes.user, userRouter); 9 | }; 10 | -------------------------------------------------------------------------------- /src/init/theApp.ts: -------------------------------------------------------------------------------- 1 | import express, { Express } from 'express'; 2 | const logger = require('morgan'); 3 | const cookieParser = require('cookie-parser'); 4 | export default (app: Express) => { 5 | app.use(logger('dev')); 6 | app.use(cookieParser()); 7 | app.use(express.json()); 8 | app.use(express.urlencoded({ extended: true })); 9 | }; 10 | -------------------------------------------------------------------------------- /src/interfaces/controllers.interface.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | 3 | interface IAuthControllerType { 4 | UserLogin: (req: Request, res: Response) => void; 5 | UserRegister: (req: Request, res: Response) => void; 6 | } 7 | interface IUserControllerType { 8 | UserProfile: (req: Request, res: Response) => void; 9 | UserUpdate: (req: Request, res: Response) => void; 10 | } 11 | export { IAuthControllerType, IUserControllerType }; 12 | -------------------------------------------------------------------------------- /src/interfaces/interface.ts: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | type IDBType = {}; 4 | type ISchemaType = typeof mongoose.Schema; 5 | 6 | interface IUser { 7 | name: String; 8 | email: String; 9 | mobile: String; 10 | password: String; 11 | } 12 | export { IDBType, ISchemaType, IUser }; 13 | -------------------------------------------------------------------------------- /src/interfaces/types.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/src/interfaces/types.d.ts -------------------------------------------------------------------------------- /src/mvc/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NourAliAbdou/express-typescript-mongoose-boilerplate/a6320f971029ec02e0d9137e3f97d501542c692a/src/mvc/.DS_Store -------------------------------------------------------------------------------- /src/mvc/controllers/auth.controller.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { transStrings } from '../../init/locales'; 3 | import { User } from '../models'; 4 | const jwt = require('jsonwebtoken'); 5 | const bcrypt = require('bcryptjs'); 6 | 7 | const UserLogin = (req: Request | any, res: Response) => { 8 | return User.findOne({ 9 | email: req.body.mobile, 10 | }).then(function (user: any, err: any) { 11 | if (err) throw err; 12 | 13 | if (!user) { 14 | res.status(403).json({ 15 | success: false, 16 | message: req.i18n.t('simpleStringWithVariable', { 17 | variable1: '3', 18 | variable2: '3', 19 | }), 20 | }); 21 | } else if (user) { 22 | 23 | bcrypt.compare(req.body.password, user.password, function (err, compRes) { 24 | if (!compRes) { 25 | res.status(403).json({ 26 | success: false, 27 | message: 'Ops! wrong Password!', 28 | }); 29 | } else { 30 | const payload = { 31 | id: user._id, 32 | role: 'user', 33 | }; 34 | const token = jwt.sign(payload, process.env.JWT_KEY); 35 | User.findById(user._id, function (err, result) { 36 | res.status(200).send({ 37 | success: true, 38 | token: token, 39 | user: { 40 | id: result._id, 41 | name: result.name, 42 | email: result.email, 43 | mobile: result.mobile, 44 | }, 45 | }); 46 | }); 47 | } 48 | }); 49 | } 50 | }); 51 | }; 52 | const UserRegister = (req: Request | any, res: Response) => { 53 | const user = new User({ 54 | name: req.body.name, 55 | email: req.body.email, 56 | mobile: req.body.mobile, 57 | password: req.body.password, 58 | created_at: new Date(), 59 | }); 60 | 61 | return req.body?.name 62 | ? user 63 | .save() 64 | .then(() => { 65 | const payload = { 66 | id: user._id, 67 | roleL: 'user', 68 | }; 69 | 70 | const signtoken = jwt.sign(payload, process.env.JWT_KEY); 71 | res.status(200).send({ 72 | success: true, 73 | message: req.t(transStrings.registeredsuccessfully, { 74 | name: user.name, 75 | }), 76 | user: user, 77 | token: signtoken, 78 | }); 79 | }) 80 | .catch(err => { 81 | console.log(err); 82 | res.status(400).send({ 83 | success: false, 84 | message: req.t(transStrings.useralreadyexists), 85 | error: err, 86 | }); 87 | }) 88 | : res.status(500).send({ 89 | success: false, 90 | message: 'Check your data', 91 | error: {}, 92 | }); 93 | }; 94 | 95 | export { UserLogin, UserRegister }; 96 | -------------------------------------------------------------------------------- /src/mvc/controllers/index.ts: -------------------------------------------------------------------------------- 1 | import * as userController from './user.controller'; 2 | import * as authController from './auth.controller'; 3 | 4 | export { userController, authController }; 5 | -------------------------------------------------------------------------------- /src/mvc/controllers/user.controller.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { getIDfromToken } from '../../helpers/getIDfromToken'; 3 | import { transStrings } from '../../init/locales'; 4 | import { User } from '../models'; 5 | const bcrypt = require('bcryptjs'); 6 | const saltRounds = 10; 7 | 8 | const UserProfile = (req: Request | any, res: Response) => { 9 | const user_id = getIDfromToken(req); 10 | console.log('user_id', user_id); 11 | return User.findById(user_id, function (err, user) { 12 | if (err) throw err; 13 | 14 | if (!user) { 15 | res.status(403).json({ 16 | success: false, 17 | message: req.i18n.t('simpleStringWithVariable', { 18 | variable1: '3', 19 | variable2: '3', 20 | }), 21 | }); 22 | } else if (user) { 23 | res.status(200).send({ 24 | success: true, 25 | user: { 26 | id: user._id, 27 | name: user.name, 28 | email: user.email, 29 | mobile: user.mobile, 30 | }, 31 | }); 32 | } 33 | }); 34 | }; 35 | const UserUpdate = async (req: Request | any, res: Response) => { 36 | const user_id = getIDfromToken(req); 37 | console.log('user_id', user_id); 38 | const { email, password, name } = req.body; 39 | if (email) delete req.body.email; 40 | if (name) req.body.name = name; 41 | if (password) { 42 | const newPassword = bcrypt.hashSync(password, saltRounds); 43 | req.body.password = newPassword; 44 | } 45 | const user = await User.findOneAndUpdate({ _id: user_id }, { $set: req.body }, { new: true }); 46 | 47 | return res.status(200).send({ 48 | success: true, 49 | message: req.t(transStrings.profileupdatedsuccessfuly), 50 | user: user, 51 | }); 52 | }; 53 | export { UserProfile, UserUpdate }; 54 | -------------------------------------------------------------------------------- /src/mvc/middlewares/auth/index.ts: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | 3 | const auth = (req, res, next) => { 4 | const token = req.body.token; 5 | 6 | if (token) { 7 | req.token = token; 8 | jwt.verify(token, process.env.JWT_KEY, function (err, decoded) { 9 | if (err) { 10 | err.message = 'Please, Login.'; 11 | return res.status(403).send({ 12 | success: false, 13 | message: 'Please, Login.', 14 | }); 15 | } 16 | req.user = decoded; 17 | console.log(decoded); 18 | next(); 19 | }); 20 | } else { 21 | return res.status(403).send({ 22 | success: false, 23 | unAuthorized: true, 24 | message: 'Unauthorized', 25 | }); 26 | } 27 | }; 28 | 29 | export default auth; 30 | -------------------------------------------------------------------------------- /src/mvc/middlewares/index.ts: -------------------------------------------------------------------------------- 1 | import auth from './auth'; 2 | import userAuth from './userAuth'; 3 | 4 | export { auth, userAuth }; 5 | -------------------------------------------------------------------------------- /src/mvc/middlewares/userAuth/index.ts: -------------------------------------------------------------------------------- 1 | import { User } from '../../models'; 2 | 3 | const userAuth = async (req, res, next) => { 4 | const user = await User.findOne({ 5 | _id: req.user.id, 6 | active: true, 7 | }); 8 | 9 | if (!user) 10 | return res.status(403).send({ 11 | success: false, 12 | unAuthorized: true, 13 | message: 'Unauthorized', 14 | }); 15 | else { 16 | const data = user.toObject(); 17 | data.role = 'user'; 18 | 19 | req.user = data; 20 | next(); 21 | } 22 | }; 23 | 24 | export default userAuth; 25 | -------------------------------------------------------------------------------- /src/mvc/models/index.ts: -------------------------------------------------------------------------------- 1 | const User = require('./user.model'); 2 | 3 | export { User }; 4 | -------------------------------------------------------------------------------- /src/mvc/models/user.model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | import { ISchemaType } from '@/interfaces/interface'; 3 | import { CreateSchema } from '../../helpers/createSchema'; 4 | 5 | const bcrypt = require('bcryptjs'); 6 | const saltRounds = 10; 7 | 8 | const schema = CreateSchema({ 9 | name: { type: String }, 10 | email: { type: String, unique: true, lowercase: true }, 11 | mobile: { type: String, unique: true }, 12 | password: { type: String }, 13 | }); 14 | 15 | schema.pre('save', function (next) { 16 | if (!this.isModified('password')) return next(); 17 | if (this.password) { 18 | this.password = bcrypt.hashSync(this.password, saltRounds); 19 | next(); 20 | } else { 21 | next(); 22 | } 23 | }); 24 | 25 | module.exports = mongoose.model('users', schema); 26 | -------------------------------------------------------------------------------- /src/mvc/routes/auth.routes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { authController } from '../controllers'; 3 | import { Routes } from './routesStrings'; 4 | const router = express.Router(); 5 | 6 | router.post(Routes.login, authController.UserLogin); 7 | router.post(Routes.register, authController.UserRegister); 8 | 9 | export default router; 10 | -------------------------------------------------------------------------------- /src/mvc/routes/index.ts: -------------------------------------------------------------------------------- 1 | import authRouter from './auth.routes'; 2 | import userRouter from './user.routes'; 3 | 4 | export { authRouter, userRouter }; 5 | -------------------------------------------------------------------------------- /src/mvc/routes/routesStrings/index.ts: -------------------------------------------------------------------------------- 1 | export const Routes = { 2 | user: '/user', 3 | login: '/login', 4 | register: '/register', 5 | profile: '/profile', 6 | update: '/update', 7 | }; 8 | -------------------------------------------------------------------------------- /src/mvc/routes/user.routes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { userController } from '../controllers'; 3 | import { auth, userAuth } from '../middlewares'; 4 | import { Routes } from './routesStrings'; 5 | 6 | const router = express.Router(); 7 | 8 | router.get(Routes.profile, [auth, userAuth], userController.UserProfile); 9 | router.post(Routes.update, [auth, userAuth], userController.UserUpdate); 10 | 11 | export default router; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "lib": [ 6 | "es2017", 7 | "esnext.asynciterable", 8 | ], 9 | "typeRoots": [ 10 | "node_modules/@types" 11 | ], 12 | "allowSyntheticDefaultImports": true, 13 | "experimentalDecorators": true, 14 | "emitDecoratorMetadata": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "node", 17 | "module": "commonjs", 18 | "pretty": true, 19 | "sourceMap": true, 20 | "declaration": true, 21 | "outDir": "dist", 22 | "allowJs": true, 23 | "noEmit": false, 24 | "esModuleInterop": true, 25 | "resolveJsonModule": true, 26 | "importHelpers": true, 27 | "baseUrl": "./src", 28 | "paths": { 29 | "@/*": [ 30 | "*" 31 | ], 32 | "@controllers/*": [ 33 | "mvc/controllers" 34 | ], 35 | "@interfaces/*": [ 36 | "interfaces/*" 37 | ], 38 | "@mvc/*": [ 39 | "mvc/*" 40 | ], 41 | "@middlewares/*": [ 42 | "middlewares/*" 43 | ], 44 | "@models/*": [ 45 | "mvc/models" 46 | ], 47 | "@routes": [ 48 | "mvc/routes/index.ts" 49 | ], 50 | "@routes/*": [ 51 | "mvc/routes/*" 52 | ], 53 | "@services/*": [ 54 | "services/*" 55 | ], 56 | "@helpers/*": [ 57 | "helpers/*" 58 | ] 59 | } 60 | }, 61 | "exclude": [ 62 | "node_modules", 63 | "dist", 64 | ] 65 | } --------------------------------------------------------------------------------