export const meta = {
  title: `Calling DynamoDB using AWS Cognito triggers`,
  description: `How to add an entry in DynamoDB, with user's information after sign-up post-confirmation`,
};

If you are using AWS Cognito to handle authentication in your application you can use triggers to handle authentication 
events. For example, send a welcome email after the user signs up. The complete documentation on AWS Cognito triggers can be found [here](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html).

In this guide, you will learn how to use a post confirmation trigger to save user's information to your DynamoDB table.
Like mentioned in the previous guides, the easiest way to interact with DynamoDB from Lambda in a Node.js environment is 
to use the [DynamoDB document client](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html).

Using this approach you can link a Cognito Identity to an user profile in your application, and have the possibility to list posts by author and be able to show their name, email 
, date of creation, etc instead of their id.

The main advantage of this method is that you don't have to manually create the user in your GraphQL API using a mutation, which is another alternative.

The main issue of this solution is that if you remove an user from AWS Cognito, your application won't know about it.

### Scenario

After user sign-up, you want to create an entry in a DynamoDB table with the user's information.

### Create GraphQL API

In this step you will create your User table, where the entry with user's information will be saved. This will be done using Amplify GraphQL API.

You can skip this part, if you already have a GraphQL API with an User model.

```sh
amplify add api

? Here is the GraphQL API that we will create. Select a setting to edit or continue:
    > Name
? Provide API name:
    > contactapi
? Here is the GraphQL API that we will create. Select a setting to edit or continue:
    > Authorization modes: API key (default, expiration time: 7 days from now)
? Choose the default authorization type for the API:
    > API Key
? Enter a description for the API key:
    > public (or some description)
? After how many days from now the API key should expire:
    > 365 (or your preferred expiration)
? Configure additional auth types?
    > No
? Here is the GraphQL API that we will create. Select a setting to edit or continue:
    > Continue
? Choose a schema template:
    > Single object with fields (e.g., “Todo” with ID, name, description)
? Do you want to edit the schema now?
    > Yes
```

The CLI should open the GraphQL schema, located at amplify/backend/api/contactapi/schema.graphql, in your text editor. Update the schema with the following and save the file:

```graphql
type User
  @model
{
  id: ID!
  name: String
  email: String
}
```

### Create the lambda function

This function will be called after user post confirmation.

```sh
amplify add function

? Provide a friendly name for your resource to be used as a label for this category in the project: mylambda
? Provide the AWS Lambda function name: mylambda
? Choose the function runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World
? Do you want to access other resources created in this project from your Lambda function? Y
? Select the category: storage
? Select the operations you want to permit for UserTable: create, read, update, delete
? Do you want to invoke this function on a recurring schedule? N
? Do you want to configure Lambda layers for this function? N
? Do you want to edit the local lambda function now? N
```

Next open the index.js file associated to your newly created lambda function, and paste the following code : 

```js
var aws = require('aws-sdk');
var ddb = new aws.DynamoDB();

exports.handler = async (event, context) => {
    
    let date = new Date();

    if (event.request.userAttributes.sub) {

        let params = {
            Item: {
                'id': {S: event.request.userAttributes.sub},
                '__typename': {S: 'User'},
                'name': {S: event.request.userAttributes.name},
                'email': {S: event.request.userAttributes.email},
                'createdAt': {S: date.toISOString()},
                'updatedAt': {S: date.toISOString()},
            },
            TableName: process.env.API_{YOUR_APP_NAME}_USERTABLE_NAME
        };

        // Call DynamoDB
        try {
            await ddb.putItem(params).promise()
            console.log("Success");
        } catch (err) {
            console.log("Error", err);
        }

        console.log("Success: Everything executed correctly");
        context.done(null, event);

    } else {
        // Nothing to do, the user's email ID is unknown
        console.log("Error: Nothing was written to DynamoDB");
        context.done(null, event);
    }
};
```

<Callout>

If you're using Amplify DataStore, likely set up through Amplify Studio, you'll also need to add the `_version` and `_lastChangedAt` field to your request to DynamoDB:

```js
let params = {
  Item: {
    id: { S: event.request.userAttributes.sub },
    __typename: { S: "User" },
    email: { S: event.request.userAttributes.email },
    createdAt: { S: date.toISOString() },
    updatedAt: { S: date.toISOString() },
    _version: { N: "1" },
    _lastChangedAt: { N: Date.now().toString() },
  },
  TableName: process.env.API_{YOUR_APP_NAME}_USERTABLE_NAME,
};
```

</Callout>

You can access your table name by calling the environment variable API_{APP_NAME}_USERTABLE_NAME.

Deploy the lambda function :

```sh
amplify push
```

Your lambda function is now ready to use!

### Configure the Post Confirmation trigger

To configure your AWS Cognito trigger to call the lambda function you just created, you should do the following :

- Go to your [AWS Console](https://console.aws.amazon.com/console/home)
- Navigate to AWS Cognito service, and choose 'Manage User Pools'
- Select the User Pool related to your application
- Go to 'Triggers' and look for Post Confirmation Trigger, then select your lambda function
