Permalink
Browse files

feat(remote cli): Implement jwt authentication strategy with verifica…

…tion against user's public key
  • Loading branch information...
zakhenry committed Jul 21, 2016
1 parent 15a8095 commit 96778a14756772934e77c6851c63beb3c2439e79
View
@@ -48,14 +48,15 @@
"@types/proxyquire": "^1.3.26",
"@types/socket.io": "^1.4.26",
"@types/validator": "^4.5.26",
"@xiphiaz/vantage": "^1.7.1",
"@xiphiaz/vantage": "^1.7.2",
"chalk": "^1.1.3",
"chance": "^1.0.3",
"class-validator": "^0.4.0-alpha.3",
"core-js": "^2.4.0",
"dotenv": "^2.0.0",
"express": "^4.13.4",
"hapi": "^13.4.0",
"jsonwebtoken": "^7.1.6",
"lodash": "^4.12.0",
"moment": "^2.13.0",
"mysql": "^2.11.1",
@@ -8,6 +8,8 @@ import { bootstrap, BootstrapResponse, deferredLog } from './index';
import { registry } from '../../common/registry/entityRegistry';
import { ClassDictionary } from './bootstrap';
import Spy = jasmine.Spy;
import { AuthService } from '../services/authService.service';
import { AuthServiceMock } from '../services/authService.service.mock';
let loggerInstance: Logger;
@@ -24,6 +26,7 @@ const providers: any[] = [
},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
describe('Bootstrap', () => {
@@ -12,11 +12,14 @@ import { AbstractController } from '../controllers/abstract.controller';
import { Route } from '../controllers/route.decorator';
import { Request } from '../controllers/request';
import { Response } from '../controllers/response';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
const providers: any[] = [
{provide: Logger, useClass: LoggerMock},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
@Injectable()
@@ -12,6 +12,8 @@ import { AbstractMigration } from '../migrations/index';
import { Database } from '../services/database.service';
import { DatabaseMock } from '../services/database.service.mock';
import Spy = jasmine.Spy;
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
let loggerInstance: Logger = new LoggerMock();
let databaseInstance: Database;
@@ -34,6 +36,7 @@ const providers: any[] = [
},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
@Injectable()
@@ -14,11 +14,14 @@ import { StoredProperty } from '../../common/models/types/storedProperty.decorat
import * as typeormColumns from 'typeorm/columns';
import { CreatedDate, UpdatedDate } from '../../common/models/types/timestamp.decorator';
import Spy = jasmine.Spy;
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
const providers: any[] = [
{provide: Logger, useClass: LoggerMock},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
@Injectable()
@@ -10,6 +10,8 @@ import { bootstrap, BootstrapResponse } from './index';
import { registry } from '../../common/registry/entityRegistry';
import { AbstractSeeder } from '../seeders/index';
import Spy = jasmine.Spy;
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
let loggerInstance: Logger = new LoggerMock();
@@ -21,6 +23,7 @@ const providers: any[] = [
},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
@Injectable()
@@ -10,6 +10,8 @@ import { RemoteCli } from '../services/remoteCli.service';
import { ServerMock } from '../servers/abstract.server.spec';
import { Server } from '../servers/abstract.server';
import Spy = jasmine.Spy;
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
let loggerInstance: Logger = new LoggerMock();
@@ -22,6 +24,7 @@ const providers: any[] = [
},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
@Injectable()
@@ -11,6 +11,8 @@ import { Response } from './response';
import { AbstractController } from './abstract.controller';
import { Route } from './route.decorator';
import { UnavailableForLegalReasonsException } from '../../common/exeptions/exceptions';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
@Injectable()
class TestController extends AbstractController {
@@ -41,6 +43,7 @@ const providers = [
{provide: Logger, useClass: LoggerMock},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
describe('Controller', () => {
@@ -17,6 +17,8 @@ import { EventEmitter } from 'events';
import { IncomingMessage } from 'http';
import { Primary } from '../../common/models/types/primary.decorator';
import * as _ from 'lodash';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
class Fruit extends AbstractModel {
@Primary()
@@ -61,6 +63,7 @@ const providers = [
{provide: Logger, useClass: LoggerMock},
{provide: Server, useClass: ServerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
describe('Resource Controller', () => {
@@ -11,6 +11,8 @@ import { RemoteCli } from '../services/remoteCli.service';
import { RemoteCliMock } from '../services/remoteCli.service.mock';
import { Route } from './route.decorator';
import { Controller } from '../../common/registry/decorators';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
@Injectable()
@Controller({
@@ -33,6 +35,7 @@ const providers = [
{provide: Server, useClass: ServerMock},
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
describe('@Route decorator', () => {
@@ -12,6 +12,8 @@ import { ServerMock } from '../servers/abstract.server.spec';
import { RemoteCli } from '../services/remoteCli.service';
import { RemoteCliMock } from '../services/remoteCli.service.mock';
import { debugLog, DebugLogMiddleware } from './debugLog.middleware';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
@Injectable()
class MiddlewareController extends AbstractController {
@@ -45,6 +47,7 @@ const providers: any[] = [
{provide: Server, useClass: ServerMock},
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
{
provide: DebugLogMiddleware,
deps: [],
@@ -13,6 +13,8 @@ import { ServerMock } from '../servers/abstract.server.spec';
import { RemoteCli } from '../services/remoteCli.service';
import { RemoteCliMock } from '../services/remoteCli.service.mock';
import { PromiseFactory } from '../../common/util/serialPromise';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
let middlewareCalls: string[] = [];
@@ -46,6 +48,7 @@ const providers = [
{provide: Server, useClass: ServerMock},
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
ReflectiveInjector
];
@@ -7,6 +7,8 @@ import { LoggerMock } from '../../common/services/logger.service.mock';
import { RemoteCliMock } from '../services/remoteCli.service.mock';
import { Response } from '../controllers/response';
import Spy = jasmine.Spy;
import { AuthService } from '../services/authService.service';
import { AuthServiceMock } from '../services/authService.service.mock';
@Injectable()
export class ServerMock extends Server {
@@ -39,6 +41,7 @@ describe('Server', () => {
{provide: Server, useClass: ServerMock},
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
let cliSpy: Spy;
@@ -116,7 +119,7 @@ describe('Server', () => {
})));
it('starts the server running and returns promise', inject([Server], (server: Server) => {
it('gets default response object from server', inject([Server], (server: Server) => {
const response: Response = (<any>server).getDefaultResponse();
expect(response instanceof Response)
@@ -7,6 +7,8 @@ import * as proxyquire from 'proxyquire';
import { Response } from '../controllers/response';
import { Request } from '../controllers/request';
import { RemoteCliMock } from '../services/remoteCli.service.mock';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
describe('Express Server', () => {
@@ -38,6 +40,7 @@ describe('Express Server', () => {
},
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
beforeEach(() => {
@@ -7,6 +7,8 @@ import { RemoteCliMock } from '../services/remoteCli.service.mock';
import * as proxyquire from 'proxyquire';
import { Response } from '../controllers/response';
import { Request } from '../controllers/request';
import { AuthServiceMock } from '../services/authService.service.mock';
import { AuthService } from '../services/authService.service';
describe('Hapi Server', () => {
@@ -29,6 +31,7 @@ describe('Hapi Server', () => {
},
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
];
beforeEach(() => {
@@ -0,0 +1,28 @@
/**
* @module server
*/
/** End Typedoc Module Declaration */
import { Injectable } from '@angular/core';
import { Logger } from '../../common/services/logger.service';
import { Service } from '../../common/registry/decorators';
import * as jwt from 'jsonwebtoken';
import { AuthService } from './authService.service';
/**
* Class allows developers to register custom commands that can be remote executed in a
* shell environment. Useful for things like migrations and debugging.
*/
@Injectable()
@Service()
export class AuthServiceMock extends AuthService {
constructor(loggerBase: Logger) {
super(loggerBase);
}
public verify(jwtToken: string, publicKeyPath: string, params: Object = {}): Promise<any> {
return Promise.resolve(jwt.decode(jwtToken));
}
}
@@ -0,0 +1,48 @@
/**
* @module server
*/
/** End Typedoc Module Declaration */
import { Injectable } from '@angular/core';
import { Logger } from '../../common/services/logger.service';
import { Service } from '../../common/registry/decorators';
import { AbstractService } from '../../common/services/service';
import { readFileSync } from 'fs';
import * as jwt from 'jsonwebtoken';
/**
* Class allows developers to register custom commands that can be remote executed in a
* shell environment. Useful for things like migrations and debugging.
*/
@Injectable()
@Service()
export class AuthService extends AbstractService {
/**
* Logger instance for the class, initialized with `remote-cli` source
*/
private logger: Logger;
constructor(loggerBase: Logger) {
super();
this.logger = loggerBase.source('authentication');
}
public verify(jwtToken: string, publicKeyPath: string, params: Object = {}): Promise<any> {
const pem = readFileSync(publicKeyPath);
return new Promise((resolve, reject) => {
jwt.verify(jwtToken, pem, params, (err:Error, decoded:any) => {
if (err){
return reject(err);
}
return resolve(decoded);
});
});
}
}
@@ -10,6 +10,8 @@ import { RemoteCliMock } from './remoteCli.service.mock';
import { registry } from '../../common/registry/entityRegistry';
import * as SQL from 'sql-template-strings';
import Spy = jasmine.Spy;
import { AuthServiceMock } from './authService.service.mock';
import { AuthService } from './authService.service';
@Injectable()
class ExampleUtil {
@@ -41,6 +43,7 @@ describe('Database', () => {
const providers = [
{provide: Logger, useClass: LoggerMock},
{provide: RemoteCli, useClass: RemoteCliMock},
{provide: AuthService, useClass: AuthServiceMock},
Database,
ExampleUtil
];
@@ -7,7 +7,7 @@ import { RemoteCli, ConnectedSocketCallback } from './remoteCli.service';
import { Logger } from '../../common/services/logger.service';
import { Service } from '../../common/registry/decorators';
import Spy = jasmine.Spy;
import { AuthService } from './authService.service';
/**
* Provides no-side effect mock for RemoteCli for use in testing fixtures
@@ -16,8 +16,8 @@ import Spy = jasmine.Spy;
@Service()
export class RemoteCliMock extends RemoteCli {
constructor(loggerBase: Logger, injector: Injector) {
super(loggerBase, injector)
constructor(loggerBase: Logger, injector: Injector, authService:AuthService) {
super(loggerBase, injector, authService);
}
/**
Oops, something went wrong.

0 comments on commit 96778a1

Please sign in to comment.