My Journal

In this journal I will be documenting what I have completed each day in regards to my serverless web app, OverAchiever.

logo

January 6th, 2020

  1. I had created a new Cloud9 in instance in my $70 AWS starter account, I had named it “OverAchiever”. This where I can create and edit my code.
  2. I connected my GitHub repo (https://github.com/Trinity-Armstrong/ICS3U-2019-Group16) to the root of my new Cloud9 instance. In other words, I had uploaded all the files and images that are stored in my github repo so I can make changes to them.
How to connect Cloud9 instance root to GitHub repo
vocstartsoft:~/environment $ git init
Initialized empty Git repository in /home/ubuntu/environment/.git/
vocstartsoft:~/environment (master) $ git remote add origin https://github.com/Mr-Coxall/Amplify-Test
vocstartsoft:~/environment (master) $ git pull origin master

January 7th 2020

  1. I created a index.html file in the root of my Cloud9. This contains the code for “Hello, World!” that I will be using to test my new website once I have connected to Amplify.
index.html
1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
  <head>
    <title>AWS Serverless Web App</title>
  </head>
  <body>
    Hello, World!
  </body>
</html>
  1. Next, I pushed all the changes I have made to my github repo in my master terminal. This includes my index.html file.
  2. Finally, I connected this instance to Amplify. I did this by going to my dashboard and opening AWS amplify through the services tab. From there, I was able to create my Amplify instance connected to GitHub and deploy my hello world program. I was able to confirm through the provided URL that my code is up and running correctly.
  3. Created a role in IAM called ‘AWS_Serverless_Web_App’ through AWS Identitiy and Access Management (IAM). After creating my database, I will be able to use this role for AWS Lambda to access it.
  4. I created a lambda function in python that returns “Hello, World!” on AWS
  5. I was able to test and confirm that this function was running correctly using test cases
  6. using configured test event, I passed my name Trinity Armstrong into the function. It outputted “Hello, Trinity Armstrong”.

January 8th 2020

  1. Created a DynamoDB table called “choclate_user” with email as my primary key
  2. Created rows in the table to ensure that is working correctly. I used the following information: first_name, last_name and age of the user
  3. I changed the capacity of my table from 5 to 1 in order to save money, as that is more than enough for the services I will be needing
  4. Created a new lambda function called get_user_info
hello_world.py Lambda function
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3

# Created by: Trinity Armstrong
# Created on: Jan 2020
# This function is the Hello, World! Lambda function

import json

def lambda_handler(event, context):
    # TODO implement

    return_var = {
        'statusCode': 200,
        'body': json.dumps('Hello, ' + event['name'])
    }

    return return_var
  1. copy pasted my code from the hello_world lambda function into my new function
  2. Tested my new lambda function by outputting “Hello, Trinity Armstrong”

January 9th, 2020

  1. Coded a function in the lambda function get_user_info that returns a row from our chocolate_user DynamoDB

2. Tested my code and it correctly outputted the row I had selected in DynamoDB (user: John Smith) Output: {‘Item’: {‘last_name’: ‘Smith’, ‘email’: ‘john.smith@gmail.com’, ‘first_name’: ‘John’, ‘age’: Decimal(‘35’)}

3. Did a second test with a different row, it was a success (user: Jane Smith) Output:{‘Item’: {‘last_name’: ‘Smith’, ‘email’: ‘jane.smith@gmail.com’, ‘first_name’: ‘Jane’, ‘age’: Decimal(‘25’)}

  1. Changed code so that an incorrect email will result in a blank row and a existing email will result in the output of the corresponding row

5. Next, I created a new API gateway, that is fully funtioning. When you enter a parameter, it outputs the corresponding information and when you enter NO parameter, there is a nice response. It is now published on the internet and later I will be able to use this URL while coding in HTML. URL:https://y8s2gy3mi8.execute-api.us-east-1.amazonaws.com/prod/user-profile?user_email=mr.coxall@mths.ca

  1. I altered my lambda code to trap errors with a try catch statement
  2. Used Javascript “Fetch” through index.html to call my API and present the data for “jane.smith@gmail.com” on my website
get_user_info.py Lambda function
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/usr/bin/env python3

# Created by: Trinity Armstrong
# Created on: Jan 2020
# This function returns a row from our chocolate_user DynamoDB

import json
import boto3
import decimal


def replace_decimals(obj):
        # Helper class to Decimals in an arbitrary object
        #   from: https://github.com/boto/boto3/issues/369

    if isinstance(obj, list):
        for i in range(len(obj)):
            obj[i] = replace_decimals(obj[i])
        return obj
    elif isinstance(obj, dict):
        for k, v in obj.items():
            obj[k] = replace_decimals(v)
        return obj
    elif isinstance(obj, set):
        return set(replace_decimals(i) for i in obj)
    elif isinstance(obj, decimal.Decimal):
        if obj % 1 == 0:
            return int(obj)
        else:
            return float(obj)
    else:
        return obj


def lambda_handler(event, context):
    # get a row from our chocolates_user table

    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('chocolate_users')
    response = table.get_item(
        Key = {
            'email':event['email_address']
        }
    )

    try:
        results = response["Item"]
        results = replace_decimals(results)
    except:
        results = {}

    return {
        'statusCode': 200,
        'body': json.dumps(results)
    }

January 10th, 2020

  1. I created an AWS Cognito user pool called “cognitoPool”
  2. I used the Cognito built-in signup URL to add myself as a user through my trinity.armstrong@ocsbstudent.ca email. I successfully recieved a link and was confirmed as a user
  3. I confirmed that this new user exists in the Cognito pool

January 13th, 2020

Updated my readthedocs webpage

January 14th, 2020

  1. I created a javascript folder called “js”
  2. I downloaded the JavaScript libraries “amazon-cognito-auth.min”, “amazon-cognito-identity.min”, “and config.js” into the folder “js”
  3. I updated the “config.js” file with my app information from AWS Cognito
  4. Typed the code for my sign in page in the file “sign-in.html”. This runs 2 input boxes for your email address and password and a sign-in button
  5. I signed into my confirmed account and it successfully outputted “You are logged in as: trinity.armstrong@ocsbstudent.ca
sign-in.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!DOCTYPE html>

<html lang="en">
  <head>
  <meta charset="utf-8">

    <!-- Javascript SDKs-->
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="js/amazon-cognito-auth.min.js"></script>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.596.0.min.js"></script>
    <script src="js/amazon-cognito-identity.min.js"></script>
    <script src="js/config.js"></script>
  </head>

  <body>
    <form>
      <h1>Please sign in</h1>

      <input type="text" id="inputUsername"  placeholder="Email address" name="username" required autofocus>
      <input type="password" id="inputPassword"  placeholder="Password" name="password" required>
      <button type="button" onclick="signInButton()">Sign in</button>
    </form>

    <br>
    <div id='logged-in'>
      <p></p>
    </div>

    <p>
      <a href="./profile.html">Profile</a>
    </p>

    <br>
    <div id='home'>
      <p>
        <a href='./index.html'>Home</a>
      </p>
    </div>

    <script>

      var data = {
        UserPoolId : _config.cognito.userPoolId,
        ClientId : _config.cognito.clientId
      };
      var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
      var cognitoUser = userPool.getCurrentUser();

      function signInButton() {
        // sign-in to AWS Cognito

        var authenticationData = {
          Username : document.getElementById("inputUsername").value,
          Password : document.getElementById("inputPassword").value,
        };

        var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);

        var poolData = {
          UserPoolId : _config.cognito.userPoolId, // Your user pool id here
          ClientId : _config.cognito.clientId, // Your client id here
        };

        var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);

        var userData = {
          Username : document.getElementById("inputUsername").value,
          Pool : userPool,
        };

        var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);

        cognitoUser.authenticateUser(authenticationDetails, {
            onSuccess: function (result) {
              var accessToken = result.getAccessToken().getJwtToken();
              console.log(result);

              //get user info, to show that you are logged in
              cognitoUser.getUserAttributes(function(err, result) {
                  if (err) {
                    console.log(err);
                    return;
                  }
                  console.log(result);
                  document.getElementById("logged-in").innerHTML = "You are logged in as: " + result[2].getValue();
              });

            },
            onFailure: function(err) {
              alert(err.message || JSON.stringify(err));
            },
        });
      }
    </script>

  </body>
</html>

January 15th, 2020

  1. I typed the code for my sign out page in the file “sign-out.html”
sign-out.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <!--Cognito JavaScript-->
    <script src="js/amazon-cognito-identity.min.js"></script>
    <script src="js/config.js"></script>
  </head>

  <body>
  <div class="container">
    <div>
      <h1>Sign Out</h1>
      <p>Successfully signed-out</p>
    </div>

    <br>
    <div id='home'>
      <p>
      <a href='./index.html'>Home</a>
      </p>
    </div>
  </div>

  <script>
    var data = {
      UserPoolId : _config.cognito.userPoolId,
      ClientId : _config.cognito.clientId
    };
    var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
    var cognitoUser = userPool.getCurrentUser();

    window.onload = function(){
      if (cognitoUser != null) {
        cognitoUser.getSession(function(err, session) {
            if (err) {
              alert(err);
              return;
            }
            console.log('session validity: ' + session.isValid());

            // sign out
            cognitoUser.signOut();
            console.log("Signed-out");
        });
      } else {
        console.log("Already signed-out")
      }
    }
  </script>

  </body>
</html>
  1. I signed into my accout, then called “signout()” function and successfully signed out. The output is “Successfully signed-out”, this proves that the code is working.

January 16th, 2020

  1. I created a profile.html file in order to add our user’s profile to my webpage once signed in
  2. I did this by copying my sign-out.html code
  3. removing the sign-out code from my profile.html file
  4. copying getUserAttributes() function from sign-in.html to add to my file
  5. copying getUser() function from temp.html to add to my file
  6. I confirmed that my code was running correctly by signing in, and checking the profile page that had successfully outputted my profile information
profile.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <!--Cognito JavaScript-->
    <script src="js/amazon-cognito-identity.min.js"></script>
    <script src="js/config.js"></script>
  </head>

  <body>
  <div class="container">
    <div>
      <h1>Profile</h1>
    </div>
    <div id='profile'>
      <p></p>
    </div>
  <div>

    <br>
    <div id='home'>
      <p>
        <a href='./index.html'>Home</a>
      </p>
    </div>

  <script>

    async function getUser(email_address) {
      // get the user info from API Gate

      const api_url = 'https://gonvpjbyuf.execute-api.us-east-1.amazonaws.com/prod/user-profile?user_email=' + email_address;
      const api_response = await fetch(api_url);
      const api_data = await(api_response).json();
      console.log(api_data);

      const div_user_info = document.getElementById('profile');
      div_user_info.innerHTML = api_data['body'];
      }

    var data = {
      UserPoolId : _config.cognito.userPoolId,
        ClientId : _config.cognito.clientId
      };
      var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
      var cognitoUser = userPool.getCurrentUser();

      window.onload = function(){
        if (cognitoUser != null) {
          cognitoUser.getSession(function(err, session) {
            if (err) {
              alert(err);
              return;
            }
            //console.log('session validity: ' + session.isValid());

            cognitoUser.getUserAttributes(function(err, result) {
              if (err) {
                console.log(err);
                return;
              }
              // user email address
              console.log(result[2].getValue());
              getUser(result[2].getValue())
            });

          });
        } else {
          console.log("Already signed-out")
        }
      }
    </script>

  </body>
</html>

January 17th, 2020

  1. I removed javascript code from my HTML files and moved them into seperate .js files
  2. Used google’s MDL code to act as the css of my website
  1. Created home page, about page , Sign in page, Sign out page and Profile page on website (html and javascript)

January 20th, 2020

  1. Created register and settings page on website
  2. Added background’s to my website pages
  3. Added my OverAchiever logo to the header of each page
  4. Changed fonts and margins to make text more visually appealing
  5. Added a button link to the registration page on the home page