From 4cf379d8b014608d5726ab3021c2228896f5c56e Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Sun, 21 May 2017 13:15:10 +0100 Subject: [PATCH 01/16] Add initial support for Cognito User Pools This includes unit tests and documentation. A simple integration test has been added. --- docs/providers/aws/README.md | 1 + .../aws/events/cognito-user-pool-trigger.md | 139 ++++++++ docs/providers/aws/guide/resources.md | 3 +- lib/plugins/Plugins.json | 1 + lib/plugins/aws/lib/naming.js | 10 + lib/plugins/aws/lib/naming.test.js | 19 + .../compile/events/cognitoUserPool/index.js | 178 ++++++++++ .../events/cognitoUserPool/index.test.js | 329 ++++++++++++++++++ .../templates/aws-csharp/serverless.yml | 3 + .../aws-groovy-gradle/serverless.yml | 3 + .../templates/aws-java-gradle/serverless.yml | 3 + .../templates/aws-java-maven/serverless.yml | 3 + .../templates/aws-nodejs/serverless.yml | 3 + .../templates/aws-python/serverless.yml | 3 + .../templates/aws-python3/serverless.yml | 3 + .../templates/aws-scala-sbt/serverless.yml | 3 + .../service/handler.js | 9 + .../service/serverless.yml | 13 + .../single-event-single-function/tests.js | 25 ++ tests/utils/index.js | 14 + 20 files changed, 764 insertions(+), 1 deletion(-) create mode 100644 docs/providers/aws/events/cognito-user-pool-trigger.md create mode 100644 lib/plugins/aws/package/compile/events/cognitoUserPool/index.js create mode 100644 lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/handler.js create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/serverless.yml create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js diff --git a/docs/providers/aws/README.md b/docs/providers/aws/README.md index f25b4437e..4e9ca5715 100644 --- a/docs/providers/aws/README.md +++ b/docs/providers/aws/README.md @@ -89,6 +89,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • IoT
  • CloudWatch Event
  • CloudWatch Log
  • +
  • Cognito User Pool Trigger
  • diff --git a/docs/providers/aws/events/cognito-user-pool-trigger.md b/docs/providers/aws/events/cognito-user-pool-trigger.md new file mode 100644 index 000000000..844b912bb --- /dev/null +++ b/docs/providers/aws/events/cognito-user-pool-trigger.md @@ -0,0 +1,139 @@ + + + +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/) + + +# Cognito User Pool Trigger + +## Valid Triggers + +Serverless supports all Cognito User Pool Triggers as specified [here][aws-triggers-list]. + +## Simple event definition + +This will create a Cognito User Pool with the specified name. You can reference the same pool multiple times. + +```yml +functions: + preSignUp: + handler: preSignUp.handler + events: + - cognitoUserPool: + pool: MyUserPool + trigger: PreSignUp + customMessage: + handler: customMessage.handler + events: + - cognitoUserPool: + pool: MyUserPool + trigger: CustomMessage +``` + +## Multiple pools event definitions + +This will create multiple Cognito User Pools with their specified names: + +```yml +functions: + preSignUpForPool1: + handler: preSignUp.handler + events: + - cognitoUserPool: + pool: MyUserPool1 + trigger: PreSignUp + preSignUpForPool2: + handler: preSignUp.handler + events: + - cognitoUserPool: + pool: MyUserPool2 + trigger: PreSignUp +``` + +You can also deploy the same function for different user pools: + +```yml +functions: + preSignUp: + handler: preSignUp.handler + events: + - cognitoUserPool: + pool: MyUserPool1 + trigger: PreSignUp + - cognitoUserPool: + pool: MyUserPool2 + trigger: PreSignUp +``` + +## Custom message trigger handlers + +For custom messages, you will need to check `event.triggerSource` type inside your handler function: + +```js +// customMessage.js +function handler(event, context, callback) { + if (event.triggerSource === 'CustomMessage_AdminCreateUser') { + // ... + } + if (event.triggerSource === 'CustomMessage_ResendCode') { + // ... + } +} +``` + +## Referencing a User Pool from the current stack + +You can attach the functions as events on a Cognito User Pool defined in the `Resources` section. + +```yml +functions: + preSignUp: + handler: preSignUpForPool1.handler + events: + - cognitoUserPool: + pool: MyUserPoolFromResources + trigger: PreSignUp + postConfirmation: + handler: postConfirmation.handler + events: + - cognitoUserPool: + pool: MyUserPoolFromResources + trigger: PostConfirmation +resources: + Resources: + MyUserPoolFromResources: + Type: AWS::Cognito::UserPool +``` + +## Overriding a generated User Pool + +A Cognito User Pool created by an event can be overridden by using the [logical resource name][logical-resource-names] in `Resources`: + +```yml +functions: + preSignUp: + handler: preSignUpForPool1.handler + events: + - cognitoUserPool: + pool: MyUserPool + trigger: PreSignUp + postConfirmation: + handler: postConfirmation.handler + events: + - cognitoUserPool: + pool: MyUserPool + trigger: PostConfirmation +resources: + Resources: + CognitoUserPoolMyUserPool: + Type: AWS::Cognito::UserPool +``` + +[aws-triggers-list]: http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared +[logical-resource-names]: https://serverless.com/framework/docs/providers/aws/guide/resources#aws-cloudformation-resource-reference diff --git a/docs/providers/aws/guide/resources.md b/docs/providers/aws/guide/resources.md index aecb4c462..f8e637ed5 100644 --- a/docs/providers/aws/guide/resources.md +++ b/docs/providers/aws/guide/resources.md @@ -70,7 +70,7 @@ We're also using the term `normalizedName` or similar terms in this guide. This |Lambda::Function | {normalizedFunctionName}LambdaFunction | HelloLambdaFunction | |Lambda::Version | {normalizedFunctionName}LambdaVersion{sha256} | HelloLambdaVersionr3pgoTvv1xT4E4NiCL6JG02fl6vIyi7OS1aW0FwAI | |Logs::LogGroup | {normalizedFunctionName}LogGroup | HelloLogGroup | -|Lambda::Permission | | | +|Lambda::Permission | | | |Events::Rule | | | |AWS::Logs::SubscriptionFilter | {normalizedFuntionName}LogsSubscriptionFilterCloudWatchLog{SequentialID} | HelloLogsSubscriptionFilterCloudWatchLog1 | |AWS::IoT::TopicRule | {normalizedFuntionName}IotTopicRule{SequentialID} | HelloIotTopicRule1 | @@ -83,6 +83,7 @@ We're also using the term `normalizedName` or similar terms in this guide. This |SNS::Topic | SNSTopic{normalizedTopicName} | SNSTopicSometopic | |SNS::Subscription | {normalizedFunctionName}SnsSubscription{normalizedTopicName} | HelloSnsSubscriptionSomeTopic | |AWS::Lambda::EventSourceMapping | | | +|Cognito::UserPool | CognitoUserPool{normalizedPoolId} | CognitoUserPoolPoolId | ## Override AWS CloudFormation Resource diff --git a/lib/plugins/Plugins.json b/lib/plugins/Plugins.json index af4fee885..7d48752fe 100644 --- a/lib/plugins/Plugins.json +++ b/lib/plugins/Plugins.json @@ -34,6 +34,7 @@ "./aws/package/compile/events/iot/index.js", "./aws/package/compile/events/cloudWatchEvent/index.js", "./aws/package/compile/events/cloudWatchLog/index.js", + "./aws/package/compile/events/cognitoUserPool/index.js", "./aws/deployFunction/index.js", "./aws/deployList/index.js", "./aws/invokeLocal/index.js" diff --git a/lib/plugins/aws/lib/naming.js b/lib/plugins/aws/lib/naming.js index e81d281fe..fe6cc84ae 100644 --- a/lib/plugins/aws/lib/naming.js +++ b/lib/plugins/aws/lib/naming.js @@ -246,6 +246,11 @@ module.exports = { .getNormalizedFunctionName(functionName)}LogsSubscriptionFilterCloudWatchLog${logsIndex}`; }, + // Cognito User Pool + getCognitoUserPoolLogicalId(poolId) { + return `CognitoUserPool${this.normalizeNameToAlphaNumericOnly(poolId)}`; + }, + // Permissions getLambdaS3PermissionLogicalId(functionName, bucketName) { return `${this.getNormalizedFunctionName(functionName)}LambdaPermission${this @@ -278,4 +283,9 @@ module.exports = { return `${this.getNormalizedFunctionName(functionName) }LambdaPermissionLogsSubscriptionFilterCloudWatchLog${logsIndex}`; }, + getLambdaCognitoUserPoolPermissionLogicalId(functionName, poolId, triggerSource) { + return `${this + .getNormalizedFunctionName(functionName)}LambdaPermissionCognitoUserPoolTriggerSource${ + this.normalizeNameToAlphaNumericOnly(poolId)}${triggerSource}`; + }, }; diff --git a/lib/plugins/aws/lib/naming.test.js b/lib/plugins/aws/lib/naming.test.js index 950e92ff0..706ecc6df 100644 --- a/lib/plugins/aws/lib/naming.test.js +++ b/lib/plugins/aws/lib/naming.test.js @@ -388,6 +388,13 @@ describe('#naming()', () => { }); }); + describe('#getCognitoUserPoolLogicalId()', () => { + it('should normalize the user pool name and add the standard prefix', () => { + expect(sdk.naming.getCognitoUserPoolLogicalId('us-east-1_v123sDAS1')) + .to.equal('CognitoUserPoolUseast1v123sDAS1'); + }); + }); + describe('#getLambdaS3PermissionLogicalId()', () => { it('should normalize the function name and add the standard suffix', () => { expect(sdk.naming.getLambdaS3PermissionLogicalId('functionName', 'bucket')) @@ -463,4 +470,16 @@ describe('#naming()', () => { .to.equal('FunctionNameLambdaPermissionLogsSubscriptionFilterCloudWatchLog0'); }); }); + + describe('#getLambdaCognitoUserPoolPermissionLogicalId()', () => { + it('should normalize the function name and add the standard suffix including the normalized ' + + ' pool name and trigger source', + () => { + expect(sdk.naming.getLambdaCognitoUserPoolPermissionLogicalId( + 'functionName', + 'poolId', + 'TriggerSource' + )).to.equal('FunctionNameLambdaPermissionCognitoUserPoolTriggerSourcePoolIdTriggerSource'); + }); + }); }); diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js new file mode 100644 index 000000000..92170483f --- /dev/null +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js @@ -0,0 +1,178 @@ +'use strict'; + +const _ = require('lodash'); + +const validTriggerSources = [ + 'PreSignUp', + 'PostConfirmation', + 'PreAuthentication', + 'PostAuthentication', + 'CustomMessage', + 'DefineAuthChallenge', + 'CreateAuthChallenge', + 'VerifyAuthChallengeResponse', +]; + +class AwsCompileCognitoUserPoolEvents { + constructor(serverless) { + this.serverless = serverless; + this.provider = this.serverless.getProvider('aws'); + + this.hooks = { + 'package:compileEvents': this.compileCognitoUserPoolEvents.bind(this), + }; + } + + compileCognitoUserPoolEvents() { + const userPools = []; + const cognitoUserPoolTriggerFunctions = []; + + // Iterate through all functions declared in `serverless.yml` + this.serverless.service.getAllFunctions().forEach((functionName) => { + const functionObj = this.serverless.service.getFunction(functionName); + + if (functionObj.events) { + functionObj.events.forEach(event => { + if (event.cognitoUserPool) { + // Check event definition for `cognitoUserPool` object + if (typeof event.cognitoUserPool === 'object') { + // Check `cognitoUserPool` object has required properties + if (!event.cognitoUserPool.pool || !event.cognitoUserPool.trigger) { + throw new this.serverless.classes + .Error([ + `Cognito User Pool event of function ${functionName} is not an object.`, + 'The correct syntax is an object with the "pool" and "trigger" properties.', + 'Please check the docs for more info.', + ].join(' ')); + } + + // Check `cognitoUserPool` trigger is valid + if (!_.includes(validTriggerSources, event.cognitoUserPool.trigger)) { + throw new this.serverless.classes + .Error([ + 'Cognito User Pool trigger source is invalid, must be one of:', + `${validTriggerSources.join(', ')}.`, + 'Please check the docs for more info.', + ].join(' ')); + } + + // Save trigger functions so we can use them to generate + // IAM permissions later + cognitoUserPoolTriggerFunctions.push({ + functionName, + poolName: event.cognitoUserPool.pool, + triggerSource: event.cognitoUserPool.trigger, + }); + + // Save user pools so we can use them to generate + // CloudFormation resources later + userPools.push(event.cognitoUserPool.pool); + } else { + throw new this.serverless.classes + .Error([ + `Cognito User Pool event of function ${functionName} is not an object.`, + 'The correct syntax is an object with the "pool" and "trigger" properties.', + 'Please check the docs for more info.', + ].join(' ')); + } + } + }); + } + }); + + // Generate CloudFormation templates for Cognito User Pool changes + _.forEach(userPools, (poolName) => { + // Create a `LambdaConfig` object for the CloudFormation template + const lambdaConfig = _.reduce(cognitoUserPoolTriggerFunctions, (result, value) => { + const lambdaLogicalId = this.provider.naming.getLambdaLogicalId(value.functionName); + + // Return a new object to avoid lint errors + return Object.assign({}, result, { [value.triggerSource]: lambdaLogicalId }); + }, {}); + + const userPoolLogicalId = this.provider.naming.getCognitoUserPoolLogicalId(poolName); + + const userPoolTemplate = { + Type: 'AWS::Cognito::UserPool', + Properties: { + UserPoolName: poolName, + LambdaConfig: lambdaConfig, + }, + }; + + // Check if pool name has been declared in `Resources` + if (_.has( + this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + poolName + )) { + // Merge with existing template + const userPoolCFResource = { + [poolName]: _.merge( + userPoolTemplate, + this.serverless.service.provider.compiledCloudFormationTemplate.Resources[poolName] + ), + }; + _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + userPoolCFResource); + } else if (_.has( + this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + userPoolLogicalId + )) { + // Merge with existing template + const userPoolCFResource = { + [userPoolLogicalId]: _.merge( + userPoolTemplate, + this.serverless.service.provider.compiledCloudFormationTemplate + .Resources[userPoolLogicalId] + ), + }; + _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + userPoolCFResource); + } else { // Otherwise create new resource + const userPoolCFResource = { + [userPoolLogicalId]: userPoolTemplate, + }; + _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + userPoolCFResource); + } + }); + + // Generate CloudFormation templates for IAM permissions to allow Cognito to trigger Lambda + cognitoUserPoolTriggerFunctions.forEach((cognitoUserPoolTriggerFunction) => { + const userPoolLogicalId = this.provider.naming + .getCognitoUserPoolLogicalId(cognitoUserPoolTriggerFunction.poolName); + const lambdaLogicalId = this.provider.naming + .getLambdaLogicalId(cognitoUserPoolTriggerFunction.functionName); + + const permissionTemplate = { + Type: 'AWS::Lambda::Permission', + Properties: { + FunctionName: { + 'Fn::GetAtt': [ + lambdaLogicalId, + 'Arn', + ], + }, + Action: 'lambda:InvokeFunction', + Principal: 'cognito-idp.amazonaws.com', + SourceArn: { + 'Fn::GetAtt': [ + userPoolLogicalId, + 'Arn', + ], + }, + }, + }; + const lambdaPermissionLogicalId = this.provider.naming + .getLambdaCognitoUserPoolPermissionLogicalId(cognitoUserPoolTriggerFunction.functionName, + cognitoUserPoolTriggerFunction.poolName, cognitoUserPoolTriggerFunction.triggerSource); + const permissionCFResource = { + [lambdaPermissionLogicalId]: permissionTemplate, + }; + _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + permissionCFResource); + }); + } +} + +module.exports = AwsCompileCognitoUserPoolEvents; diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js new file mode 100644 index 000000000..99541e13e --- /dev/null +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js @@ -0,0 +1,329 @@ +'use strict'; + +const expect = require('chai').expect; +const AwsProvider = require('../../../../provider/awsProvider'); +const AwsCompileCognitoUserPoolEvents = require('./index'); +const Serverless = require('../../../../../../Serverless'); + +describe('AwsCompileCognitoUserPoolEvents', () => { + let serverless; + let awsCompileCognitoUserPoolEvents; + + beforeEach(() => { + serverless = new Serverless(); + serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} }; + serverless.setProvider('aws', new AwsProvider(serverless)); + awsCompileCognitoUserPoolEvents = new AwsCompileCognitoUserPoolEvents(serverless); + awsCompileCognitoUserPoolEvents.serverless.service.service = 'new-service'; + }); + + describe('#constructor()', () => { + it('should set the provider variable to an instance of AwsProvider', () => + expect(awsCompileCognitoUserPoolEvents.provider).to.be.instanceof(AwsProvider)); + }); + + describe('#compileCognitoUserPoolEvents()', () => { + it('should throw an error if cognitoUserPool event type is not an object', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: 42, + }, + ], + }, + }; + + expect(() => awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents()).to.throw(Error); + }); + + it('should throw an error if the "pool" property is not given', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: null, + }, + }, + ], + }, + }; + + expect(() => awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents()).to.throw(Error); + }); + + it('should throw an error if the "trigger" property is not given', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + trigger: null, + }, + }, + ], + }, + }; + + expect(() => awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents()).to.throw(Error); + }); + + it('should throw an error if the "trigger" property is invalid', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'invalidTrigger', + }, + }, + ], + }, + }; + + expect(() => awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents()).to.throw(Error); + }); + + it('should create corresponding resources when Cognito User Pool events are given ' + + 'as separate functions', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool1', + trigger: 'PreSignUp', + }, + }, + ], + }, + second: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool2', + trigger: 'PostConfirmation', + }, + }, + ], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool1.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool2.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool1PreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .SecondLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool2PostConfirmation.Type + ).to.equal('AWS::Lambda::Permission'); + }); + + it('should create corresponding resources when Cognito User Pool events are given ' + + 'with the same function', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool1', + trigger: 'PreSignUp', + }, + }, + { + cognitoUserPool: { + pool: 'MyUserPool2', + trigger: 'PostConfirmation', + }, + }, + ], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool1.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool2.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool1PreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool2PostConfirmation.Type + ).to.equal('AWS::Lambda::Permission'); + }); + + it('should create single user pool resource when the same pool referenced repeatedly', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'PreSignUp', + }, + }, + ], + }, + second: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'PostConfirmation', + }, + }, + ], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .CognitoUserPoolMyUserPool.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(Object.keys(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .CognitoUserPoolMyUserPool.Properties.LambdaConfig).length + ).to.equal(2); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .SecondLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPostConfirmation.Type + ).to.equal('AWS::Lambda::Permission'); + }); + + it('should merge corresponding resources when Cognito User Pool is predefined ' + + 'in Resources', () => { + serverless.service.provider.compiledCloudFormationTemplate = { + Resources: { + MyUserPool: { + Type: 'AWS::Cognito::UserPool', + Properties: { + UserPoolName: 'my-user-pool', + }, + }, + }, + }; + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'PreSignUp', + }, + }, + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'PostConfirmation', + }, + }, + ], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.MyUserPool.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.MyUserPool.Properties.UserPoolName + ).to.equal('my-user-pool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPostConfirmation.Type + ).to.equal('AWS::Lambda::Permission'); + }); + + it('should merge corresponding resources when generated Cognito User Pool is overridden ' + + 'in Resources', () => { + serverless.service.provider.compiledCloudFormationTemplate = { + Resources: { + CognitoUserPoolMyUserPool: { + Type: 'AWS::Cognito::UserPool', + Properties: { + UserPoolName: 'my-user-pool', + }, + }, + }, + }; + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'PreSignUp', + }, + }, + { + cognitoUserPool: { + pool: 'MyUserPool', + trigger: 'PostConfirmation', + }, + }, + ], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool.Properties.UserPoolName + ).to.equal('my-user-pool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPostConfirmation.Type + ).to.equal('AWS::Lambda::Permission'); + }); + + it('should not create corresponding resources when Cognito User Pool events' + + ' are not given', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect( + awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + ).to.deep.equal({}); + }); + }); +}); diff --git a/lib/plugins/create/templates/aws-csharp/serverless.yml b/lib/plugins/create/templates/aws-csharp/serverless.yml index 57e708604..e1f60bedb 100644 --- a/lib/plugins/create/templates/aws-csharp/serverless.yml +++ b/lib/plugins/create/templates/aws-csharp/serverless.yml @@ -79,6 +79,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-groovy-gradle/serverless.yml b/lib/plugins/create/templates/aws-groovy-gradle/serverless.yml index ca9c60b82..9ef210f6b 100644 --- a/lib/plugins/create/templates/aws-groovy-gradle/serverless.yml +++ b/lib/plugins/create/templates/aws-groovy-gradle/serverless.yml @@ -77,6 +77,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-java-gradle/serverless.yml b/lib/plugins/create/templates/aws-java-gradle/serverless.yml index 53a22f47c..d421ab1d5 100644 --- a/lib/plugins/create/templates/aws-java-gradle/serverless.yml +++ b/lib/plugins/create/templates/aws-java-gradle/serverless.yml @@ -77,6 +77,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-java-maven/serverless.yml b/lib/plugins/create/templates/aws-java-maven/serverless.yml index a677a2212..d6fe45620 100644 --- a/lib/plugins/create/templates/aws-java-maven/serverless.yml +++ b/lib/plugins/create/templates/aws-java-maven/serverless.yml @@ -77,6 +77,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-nodejs/serverless.yml b/lib/plugins/create/templates/aws-nodejs/serverless.yml index 6cdb54b2c..059b386d4 100644 --- a/lib/plugins/create/templates/aws-nodejs/serverless.yml +++ b/lib/plugins/create/templates/aws-nodejs/serverless.yml @@ -82,6 +82,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-python/serverless.yml b/lib/plugins/create/templates/aws-python/serverless.yml index d3d0b6285..110ae584f 100644 --- a/lib/plugins/create/templates/aws-python/serverless.yml +++ b/lib/plugins/create/templates/aws-python/serverless.yml @@ -82,6 +82,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-python3/serverless.yml b/lib/plugins/create/templates/aws-python3/serverless.yml index 156d8608a..73cce39e6 100644 --- a/lib/plugins/create/templates/aws-python3/serverless.yml +++ b/lib/plugins/create/templates/aws-python3/serverless.yml @@ -82,6 +82,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/lib/plugins/create/templates/aws-scala-sbt/serverless.yml b/lib/plugins/create/templates/aws-scala-sbt/serverless.yml index 309390a97..c7ce81f69 100644 --- a/lib/plugins/create/templates/aws-scala-sbt/serverless.yml +++ b/lib/plugins/create/templates/aws-scala-sbt/serverless.yml @@ -79,6 +79,9 @@ functions: # state: # - pending # - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp # Define function environment variables here # environment: diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/handler.js b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/handler.js new file mode 100644 index 000000000..b7f044321 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/handler.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports.preSignUp = (event, context, callback) => { + const nextEvent = Object.assign({}, event); + nextEvent.response.autoConfirmUser = true; + + process.stdout.write(JSON.stringify(nextEvent)); + callback(null, nextEvent); +}; diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/serverless.yml b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/serverless.yml new file mode 100644 index 000000000..97167e310 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/serverless.yml @@ -0,0 +1,13 @@ +service: aws-nodejs + +provider: + name: aws + runtime: nodejs6.10 + +functions: + preSignUp: + handler: handler.preSignUp + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_1} + trigger: PreSignUp diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js new file mode 100644 index 000000000..7dad8ba60 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js @@ -0,0 +1,25 @@ +'use strict'; + +const path = require('path'); +const expect = require('chai').expect; +const Utils = require('../../../../utils/index'); + +describe('AWS - Cognito User Pool Trigger: Single event with single function', () => { + beforeAll(() => { + Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); + Utils.deployService(); + }); + + it('should trigger function when PreSignUp event is triggered', () => Utils + .createCognitoUser('CognitoUserPoolAwsnodejs-1', 'test@test.com', 'password123') + .delay(60000) + .then(() => { + const logs = Utils.getFunctionLogs('preSignUp'); + expect(/"triggerSource":"preSignup"/g.test(logs)).to.equal(true); + }) + ); + + afterAll(() => { + Utils.removeService(); + }); +}); diff --git a/tests/utils/index.js b/tests/utils/index.js index a6d6cd5a3..1b5f11346 100644 --- a/tests/utils/index.js +++ b/tests/utils/index.js @@ -51,6 +51,8 @@ module.exports = { process.env.TOPIC_2 = `${serviceName}-1`; process.env.BUCKET_1 = `${serviceName}-1`; process.env.BUCKET_2 = `${serviceName}-2`; + process.env.COGNITO_USER_POOL_1 = `${serviceName}-1`; + process.env.COGNITO_USER_POOL_2 = `${serviceName}-2`; // return the name of the CloudFormation stack return `${serviceName}-dev`; @@ -163,6 +165,18 @@ module.exports = { return cwe.putEventsPromised(params); }, + createCognitoUser(userPoolId, username, password) { + const cisp = new AWS.CognitoIdentityServiceProvider({ region: 'us-east-1' }); + BbPromise.promisifyAll(cisp, { suffix: 'Promised' }); + + const params = { + UserPoolId: userPoolId, + Username: username, + TemporaryPassword: password, + }; + return cisp.adminCreateUserPromised(params); + }, + getFunctionLogs(functionName) { const logs = execSync(`${serverlessExec} logs --function ${functionName} --noGreeting true`); const logsString = new Buffer(logs, 'base64').toString(); From e12e45ebd2ec6ac2760d5e0f4f91cc86166d8c36 Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Mon, 22 May 2017 02:44:42 +0100 Subject: [PATCH 02/16] Use Lambda logical ID to retrieve its' ARN --- .../aws/package/compile/events/cognitoUserPool/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js index 92170483f..af44b3683 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js @@ -87,7 +87,14 @@ class AwsCompileCognitoUserPoolEvents { const lambdaLogicalId = this.provider.naming.getLambdaLogicalId(value.functionName); // Return a new object to avoid lint errors - return Object.assign({}, result, { [value.triggerSource]: lambdaLogicalId }); + return Object.assign({}, result, { + [value.triggerSource]: { + 'Fn::GetAtt': [ + lambdaLogicalId, + 'Arn', + ], + }, + }); }, {}); const userPoolLogicalId = this.provider.naming.getCognitoUserPoolLogicalId(poolName); From 1216447117ecd0041a1e612fef068ec81bc2ecc5 Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Mon, 22 May 2017 03:03:02 +0100 Subject: [PATCH 03/16] Add remaining integration tests Now includes test cases for single/multiple user pools with single/multiple event definitions on single/multiple functions. --- .../service/handler.js | 27 +++++++ .../service/serverless.yml | 31 ++++++++ .../tests.js | 76 +++++++++++++++++++ .../service/handler.js | 0 .../service/serverless.yml | 16 ++++ .../tests.js | 53 +++++++++++++ .../single-event-single-function/tests.js | 25 ------ .../service/handler.js | 22 ++++++ .../service/serverless.yml | 19 +++++ .../tests.js | 34 +++++++++ .../service/handler.js | 9 +++ .../service/serverless.yml | 0 .../tests.js | 29 +++++++ tests/utils/index.js | 14 ++++ 14 files changed, 330 insertions(+), 25 deletions(-) create mode 100644 tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/handler.js create mode 100644 tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/serverless.yml create mode 100644 tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js rename tests/integration/aws/cognito-user-pool-trigger/{single-event-single-function => multiple-pools-single-event-single-function}/service/handler.js (100%) create mode 100644 tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/serverless.yml create mode 100644 tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js delete mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/handler.js create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/serverless.yml create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/handler.js rename tests/integration/aws/cognito-user-pool-trigger/{single-event-single-function => single-pool-single-event-single-function}/service/serverless.yml (100%) create mode 100644 tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/handler.js b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/handler.js new file mode 100644 index 000000000..a1e2afe62 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/handler.js @@ -0,0 +1,27 @@ +'use strict'; + +const preSignUp = (event, context, callback) => { + const nextEvent = Object.assign({}, event); + nextEvent.response.autoConfirmUser = true; + + process.stdout.write(JSON.stringify(nextEvent)); + callback(null, nextEvent); +}; + +const customMessage = (event, context, callback) => { + const nextEvent = Object.assign({}, event); + if (event.triggerSource === 'CustomMessage_SignUp') { + nextEvent.response.smsMessage = `Welcome to the service. Your confirmation code is ${ + event.request.codeParameter}`; + nextEvent.response.emailSubject = 'Welcome to the service'; + nextEvent.response.emailMessage = `Thank you for signing up. ${ + event.request.codeParameter} is your verification code`; + } + process.stdout.write(JSON.stringify(nextEvent)); + callback(null, nextEvent); +}; + +module.exports.preSignUp1 = preSignUp; +module.exports.preSignUp2 = preSignUp; +module.exports.customMessage1 = customMessage; +module.exports.customMessage2 = customMessage; diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/serverless.yml b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/serverless.yml new file mode 100644 index 000000000..7dc6f310a --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/serverless.yml @@ -0,0 +1,31 @@ +service: aws-nodejs + +provider: + name: aws + runtime: nodejs6.10 + +functions: + preSignUp1: + handler: handler.preSignUp1 + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_1} + trigger: PreSignUp + customMessage1: + handler: handler.customMessage1 + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_1} + trigger: CustomMessage + preSignUp2: + handler: handler.preSignUp2 + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_2} + trigger: PreSignUp + customMessage2: + handler: handler.customMessage2 + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_2} + trigger: CustomMessage diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js new file mode 100644 index 000000000..b4c444750 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js @@ -0,0 +1,76 @@ +'use strict'; + +const path = require('path'); +const expect = require('chai').expect; +const Utils = require('../../../../utils/index'); + +describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + + 'events with multiple functions', () => { + beforeAll(() => { + Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); + Utils.deployService(); + }); + + it('should call the specified function on the first User Pool when PreSignUp ' + + 'event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .then((poolId) => + Promise.all([ + poolId, + Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'), + ]) + ) + .delay(60000) + .then((promiseResponse) => { + const poolId = promiseResponse[0]; + const logs = Utils.getFunctionLogs('preSignUp'); + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); + }) + ); + + it('should call the specified function on the first User Pool when CustomMessage ' + + 'event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .then((poolId) => { + const logs = Utils.getFunctionLogs('customMessage'); + + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); + }) + ); + + it('should call the specified function on the second User Pool when PreSignUp ' + + 'event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-2') + .then((poolId) => + Promise.all([ + poolId, + Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'), + ]) + ) + .delay(60000) + .then((promiseResponse) => { + const poolId = promiseResponse[0]; + const logs = Utils.getFunctionLogs('preSignUp'); + + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); + }) + ); + + it('should call the specified function on the second User Pool when CustomMessage ' + + 'event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-2') + .then((poolId) => { + const logs = Utils.getFunctionLogs('customMessage'); + + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); + }) + ); + + afterAll(() => { + Utils.removeService(); + }); +}); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/handler.js b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/handler.js similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/handler.js rename to tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/handler.js diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/serverless.yml b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/serverless.yml new file mode 100644 index 000000000..121de6025 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/serverless.yml @@ -0,0 +1,16 @@ +service: aws-nodejs + +provider: + name: aws + runtime: nodejs6.10 + +functions: + preSignUp: + handler: handler.preSignUp + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_1} + trigger: PreSignUp + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_2} + trigger: PreSignUp diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js new file mode 100644 index 000000000..324b1b216 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js @@ -0,0 +1,53 @@ +'use strict'; + +const path = require('path'); +const expect = require('chai').expect; +const Utils = require('../../../../utils/index'); + +describe('AWS - Cognito User Pool Trigger: Multiple User Pools with single ' + + 'event with single function', () => { + beforeAll(() => { + Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); + Utils.deployService(); + }); + + it('should call the specified function on the first User Pool when PreSignUp ' + + 'event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .then((poolId) => + Promise.all([ + poolId, + Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'), + ]) + ) + .delay(60000) + .then((promiseResponse) => { + const poolId = promiseResponse[0]; + const logs = Utils.getFunctionLogs('preSignUp'); + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); + }) + ); + + it('should call the specified function on the second User Pool when PreSignUp ' + + 'event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-2') + .then((poolId) => + Promise.all([ + poolId, + Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!'), + ]) + ) + .delay(60000) + .then((promiseResponse) => { + const poolId = promiseResponse[0]; + const logs = Utils.getFunctionLogs('preSignUp'); + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); + }) + ); + + afterAll(() => { + Utils.removeService(); + }); +}); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js deleted file mode 100644 index 7dad8ba60..000000000 --- a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/tests.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -const path = require('path'); -const expect = require('chai').expect; -const Utils = require('../../../../utils/index'); - -describe('AWS - Cognito User Pool Trigger: Single event with single function', () => { - beforeAll(() => { - Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); - Utils.deployService(); - }); - - it('should trigger function when PreSignUp event is triggered', () => Utils - .createCognitoUser('CognitoUserPoolAwsnodejs-1', 'test@test.com', 'password123') - .delay(60000) - .then(() => { - const logs = Utils.getFunctionLogs('preSignUp'); - expect(/"triggerSource":"preSignup"/g.test(logs)).to.equal(true); - }) - ); - - afterAll(() => { - Utils.removeService(); - }); -}); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/handler.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/handler.js new file mode 100644 index 000000000..2801cf8c5 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/handler.js @@ -0,0 +1,22 @@ +'use strict'; + +module.exports.preSignUp = (event, context, callback) => { + const nextEvent = Object.assign({}, event); + nextEvent.response.autoConfirmUser = true; + + process.stdout.write(JSON.stringify(nextEvent)); + callback(null, nextEvent); +}; + +module.exports.customMessage = (event, context, callback) => { + const nextEvent = Object.assign({}, event); + if (event.triggerSource === 'CustomMessage_SignUp') { + nextEvent.response.smsMessage = `Welcome to the service. Your confirmation code is ${ + event.request.codeParameter}`; + nextEvent.response.emailSubject = 'Welcome to the service'; + nextEvent.response.emailMessage = `Thank you for signing up. ${ + event.request.codeParameter} is your verification code`; + } + process.stdout.write(JSON.stringify(nextEvent)); + callback(null, nextEvent); +}; diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/serverless.yml b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/serverless.yml new file mode 100644 index 000000000..9ecaf3f5f --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/serverless.yml @@ -0,0 +1,19 @@ +service: aws-nodejs + +provider: + name: aws + runtime: nodejs6.10 + +functions: + preSignUp: + handler: handler.preSignUp + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_1} + trigger: PreSignUp + customMessage: + handler: handler.customMessage + events: + - cognitoUserPool: + pool: ${env:COGNITO_USER_POOL_1} + trigger: CustomMessage diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js new file mode 100644 index 000000000..aa40daa0f --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js @@ -0,0 +1,34 @@ +'use strict'; + +const path = require('path'); +const expect = require('chai').expect; +const Utils = require('../../../../utils/index'); + +describe('AWS - Cognito User Pool Trigger: Single User Pool with multiple ' + + 'events with multiple functions', () => { + beforeAll(() => { + Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); + Utils.deployService(); + }); + + it('should call the specified function when PreSignUp event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .then((poolId) => + Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!') + ) + .delay(60000) + .then(() => { + const logs = Utils.getFunctionLogs('preSignUp'); + expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); + }) + ); + + it('should call the specified function when CustomMessage event is triggered', () => { + const logs = Utils.getFunctionLogs('customMessage'); + expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); + }); + + afterAll(() => { + Utils.removeService(); + }); +}); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/handler.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/handler.js new file mode 100644 index 000000000..b7f044321 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/handler.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports.preSignUp = (event, context, callback) => { + const nextEvent = Object.assign({}, event); + nextEvent.response.autoConfirmUser = true; + + process.stdout.write(JSON.stringify(nextEvent)); + callback(null, nextEvent); +}; diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/serverless.yml b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/serverless.yml similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/single-event-single-function/service/serverless.yml rename to tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/serverless.yml diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js new file mode 100644 index 000000000..b589d8d97 --- /dev/null +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js @@ -0,0 +1,29 @@ +'use strict'; + +const path = require('path'); +const expect = require('chai').expect; +const Utils = require('../../../../utils/index'); + +describe('AWS - Cognito User Pool Trigger: Single User Pool with single ' + + 'event with single function', () => { + beforeAll(() => { + Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); + Utils.deployService(); + }); + + it('should call the specified function when PreSignUp event is triggered', () => Utils + .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .then((poolId) => + Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!') + ) + .delay(60000) + .then(() => { + const logs = Utils.getFunctionLogs('preSignUp'); + expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); + }) + ); + + afterAll(() => { + Utils.removeService(); + }); +}); diff --git a/tests/utils/index.js b/tests/utils/index.js index 1b5f11346..a56f3411b 100644 --- a/tests/utils/index.js +++ b/tests/utils/index.js @@ -165,6 +165,20 @@ module.exports = { return cwe.putEventsPromised(params); }, + getCognitoUserPoolId(userPoolName) { + const cisp = new AWS.CognitoIdentityServiceProvider({ region: 'us-east-1' }); + BbPromise.promisifyAll(cisp, { suffix: 'Promised' }); + + const params = { + MaxResults: 1, + }; + + return cisp.listUserPoolsPromised(params) + .then((data) => data.UserPools.find((userPool) => + RegExp(userPoolName, 'g').test(userPool.Name)).Id + ); + }, + createCognitoUser(userPoolId, username, password) { const cisp = new AWS.CognitoIdentityServiceProvider({ region: 'us-east-1' }); BbPromise.promisifyAll(cisp, { suffix: 'Promised' }); From 838cd1b2583869a73ce6031ace89b94c7549e58d Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Thu, 25 May 2017 18:49:58 +0100 Subject: [PATCH 04/16] Tidy and fix documentation As requested in PR review --- docs/providers/aws/events/cognito-user-pool-trigger.md | 7 ++++--- docs/providers/aws/guide/serverless.yml.md | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/providers/aws/events/cognito-user-pool-trigger.md b/docs/providers/aws/events/cognito-user-pool-trigger.md index 844b912bb..1718dddbb 100644 --- a/docs/providers/aws/events/cognito-user-pool-trigger.md +++ b/docs/providers/aws/events/cognito-user-pool-trigger.md @@ -1,5 +1,5 @@ -### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/) +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/cognito-user-pool-trigger) # Cognito User Pool Trigger @@ -129,6 +129,7 @@ functions: - cognitoUserPool: pool: MyUserPool trigger: PostConfirmation + resources: Resources: CognitoUserPoolMyUserPool: @@ -136,4 +137,4 @@ resources: ``` [aws-triggers-list]: http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared -[logical-resource-names]: https://serverless.com/framework/docs/providers/aws/guide/resources#aws-cloudformation-resource-reference +[logical-resource-names]: ../guide/resources#aws-cloudformation-resource-reference diff --git a/docs/providers/aws/guide/serverless.yml.md b/docs/providers/aws/guide/serverless.yml.md index cf2ee10a6..cb0c1b9d4 100644 --- a/docs/providers/aws/guide/serverless.yml.md +++ b/docs/providers/aws/guide/serverless.yml.md @@ -136,6 +136,9 @@ functions: - cloudwatchLog: logGroup: '/aws/lambda/hello' filter: '{$.userIdentity.type = Root}' + - cognitoUserPool: + pool: MyUserPool + trigger: PreSignUp # The "Resources" your "Functions" use. Raw AWS CloudFormation goes in here. resources: From 271e3c8d56afb1b8e6c7e53ae02037b90b09f777 Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Thu, 25 May 2017 22:19:30 +0100 Subject: [PATCH 05/16] Fix integration tests There were several resource names that were incorrectly specified that were causing the tests to fail. `Utils.getCognitoUserPoolId` was only returning a single item, which was also causing failures. --- .../tests.js | 17 +++++++++-------- .../tests.js | 4 ++-- .../tests.js | 15 ++++++++++----- .../tests.js | 2 +- tests/utils/index.js | 2 +- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js index b4c444750..ece3024f1 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js @@ -13,7 +13,7 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + it('should call the specified function on the first User Pool when PreSignUp ' + 'event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) .then((poolId) => Promise.all([ poolId, @@ -23,7 +23,8 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + .delay(60000) .then((promiseResponse) => { const poolId = promiseResponse[0]; - const logs = Utils.getFunctionLogs('preSignUp'); + const logs = Utils.getFunctionLogs('preSignUp1'); + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); }) @@ -31,9 +32,9 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + it('should call the specified function on the first User Pool when CustomMessage ' + 'event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) .then((poolId) => { - const logs = Utils.getFunctionLogs('customMessage'); + const logs = Utils.getFunctionLogs('customMessage1'); expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); @@ -42,7 +43,7 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + it('should call the specified function on the second User Pool when PreSignUp ' + 'event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-2') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_2) .then((poolId) => Promise.all([ poolId, @@ -52,7 +53,7 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + .delay(60000) .then((promiseResponse) => { const poolId = promiseResponse[0]; - const logs = Utils.getFunctionLogs('preSignUp'); + const logs = Utils.getFunctionLogs('preSignUp2'); expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); expect(/"triggerSource":"PreSignUp_\w+"/g.test(logs)).to.equal(true); @@ -61,9 +62,9 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + it('should call the specified function on the second User Pool when CustomMessage ' + 'event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-2') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_2) .then((poolId) => { - const logs = Utils.getFunctionLogs('customMessage'); + const logs = Utils.getFunctionLogs('customMessage2'); expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js index 324b1b216..03bbbfde0 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js +++ b/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js @@ -13,7 +13,7 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with single ' + it('should call the specified function on the first User Pool when PreSignUp ' + 'event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) .then((poolId) => Promise.all([ poolId, @@ -31,7 +31,7 @@ describe('AWS - Cognito User Pool Trigger: Multiple User Pools with single ' + it('should call the specified function on the second User Pool when PreSignUp ' + 'event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-2') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_2) .then((poolId) => Promise.all([ poolId, diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js index aa40daa0f..28ab9ebfa 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js @@ -12,7 +12,7 @@ describe('AWS - Cognito User Pool Trigger: Single User Pool with multiple ' + }); it('should call the specified function when PreSignUp event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) .then((poolId) => Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!') ) @@ -23,10 +23,15 @@ describe('AWS - Cognito User Pool Trigger: Single User Pool with multiple ' + }) ); - it('should call the specified function when CustomMessage event is triggered', () => { - const logs = Utils.getFunctionLogs('customMessage'); - expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); - }); + it('should call the specified function when CustomMessage event is triggered', () => Utils + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) + .then((poolId) => { + const logs = Utils.getFunctionLogs('customMessage1'); + + expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); + expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); + }) + ); afterAll(() => { Utils.removeService(); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js index b589d8d97..e6c3f87b6 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js @@ -12,7 +12,7 @@ describe('AWS - Cognito User Pool Trigger: Single User Pool with single ' + }); it('should call the specified function when PreSignUp event is triggered', () => Utils - .getCognitoUserPoolId('CognitoUserPoolAwsnodejs-1') + .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) .then((poolId) => Utils.createCognitoUser(poolId, 'test@test.com', 'Password123!') ) diff --git a/tests/utils/index.js b/tests/utils/index.js index a56f3411b..80113feb1 100644 --- a/tests/utils/index.js +++ b/tests/utils/index.js @@ -170,7 +170,7 @@ module.exports = { BbPromise.promisifyAll(cisp, { suffix: 'Promised' }); const params = { - MaxResults: 1, + MaxResults: 5, }; return cisp.listUserPoolsPromised(params) From ab92e3b8b1cd4b80fd9520a14388f2430468b758 Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Thu, 25 May 2017 22:21:20 +0100 Subject: [PATCH 06/16] Add fix for multiple pools with the same trigger If multiple pools were specified that had the same trigger i.e. `PreSignUp` then the last function would incorrectly be attached to each pool. Also added a test case. --- .../compile/events/cognitoUserPool/index.js | 16 ++++-- .../events/cognitoUserPool/index.test.js | 55 +++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js index af44b3683..a30e1cc25 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js @@ -83,7 +83,11 @@ class AwsCompileCognitoUserPoolEvents { // Generate CloudFormation templates for Cognito User Pool changes _.forEach(userPools, (poolName) => { // Create a `LambdaConfig` object for the CloudFormation template - const lambdaConfig = _.reduce(cognitoUserPoolTriggerFunctions, (result, value) => { + const currentPoolTriggerFunctions = _.filter(cognitoUserPoolTriggerFunctions, { + poolName, + }); + + const lambdaConfig = _.reduce(currentPoolTriggerFunctions, (result, value) => { const lambdaLogicalId = this.provider.naming.getLambdaLogicalId(value.functionName); // Return a new object to avoid lint errors @@ -107,11 +111,14 @@ class AwsCompileCognitoUserPoolEvents { }, }; - // Check if pool name has been declared in `Resources` + // Check if pool name has been declared in `Resources` and the resource has + // the correct `Type` if (_.has( this.serverless.service.provider.compiledCloudFormationTemplate.Resources, poolName - )) { + ) && this.serverless.service.provider.compiledCloudFormationTemplate + .Resources[poolName].Type === 'AWS::Cognito::UserPool' + ) { // Merge with existing template const userPoolCFResource = { [poolName]: _.merge( @@ -124,8 +131,7 @@ class AwsCompileCognitoUserPoolEvents { } else if (_.has( this.serverless.service.provider.compiledCloudFormationTemplate.Resources, userPoolLogicalId - )) { - // Merge with existing template + )) { // Merge with existing template const userPoolCFResource = { [userPoolLogicalId]: _.merge( userPoolTemplate, diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js index 99541e13e..c729d04b6 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js @@ -168,6 +168,61 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal('AWS::Lambda::Permission'); }); + it('should create corresponding resources when Cognito User Pool events are given ' + + 'with different functions and single event', () => { + awsCompileCognitoUserPoolEvents.serverless.service.functions = { + first: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool1', + trigger: 'PreSignUp', + }, + }, + ], + }, + second: { + events: [ + { + cognitoUserPool: { + pool: 'MyUserPool2', + trigger: 'PreSignUp', + }, + }, + ], + }, + }; + + awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool1.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool1 + .Properties.LambdaConfig.PreSignUp['Fn::GetAtt'][0] + ).to.equal(serverless.service.serverless.getProvider('aws') + .naming.getLambdaLogicalId('first')); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool2.Type + ).to.equal('AWS::Cognito::UserPool'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool2 + .Properties.LambdaConfig.PreSignUp['Fn::GetAtt'][0] + ).to.equal(serverless.service.serverless.getProvider('aws') + .naming.getLambdaLogicalId('second')); + + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool1PreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + expect(awsCompileCognitoUserPoolEvents.serverless.service.provider + .compiledCloudFormationTemplate.Resources + .SecondLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool2PreSignUp.Type + ).to.equal('AWS::Lambda::Permission'); + }); + it('should create single user pool resource when the same pool referenced repeatedly', () => { awsCompileCognitoUserPoolEvents.serverless.service.functions = { first: { From 2f5c84cff9f60ccc7929e0b4c08bce8a0ae46504 Mon Sep 17 00:00:00 2001 From: Hassan Khan Date: Thu, 25 May 2017 22:28:21 +0100 Subject: [PATCH 07/16] Add line before `resources` in example As per PR review --- docs/providers/aws/events/cognito-user-pool-trigger.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/providers/aws/events/cognito-user-pool-trigger.md b/docs/providers/aws/events/cognito-user-pool-trigger.md index 1718dddbb..25b03f826 100644 --- a/docs/providers/aws/events/cognito-user-pool-trigger.md +++ b/docs/providers/aws/events/cognito-user-pool-trigger.md @@ -105,6 +105,7 @@ functions: - cognitoUserPool: pool: MyUserPoolFromResources trigger: PostConfirmation + resources: Resources: MyUserPoolFromResources: From f0253fe7f6519ca9c615f04f0a464b97e65dff6c Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 31 May 2017 15:19:21 +0200 Subject: [PATCH 08/16] Add DependsOn to UserPool template --- .../aws/package/compile/events/cognitoUserPool/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js index a30e1cc25..a48db5ceb 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js @@ -103,12 +103,16 @@ class AwsCompileCognitoUserPoolEvents { const userPoolLogicalId = this.provider.naming.getCognitoUserPoolLogicalId(poolName); + const DependsOn = _.map(currentPoolTriggerFunctions, (value) => this + .provider.naming.getLambdaLogicalId(value.functionName)); + const userPoolTemplate = { Type: 'AWS::Cognito::UserPool', Properties: { UserPoolName: poolName, LambdaConfig: lambdaConfig, }, + DependsOn, }; // Check if pool name has been declared in `Resources` and the resource has From f0e12ee9ebc50c5444c129f2e2ccbcc858960d1c Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 13:25:03 +0200 Subject: [PATCH 09/16] Fix integration tests --- .../single-pool-multiple-events-multiple-functions/tests.js | 2 +- tests/utils/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js index 28ab9ebfa..5eec33fab 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js +++ b/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js @@ -26,7 +26,7 @@ describe('AWS - Cognito User Pool Trigger: Single User Pool with multiple ' + it('should call the specified function when CustomMessage event is triggered', () => Utils .getCognitoUserPoolId(process.env.COGNITO_USER_POOL_1) .then((poolId) => { - const logs = Utils.getFunctionLogs('customMessage1'); + const logs = Utils.getFunctionLogs('customMessage'); expect(RegExp(`"userPoolId":"${poolId}"`, 'g').test(logs)).to.equal(true); expect(/"triggerSource":"CustomMessage_AdminCreateUser"/g.test(logs)).to.equal(true); diff --git a/tests/utils/index.js b/tests/utils/index.js index 80113feb1..358f6a1bd 100644 --- a/tests/utils/index.js +++ b/tests/utils/index.js @@ -170,7 +170,7 @@ module.exports = { BbPromise.promisifyAll(cisp, { suffix: 'Promised' }); const params = { - MaxResults: 5, + MaxResults: 50, }; return cisp.listUserPoolsPromised(params) From 55d0a5e8b01b275704004ed0242706364868f8e9 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 14:07:33 +0200 Subject: [PATCH 10/16] Remove merging of existing user pool resources Since this is not possible because resources are merged after all the events are compiled. --- .../aws/events/cognito-user-pool-trigger.md | 25 ---- .../compile/events/cognitoUserPool/index.js | 43 +------ .../events/cognitoUserPool/index.test.js | 110 +----------------- 3 files changed, 10 insertions(+), 168 deletions(-) diff --git a/docs/providers/aws/events/cognito-user-pool-trigger.md b/docs/providers/aws/events/cognito-user-pool-trigger.md index 25b03f826..127c05892 100644 --- a/docs/providers/aws/events/cognito-user-pool-trigger.md +++ b/docs/providers/aws/events/cognito-user-pool-trigger.md @@ -87,31 +87,6 @@ function handler(event, context, callback) { } ``` -## Referencing a User Pool from the current stack - -You can attach the functions as events on a Cognito User Pool defined in the `Resources` section. - -```yml -functions: - preSignUp: - handler: preSignUpForPool1.handler - events: - - cognitoUserPool: - pool: MyUserPoolFromResources - trigger: PreSignUp - postConfirmation: - handler: postConfirmation.handler - events: - - cognitoUserPool: - pool: MyUserPoolFromResources - trigger: PostConfirmation - -resources: - Resources: - MyUserPoolFromResources: - Type: AWS::Cognito::UserPool -``` - ## Overriding a generated User Pool A Cognito User Pool created by an event can be overridden by using the [logical resource name][logical-resource-names] in `Resources`: diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js index a48db5ceb..f4b472023 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js @@ -115,43 +115,12 @@ class AwsCompileCognitoUserPoolEvents { DependsOn, }; - // Check if pool name has been declared in `Resources` and the resource has - // the correct `Type` - if (_.has( - this.serverless.service.provider.compiledCloudFormationTemplate.Resources, - poolName - ) && this.serverless.service.provider.compiledCloudFormationTemplate - .Resources[poolName].Type === 'AWS::Cognito::UserPool' - ) { - // Merge with existing template - const userPoolCFResource = { - [poolName]: _.merge( - userPoolTemplate, - this.serverless.service.provider.compiledCloudFormationTemplate.Resources[poolName] - ), - }; - _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, - userPoolCFResource); - } else if (_.has( - this.serverless.service.provider.compiledCloudFormationTemplate.Resources, - userPoolLogicalId - )) { // Merge with existing template - const userPoolCFResource = { - [userPoolLogicalId]: _.merge( - userPoolTemplate, - this.serverless.service.provider.compiledCloudFormationTemplate - .Resources[userPoolLogicalId] - ), - }; - _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, - userPoolCFResource); - } else { // Otherwise create new resource - const userPoolCFResource = { - [userPoolLogicalId]: userPoolTemplate, - }; - _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, - userPoolCFResource); - } + const userPoolCFResource = { + [userPoolLogicalId]: userPoolTemplate, + }; + + _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, + userPoolCFResource); }); // Generate CloudFormation templates for IAM permissions to allow Cognito to trigger Lambda diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js index c729d04b6..b64d61297 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js @@ -86,8 +86,7 @@ describe('AwsCompileCognitoUserPoolEvents', () => { expect(() => awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents()).to.throw(Error); }); - it('should create corresponding resources when Cognito User Pool events are given ' + - 'as separate functions', () => { + it('should create resources when CUP events are given as separate functions', () => { awsCompileCognitoUserPoolEvents.serverless.service.functions = { first: { events: [ @@ -129,8 +128,7 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal('AWS::Lambda::Permission'); }); - it('should create corresponding resources when Cognito User Pool events are given ' + - 'with the same function', () => { + it('should create resources when CUP events are given with the same function', () => { awsCompileCognitoUserPoolEvents.serverless.service.functions = { first: { events: [ @@ -168,8 +166,7 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal('AWS::Lambda::Permission'); }); - it('should create corresponding resources when Cognito User Pool events are given ' + - 'with different functions and single event', () => { + it('should create resources when CUP events are given with diff funcs and single event', () => { awsCompileCognitoUserPoolEvents.serverless.service.functions = { first: { events: [ @@ -267,106 +264,7 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal('AWS::Lambda::Permission'); }); - it('should merge corresponding resources when Cognito User Pool is predefined ' + - 'in Resources', () => { - serverless.service.provider.compiledCloudFormationTemplate = { - Resources: { - MyUserPool: { - Type: 'AWS::Cognito::UserPool', - Properties: { - UserPoolName: 'my-user-pool', - }, - }, - }, - }; - awsCompileCognitoUserPoolEvents.serverless.service.functions = { - first: { - events: [ - { - cognitoUserPool: { - pool: 'MyUserPool', - trigger: 'PreSignUp', - }, - }, - { - cognitoUserPool: { - pool: 'MyUserPool', - trigger: 'PostConfirmation', - }, - }, - ], - }, - }; - - awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); - - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources.MyUserPool.Type - ).to.equal('AWS::Cognito::UserPool'); - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources.MyUserPool.Properties.UserPoolName - ).to.equal('my-user-pool'); - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPreSignUp.Type - ).to.equal('AWS::Lambda::Permission'); - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPostConfirmation.Type - ).to.equal('AWS::Lambda::Permission'); - }); - - it('should merge corresponding resources when generated Cognito User Pool is overridden ' + - 'in Resources', () => { - serverless.service.provider.compiledCloudFormationTemplate = { - Resources: { - CognitoUserPoolMyUserPool: { - Type: 'AWS::Cognito::UserPool', - Properties: { - UserPoolName: 'my-user-pool', - }, - }, - }, - }; - awsCompileCognitoUserPoolEvents.serverless.service.functions = { - first: { - events: [ - { - cognitoUserPool: { - pool: 'MyUserPool', - trigger: 'PreSignUp', - }, - }, - { - cognitoUserPool: { - pool: 'MyUserPool', - trigger: 'PostConfirmation', - }, - }, - ], - }, - }; - - awsCompileCognitoUserPoolEvents.compileCognitoUserPoolEvents(); - - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool.Type - ).to.equal('AWS::Cognito::UserPool'); - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources.CognitoUserPoolMyUserPool.Properties.UserPoolName - ).to.equal('my-user-pool'); - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPreSignUp.Type - ).to.equal('AWS::Lambda::Permission'); - expect(awsCompileCognitoUserPoolEvents.serverless.service.provider - .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPostConfirmation.Type - ).to.equal('AWS::Lambda::Permission'); - }); - - it('should not create corresponding resources when Cognito User Pool events' + - ' are not given', () => { + it('should not create resources when CUP events are not given', () => { awsCompileCognitoUserPoolEvents.serverless.service.functions = { first: { events: [], From 0921dc81448f8bddaeff2080dac0861701164939 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 14:35:21 +0200 Subject: [PATCH 11/16] Update naming for permission resource --- docs/providers/aws/guide/resources.md | 2 +- lib/plugins/aws/lib/naming.js | 4 ++-- lib/plugins/aws/lib/naming.test.js | 16 +++++++--------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/providers/aws/guide/resources.md b/docs/providers/aws/guide/resources.md index f8e637ed5..6007cbbc1 100644 --- a/docs/providers/aws/guide/resources.md +++ b/docs/providers/aws/guide/resources.md @@ -70,7 +70,7 @@ We're also using the term `normalizedName` or similar terms in this guide. This |Lambda::Function | {normalizedFunctionName}LambdaFunction | HelloLambdaFunction | |Lambda::Version | {normalizedFunctionName}LambdaVersion{sha256} | HelloLambdaVersionr3pgoTvv1xT4E4NiCL6JG02fl6vIyi7OS1aW0FwAI | |Logs::LogGroup | {normalizedFunctionName}LogGroup | HelloLogGroup | -|Lambda::Permission |
    • **Schedule**: {normalizedFunctionName}LambdaPermissionEventsRuleSchedule{index}
    • **CloudWatch Event**: {normalizedFunctionName}LambdaPermissionEventsRuleCloudWatchEvent{index}
    • **CloudWatch Log**: {normalizedFunctionName}LambdaPermissionLogsSubscriptionFilterCloudWatchLog{index}
    • **IoT**: {normalizedFunctionName}LambdaPermissionIotTopicRule{index}
    • **S3**: {normalizedFunctionName}LambdaPermission{normalizedBucketName}S3
    • **APIG**: {normalizedFunctionName}LambdaPermissionApiGateway
    • **SNS**: {normalizedFunctionName}LambdaPermission{normalizedTopicName}SNS
    • **Alexa Skill**: {normalizedFunctionName}LambdaPermissionAlexaSkill
    • **Cognito User Pool Trigger Source**: {normalizedFunctionName}LambdaPermissionCognitoUserPoolTriggerSource
    |
    • **Schedule**: HelloLambdaPermissionEventsRuleSchedule1
    • **CloudWatch Event**: HelloLambdaPermissionEventsRuleCloudWatchEvent1
    • **CloudWatch Log**: HelloLambdaPermissionLogsSubscriptionFilterCloudWatchLog1
    • **IoT**: HelloLambdaPermissionIotTopicRule1
    • **S3**: HelloLambdaPermissionBucketS3
    • **APIG**: HelloLambdaPermissionApiGateway
    • **SNS**: HelloLambdaPermissionTopicSNS
    • **Alexa Skill**: HelloLambdaPermissionAlexaSkill
    • **Cognito User Pool Trigger Source**: HelloLambdaPermissionCognitoUserPoolTriggerSource
    | +|Lambda::Permission |
    • **Schedule**: {normalizedFunctionName}LambdaPermissionEventsRuleSchedule{index}
    • **CloudWatch Event**: {normalizedFunctionName}LambdaPermissionEventsRuleCloudWatchEvent{index}
    • **CloudWatch Log**: {normalizedFunctionName}LambdaPermissionLogsSubscriptionFilterCloudWatchLog{index}
    • **IoT**: {normalizedFunctionName}LambdaPermissionIotTopicRule{index}
    • **S3**: {normalizedFunctionName}LambdaPermission{normalizedBucketName}S3
    • **APIG**: {normalizedFunctionName}LambdaPermissionApiGateway
    • **SNS**: {normalizedFunctionName}LambdaPermission{normalizedTopicName}SNS
    • **Alexa Skill**: {normalizedFunctionName}LambdaPermissionAlexaSkill
    • **Cognito User Pool Trigger Source**: {normalizedFunctionName}LambdaPermissionCognitoUserPool{normalizedPoolId}TriggerSource{triggerSource}
    |
    • **Schedule**: HelloLambdaPermissionEventsRuleSchedule1
    • **CloudWatch Event**: HelloLambdaPermissionEventsRuleCloudWatchEvent1
    • **CloudWatch Log**: HelloLambdaPermissionLogsSubscriptionFilterCloudWatchLog1
    • **IoT**: HelloLambdaPermissionIotTopicRule1
    • **S3**: HelloLambdaPermissionBucketS3
    • **APIG**: HelloLambdaPermissionApiGateway
    • **SNS**: HelloLambdaPermissionTopicSNS
    • **Alexa Skill**: HelloLambdaPermissionAlexaSkill
    • **Cognito User Pool Trigger Source**: HelloLambdaPermissionCognitoUserPoolMyPoolTriggerSourceCustomMessage
    | |Events::Rule |
    • **Schedule**: {normalizedFuntionName}EventsRuleSchedule{SequentialID}
    • **CloudWatch Event**: {normalizedFuntionName}EventsRuleCloudWatchEvent{SequentialID}
    |
    • **Schedule**: HelloEventsRuleSchedule1
    • **CloudWatch Event**: HelloEventsRuleCloudWatchEvent1
    | |AWS::Logs::SubscriptionFilter | {normalizedFuntionName}LogsSubscriptionFilterCloudWatchLog{SequentialID} | HelloLogsSubscriptionFilterCloudWatchLog1 | |AWS::IoT::TopicRule | {normalizedFuntionName}IotTopicRule{SequentialID} | HelloIotTopicRule1 | diff --git a/lib/plugins/aws/lib/naming.js b/lib/plugins/aws/lib/naming.js index fe6cc84ae..82fe10abe 100644 --- a/lib/plugins/aws/lib/naming.js +++ b/lib/plugins/aws/lib/naming.js @@ -285,7 +285,7 @@ module.exports = { }, getLambdaCognitoUserPoolPermissionLogicalId(functionName, poolId, triggerSource) { return `${this - .getNormalizedFunctionName(functionName)}LambdaPermissionCognitoUserPoolTriggerSource${ - this.normalizeNameToAlphaNumericOnly(poolId)}${triggerSource}`; + .getNormalizedFunctionName(functionName)}LambdaPermissionCognitoUserPool${ + this.normalizeNameToAlphaNumericOnly(poolId)}TriggerSource${triggerSource}`; }, }; diff --git a/lib/plugins/aws/lib/naming.test.js b/lib/plugins/aws/lib/naming.test.js index 706ecc6df..ae1f77de0 100644 --- a/lib/plugins/aws/lib/naming.test.js +++ b/lib/plugins/aws/lib/naming.test.js @@ -472,14 +472,12 @@ describe('#naming()', () => { }); describe('#getLambdaCognitoUserPoolPermissionLogicalId()', () => { - it('should normalize the function name and add the standard suffix including the normalized ' + - ' pool name and trigger source', - () => { - expect(sdk.naming.getLambdaCognitoUserPoolPermissionLogicalId( - 'functionName', - 'poolId', - 'TriggerSource' - )).to.equal('FunctionNameLambdaPermissionCognitoUserPoolTriggerSourcePoolIdTriggerSource'); - }); + it('should normalize the function name and add the standard suffix', () => { + expect(sdk.naming.getLambdaCognitoUserPoolPermissionLogicalId( + 'functionName', + 'Pool1', + 'CustomMessage' + )).to.equal('FunctionNameLambdaPermissionCognitoUserPoolPool1TriggerSourceCustomMessage'); + }); }); }); From dfbc5bb5ef04864cd615fcd09bbd7b6eaac8b32e Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 14:36:31 +0200 Subject: [PATCH 12/16] Update doc file name To reflect the event name. --- docs/providers/aws/README.md | 2 +- .../{cognito-user-pool-trigger.md => cognito-user-pool.md} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename docs/providers/aws/events/{cognito-user-pool-trigger.md => cognito-user-pool.md} (99%) diff --git a/docs/providers/aws/README.md b/docs/providers/aws/README.md index 4e9ca5715..a18b15f07 100644 --- a/docs/providers/aws/README.md +++ b/docs/providers/aws/README.md @@ -89,7 +89,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • IoT
  • CloudWatch Event
  • CloudWatch Log
  • -
  • Cognito User Pool Trigger
  • +
  • Cognito User Pool Trigger
  • diff --git a/docs/providers/aws/events/cognito-user-pool-trigger.md b/docs/providers/aws/events/cognito-user-pool.md similarity index 99% rename from docs/providers/aws/events/cognito-user-pool-trigger.md rename to docs/providers/aws/events/cognito-user-pool.md index 127c05892..fe980b8b7 100644 --- a/docs/providers/aws/events/cognito-user-pool-trigger.md +++ b/docs/providers/aws/events/cognito-user-pool.md @@ -7,7 +7,7 @@ layout: Doc --> -### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/cognito-user-pool-trigger) +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/cognito-user-pool) # Cognito User Pool Trigger From 5ab4230df89a25242cc47a9c17554746890a252b Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 14:38:04 +0200 Subject: [PATCH 13/16] Update docs --- docs/providers/aws/README.md | 2 +- docs/providers/aws/events/cognito-user-pool.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/providers/aws/README.md b/docs/providers/aws/README.md index a18b15f07..6061c79eb 100644 --- a/docs/providers/aws/README.md +++ b/docs/providers/aws/README.md @@ -89,7 +89,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • IoT
  • CloudWatch Event
  • CloudWatch Log
  • -
  • Cognito User Pool Trigger
  • +
  • Cognito User Pool
  • diff --git a/docs/providers/aws/events/cognito-user-pool.md b/docs/providers/aws/events/cognito-user-pool.md index fe980b8b7..0c2b65207 100644 --- a/docs/providers/aws/events/cognito-user-pool.md +++ b/docs/providers/aws/events/cognito-user-pool.md @@ -1,6 +1,6 @@ -# Cognito User Pool Trigger +# Cognito User Pool ## Valid Triggers From f1367f30ab8080d1a78616edcbb3d12063c85b64 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 14:45:07 +0200 Subject: [PATCH 14/16] Cosmetic updates for error messages --- .../aws/package/compile/events/cognitoUserPool/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js index f4b472023..d94063701 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.js @@ -40,7 +40,7 @@ class AwsCompileCognitoUserPoolEvents { if (!event.cognitoUserPool.pool || !event.cognitoUserPool.trigger) { throw new this.serverless.classes .Error([ - `Cognito User Pool event of function ${functionName} is not an object.`, + `Cognito User Pool event of function "${functionName}" is not an object.`, 'The correct syntax is an object with the "pool" and "trigger" properties.', 'Please check the docs for more info.', ].join(' ')); @@ -70,7 +70,7 @@ class AwsCompileCognitoUserPoolEvents { } else { throw new this.serverless.classes .Error([ - `Cognito User Pool event of function ${functionName} is not an object.`, + `Cognito User Pool event of function "${functionName}" is not an object.`, 'The correct syntax is an object with the "pool" and "trigger" properties.', 'Please check the docs for more info.', ].join(' ')); From 78b4960d279a96d10445988543d40cbd1f099b44 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 1 Jun 2017 14:54:19 +0200 Subject: [PATCH 15/16] Fix tests --- .../compile/events/cognitoUserPool/index.test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js index b64d61297..6ec9a6c28 100644 --- a/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js +++ b/lib/plugins/aws/package/compile/events/cognitoUserPool/index.test.js @@ -120,11 +120,11 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal('AWS::Cognito::UserPool'); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool1PreSignUp.Type + .FirstLambdaPermissionCognitoUserPoolMyUserPool1TriggerSourcePreSignUp.Type ).to.equal('AWS::Lambda::Permission'); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .SecondLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool2PostConfirmation.Type + .SecondLambdaPermissionCognitoUserPoolMyUserPool2TriggerSourcePostConfirmation.Type ).to.equal('AWS::Lambda::Permission'); }); @@ -158,11 +158,11 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal('AWS::Cognito::UserPool'); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool1PreSignUp.Type + .FirstLambdaPermissionCognitoUserPoolMyUserPool1TriggerSourcePreSignUp.Type ).to.equal('AWS::Lambda::Permission'); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool2PostConfirmation.Type + .FirstLambdaPermissionCognitoUserPoolMyUserPool2TriggerSourcePostConfirmation.Type ).to.equal('AWS::Lambda::Permission'); }); @@ -212,11 +212,11 @@ describe('AwsCompileCognitoUserPoolEvents', () => { expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool1PreSignUp.Type + .FirstLambdaPermissionCognitoUserPoolMyUserPool1TriggerSourcePreSignUp.Type ).to.equal('AWS::Lambda::Permission'); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .SecondLambdaPermissionCognitoUserPoolTriggerSourceMyUserPool2PreSignUp.Type + .SecondLambdaPermissionCognitoUserPoolMyUserPool2TriggerSourcePreSignUp.Type ).to.equal('AWS::Lambda::Permission'); }); @@ -256,11 +256,11 @@ describe('AwsCompileCognitoUserPoolEvents', () => { ).to.equal(2); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .FirstLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPreSignUp.Type + .FirstLambdaPermissionCognitoUserPoolMyUserPoolTriggerSourcePreSignUp.Type ).to.equal('AWS::Lambda::Permission'); expect(awsCompileCognitoUserPoolEvents.serverless.service.provider .compiledCloudFormationTemplate.Resources - .SecondLambdaPermissionCognitoUserPoolTriggerSourceMyUserPoolPostConfirmation.Type + .SecondLambdaPermissionCognitoUserPoolMyUserPoolTriggerSourcePostConfirmation.Type ).to.equal('AWS::Lambda::Permission'); }); From 7410e5c400b12229432b66b16785fea832150f03 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Tue, 6 Jun 2017 09:30:04 +0200 Subject: [PATCH 16/16] Rename integration test to drop "Trigger" suffix --- .../service/handler.js | 0 .../service/serverless.yml | 0 .../multiple-pools-multiple-events-multiple-functions/tests.js | 2 +- .../service/handler.js | 0 .../service/serverless.yml | 0 .../multiple-pools-single-event-single-function/tests.js | 2 +- .../service/handler.js | 0 .../service/serverless.yml | 0 .../single-pool-multiple-events-multiple-functions/tests.js | 2 +- .../single-pool-single-event-single-function/service/handler.js | 0 .../service/serverless.yml | 0 .../single-pool-single-event-single-function/tests.js | 2 +- 12 files changed, 4 insertions(+), 4 deletions(-) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/multiple-pools-multiple-events-multiple-functions/service/handler.js (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/multiple-pools-multiple-events-multiple-functions/service/serverless.yml (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/multiple-pools-multiple-events-multiple-functions/tests.js (96%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/multiple-pools-single-event-single-function/service/handler.js (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/multiple-pools-single-event-single-function/service/serverless.yml (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/multiple-pools-single-event-single-function/tests.js (95%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/single-pool-multiple-events-multiple-functions/service/handler.js (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/single-pool-multiple-events-multiple-functions/service/serverless.yml (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/single-pool-multiple-events-multiple-functions/tests.js (93%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/single-pool-single-event-single-function/service/handler.js (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/single-pool-single-event-single-function/service/serverless.yml (100%) rename tests/integration/aws/{cognito-user-pool-trigger => cognito-user-pool}/single-pool-single-event-single-function/tests.js (91%) diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/handler.js b/tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/service/handler.js similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/handler.js rename to tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/service/handler.js diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/serverless.yml b/tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/service/serverless.yml similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/service/serverless.yml rename to tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/service/serverless.yml diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/tests.js similarity index 96% rename from tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js rename to tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/tests.js index ece3024f1..df2ba5d40 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-multiple-events-multiple-functions/tests.js +++ b/tests/integration/aws/cognito-user-pool/multiple-pools-multiple-events-multiple-functions/tests.js @@ -4,7 +4,7 @@ const path = require('path'); const expect = require('chai').expect; const Utils = require('../../../../utils/index'); -describe('AWS - Cognito User Pool Trigger: Multiple User Pools with multiple ' + +describe('AWS - Cognito User Pool: Multiple User Pools with multiple ' + 'events with multiple functions', () => { beforeAll(() => { Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/handler.js b/tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/service/handler.js similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/handler.js rename to tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/service/handler.js diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/serverless.yml b/tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/service/serverless.yml similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/service/serverless.yml rename to tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/service/serverless.yml diff --git a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/tests.js similarity index 95% rename from tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js rename to tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/tests.js index 03bbbfde0..9a9477545 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/multiple-pools-single-event-single-function/tests.js +++ b/tests/integration/aws/cognito-user-pool/multiple-pools-single-event-single-function/tests.js @@ -4,7 +4,7 @@ const path = require('path'); const expect = require('chai').expect; const Utils = require('../../../../utils/index'); -describe('AWS - Cognito User Pool Trigger: Multiple User Pools with single ' + +describe('AWS - Cognito User Pool: Multiple User Pools with single ' + 'event with single function', () => { beforeAll(() => { Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/handler.js b/tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/service/handler.js similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/handler.js rename to tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/service/handler.js diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/serverless.yml b/tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/service/serverless.yml similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/service/serverless.yml rename to tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/service/serverless.yml diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js b/tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/tests.js similarity index 93% rename from tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js rename to tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/tests.js index 5eec33fab..96d25c39b 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/single-pool-multiple-events-multiple-functions/tests.js +++ b/tests/integration/aws/cognito-user-pool/single-pool-multiple-events-multiple-functions/tests.js @@ -4,7 +4,7 @@ const path = require('path'); const expect = require('chai').expect; const Utils = require('../../../../utils/index'); -describe('AWS - Cognito User Pool Trigger: Single User Pool with multiple ' + +describe('AWS - Cognito User Pool: Single User Pool with multiple ' + 'events with multiple functions', () => { beforeAll(() => { Utils.createTestService('aws-nodejs', path.join(__dirname, 'service')); diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/handler.js b/tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/service/handler.js similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/handler.js rename to tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/service/handler.js diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/serverless.yml b/tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/service/serverless.yml similarity index 100% rename from tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/service/serverless.yml rename to tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/service/serverless.yml diff --git a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js b/tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/tests.js similarity index 91% rename from tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js rename to tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/tests.js index e6c3f87b6..b77837821 100644 --- a/tests/integration/aws/cognito-user-pool-trigger/single-pool-single-event-single-function/tests.js +++ b/tests/integration/aws/cognito-user-pool/single-pool-single-event-single-function/tests.js @@ -4,7 +4,7 @@ const path = require('path'); const expect = require('chai').expect; const Utils = require('../../../../utils/index'); -describe('AWS - Cognito User Pool Trigger: Single User Pool with single ' + +describe('AWS - Cognito User Pool: Single User Pool with single ' + 'event with single function', () => { beforeAll(() => { Utils.createTestService('aws-nodejs', path.join(__dirname, 'service'));