Skip to content

Instantly share code, notes, and snippets.

@germanviscuso germanviscuso/README.md
Last active Apr 30, 2019

Embed
What would you like to do?
DynamoDB connection from an Alexa skill

Alexa Skill Persistence with DynamoDB

This document covers how to use Dynamo DB persistence in your Alexa skill using a direct connection the AWS SDK rather than using the ASK SDK persistence adapter (you can see how to use the adapter here).

Setup w/ ASK CLI

About

This readme assumes you have your developer environment ready to go and that you have some familiarity with CLI (Command Line Interface) Tools, AWS, and the ASK Developer Portal.

Pre-requisites

Tools Installation

  1. Make sure you are running the latest version of the CLI

    npm update -g ask-cli
  2. Create the skill.

    ask new

Skill Deployment

ASK CLI will create the skill and the lambda function for you. The Lambda function will be created in us-east-1 (Northern Virginia) by default. If you want the back-end in Europe export this environment variable: AWS_REGION=eu-west-1.

  1. Navigate to the project's root directory. you should see a file named 'skill.json' there.
  2. Deploy the skill and the lambda function in one step by running the following command:
    ask deploy
  3. Once deployed, additional permissions need to be added to the AWS IAM role being used by the function since it is persisting data in Amazon DynamoDB. Locate the execution role used by the skill's Lambda function in the AWS IAM Console.
    1. Open the AWS Console: https://console.aws.amazon.com/iam
    2. Click on Roles.
    3. Type (at least part of) the name of your skill in the search box. (Replace spaces with dashes.)
    4. Click the role that corresponds to your skill's function.

      Note: If you can't find the correct role, first locate your skill's function in AWS Lambda. Scroll down to the section labeled Execution Role and find the role name there.

  4. On the right side of the Permissions tab, click + Add inline policy.
  5. Click the JSON tab.
  6. Select the existing JSON and replace it with the following policy document. This policy grants access to the role to (1) create the needed table and (2) read/write items to the table. It is restricted to this for just a table named 'My-Table' (replace it with yours).
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "DynamoDBTableAccess",
                "Effect": "Allow",
                "Action": [
                    "dynamodb:CreateTable",
                    "dynamodb:PutItem",
                    "dynamodb:GetItem",
                    "dynamodb:UpdateItem",
                    "dynamodb:PutItem",
                    "dynamodb:DeleteItem",
                    "dynamodb:Scan",
                    "dynamodb:Query"
                ],
                "Resource": "arn:aws:dynamodb:*:*:table/My-Table"
            }
        ]
    }
     > Note: The table name as specified in the sample code is `My-Table`.  If you want to use a different name, change it in the policy and in the sample code.  The name doesn't matter as long as they match.
    
  7. Click Review Policy.
  8. Enter DynamoDBTableAccess as the Name.
  9. Click Create Policy.

Usage

  1. lambda/custom/package.json

    You need to include the AWS package in imports:

    {
       "name": "hello-world",
       "version": "0.9.0",
       "description": "alexa hello world sample skill",
       "main": "index.js",
       "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1"
       },
       "dependencies": {
          "ask-sdk-core": "^2.0.7",
          "ask-sdk-model": "^1.4.1",
          "aws-sdk": "^2.326.0"
       }
    }

    Note that there's no need to incluse any SDK persistence adapter in the dependencies

  2. ./lambda/custom/index.js

    Incorporate @javichur's DB helper file (MIT licensed) in your lambda and call the helper functions like this (using async/await):

    const DBHelper = require('./dbHelper');
    const dynamoDb = new DBHelper("My-Table", "userId", null); // "Primary partition key" = userId (String)
    
    // parent function must be defined as "async"
    let data;
    try {
       data = await dynamoDb.getItem(userID);
    .catch((err) => {
       // error accessing dynamodb
       ...
    });
    if(data){
       // data exists
    }
    ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.