Skip to content
This repository was archived by the owner on May 8, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/common/stores/mock.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ export abstract class MockStore<T extends AbstractModel> extends AbstractStore<T
/**
* @inheritdoc
*/
public findOne(id?: identifier): Promise<T> {
public async findOne(id?: identifier): Promise<T> {

try {
return Promise.resolve(this.modelCollection.findById(id));
} catch (e){
return this.saveOne(this.getMock(id))
return await this.modelCollection.findById(id);
} catch (e) {
return await this.saveOne(this.getMock(id));
}
}

Expand Down
16 changes: 7 additions & 9 deletions src/common/stores/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,13 @@ export abstract class AbstractStore<T extends AbstractModel> {
* @param validatorOptions
* @returns {Promise<T>}
*/
public validate(model: T, validatorOptions?: ValidatorOptions): Promise<T> | never {

return this.validator.validate(model, validatorOptions)
.then((errors: ValidationError[]) => {
if (errors.length) {
throw new ValidationException(null, errors)
}
return model;
});
public async validate(model: T, validatorOptions?: ValidatorOptions): Promise<T> | never {

const errors: ValidationError[] = await this.validator.validate(model, validatorOptions);
if (errors.length) {
throw new ValidationException(null, errors)
}
return model;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/server/controllers/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class Request {
* Extract the passed body object from the raw request
* @returns {Promise<T>}
*/
public getPayload(): Promise<any> {
public getPayload<T>(): Promise<T> {
return new Promise((resolve, reject) => {
this.raw.setEncoding('utf8');

Expand Down
59 changes: 25 additions & 34 deletions src/server/controllers/resource.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,9 @@ export abstract class ResourceController<M extends AbstractModel> extends Abstra
* @returns {any}
*/
@Route('GET', '/:id')
public getOne(request: Request, response: Response): Promise<Response> {

return this.modelStore
.findOne(request.params()
.get('id'))
.then((model: M) => response.data(model));
public async getOne(request: Request, response: Response): Promise<Response> {
const model: M = await this.modelStore.findOne(request.params().get('id'));
return response.data(model);
}

/**
Expand All @@ -47,11 +44,9 @@ export abstract class ResourceController<M extends AbstractModel> extends Abstra
* @returns {any}
*/
@Route('GET', '/')
public getMany(request: Request, response: Response): Promise<Response> {

return this.modelStore
.findMany()
.then((collection: Collection<M>) => response.data(collection));
public async getMany(request: Request, response: Response): Promise<Response> {
const collection: Collection<M> = await this.modelStore.findMany();
return response.data(collection);
}

/**
Expand Down Expand Up @@ -85,12 +80,11 @@ export abstract class ResourceController<M extends AbstractModel> extends Abstra
* @returns {Promise<Response>}
*/
@Route('DELETE', '/:id')
public deleteOne(request: Request, response: Response): Promise<Response> {
public async deleteOne(request: Request, response: Response): Promise<Response> {

return request.getPayload()
.then((data: any) => this.modelStore.hydrate(data))
.then((model: M) => this.modelStore.deleteOne(model))
.then((model: M) => response.data(model));
const model: M = await this.modelStore.hydrate(await request.getPayload());
await this.modelStore.deleteOne(model);
return response.data(model);
}

/**
Expand All @@ -101,28 +95,25 @@ export abstract class ResourceController<M extends AbstractModel> extends Abstra
* @param checkExists
* @returns {Promise<Response>}
*/
protected savePayload(request: Request, response: Response, checkExists: boolean = false, validatorOptions: ValidatorOptions = {}): Promise<Response> {
let modelPayload = request.getPayload()
.then((data: any) => this.modelStore.hydrate(data));
protected async savePayload(
request: Request,
response: Response,
checkExists: boolean = false,
validatorOptions: ValidatorOptions = {},
): Promise<Response> | never {

if (checkExists) {

modelPayload = modelPayload.then((payload: M) => {
return this.modelStore.hasOne(payload)
.then((exists: boolean) => {
if (!exists) {
throw new NotFoundException(`Model with id [${payload.getIdentifier()}] does not exist`);
}
return payload;
});
})
const model = await this.modelStore.hydrate(await request.getPayload());

if (checkExists) {
const exists = await this.modelStore.hasOne(model);
if (!exists) {
throw new NotFoundException(`Model with id [${model.getIdentifier()}] does not exist`);
}
}

return modelPayload
.then((model: M) => this.modelStore.validate(model, validatorOptions))
.then((model: M) => this.modelStore.saveOne(model))
.then((model: M) => response.data(model));
await this.modelStore.validate(model, validatorOptions);
await this.modelStore.saveOne(model);
return response.data(model);
}

}
3 changes: 1 addition & 2 deletions src/server/middleware/debugLog.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ export class DebugLogMiddleware implements InjectableMiddleware {
export function debugLog(...messages: string[]): InjectableMiddlewareFactory {

return (injector: ReflectiveInjector): Middleware => {
return injector.get(DebugLogMiddleware)
.middlewareFactory(messages);
return injector.get(DebugLogMiddleware).middlewareFactory(messages);
}

}
34 changes: 16 additions & 18 deletions src/server/services/jwtAuthStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {

export const jwtAuthStrategyFactory:AuthenticationStrategyFactory = (remoteCliContext: RemoteCliContext): AuthenticationStrategy => {
return function (vantage: any, options: any) {
return function (args: {client: {jwt: string, publicKeyPath: string, columns: number}}, cb: AuthenticationCallback) {
return async function (args: {client: {jwt: string, publicKeyPath: string, columns: number}}, cb: AuthenticationCallback) {

try {
remoteCliContext.logger.silly.debug('Passed client arguments: ', args);
Expand All @@ -32,23 +32,21 @@ export const jwtAuthStrategyFactory:AuthenticationStrategyFactory = (remoteCliCo

remoteCliContext.logger.info(`Authenticating JSON web token against public key [${keyPath}]`);

remoteCliContext.authService.verify(token, keyPath)
.then((payload: any) => {
remoteCliContext.logger.info(`${payload.username} has been authenticated with token`)
.debug('Token:', token);
let displayBanner = `Hi ${payload.username}, Welcome to Zeroth runtime cli.`;
if (args.client.columns >= 80) {
displayBanner = bannerBg(undefined, token);
}
this.log(chalk.grey(`You were authenticated with a JSON Web token verified against the public key at ${keyPath}`));
this.log(displayBanner);
this.log(` Type 'help' for a list of available commands`);

return cb(null, true);
})
.catch((e: Error) => {
return cb(e.message, false);
});
const payload = await remoteCliContext.authService.verify(token, keyPath);

remoteCliContext.logger.info(`${payload.username} has been authenticated with token`)
.debug('Token:', token);

let displayBanner = `Hi ${payload.username}, Welcome to Zeroth runtime cli.`;
if (args.client.columns >= 80) {
displayBanner = bannerBg(undefined, token);
}

this.log(chalk.grey(`You were authenticated with a JSON Web token verified against the public key at ${keyPath}`));
this.log(displayBanner);
this.log(` Type 'help' for a list of available commands`);

return cb(null, true);

} catch (e) {
remoteCliContext.logger.error('Authentication error', e.message).debug(e.stack);
Expand Down
60 changes: 32 additions & 28 deletions src/server/stores/db.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,50 +73,54 @@ export abstract class DatabaseStore<T extends AbstractModel> extends AbstractSto
/**
* @inheritdoc
*/
public findMany(query?: Query): Promise<Collection<T>> {
return this.getRepository()
.then((repo) => repo.find({
//@todo define query and restrict count with pagination
}))
.then((entityArray: T[]): Collection<T> => {

if (!entityArray.length) {
throw new NotFoundException(`No ${this.modelStatic.name} found with query params [${JSON.stringify(query)}]`);
}

return new Collection(entityArray);
})
.catch((e) => {
this.logger.error(e);
throw e;
public async findMany(query?: Query): Promise<Collection<T>> {

try {
const repo = await this.getRepository();

const entityArray: T[] = await repo.find({
//@todo define query interface and restrict count with pagination
});

if (!entityArray.length) {
throw new NotFoundException(`No ${this.modelStatic.name} found with query params [${JSON.stringify(query)}]`);
}

return new Collection(entityArray);

} catch (e) {
this.logger.error(e);
throw e;
}
}

/**
* @inheritdoc
*/
public saveOne(model: T): Promise<T> {
return this.getRepository()
.then((repo) => repo.persist(model));
public async saveOne(model: T): Promise<T> {
const repo = await this.getRepository();
return repo.persist(model);
}

/**
* @inheritdoc
*/
public deleteOne(model: T): Promise<T> {
return this.getRepository()
.then((repo) => repo.remove(model));
public async deleteOne(model: T): Promise<T> {
const repo = await this.getRepository();
return repo.remove(model);
}

/**
* @inheritdoc
*/
public hasOne(model: T): Promise<boolean> {
return this.getRepository()
.then((repo) => repo.findOneById(model))
.then(() => true)
.catch(() => false)
;
public async hasOne(model: T): Promise<boolean> {
const repo = await this.getRepository();
try {
await repo.findOneById(model.getIdentifier());
return true;
} catch (e) {
return false;
}
}

}