Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cognito User Pool Triggers #3657

Merged
merged 16 commits into from Jun 6, 2017
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/providers/aws/README.md
Expand Up @@ -89,6 +89,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
<li><a href="./events/iot.md">IoT</a></li>
<li><a href="./events/cloudwatch-event.md">CloudWatch Event</a></li>
<li><a href="./events/cloudwatch-log.md">CloudWatch Log</a></li>
<li><a href="./events/cognito-user-pool-trigger.md">Cognito User Pool Trigger</a></li>
</ul>
</div>
</div>
Expand Down
141 changes: 141 additions & 0 deletions docs/providers/aws/events/cognito-user-pool-trigger.md
@@ -0,0 +1,141 @@
<!--
title: Serverless Framework - AWS Lambda Events - Cognito User Pool Trigger
menuText: Cognito User Pool Trigger
menuOrder: 10
description: Setting up AWS Cognito User Pool Triggers with AWS Lambda via the Serverless Framework
layout: Doc
-->

<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/cognito-user-pool-trigger)
<!-- DOCS-SITE-LINK:END -->

# 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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A newline between the end of the functions definition and the resources section would make this easier to digest.

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]: ../guide/resources#aws-cloudformation-resource-reference
3 changes: 2 additions & 1 deletion docs/providers/aws/guide/resources.md
Expand Up @@ -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 | <ul><li>**Schedule**: {normalizedFunctionName}LambdaPermissionEventsRuleSchedule{index}</li><li>**CloudWatch Event**: {normalizedFunctionName}LambdaPermissionEventsRuleCloudWatchEvent{index}</li><li>**CloudWatch Log**: {normalizedFunctionName}LambdaPermissionLogsSubscriptionFilterCloudWatchLog{index}</li><li>**IoT**: {normalizedFunctionName}LambdaPermissionIotTopicRule{index} </li><li>**S3**: {normalizedFunctionName}LambdaPermission{normalizedBucketName}S3</li><li>**APIG**: {normalizedFunctionName}LambdaPermissionApiGateway</li><li>**SNS**: {normalizedFunctionName}LambdaPermission{normalizedTopicName}SNS</li><li>**Alexa Skill**: {normalizedFunctionName}LambdaPermissionAlexaSkill</li> </ul> | <ul><li>**Schedule**: HelloLambdaPermissionEventsRuleSchedule1</li><li>**CloudWatch Event**: HelloLambdaPermissionEventsRuleCloudWatchEvent1</li><li>**CloudWatch Log**: HelloLambdaPermissionLogsSubscriptionFilterCloudWatchLog1</li><li>**IoT**: HelloLambdaPermissionIotTopicRule1 </li><li>**S3**: HelloLambdaPermissionBucketS3</li><li>**APIG**: HelloLambdaPermissionApiGateway</li><li>**SNS**: HelloLambdaPermissionTopicSNS</li><li>**Alexa Skill**: HelloLambdaPermissionAlexaSkill</li> </ul>|
|Lambda::Permission | <ul><li>**Schedule**: {normalizedFunctionName}LambdaPermissionEventsRuleSchedule{index}</li><li>**CloudWatch Event**: {normalizedFunctionName}LambdaPermissionEventsRuleCloudWatchEvent{index}</li><li>**CloudWatch Log**: {normalizedFunctionName}LambdaPermissionLogsSubscriptionFilterCloudWatchLog{index}</li><li>**IoT**: {normalizedFunctionName}LambdaPermissionIotTopicRule{index} </li><li>**S3**: {normalizedFunctionName}LambdaPermission{normalizedBucketName}S3</li><li>**APIG**: {normalizedFunctionName}LambdaPermissionApiGateway</li><li>**SNS**: {normalizedFunctionName}LambdaPermission{normalizedTopicName}SNS</li><li>**Alexa Skill**: {normalizedFunctionName}LambdaPermissionAlexaSkill</li><li>**Cognito User Pool Trigger Source**: {normalizedFunctionName}LambdaPermissionCognitoUserPoolTriggerSource</li> </ul> | <ul><li>**Schedule**: HelloLambdaPermissionEventsRuleSchedule1</li><li>**CloudWatch Event**: HelloLambdaPermissionEventsRuleCloudWatchEvent1</li><li>**CloudWatch Log**: HelloLambdaPermissionLogsSubscriptionFilterCloudWatchLog1</li><li>**IoT**: HelloLambdaPermissionIotTopicRule1 </li><li>**S3**: HelloLambdaPermissionBucketS3</li><li>**APIG**: HelloLambdaPermissionApiGateway</li><li>**SNS**: HelloLambdaPermissionTopicSNS</li><li>**Alexa Skill**: HelloLambdaPermissionAlexaSkill</li><li>**Cognito User Pool Trigger Source**: HelloLambdaPermissionCognitoUserPoolTriggerSource</li> </ul>|
|Events::Rule | <ul><li>**Schedule**: {normalizedFuntionName}EventsRuleSchedule{SequentialID}</li><li>**CloudWatch Event**: {normalizedFuntionName}EventsRuleCloudWatchEvent{SequentialID}</li> </ul> | <ul><li>**Schedule**: HelloEventsRuleSchedule1</li><li>**CloudWatch Event**: HelloEventsRuleCloudWatchEvent1</li></ul> |
|AWS::Logs::SubscriptionFilter | {normalizedFuntionName}LogsSubscriptionFilterCloudWatchLog{SequentialID} | HelloLogsSubscriptionFilterCloudWatchLog1 |
|AWS::IoT::TopicRule | {normalizedFuntionName}IotTopicRule{SequentialID} | HelloIotTopicRule1 |
Expand All @@ -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 | <ul><li>**DynamoDB:** {normalizedFunctionName}EventSourceMappingDynamodb{tableName}</li><li>**Kinesis:** {normalizedFunctionName}EventSourceMappingKinesis{streamName}</li></ul> | <ul><li>**DynamoDB:** HelloLambdaEventSourceMappingDynamodbUsers</li><li>**Kinesis:** HelloLambdaEventSourceMappingKinesisMystream</li></ul> |
|Cognito::UserPool | CognitoUserPool{normalizedPoolId} | CognitoUserPoolPoolId |

## Override AWS CloudFormation Resource

Expand Down
3 changes: 3 additions & 0 deletions docs/providers/aws/guide/serverless.yml.md
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions lib/plugins/Plugins.json
Expand Up @@ -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"
Expand Down
10 changes: 10 additions & 0 deletions lib/plugins/aws/lib/naming.js
Expand Up @@ -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
Expand Down Expand Up @@ -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}`;
},
};
19 changes: 19 additions & 0 deletions lib/plugins/aws/lib/naming.test.js
Expand Up @@ -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'))
Expand Down Expand Up @@ -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');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick question: Do you know if there's a limit for the resource logical Id length in CloudFormation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't seem to find any information regarding length limits, the only thing I can find is this.

});
});
});