Skip to content

Commit 05e94fe

Browse files
author
hirsch88
committed
refactored middlewares
1 parent 17944fb commit 05e94fe

File tree

9 files changed

+166
-132
lines changed

9 files changed

+166
-132
lines changed

src/api/controllers/UserController.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ import { Controller, Get, Post, Put, Delete, RequestParam, RequestBody, Response
33
import { my } from 'my-express';
44
import { UserService } from '../services/UserService';
55
import { Types } from '../../constants/Types';
6-
import { Service } from '../../constants/Targets';
7-
import { authenticate, populateUser } from '../middlewares';
6+
import { Service, Middleware } from '../../constants/Targets';
7+
// import { authenticate, populateUser } from '../middlewares';
8+
import { AuthenticateMiddleware } from '../middlewares/AuthenticateMiddleware';
9+
import { PopulateUserMiddleware } from '../middlewares/PopulateUserMiddleware';
10+
import { ioc } from '../../core/IoC';
11+
12+
// Get middlewares
13+
const authenticate = ioc.Container.getNamed<AuthenticateMiddleware>(Types.Middleware, Middleware.AuthenticateMiddleware);
14+
const populateUser = ioc.Container.getNamed<PopulateUserMiddleware>(Types.Middleware, Middleware.PopulateUserMiddleware);
815

916
/**
1017
* UserController is in charge of the user resource and should
1118
* provide all crud actions.
1219
*/
1320
@injectable()
14-
@Controller('/user', authenticate)
21+
@Controller('/user', authenticate.use)
1522
export class UserController {
1623

1724
constructor( @inject(Types.Service) @named(Service.UserService) private userService: UserService) { }
@@ -28,7 +35,7 @@ export class UserController {
2835
return res.created(user.toJSON());
2936
}
3037

31-
@Get('/me', populateUser)
38+
@Get('/me', populateUser.use)
3239
public async findMe( @Request() req: my.Request, @Response() res: my.Response): Promise<any> {
3340
return res.found(req.user);
3441
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { injectable, inject, named } from 'inversify';
2+
import * as Request from 'request';
3+
import { my } from 'my-express';
4+
import { Log } from '../../core/log';
5+
import { Types } from '../../constants/Types';
6+
import { Lib, Core } from '../../constants/Targets';
7+
8+
9+
@injectable()
10+
export class AuthenticateMiddleware {
11+
12+
public log: Log;
13+
14+
constructor(
15+
@inject(Types.Core) @named(Core.Log) Logger: typeof Log,
16+
@inject(Types.Lib) @named(Lib.Request) private request: typeof Request
17+
) {
18+
this.log = new Logger('api:middleware:AuthenticateMiddleware');
19+
}
20+
21+
22+
public use = (req: my.Request, res: my.Response, next: my.NextFunction): void => {
23+
// console.log(this.request());
24+
// return next();
25+
const token = this.getToken(req);
26+
27+
if (token === null) {
28+
this.log.warn('No token given');
29+
return res.failed(403, 'You are not allowed to request this resource!');
30+
}
31+
this.log.debug('Token is provided');
32+
33+
// Request user info at auth0 with the provided token
34+
this.request({
35+
method: 'POST',
36+
url: `${process.env.AUTH0_HOST}/tokeninfo`,
37+
form: {
38+
id_token: token
39+
}
40+
}, (error: any, response: Request.RequestResponse, body: any) => {
41+
// Verify if the requests was successful and append user
42+
// information to our extended express request object
43+
if (!error && response.statusCode === 200) {
44+
req.tokeninfo = JSON.parse(body);
45+
this.log.info(`Retrieved user ${req.tokeninfo.email}`);
46+
return next();
47+
}
48+
49+
// Catch auth0 exception and return it as it is
50+
this.log.warn(`Could not retrieve the user, because of`, body);
51+
let statusCode = 401;
52+
if (response && response.statusCode) {
53+
statusCode = response.statusCode;
54+
} else {
55+
this.log.warn('It seems your oauth server is down!');
56+
}
57+
res.failed(statusCode, body);
58+
59+
});
60+
}
61+
62+
private getToken(req: my.Request): string | null {
63+
const authorization = req.headers.authorization;
64+
65+
// Retrieve the token form the Authorization header
66+
if (authorization && authorization.split(' ')[0] === 'Bearer') {
67+
return authorization.split(' ')[1];
68+
}
69+
70+
// No token was provided by the client
71+
return null;
72+
}
73+
74+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { injectable, inject, named } from 'inversify';
2+
import * as Request from 'request';
3+
import { my } from 'my-express';
4+
import { Log } from '../../core/log';
5+
import { UserService } from '../services/UserService';
6+
import { Types } from '../../constants/Types';
7+
import { Service, Core } from '../../constants/Targets';
8+
9+
10+
@injectable()
11+
export class PopulateUserMiddleware {
12+
13+
public log: Log;
14+
15+
constructor(
16+
@inject(Types.Core) @named(Core.Log) Logger: typeof Log,
17+
@inject(Types.Service) @named(Service.UserService) private userService: UserService
18+
) {
19+
this.log = new Logger('api:middleware:PopulateUserMiddleware');
20+
}
21+
22+
23+
public use = (req: my.Request, res: my.Response, next: my.NextFunction): void => {
24+
// Check if the authenticate middleware was successful
25+
if (!req.tokeninfo || !req.tokeninfo.user_id) {
26+
return res.failed(400, 'Missing token information!');
27+
}
28+
// Find user from the token and store him in the request object
29+
this.userService.findByUserId(req.tokeninfo.user_id)
30+
.then((user) => {
31+
req.user = user.toJSON();
32+
this.log.debug(`populated user with the id=${req.user.id} to the request object`);
33+
next();
34+
})
35+
.catch((error) => {
36+
this.log.warn(`could not populate user to the request object`);
37+
next(error);
38+
});
39+
}
40+
41+
}

src/api/middlewares/authenticate.ts

Lines changed: 0 additions & 67 deletions
This file was deleted.

src/api/middlewares/index.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/api/middlewares/populateUser.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/constants/Targets.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@ export const Repository = {
3535
};
3636

3737
export const Middleware = {
38-
AuthenticateMiddleware: 'AuthenticateMiddleware'
38+
AuthenticateMiddleware: 'AuthenticateMiddleware',
39+
PopulateUserMiddleware: 'PopulateUserMiddleware'
3940
};

src/container.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,26 @@
66
* will then be bonded to the express structure with their defined routes.
77
*/
88

9-
import { Container } from 'inversify';
9+
import { Container, decorate, injectable } from 'inversify';
1010
import { ioc } from './core/IoC';
11+
import { Types } from './constants/Types';
12+
import { Lib } from './constants/Targets';
13+
14+
import * as request from 'request';
15+
16+
17+
ioc.configureLib((container: Container) => {
18+
19+
decorate(injectable(), request);
20+
21+
container
22+
.bind<any>(Types.Lib)
23+
.toConstantValue(request)
24+
.whenTargetNamed(Lib.Request);
25+
26+
return container;
27+
});
28+
1129

1230
ioc.configure((container: Container) => {
1331

src/core/IoC.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as glob from 'glob';
1111
import { interfaces } from 'inversify-express-utils';
1212
import { Container } from 'inversify';
1313
import { Types } from '../constants/Types';
14-
import { Core, Controller, Model, Service, Repository } from '../constants/Targets';
14+
import { Core, Controller, Model, Service, Repository, Middleware } from '../constants/Targets';
1515

1616
import { events, EventEmitter } from './api/events';
1717
import { Log } from './log';
@@ -22,6 +22,7 @@ const log = new Log('core:IoC');
2222
class IoC {
2323

2424
public container: Container;
25+
public libConfiguration: (container: Container) => Container;
2526
public customConfiguration: (container: Container) => Container;
2627

2728
constructor() {
@@ -36,13 +37,20 @@ class IoC {
3637
this.customConfiguration = configuration;
3738
}
3839

40+
public configureLib(configuration: (container: Container) => Container): void {
41+
this.libConfiguration = configuration;
42+
}
43+
3944
public async bindModules(): Promise<void> {
4045
this.bindCore();
41-
await this.bindControllers();
46+
47+
this.container = this.libConfiguration(this.container);
4248

4349
await this.bindModels();
4450
await this.bindRepositories();
4551
await this.bindServices();
52+
await this.bindMiddlewares();
53+
await this.bindControllers();
4654

4755
this.container = this.customConfiguration(this.container);
4856
}
@@ -79,6 +87,15 @@ class IoC {
7987
});
8088
}
8189

90+
private bindMiddlewares(): Promise<void> {
91+
return this.bindFiles('/middlewares/**/*Middleware.ts', Middleware, (name: any, value: any) => {
92+
this.container
93+
.bind<any>(Types.Middleware)
94+
.to(value)
95+
.whenTargetNamed(name);
96+
});
97+
}
98+
8299
private bindControllers(): Promise<void> {
83100
return this.bindFiles('/controllers/**/*Controller.ts', Controller, (name: any, value: any) => {
84101
this.container

0 commit comments

Comments
 (0)