Skip to content

Commit

Permalink
feat: adding authorizer decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
davidecavaliere committed Sep 28, 2018
1 parent 89ad199 commit a2b138c
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './lib/endpoint/endpoint.decorator';
export * from './lib/lambda/lambda.decorator';
export * from './lib/lambda/authorizer.decorator';
export * from './lib/index';
79 changes: 79 additions & 0 deletions src/lib/lambda/authorizer.decorator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// tslint:disable:no-expression-statement no-object-mutation
import test from 'ava';
import { Lambda, LambdaOptions } from './lambda.decorator';
import { Endpoint } from '../../';
import { boostrap } from '../index';
import { Authorizer, getAuthorizerMetadata } from './authorizer.decorator';

const option1: LambdaOptions = {
method: 'get',
name: 'lambda-name-1',
path: '/'
};

const option2: LambdaOptions = {
method: 'get',
name: 'lambda-name-2',
path: ':id'
};

@Endpoint({
name: 'endpoint'
})
class TestClass {
public readonly toTestAccessToInstance: string = 'base';

@Lambda(option1)
public findAll(arg1, arg2, arg3) {
// console.log('running original findAll()');
return this.toTestAccessToInstance + arg1 + arg2 + arg3;
}

@Lambda(option2)
public findOne() {
return 1;
}

@Authorizer()
public async authorize(token, resource): Promise<boolean> {
console.log('token', token);
console.log('resource', resource);
return token.scope.some(value => value === resource);
}
}

let instance: TestClass;

test.beforeEach(() => {
instance = boostrap(TestClass, 'express');
});

test('authorize function', (t) => {
t.plan(1);

return instance.authorize.apply(instance, [{
authorizationToken: {
scope: ['some-method-arn']
},
methodArn: 'some-method-arn'
}]).then((value) => {
t.deepEqual(value, {

principalId: {
scope: ['some-method-arn']
},
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: 'Allow',
Resource: 'some-method-arn',
},
],
}
});
});
});


80 changes: 80 additions & 0 deletions src/lib/lambda/authorizer.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// tslint:disable:only-arrow-functions readonly-array prefer- no-if-statement no-object-mutation no-this no-object-literal-type-assertion

import debug from 'debug';
import 'reflect-metadata';
import { getSingleton } from '../index';
import { CustomAuthorizerEvent, CustomAuthorizerResult } from 'aws-lambda';

const d = debug('microgamma:apigator:authorizer');

export const AuthorizerMetadata = Symbol('Authorizer');

export interface AuthorizerOptions {
name: string;
}

export function Authorizer(options?: AuthorizerOptions) {
d('constructing a class decorator', options);
return (target: any, key: string, descriptor) => {
d('decorating method');
d('target', target);
d('function name', key);
d('descriptor', descriptor);

Reflect.defineMetadata(AuthorizerMetadata, {
name: options ? options.name : key
}, target);

const instance = getSingleton(target.constructor.name);
d('current instance is:', instance);

const originalFunction = descriptor.value;
d('original function is', originalFunction);

descriptor.value = async (...args: any[]) => {
try {

const authContext: CustomAuthorizerEvent = args[0];
d('authContext is', authContext);
const newArgs = [authContext.authorizationToken, authContext.methodArn];

const retValue = await originalFunction.apply(instance, newArgs);

d('retValue', retValue);

return {
principalId: authContext.authorizationToken,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: retValue ? 'Allow' : 'Deny',
Resource: authContext.methodArn,
},
],
}
} as CustomAuthorizerResult;

} catch (e) {

d('something is going on', e);

if (e.message.match(/^\[[0-9]{3,}\](.)+/)) {
throw Error(e);
}

throw Error(`[500] ${e}`);
}
};

return descriptor;
};
}

export function getAuthorizerMetadata(instance): AuthorizerOptions {
d('metadata keys', Reflect.getMetadataKeys(instance));
const metadata = Reflect.getMetadata(AuthorizerMetadata, instance);
d('metadata', metadata);
return metadata;
}

0 comments on commit a2b138c

Please sign in to comment.