An open API service indexing awesome lists of open source software.

https://github.com/plopezm/decorated-express


https://github.com/plopezm/decorated-express

decorations express rest rest-api typescript

Last synced: 5 months ago
JSON representation

Awesome Lists containing this project

README

          

# decorated-express

This library wraps an express application into a typescript class and provides decorators to ease restful developments. If you want to check an example application implemented using this library, please go [node-auth-typescript](https://github.com/plopezm/node-auth-typescript)

# Installing @plopezm/decorated-express

```
npm install express --save
npm install @types/express --save-dev
npm install @plopezm/decorated-express --save
```

# How to use it

Using this library is really easy:

1. We have to define a resource:

```
import * as express from "express";
import { GET, POST } from "@plopezm/decorated-express";
import { UserService } from "../services/user-service";

// This paths will be the prefixx path to all methods
@RoutePath('/tests')
export class UserResource {

userService: UserService;

constructor(){
this.userService = new UserService();
}

// This path is the specific path for this method
@GET("/hello")
helloworld(req: express.Request, res: express.Response, next: Function){
res.json({
message: 'Hello World!'
});
}

@GET("/users/:username")
findUser(req: express.Request, res: express.Response, next: Function){
let id = req.params.username;
let user = this.userService.get(id);
res.json(user);
}

@POST("/users")
createUser(req: express.Request, res: express.Response, next: Function) {
let user = this.userService.create(req.body);
res.json(user);
}

}

```

2. In index.js create a server a add this resource:

```
import * as express from 'express';
import * as mongoose from 'mongoose';
import * as bodyParser from 'body-parser';
import * as logger from "morgan";

import { Server } from "@plopezm/decorated-express";

// Creates a new instance of a express server
let server = Server.bootstrap(express());
// Config method allows us to set the desired middleware to be used
server.config(logger("dev"),
bodyParser.json(),
bodyParser.urlencoded({extended: true}));
// Register our decorated resources
server.registerResource(UserResource);
// Server starts in the path '/api/v1'
server.start('/api/v1', 8080);

```

The resource path is /tests and server path is /api/v1, so in order to call /hello method, we have to request localhost:8080/api/v1/tests/hello.

# Adding resource middlewares

Probably you would like to add some other middlewares to a specific resource in order to add security, logger, etc. This can be done using annotation @Middlewares(...). It is possible to add as many middlewares as you want.

```
// Declaring our example middlewares
function sayHelloWorldMiddleware(req: express.Request, res: express.Response, next: Function) {
console.log("Hello world middleware 1");
next();
}

function sayHelloWorldMiddleware2(req: express.Request, res: express.Response, next: Function) {
console.log("Hello world middleware 2");
next();
}

export class UserResource {

userService: UserService;

constructor(){
this.userService = new UserService();
}

@GET("/hello")
@Middlewares(sayHelloWorldMiddleware, sayHelloWorldMiddleware2)
helloworld(req: express.Request, res: express.Response, next: Function){
res.json({
message: 'Hello World!'
});
}

...
```
# Setting Basic authentication

This library provides a way to manage automatically HTTP Basic Authentication using @BasicAuth annotation

```
import { GET, POST, DELETE, PUT, Middlewares, BasicAuth, AuthenticationData } from "@plopezm/decorated-express";

class Resource {

static isUserValid(user: string, passwd: string): boolean{
return user === "testing" && password === "testing"
}

@GET("/users/:username")
@BasicAuth(Resource.isUserValid)
findUser(req: express.Request, res: express.Response, next: Function){
let authentication: AuthenticationData = res.locals.auth;
...
}
}

```

AuthenticationData interface provides the user credentials

```
export interface BasicData {
username: string;
passwd: string;
}

export interface JWTData {
payload: any;
}

export interface AuthenticationData {
basic?: BasicData;
jwt?: JWTData;
}
```

# Setting JWT authentication

JWT authentication has been implemented using jsonwebtoken library. Using @JWTAuth() annotation is it possible to enable JWT authentication for a resource.

We have to decide the algorithm type that we are going to use, for more information you can read [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken). Anyway I am going to explain how to use some security methods.

### Supported signature algorithms

Signature algorithm. Could be one of these values :

* - HS256: HMAC using SHA-256 hash algorithm (default)
* - HS384: HMAC using SHA-384 hash algorithm
* - HS512: HMAC using SHA-512 hash algorithm
* - RS256: RSASSA using SHA-256 hash algorithm
* - RS384: RSASSA using SHA-384 hash algorithm
* - RS512: RSASSA using SHA-512 hash algorithm
* - ES256: ECDSA using P-256 curve and SHA-256 hash algorithm
* - ES384: ECDSA using P-384 curve and SHA-384 hash algorithm
* - ES512: ECDSA using P-521 curve and SHA-512 hash algorithm
* - none: No digital signature or MAC value included

### Setting JWT authentication with HMAC

Creating a valid token with HMAC requires only a symmetric password. Using the following function:

```
export class JWTFactory {
static generateToken(secret: string, payload: any, options: SignOptions = {expiresIn: 1440}): any
}
```

Example usage:

```
let signOptions: SignOptions = {
expiresIn: 10
};
let token = JWTFactory.generateToken("testing", {username: res.locals.auth.basic}, signOptions);
```

In order to authenticate a token the client MUST send the token in the Authorization header as 'Bearer' type. The framework will check that header in order to check the token validity.

JWTAuth annotation definition:

```
function JWTAuth(cert: string, options?: VerifyOptions)
```

Example:

```
class Resource {
@GET("/users/:username")
@JWTAuth("secret")
// OR
//@JWTAuth("secret", {algorithm: 'HS512'})
protectedMethod(req: express.Request, res: express.Response, next: Function) {
let jwtPayload: JWTData = res.locals.auth.jwt.payload;
...
}
}
```