Skip to content
This repository has been archived by the owner on Jun 7, 2020. It is now read-only.

Latest commit

Β 

History

History
228 lines (185 loc) Β· 9.21 KB

README.md

File metadata and controls

228 lines (185 loc) Β· 9.21 KB


mango
Mango

TypeScript server template with routing-controllers, typeorm and typedi

⚑ Mango is a server template which makes it easy to build backend powered by NodeJS, Express, typeorm, typedi and routing-controllers. It minimises the setup time and makes your development cycle faster by using TypeScript. If you were looking for a server template with useful things, Mango is for you πŸ€—

Features β€’ How to use β€’ Structure β€’ Changelog β€’ Credits

⚑ Features

  • TypeScript
    • TypeScript compiles to clean, simple JavaScript code which runs on any browser, in Node.js, or in any JavaScript engine that supports ECMAScript 3 (or newer).
  • TypeORM
    • Mango uses TypeORM to map models to your database manager, everything is typed and easier to mantain.
  • TypeDI
    • Mango uses Typedi for dependencies injection
  • routing-controllers
    • Every controller has it's own file, you declare your routes with annotations and they get registered on server start.
  • JWT middleware (there's a refresh token flow, no need to use 2 tokens!)
  • Resource activation protection, if a user doesn't own a resource he won't be able to modify it
  • Logging, uses winston, everything gets logged to a file.
  • User CRUD and also profile picture upload with multer
  • dotEnv variables
  • pm2 ready

And many other features

❓ How to use

To clone and run this server template, you'll need Git and NodeJS MySQL is also needed (or change the database driver in database.ts file, check TypeORM documentation for a how-to)

# Clone this repository
$ git clone https://github.com/MrARC/Mango

# Go into the repository
$ cd Mango/server

# Install dependencies
$ npm install

# Create .env file
$ cp .example.env .env

# Run the server
$ npm run dev

πŸ‘¨β€πŸ’» Creating an API response

You may want to use a standard response for all your API calls, you can import the ApiResponse object from handlers/api_response.handler and create a new instance of it

example:

const response = new ApiResponse(response)
            .withData({msg: 'hello'}).withStatusCode(HTTP_STATUS_CODE.OK).build();

A request can have the following properties

Method Description Note
.withData(object) Anything you want
.withStatusCode(HTTP_STATUS_CODE) HTTP Status code (see HTTP_STATUS_CODE class) Defaults to 200
.build() Finish building request Required to finish building request

πŸ’₯ How to add a new module (controller, service and repo)

Adding a new module it's easy with plop, just open your console shell, execute:

npm add:module

and follow the steps βœ…

module

πŸ” Adding authorization or role protection to routes

Adding authorization to a route it's easy, just use the @Authorized annotation and add a roles property (can be an array of roles or a single role (or null if you only want to verify if there's a valid JWT token in request), but there's a weight system in place so users with high role can use routes that are for lower roles)

    @Post()
    // use only @Authorized() if you want to verify only jwt token
    @Authorized(RoleType.USER)
    public async blabla(@Res() response: Response, @Body({ required: true }) user: User): Promise<Response> {
      ...
    }

βœ… JWT refresh in Mango

I made a sequence diagram to try to explain this process:

diagram

πŸ€” Explanation

Basically there's only one JWT token you will store in the client (web, mobile app, whatever), this JWT token is short-lived (it has a life span of only a few minutes, 15 minutes in production mode), all requests made in that span of time will be passed if the JWT is valid. If the JWT token is expired, Mango will check if is not older than 1 week and will try to update the old token in database and issue a new JWT token with the new parameters, otherwise it will throw a ForbiddenError with a 403 status code. The new JWT token will be present in the server response inside a custom header parameter (X-Auth-Token), this parameter will hold your new JWT token for the new requests.

πŸ“ Note

You will have to implement some logic on your frontend or mobile app to replace the stored JWT token if the header X-Auth-Token is present in the server response, Mango will refuse to update any already updated JWT token and will throw a UnauthorizedError with a 401 status code.

πŸ“‚ Structure

.
β”œβ”€β”€ docs
β”‚   β”œβ”€β”€ mango.png
β”‚   └── plop.gif
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
└── server
    β”œβ”€β”€ ecosystem.config.js
    β”œβ”€β”€ .editorconfig
    β”œβ”€β”€ .example.env
    β”œβ”€β”€ nodemon.json
    β”œβ”€β”€ package.json
    β”œβ”€β”€ package-lock.json
    β”œβ”€β”€ plopfile.js
    β”œβ”€β”€ plop-templates
    β”‚   β”œβ”€β”€ controller.hbs
    β”‚   β”œβ”€β”€ repository.hbs
    β”‚   └── service.hbs
    β”œβ”€β”€ public
    β”‚   └── index.html
    β”œβ”€β”€ src
    β”‚   β”œβ”€β”€ api
    β”‚   β”‚   β”œβ”€β”€ auth
    β”‚   β”‚   β”‚   β”œβ”€β”€ auth.controller.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ jwt.service.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ token.model.ts
    β”‚   β”‚   β”‚   └── token.repository.ts
    β”‚   β”‚   β”œβ”€β”€ common
    β”‚   β”‚   β”‚   β”œβ”€β”€ CUD.ts
    β”‚   β”‚   β”‚   └── CUID.ts
    β”‚   β”‚   β”œβ”€β”€ health
    β”‚   β”‚   β”‚   β”œβ”€β”€ health.controller.ts
    β”‚   β”‚   β”‚   └── health.service.ts
    β”‚   β”‚   β”œβ”€β”€ index
    β”‚   β”‚   β”‚   └── index.controller.ts
    β”‚   β”‚   β”œβ”€β”€ me
    β”‚   β”‚   β”‚   └── me.controller.ts
    β”‚   β”‚   └── users
    β”‚   β”‚       β”œβ”€β”€ user.model.ts
    β”‚   β”‚       β”œβ”€β”€ user_profile_picture.model.ts
    β”‚   β”‚       β”œβ”€β”€ user.repository.ts
    β”‚   β”‚       β”œβ”€β”€ user_role.model.ts
    β”‚   β”‚       β”œβ”€β”€ users.controller.ts
    β”‚   β”‚       └── user.service.ts
    β”‚   β”œβ”€β”€ app.ts
    β”‚   β”œβ”€β”€ database
    β”‚   β”‚   β”œβ”€β”€ database.ts
    β”‚   β”‚   └── redis.ts
    β”‚   β”œβ”€β”€ handlers
    β”‚   β”‚   β”œβ”€β”€ api_error.handler.ts
    β”‚   β”‚   └── api_response.handler.ts
    β”‚   β”œβ”€β”€ helpers
    β”‚   β”‚   β”œβ”€β”€ authorization_checker.helper.ts
    β”‚   β”‚   └── current_user_checker.helper.ts
    β”‚   β”œβ”€β”€ logger
    β”‚   β”‚   └── logger.service.ts
    β”‚   β”œβ”€β”€ middleware
    β”‚   β”‚   β”œβ”€β”€ error.middleware.ts
    β”‚   β”‚   β”œβ”€β”€ http_logging.middleware.ts
    β”‚   β”‚   └── not_found.middleware.ts
    β”‚   β”œβ”€β”€ utils
    β”‚   β”‚   β”œβ”€β”€ json.utils.ts
    β”‚   β”‚   └── upload.utils.ts
    β”‚   └── www.ts
    β”œβ”€β”€ tests
    β”‚   β”œβ”€β”€ src
    β”‚   β”‚   β”œβ”€β”€ controllers
    β”‚   β”‚   β”‚   └── index.controller.spec.ts
    β”‚   β”‚   └── setup.ts
    β”‚   └── tsconfig.json
    β”œβ”€β”€ tsconfig.json
    └── tslint.json

πŸ“‹ ToDo

  • Add JWT token refresh
  • Better authorization token flow
  • Better project structure
  • Better readme
  • Create a config file
  • Add docker support
  • Add GraphQL?
  • Add unit test and integration tests (help wanted)

✍ Changelog

  • 0.1 - First release
  • 0.1.1 - Refactored authorization function, moved JWT middleware to auth function
  • 0.1.2 - Refactored logging system, now it supports context for file, changed the way repositories are created (uses typedi injection), added current user checker, added some validation to me controller, tokens are now deleted when user changes his password or email. Refactored profile upload methods.
  • 0.1.3 - Better project structure
  • 0.1.4 - Better project structure again, removed graphics magick dependence and replaced it with sharp
  • 0.1.5 - Fixed bug with refresh token flow, user would have to make request again to be found by user controller, improved logging
  • 0.1.6 - Decoupled database from main server start, fixed load order error with repository injectors in routing-controllers helpers, indented with 2 spaces instead of 4, improved logging, fixed user profile update method

πŸ€— Credits

Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY