├── images
├── m-amplify_header.png
├── m-cloud9_step3.png
├── m-cloud9_step4.png
├── m-cloud9_step5.png
├── m-cloud9_step6.png
├── step3-13_appsync.png
├── step3-14_queries.png
├── step3-9_sign_out.png
├── step4-1_github.png
├── step4-4_merged.png
├── step5-3_search.png
├── m-cloud9_finished.png
├── step1_2_cloud9ide.png
├── step2-12_branches.png
├── step2-5-3_add_tags.png
├── step3-1_Cloud9_IDE.png
├── step3-2_git_branch.png
├── step3-8_login_page.png
├── step5-2_test_notes.png
├── m-cloud9_landingPage.png
├── step2-14_application.png
├── step2-1_AWS_Amplify.png
├── step2-5-1_Create_Role.png
├── step3-12_amplify_push.png
├── step3-17_list_notes.png
├── step3-21_git_commit.png
├── step3-5_amplify_push.png
├── step3-6_amplify_serve.png
├── step4-2_pull_request.png
├── step5-1_amplify_push.png
├── step2-10_Access_Control.png
├── step2-7_save_and_deploy.png
├── step2_0_coderepository.png
├── step3-18_app_with_notes.png
├── step3-19_different_user.png
├── step3-20_confirm_owner.png
├── step3-7_Preview_running.png
├── step4-5_amplify_deploy.png
├── step4-7_access_control.png
├── step2-11_Password_on_Test.png
├── step2-13_password_prompt.png
├── step2-4_Select_environment.png
├── step2-9-1_connect_branch.png
├── step2-9-3_save_and_deploy.png
├── step2-9-4_deploy_complete.png
├── step3-15_queries_loggedin.png
├── step3-16_successful_query.png
├── step4-3_merge_pull_request.png
├── step4-8_application_login.png
├── step2-5-2_attach_permissions.png
├── step2-8_deployment_complete.png
├── step3-10_amplify_api_config.png
├── step3-3_amplify_env_checkout.png
├── step3-4_ampligy_auth_config.png
├── step4-6_deployment_finished.png
├── step2-2_Add_Repository_Service.png
├── step2-3_Add_Repository_Branch.png
├── step2-6_Finish_Build_Settings.png
├── step2-9-2_Select_Branch_and_backend.png
└── step3-11_amplify_api_config_finished.png
├── TriggerDeployment.md
├── README.md
├── AppSetup.md
├── DeploymentSetup.md
├── AddingSearch.md
└── ApplicationDevelopment.md
/images/m-amplify_header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-amplify_header.png
--------------------------------------------------------------------------------
/images/m-cloud9_step3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-cloud9_step3.png
--------------------------------------------------------------------------------
/images/m-cloud9_step4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-cloud9_step4.png
--------------------------------------------------------------------------------
/images/m-cloud9_step5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-cloud9_step5.png
--------------------------------------------------------------------------------
/images/m-cloud9_step6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-cloud9_step6.png
--------------------------------------------------------------------------------
/images/step3-13_appsync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-13_appsync.png
--------------------------------------------------------------------------------
/images/step3-14_queries.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-14_queries.png
--------------------------------------------------------------------------------
/images/step3-9_sign_out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-9_sign_out.png
--------------------------------------------------------------------------------
/images/step4-1_github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-1_github.png
--------------------------------------------------------------------------------
/images/step4-4_merged.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-4_merged.png
--------------------------------------------------------------------------------
/images/step5-3_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step5-3_search.png
--------------------------------------------------------------------------------
/images/m-cloud9_finished.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-cloud9_finished.png
--------------------------------------------------------------------------------
/images/step1_2_cloud9ide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step1_2_cloud9ide.png
--------------------------------------------------------------------------------
/images/step2-12_branches.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-12_branches.png
--------------------------------------------------------------------------------
/images/step2-5-3_add_tags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-5-3_add_tags.png
--------------------------------------------------------------------------------
/images/step3-1_Cloud9_IDE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-1_Cloud9_IDE.png
--------------------------------------------------------------------------------
/images/step3-2_git_branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-2_git_branch.png
--------------------------------------------------------------------------------
/images/step3-8_login_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-8_login_page.png
--------------------------------------------------------------------------------
/images/step5-2_test_notes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step5-2_test_notes.png
--------------------------------------------------------------------------------
/images/m-cloud9_landingPage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/m-cloud9_landingPage.png
--------------------------------------------------------------------------------
/images/step2-14_application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-14_application.png
--------------------------------------------------------------------------------
/images/step2-1_AWS_Amplify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-1_AWS_Amplify.png
--------------------------------------------------------------------------------
/images/step2-5-1_Create_Role.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-5-1_Create_Role.png
--------------------------------------------------------------------------------
/images/step3-12_amplify_push.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-12_amplify_push.png
--------------------------------------------------------------------------------
/images/step3-17_list_notes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-17_list_notes.png
--------------------------------------------------------------------------------
/images/step3-21_git_commit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-21_git_commit.png
--------------------------------------------------------------------------------
/images/step3-5_amplify_push.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-5_amplify_push.png
--------------------------------------------------------------------------------
/images/step3-6_amplify_serve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-6_amplify_serve.png
--------------------------------------------------------------------------------
/images/step4-2_pull_request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-2_pull_request.png
--------------------------------------------------------------------------------
/images/step5-1_amplify_push.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step5-1_amplify_push.png
--------------------------------------------------------------------------------
/images/step2-10_Access_Control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-10_Access_Control.png
--------------------------------------------------------------------------------
/images/step2-7_save_and_deploy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-7_save_and_deploy.png
--------------------------------------------------------------------------------
/images/step2_0_coderepository.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2_0_coderepository.png
--------------------------------------------------------------------------------
/images/step3-18_app_with_notes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-18_app_with_notes.png
--------------------------------------------------------------------------------
/images/step3-19_different_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-19_different_user.png
--------------------------------------------------------------------------------
/images/step3-20_confirm_owner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-20_confirm_owner.png
--------------------------------------------------------------------------------
/images/step3-7_Preview_running.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-7_Preview_running.png
--------------------------------------------------------------------------------
/images/step4-5_amplify_deploy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-5_amplify_deploy.png
--------------------------------------------------------------------------------
/images/step4-7_access_control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-7_access_control.png
--------------------------------------------------------------------------------
/images/step2-11_Password_on_Test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-11_Password_on_Test.png
--------------------------------------------------------------------------------
/images/step2-13_password_prompt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-13_password_prompt.png
--------------------------------------------------------------------------------
/images/step2-4_Select_environment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-4_Select_environment.png
--------------------------------------------------------------------------------
/images/step2-9-1_connect_branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-9-1_connect_branch.png
--------------------------------------------------------------------------------
/images/step2-9-3_save_and_deploy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-9-3_save_and_deploy.png
--------------------------------------------------------------------------------
/images/step2-9-4_deploy_complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-9-4_deploy_complete.png
--------------------------------------------------------------------------------
/images/step3-15_queries_loggedin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-15_queries_loggedin.png
--------------------------------------------------------------------------------
/images/step3-16_successful_query.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-16_successful_query.png
--------------------------------------------------------------------------------
/images/step4-3_merge_pull_request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-3_merge_pull_request.png
--------------------------------------------------------------------------------
/images/step4-8_application_login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-8_application_login.png
--------------------------------------------------------------------------------
/images/step2-5-2_attach_permissions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-5-2_attach_permissions.png
--------------------------------------------------------------------------------
/images/step2-8_deployment_complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-8_deployment_complete.png
--------------------------------------------------------------------------------
/images/step3-10_amplify_api_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-10_amplify_api_config.png
--------------------------------------------------------------------------------
/images/step3-3_amplify_env_checkout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-3_amplify_env_checkout.png
--------------------------------------------------------------------------------
/images/step3-4_ampligy_auth_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-4_ampligy_auth_config.png
--------------------------------------------------------------------------------
/images/step4-6_deployment_finished.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step4-6_deployment_finished.png
--------------------------------------------------------------------------------
/images/step2-2_Add_Repository_Service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-2_Add_Repository_Service.png
--------------------------------------------------------------------------------
/images/step2-3_Add_Repository_Branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-3_Add_Repository_Branch.png
--------------------------------------------------------------------------------
/images/step2-6_Finish_Build_Settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-6_Finish_Build_Settings.png
--------------------------------------------------------------------------------
/images/step2-9-2_Select_Branch_and_backend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step2-9-2_Select_Branch_and_backend.png
--------------------------------------------------------------------------------
/images/step3-11_amplify_api_config_finished.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattmerriel/amplify-workshop/HEAD/images/step3-11_amplify_api_config_finished.png
--------------------------------------------------------------------------------
/TriggerDeployment.md:
--------------------------------------------------------------------------------
1 | # Trigger and Automated Deployment #
2 |
3 | ## Overview
4 | We now have an application that's working with our backend infrastructure and is ready to be deployed into our testing environment.
5 |
6 | ## Merging our Code
7 | We now want to copy the changes we've made in our "dev" branch, into our "test" branch so that it can be deployed and made available to our testers prior to being merged into production. Given our current setup, the easiest way to do this is through the GitHub Web UI.
8 |
9 | 1. Open you GitHub project in a new browser tab/window and you should see something similar to the below:
10 | 
11 |
12 | 2. Click on the "Compare & pull request" button and then make sure to select the "test" branch from the "base" dropdown.
13 | 
14 |
15 | 3. Once GitHub confirms that it's able to be merged, go ahead and click "Create pull request".
16 | 4. This will open a new window where you can simply click "Merge pull request", and then "Confirm merge".
17 | .
18 |
19 | once you've confirmed the merge, the status should automatically change to "Merged".
20 | 
21 |
22 | ## Amplify Deploy
23 | 1. If we then take a look our our amplify console https://console.aws.amazon.com/amplify/home?region=us-east-1#/ and select our application, we should see that our "test" environment has automatically triggered a deployment.
24 | 
25 |
26 | 2. The deployment process will slowly work through each of the steps and should eventually pass verification. We can tell it's worked, as we can see the login screen in the screenshots at the bottom of the page.
27 | 
28 |
29 | 3. Clicking on the "Domain" link should open our newly deployed application and first present us with the "Access-Control" username and password prompt we set up earlier (unless your browser still has it cached) before sending you to the login page for the application.
30 | 
31 | 
32 |
33 | It's important to note that the test users we setup in our "dev" environment will NOT exist in our "test" environment as it's a different Cognito User Pool.
34 |
35 | 4. Go ahead and create a new user and test the application out. It should work exactly the same way as it did when it was in our "dev" environment.
36 |
37 | ## Deploy to "Production"
38 | the process of deploying our application is the same as deploying into "test" only we'd use the "test" branch as the source and "master" as the destination.
39 |
40 | ## Next Steps
41 | We have our application, we have our deployment process. Now it's time to add some additional functionality to our application. In the next and final step (available [here](AddingSearch.md)) we will add search functionality by using an Elasticsearch domain.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started: Intro to AWS Amplify: build a multi-tenant SaaS app #
2 |
3 | ## What is this?
4 | This is the Intro to AWS Amplify: Build a multi-tenant SaaS app repository as part of the event organised by the [Melbourne AWS Programming and Tools Meetup](https://www.meetup.com/Melbourne-AWS-Programming-and-Tools-Meetup/events/261692367/).
5 |
6 | This repository contains instructions and assets to build your first AWS Amplify application with React and Node JS hosted on AWS. It is split up into 6 Parts, each containing instructions to get your first Amplify project published.
7 |
8 | | Part | Description |
9 | |:---:|:---|
10 | | Preparation | This Branch (Current Page) provides an introduction and instructions on creating the required AWS environment. |
11 | | App Setup | This Section outlines the steps to setup out new Amplify application and host it in a repository. |
12 | | Deployment Setup | Now that we have our base application configured, we can setup our deployment pipelines |
13 | | Application Development | In this part, we start building out our applications functionality |
14 | | Trigger Deployment | Next we can go ahead and push our changes into our automated pipelines |
15 | | Adding Search | Finally, we can add some search functionality to our application and deploy our changes to production |
16 |
17 | ## What is AWS Amplify
18 |
19 | AWS Amplify is an Open Source library under Apache 2.0 for developers looking to build cloud connected applications with JavaScript on web or mobile platforms. AWS Amplify is designed to give a declarative interface to client developers looking to perform common actions using cloud services in a scalable and secure manner.
20 |
21 | 
22 |
23 | The AWS Amplify library modules are broken down into categories (Auth, Analytics, Storage, APIs, Caching) to quickly add features such as User SignUp/SignIn, MFA, tracking or metric analytics, content management or Serverless API integration. The library also has internationalization and localization for multi-language support, as well as caching capabilities. Finally, there are components and extensions for React and React Native, allowing developers writing applications on those platforms to add these capabilities with framework specific standards. JavaScript developers can also use the library to build their own custom UI components, such as custom authentication flows. AWS Amplify is designed to be extended with different implementations among community and partner contributors.
24 |
25 |
26 | ## Preparation:
27 | ### Before we get started
28 | in order to follow along with this workshop, you'll need to already have the following:
29 | - AWS Account We will be using AWS as our Cloud provider. sign-up [here](https://aws.amazon.com) if you don't already have one
30 | - Github Account to download this repository into your Cloud9 instance.
31 |
32 | for the purposes of this workshop, we will be deploying all of our resources in the us-east-1 region.
33 |
34 | The first step once you've got your AWS account is to create a Cloud9 instance which will house the project and provide an IDE from which to work. More information on Cloud9 can be found at it's [product page](https://aws.amazon.com/cloud9/) .
35 |
36 | 1. Browse to the Cloud9 Management https://console.aws.amazon.com/cloud9/home/product
37 | 
38 |
39 | 2. Create a new Cloud9 environment by clicking the "create environment" button available on the right hand side of the landing page.
40 | 3. Give your environment a name and click "Next step". For this example i'm using "Amplify-Workshop".
41 | 
42 |
43 | 4.here we can configure your environment settings, but for this workshop we will can just click the "Next step".
44 | 
45 |
46 | 5. Review the environment details and click "Create environment".
47 | 
48 |
49 | 6. Wait for the creation of your Cloud9 instance to complete. This can take a few minutes.
50 | 
51 |
52 | 7. Once you see your new Cloud9 IDE, your ready to move onto Part 1 of the workshop.
53 | 
54 |
55 | ## Conclusion
56 | you should now have your AWS account with a Cloud9 instance running in the us-east-1 region. At this point in time, your ready to move onto [Part 1](/AppSetup.md) of the workshop where we will start to install and configure our new Note taking application.
57 |
58 |
--------------------------------------------------------------------------------
/AppSetup.md:
--------------------------------------------------------------------------------
1 | # Application Setup #
2 |
3 | ## Overview
4 | By now, you should have your Cloud9 instance configured and ready to go. In this section we will install the required libraries in our Cloud9 instance and bootstrap our Amplify Application. We will then create several Amplify environments which will form a part of our deployment pipelines. We will then finish off the section be commiting our new application into a github repository in preperation for the next step of the workshop.
5 |
6 | ## Bootstrap Project
7 | 1. To get started, make sure you are logged into your AWS Cloud9 environment. If you have followed the instuctions outlined in the previous part, you can find a list of your Cloud9 environments by visiting the Cloud9 management console [here](https://us-east-1.console.aws.amazon.com/cloud9/home?region=us-east-1#).
8 |
9 | 2. You should now be presented with your Cloud9 IDE as shown below.
10 | 
11 |
12 | 3. From the bash terminal (located in the bottom of the IDE) we can now start installing and configuring our application. Start by installing the create-react-app npm package.
13 | ```bash
14 | npm install -g create-react-app
15 | ```
16 |
17 | 4. Next, we can bootstrap our new react application. for the purposes of this workshop, we I am naming the project "notes with amplify".
18 | ```bash
19 | create-react-app noteswithamplify
20 | ```
21 |
22 | 5. cd into the directory.
23 | ```bash
24 | cd noteswithamplify
25 | ```
26 |
27 | 6. Install the AWS Amplify CLI tools so that we can interact with our Amplify application. Will also need to install a new other packages that we will need throughout the rest of the project.
28 | ```bash
29 | npm install -g @aws-amplify/cli
30 | npm install --save aws-amplify aws-amplify-react uuid bootstrap
31 | ```
32 |
33 | 7. Next we need to configure our Amplify environment by providing it with our AWS region and IAM user details. AWS Amplify will do most of the work for us and will only require us to complete the IAM user creation and provide the accessKeyId and secretAccessKey.
34 | ```bash
35 | amplify configure
36 | ```
37 | The Amplify CLI will prompt us for some answers. For the purposes of the workshop, go ahead and use the values shown below.
38 | - Specify the AWS Region:us-east-1
39 | - Specify the username of the new IAM useramplify-workshop-user
40 | At this stage the Amplify CLI will provide us a link to open to complete the creation of the IAM user it will use to interact with our AWS environment. Right-Click on the link and follow the process to complete the creation of the new user. Copy the accessId and secretAccessKey and enter them in the following prompts. You can also define a profile to use.
41 |
42 | ## Initialise Amplify Project
43 | 8. We are now ready to initialise our new AWS Amplify Project. Like the aws configure command above, this command will also prompt for some values. No ahead and enter the values as shown below, most of which are the default values.
44 | ```bash
45 | amplify init
46 | ```
47 | - Enter a name for the project: noteswithamplify
48 | - Enter a name for the environment: prod
49 | - Choose your default editor: None
50 | - Choose the type of app that you’re building: javascript
51 | - Please tell us about your project
52 | - What javascript framework are you using: react
53 | - Source Directory Path: src
54 | - Distribution Directory Path: build
55 | - Build Command: npm run-script build
56 | - Start Commend: npm run-script start
57 | - Do you want to use an AWS profile: yes
58 | - Please choose the profile you want to use: default
59 |
60 | 9. This will go ahead and configure our base Amplify project and create a prod environment. This environment will host our production environment, however we will also need an environment to run our test branch and develop our features in. To achieve this we can add two additional environments to our configuration as shown below.
61 | ```bash
62 | amplify env add
63 | ```
64 | - Do you want to use an existing environment? No
65 | - Enter a name for the environment: test
66 | - Do you want to use an AWS profile: Yes
67 | - Please choose the profile you want to use: default
68 | ```bash
69 | amplify env add
70 | ```
71 | - Do you want to use an existing environment? No
72 | - Enter a name for the environment: dev
73 | - Do you want to use an AWS profile: Yes
74 | - Please choose the profile you want to use: default
75 |
76 | 10. Now that we have our Amplify baseline created and our 3 environments created it's time to commit our code to a git repository. In order to work with the next part of the workshop, one of the following git repositories is required to be used:
77 | - AWS CodeCommit
78 | - GitHub
79 | - BitBucket
80 | - GitLab
81 |
82 | ## Next Steps
83 |
84 | These instructions are for committing your repository to GitHub. If you want to use one of the other Git repositories, you'll need to change the remote URL to the URL of your preferred repository host.
85 |
86 | First of all, you'll need to create a Git repository and commit all of your files to it. You can do this using the following commands:
87 |
88 | ```
89 | git init .
90 | git add .
91 | git commit -m "Initial commit"
92 | ```
93 |
94 | Next, you'll need to create a new repository in GitHub. Head over to [this page](https://github.com/new), and create a new repository called `amplify`. Make sure that the 'Initialise this repository with a README' box is unchecked, and that you're not adding a `.gitignore ` page or a license. When you've done that, hit the 'Create repository' button.
95 |
96 | Now, you can push your code to GitHub using the following commands:
97 |
98 | ```
99 | git remote add origin https://github.com//amplify
100 | git push -u origin master
101 |
102 | ```
103 |
104 | Then, create and push a new branch called `test`. We'll need this for the next section of the workshop.
105 |
106 | ```
107 | git branch test
108 | git push -u origin test
109 | ```
110 |
111 | Once this has been done, you're ready to move onto the next part of the workshop where we will configure our Amplify Deploy processes. Click [here](/DeploymentSetup.md) to process to the next part.
112 |
--------------------------------------------------------------------------------
/DeploymentSetup.md:
--------------------------------------------------------------------------------
1 | # Deployment Setup #
2 |
3 | ## Overview
4 | By now you should have your react application bootstrapped and your amplify project initialized and committed to a git repository. If you take a look at your project, you should see something similar to the below (example taken from github).
5 | 
6 |
7 | In this part of the workshop we will configure Amplify Deploy which will run our builds, deployment and testing for us.
8 |
9 | 1. The first step is to open the Amplify management console available [here](https://console.aws.amazon.com/amplify/home?region=us-east-1#/). If it's your first time using AWS Amplify, you will see the getting started dashboard as shown below. Simply click on the "GET STARTED" button under "Deploy".
10 | 
11 | 2. The next step is to connect your Git repository to your AWS Amplify environment. This will allow Amplify to clone the repository and be triggered whenever a commit occurs. Select your Repository service provide from the list shown below and click "Next". You will then be automatically requested to allow AWS Amplify access to your repository (this may require you logging into your account). For the example in this workshop, we have used a GitHub repository.
12 | 
13 | 3. Once access to your account has been granted, the next step is to select the repository from the list and define the branch you wish to follow. We will be creating two separate deployments, one to deploy our production environment based off our "Master" branch and a second one to deploy from out test branch. To start off with, go ahead and select the "Master" branch and click "Next".
14 | 
15 | 4. At this stage, we need to tell it which Amplify environment we wish tyo use in conjunction with our "Master" branch. By default, Amplify will populate the list of available environments from our repository (this is why we created the three seperate environments in the last part). Go ahead and select the "prod" environment.
16 | 
17 | 5. Assuming you've never used Amplify Deploy before, you'll need to go ahead and create an IAM role that it can use. Click the "Create new role" button, and select "Amplify" from the list of services presented. This defines which AWS service the request will be originating from.
18 | 
19 | 6. By default, the Amplify console automatically selects the "AdministratorAccess" policy to apply to our new role. While this is OK for the purposes of our workshop, It's highly advisable that you define your own fine-grained policy when using Amplify in a production environment. As this will be a short lived environment, simply go ahead and access the policy and click "Next: Tags".
20 | 
21 | 7. Just go ahead and click "next". No need to worry about giving our new IAM role Tags in this workshop example.
22 | 
23 | 8. Once your review the settings and create the new role, you can go back to our previous tab and click the "Refresh existing roles" button. Then select the new role from the list ("amplifyconsole-backend-role" if you followed the instructions and accepted the default values). Given we haven't defined and build settings as of yet, we can simply accept the defaults and click "Next".
24 | 
25 | 9. All we need to do now is give our variables a quick review and click "Save and deploy". Note that this will take a couple of minutes to complete and it's usually helpful to wait at this point before configuring the next branch, in case something goes wrong.
26 | 
27 | 10. After a few minutes you should see that our new pipeline has completed the deployment of our "Master" branch into our "prod" environment. This console provides the URL we can use to visit our site as well has the verification screenshots of our new application across a range of screen sizes. Once you've confirmed that the deployment has succeed, go ahead and browse back to the "Amplify Deploy All Apps" page. The easiest way to to click on our application name, on the top left of the Amplify Deploy pane.
28 | 
29 | 11. OK, so we have a successfully deployed "Master" branch so now it's time to add another pipeline for your testing branch. From this page, simply click on the "Connect branch" button located on the top right of the page.
30 | 
31 | 12. Save deal as when we configured our "master" back in step 3, only this time we don't need to provide access to our Git repository first (because AWS Amplify already has access). Go ahead and select the "test" branch and the "test" environment. If you don't see a test branch, simply go ahead and create one and push the change to your git repository and then refresh the page.
32 |
33 | I have experienced situations where the "Next" doesn't want to become selectable. If this happens, simply click "Cancel" and then restart the process from step 11. If it occurs a second time forcing a refresh of the whole page seams to fix it.
34 | 
35 | 13. Same as last time, make sure all the details are correct and then click "Save and deploy".
36 | 
37 | 14. At this stage, our new "test" pipeline will go through the process of downloading and deploying our workload. You should wait for the pipeline to succeed before proceeding to the next step.
38 | 
39 | 15. So we now have a Production environment running, deployed off our "Master" branch and a testing environment deployed off our "test" branch. This problem is, we'd prefer if the public didn't have access to our testing environment so lets go ahed and configure a simple username and password prompt on it. As shown below, from the left hand menu, click on "Access Control".
40 | 
41 | 16. Now, simply click on the "Manage access" button (top right hand side of the page) and we're presented with a page where we can define a username and password for each of our branches, or a single one for all deployments. For our purposes, we just want to password protect our testing environment so:
42 | * Select "Restricted - password required" from the "Access settings dropdown.
43 | * enter a username in the first column. For our example we are using "tester" as our username.
44 | * Enter and verify a password.
45 | Go ahead and click "Save" once your down.
46 | 
47 | 17. Back on our "Amplify Deploy" page, under the "test" application pipeline, you will see the url of the application. Go ahead and click it to validate the password protection.
48 | 
49 | 18. The page should open in a new tab and prompt for a username and password. Go ahead and enter the details you defined in step 16 and click "Sign in".
50 | 
51 | 19. And voila!, our application.... isn't it wonderful.
52 | 
53 |
54 | ## What did we just do?
55 | OK so we have some running React boilerplate running, why did we need to go through so many steps to get there?
56 |
57 | So firstly, we've provided AWS Amplify with access to our Git Repository and will allow it to trigger events as well as access the current version of our source code. From their, we've configured two separate deployment pipelines... The first is to handle our Production deployments and the other is for our testing deployment. Whenever we make a commit to either of those branches, Amplify we automatically trigger a deployment for us.
58 |
59 | You might have noticed that we didn't setup a pipeline for our "dev" branch. the reason for this is to allow us to use that branch (as well as the dev amplify environment) as our personal development branch that we can use to build out our features without constantly triggering automated deployments. Once we have completed our new feature, we can simply merge it into our testing branch and have it picked up by the appropriate pipeline.
60 |
61 | ## Next Steps
62 | It's at this stage that we are ready to start building out the functionality of our new application. You can move onto the next part of the workshop by clicking [here](/ApplicationDevelopment.md)
--------------------------------------------------------------------------------
/AddingSearch.md:
--------------------------------------------------------------------------------
1 | # Adding and Deploying Search Functionality #
2 |
3 | ## Overview
4 | As our final task, we will look at adding some search functionality to our application as it's somthing almost everybody needs when working with notes. We will then close out the work by working this update through our deployment process.
5 |
6 | ## Adding Search
7 | The process of adding search is very simple and consists of only 3 steps. Before we start, we need to browse back to our Cloud9 IDE [here](https://us-east-1.console.aws.amazon.com/cloud9/home?region=us-east-1#).
8 |
9 | 1. Firstly, we need to open our GraphQL schema file which is /amplify/backend/api/amplifynotes/schema.graphql and replace the contents with the below:
10 | ```
11 | type Note @model @auth(rules: [{allow: owner}]) @searchable{
12 | id: ID!
13 | note: String!
14 | }
15 | ```
16 | Tha'ts right, all we've done is add the @searchable directive to our Note object type. And that's our GraphQL endpoint taken care of.
17 |
18 | 2. Next, we need to update out backend infrastructure as we will need to deploy our Elasticsearch service. To do this, all we need to do is tell Amplify to update our cloud environment by running 'amplify push' again.
19 | ```bash
20 | amplify push
21 | ```
22 | when we do this, we can see that Amplify has identified that an update is required to our API configuration. We can do ahead and hit "Enter" to continue.
23 | 
24 |
25 | NOTE: this will take some time to deploy.
26 |
27 | 3. The final step is to update our /src/App.js file with some additional code to add a search button as well as handle/display the results. Replace the contents of the file with the below.
28 |
29 | ```js
30 | import React, {Component} from 'react';
31 | import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';
32 | import Amplify, {API,graphqlOperation} from 'aws-amplify';
33 | // Get the aws resources configuration parameters
34 | import awsconfig from './aws-exports'; // if you are using Amplify CLI
35 | import 'bootstrap/dist/css/bootstrap.min.css';
36 |
37 | Amplify.configure(awsconfig);
38 |
39 | const headerStyle = {
40 | 'background-color': '#282c34',
41 | 'min-height': '10vh',
42 | display: 'flex',
43 | 'flex-direction': 'column',
44 | 'align-items': 'center',
45 | 'justify-content': 'center',
46 | 'font-size': 'calc(10px + 2vmin)',
47 | color: 'white'
48 | };
49 |
50 | const createNote = `mutation createNote($note: String!){
51 | createNote(input:{
52 | note: $note
53 | }){
54 | __typename
55 | id
56 | note
57 | }
58 | }`;
59 |
60 | const readNote = `query listNotes{
61 | listNotes{
62 | items{
63 | __typename
64 | id
65 | note
66 | }
67 | }
68 | }`;
69 |
70 | const updateNote = `mutation updateNote($id: ID!,$note: String){
71 | updateNote(input:{
72 | id: $id
73 | note: $note
74 | }){
75 | __typename
76 | id
77 | note
78 | }
79 | }`;
80 |
81 | const deleteNote = `mutation deleteNote($id: ID!){
82 | deleteNote(input:{
83 | id: $id
84 | }){
85 | __typename
86 | id
87 | note
88 | }
89 | }`;
90 |
91 | const searchNote = `query searchNotes($search: String){
92 | searchNotes(filter:{note:{match:$search}}){
93 | items{
94 | id
95 | note
96 | }
97 | }
98 | }`
99 |
100 | class App extends Component {
101 | constructor(props){
102 | super(props);
103 | this.state={
104 | id:"",
105 | notes:[],
106 | searchResults:[],
107 | value:"",
108 | displayAdd:true,
109 | displayUpdate:false,
110 | displaySearch:false
111 | };
112 | this.handleChange = this.handleChange.bind(this);
113 | this.handleSubmit = this.handleSubmit.bind(this);
114 | this.handleUpdate = this.handleUpdate.bind(this);
115 | this.handleSearch = this.handleSearch.bind(this);
116 | }
117 |
118 | async componentDidMount(){
119 | const notes = await API.graphql(graphqlOperation(readNote));
120 | this.setState({notes:notes.data.listNotes.items});
121 | }
122 |
123 | handleChange(event) {
124 | this.setState({value:event.target.value});
125 | }
126 | async handleSubmit(event) {
127 | event.preventDefault();
128 | event.stopPropagation();
129 | const note = {"note":this.state.value}
130 | await API.graphql(graphqlOperation(createNote, note));
131 | this.listNotes();
132 | this.setState({value:""});
133 | }
134 | async handleDelete(id) {
135 | const noteId = {"id":id};
136 | await API.graphql(graphqlOperation(deleteNote, noteId));
137 | this.listNotes();
138 | }
139 | async handleUpdate(event) {
140 | event.preventDefault();
141 | event.stopPropagation();
142 | const note = {"id":this.state.id,"note":this.state.value};
143 | await API.graphql(graphqlOperation(updateNote, note));
144 | this.listNotes();
145 | this.setState({displayAdd:true,displayUpdate:false,value:""});
146 | }
147 | async handleSearch(event) {
148 | event.preventDefault();
149 | event.stopPropagation();
150 | const search = {"search":this.state.value};
151 | const result = await API.graphql(graphqlOperation(searchNote, search));
152 | this.setState({searchResults:result.data.searchNotes.items,notes:[],displaySearch:true,value:""});
153 | if(JSON.stringify(result.data.searchNotes.items) === '[]'){
154 | this.setState({searchResults:[{note:"No Match: Clear the search to go back to your Notes"}]});
155 | };
156 | }
157 | selectNote(note){
158 | this.setState({id:note.id,value:note.note,displayAdd:false,displayUpdate:true});
159 | }
160 | async listNotes(){
161 | const notes = await API.graphql(graphqlOperation(readNote));
162 | this.setState({notes:notes.data.listNotes.items,searchResults:[],displaySearch:false});
163 | }
164 |
165 | render() {
166 | const data = [].concat(this.state.notes)
167 | .map((item,i)=>
168 |
221 | );
222 | }
223 | }
224 | export default withAuthenticator(App, { includeGreetings: true });
225 | ```
226 | So, what did we just change? well, their isn't that many lines of code that we've added:
227 | * Lines 62-69 Contain a new const for "searchNote". This is just another GraphQL query like the others.
228 | * Lines 77, 80 and 81 add some additional variables for our scope handling.
229 | * Line 86 add the handle for our search binding.
230 | * Lines 118-127 is the new async handle for our search
231 | * Lines 133, 139, 146-151, 154, 155 and 184-189 Handle the display of the notes
232 | * Lines 61, 165 and 166 add the search button to our form.
233 |
234 | 4. And we're ready to test. Like before, we can test our new code by using the Amplify CLI.
235 | ```bash
236 | amplify serve
237 | ```
238 |
239 | You can now log in create some sample notes and then try to search for it.
240 | 
241 | 
242 |
243 | ## Deploy search function
244 | By following the steps outlined in the [Application Development](ApplicaitonDevelopment.md) part of the workshop you should be able to commit your code back to your "dev" branch.
245 |
246 | Once you've done that, create a pull request to the "test" branch as outlined in [Trigger Deployment](TriggerDeployment.md) and once you approve it, the new Elasticsearch functionality will be deployed into "test".
247 |
248 | Finally, you can perform the same tasks to move it into Production.
249 |
250 | ## What to from here?
251 | And that's it, you now have a fully working Multi-Tenant Notes Application with the beginnings of an automated deployment pipeline. But where can you go from here? well, their are a number of things that could be done to expand the functionality of the solution and some are listed below for reference:
252 |
253 | * Customize the login screen and functions - https://aws-amplify.github.io/docs/js/authentication#customize-your-own-components
254 | * Add Federation to allow social logins - https://aws-amplify.github.io/docs/js/authentication#identity-pool-federation
255 | * Enable MFA - https://aws-amplify.github.io/docs/js/authentication#enabling-mfa
256 | * Leverage Amazon Pinpoint for application analytics - https://aws-amplify.github.io/docs/js/analytics#analytics
257 | * Add a service worker to support offline experiences - https://aws-amplify.github.io/docs/js/service-workers#service-workers
258 |
259 |
--------------------------------------------------------------------------------
/ApplicationDevelopment.md:
--------------------------------------------------------------------------------
1 | # Application Development #
2 |
3 | ## Overview
4 | By now, we have:
5 | * Our Cloud9 IDE with the required packages installed and ready for use.
6 | * Our bootstrapped application committed to our Git repository with our "master" and "test" branches configured
7 | * Two Amplify Deploy pipelines configured and had the complete their initial deployments.
8 |
9 | In this part of the workshop, we will start building out our applications functionality by adding in some basic authentication and a GraphQL endpoint that will be responsible for providing access to our users notes.
10 |
11 | ## Configuring Dev Branch
12 | The first thing we need to do is setup our new "dev" branch as point to our "dev" Amplify environment.
13 |
14 | 1. Firstly, browse back to your Cloud9 IDE and make sure that your bash session is in the right folder.
15 | 
16 |
17 | 2. here we can see that we are currently in our "test" branch (as indicated by the (test) immediately before the $ symbol). We first need to create ourselves a new branch called "dev" so that we can develop our new functionality before merging it back into our test environment.
18 | ```bash
19 | git checkout -b dev
20 | ```
21 | you should now have (dev) immediately before the $ rather than (test) as shown below/
22 | 
23 |
24 | 3. The next thing we need to do is tell Amplify that we want to be using our "dev" environment that we created earlier. This is pretty simple and is just a single command.
25 | ```bash
26 | amplify env checkout dev
27 | ```
28 | 
29 |
30 | We are now ready to start editing our application.
31 |
32 | ## Adding Authentication
33 | The next thing we are going to do is add some authentication to our application. To do this we will use the "amplify auth" feature that will automatically add in a cognito user pool for us to use. We can then make a few simple changes to our React application to leverage this feature.
34 |
35 | 4. To add Authentication, we firstly need to tell Amplify to add the required components to our applications codebase. To do this, we simply run the "amplify add" command from the bash terminal.
36 | ```bash
37 | amplify add auth
38 | ```
39 | The Amplify CLI will then go through a series of questions to define how our solution is configured. For our example we can simply accept the defaults, however it's important to note that when working on a production application, these setting can not be changed once deployed.... So some thought might need to go into their answers.
40 | 
41 |
42 | 5. Now that we've added authentication to our code base, we need to tell Amplify to deploy the required backend resources so that we can leverage them (in this case Amazon Cognito). As stated in the console, this easiest way to do this is to perform an "amplify push" which will use cloudformation templates to deploy the required resources.
43 | ```bash
44 | amplify push
45 | ```
46 | We immediately get presented with information saying that Amplify is going to need to "Create" the resources required for our "Auth" component and it will do this in our "dev" environment. this is what we want, so we can simply hit enter to proceed. As soon as you hit Enter, the cloudformation deployment will start and take a couple of minutes to complete.
47 |
48 | 
49 |
50 | 6. We have our configuration defined, CloudFormation deployed... Time to leverage it in our React application. to do this is as easy as adding the following lines to our /src/App.js file (Do not do anything yet, the below is for illustration purposes).
51 | ```js
52 | import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';
53 | import Amplify from 'aws-amplify';
54 | // Get the aws resources configuration parameters
55 | import awsconfig from './aws-exports'; // if you are using Amplify CLI
56 |
57 | Amplify.configure(awsconfig);
58 |
59 | // ...
60 |
61 | export default withAuthenticator(App);
62 | ```
63 |
64 | to make life easy, open the /src/App.js file and replace it with the below code.
65 | ```js
66 | import React from 'react';
67 | import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';
68 | import Amplify from 'aws-amplify';
69 | import logo from './logo.svg';
70 | import './App.css';
71 | // Get the aws resources configuration parameters
72 | import awsconfig from './aws-exports'; // if you are using Amplify CLI
73 |
74 | Amplify.configure(awsconfig);
75 |
76 | function App() {
77 | return (
78 |
94 | );
95 | }
96 |
97 | export default withAuthenticator(App, { includeGreetings: true });
98 | ```
99 | don't forget to save the file once your done.
100 |
101 | 7. Time to test it. The quickest and easiest way to do this is to just run "Amplify serve" which will start a local development instance that you can use.
102 | ```bash
103 | amplify serve
104 | ```
105 | 
106 |
107 | But Argh! how do we get to local host when we are developing on a remote Cloud9 instance? The easiest way is to click on the "Preview" dropdown at the top of the page, and select "Preview Running Application". This will open up a new tab with your site. If you'd like to view it in a full window, click the button on the far right of it's address bar.
108 | .
109 |
110 | Once you've open the preview page you should be presented with a login screen.
111 | 
112 |
113 | Go ahead and click "Create account" and go through the process. The default configuration requires a verification code to be confirmed via email before a user can login so pick an email address you have access to. You can also test out the "Reset Password" flow as that should also be working at this point.
114 |
115 | Once you've verified an account you should be able to login using a newly created username and password and be presented with our application once again. Only this time, their is a Menubar at the top displaying your username and a "SIGN OUT" Button (the menu bar came from the "includeGreeting: true" parameter we passed in the last line of our /src/App.js file).
116 | 
117 |
118 | ## Adding a GraphQL API
119 | So, we have an application that has fully working authentication (ok, it's not the prettiest login screen ... but it works) but doesn't do much other than that. Now would be a good time to actually add some functionality to our application and we'll do that by adding in a GraphQL endpoint which will store our notes in a dynamoDB table. We'll also need to add some basic UI bootstrap to present the notes back to the user.
120 |
121 | 1. To add an API, we do much the same thing we did when we added authentication. We simply run the "amplify add" command from the bash terminal.
122 | ```bash
123 | amplify add api
124 | ```
125 |
126 | The Amplify CLI will then go through a series of questions to define how our solution is configured. For our example, we will only deviate from the defaults for out authorization, where we will select "Amazon Cognito User Pool" rather than "API Key".
127 | 
128 |
129 | Once you get to the "Do you want to edit the schema now?" question, it will prompt you to edit the schema file it has created. Simply click on the link it provides and select "Open". Then replace everything in the file with the below. Don't forget to save the file before returning to the terminal.
130 | ```
131 | type Note @model @auth(rules: [{allow: owner}]){
132 | id: ID!
133 | note: String!
134 | }
135 | ```
136 |
137 | press "Enter" to complete the configuration process.
138 | 
139 |
140 | 2. Now that we've added an API to our code base, we need to tell Amplify to deploy the required backend resources so that we can leverage it. As stated in the console, this easiest way to do this is to perform an "amplify push" which will use cloudformation templates to deploy the required resources.
141 | ```bash
142 | amplify push
143 | ```
144 | We immediately get presented with similar information to what we did last time, however now it shows that we will be creating our API, while making no changes to our Auth resources. Press "Enter" to continue.
145 |
146 | 
147 |
148 | The next question asks us if we want to generate code for our newly created GraphQL API. For our example we will be writing our own so answer "n" to this question. After that, the Amplify CLI will again go and deploy a series of CloudFormation templates responsible for our API. Note that this does take a couple of minutes, but make sure it completes before proceeding to the next step.
149 |
150 | 3. Before we go ahead and add some more code to our /src/App.js file, lets make sure that our new API endpoint is working correctly. To do this, go ahead and open up a new tab and browse to https://console.aws.amazon.com/appsync/home?region=us-east-1 and open up your new API.
151 | 
152 |
153 | 4. Click on "Queries" from the Left hand menu, and then click the "Login with User Pools" button.
154 | 
155 |
156 | We need to provide AppSync with three pieces of information before we can start making queries against our API:
157 | * ClientID this can be found in the /src/aws-exports.js file of our project. It's the "aws_user_pools_web_client_id" value.
158 | * Username is simply the username of the test user we created earlier
159 | * Password and it's password.
160 | Enter the information and click "Login". At this point you should be back at the "Queries" page.
161 | 
162 |
163 | 5. Firstly, lets try and create a new note. To do this, enter the below query into the window (feel free to delete the code that's already their) and click the play button.
164 | ```
165 | mutation createNote {
166 | createNote(input: {
167 | note: "Test Note Number 1"
168 | }) {
169 | id note
170 | }
171 | }
172 | ```
173 |
174 | if everything is working correctly, you should get a response confirming the creation of your new note as shown below.
175 | 
176 |
177 | go ahead and create a few more notes using the below queries. Make sure to run each query separately!
178 | ```
179 | mutation createNote {
180 | createNote(input: {
181 | note: "Test Note Number 2"
182 | }) {
183 | id note
184 | }
185 | }
186 | ```
187 | ```
188 | mutation createNote {
189 | createNote(input: {
190 | note: "Test Note Number 3"
191 | }) {
192 | id note
193 | }
194 | }
195 | ```
196 |
197 | we can also test retrieving notes by running a query request.
198 | ```
199 | query listNotes {
200 | listNotes {
201 | items {
202 | note
203 | }
204 | }
205 | }
206 | ```
207 | this should return a list of all of our notes without the id field.
208 | 
209 |
210 | 6. Now that we know our API is working correctly, It's time to update our application. Back in our Cloud9 IDE,replace the contents of your /src/App.js file with the code below and don't forget to save it:
211 | ```js
212 | import React, {Component} from 'react';
213 | import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';
214 | import Amplify, {API,graphqlOperation} from 'aws-amplify';
215 | // Get the aws resources configuration parameters
216 | import awsconfig from './aws-exports'; // if you are using Amplify CLI
217 | import 'bootstrap/dist/css/bootstrap.min.css';
218 |
219 | Amplify.configure(awsconfig);
220 |
221 | const headerStyle = {
222 | 'background-color': '#282c34',
223 | 'min-height': '10vh',
224 | display: 'flex',
225 | 'flex-direction': 'column',
226 | 'align-items': 'center',
227 | 'justify-content': 'center',
228 | 'font-size': 'calc(10px + 2vmin)',
229 | color: 'white'
230 | };
231 |
232 | const createNote = `mutation createNote($note: String!){
233 | createNote(input:{
234 | note: $note
235 | }){
236 | __typename
237 | id
238 | note
239 | }
240 | }`;
241 |
242 | const readNote = `query listNotes{
243 | listNotes{
244 | items{
245 | __typename
246 | id
247 | note
248 | }
249 | }
250 | }`;
251 |
252 | const updateNote = `mutation updateNote($id: ID!,$note: String){
253 | updateNote(input:{
254 | id: $id
255 | note: $note
256 | }){
257 | __typename
258 | id
259 | note
260 | }
261 | }`;
262 |
263 | const deleteNote = `mutation deleteNote($id: ID!){
264 | deleteNote(input:{
265 | id: $id
266 | }){
267 | __typename
268 | id
269 | note
270 | }
271 | }`;
272 |
273 | class App extends Component {
274 | constructor(props){
275 | super(props);
276 | this.state={
277 | id:"",
278 | notes:[],
279 | value:"",
280 | displayAdd:true,
281 | displayUpdate:false
282 | };
283 | this.handleChange = this.handleChange.bind(this);
284 | this.handleSubmit = this.handleSubmit.bind(this);
285 | this.handleUpdate = this.handleUpdate.bind(this);
286 | }
287 |
288 | async componentDidMount(){
289 | const notes = await API.graphql(graphqlOperation(readNote));
290 | this.setState({notes:notes.data.listNotes.items});
291 | }
292 |
293 | handleChange(event) {
294 | this.setState({value:event.target.value});
295 | }
296 | async handleSubmit(event) {
297 | event.preventDefault();
298 | event.stopPropagation();
299 | const note = {"note":this.state.value}
300 | await API.graphql(graphqlOperation(createNote, note));
301 | this.listNotes();
302 | this.setState({value:""});
303 | }
304 | async handleDelete(id) {
305 | const noteId = {"id":id};
306 | await API.graphql(graphqlOperation(deleteNote, noteId));
307 | this.listNotes();
308 | }
309 | async handleUpdate(event) {
310 | event.preventDefault();
311 | event.stopPropagation();
312 | const note = {"id":this.state.id,"note":this.state.value};
313 | await API.graphql(graphqlOperation(updateNote, note));
314 | this.listNotes();
315 | this.setState({displayAdd:true,displayUpdate:false,value:""});
316 | }
317 | selectNote(note){
318 | this.setState({id:note.id,value:note.note,displayAdd:false,displayUpdate:true});
319 | }
320 | async listNotes(){
321 | const notes = await API.graphql(graphqlOperation(readNote));
322 | this.setState({notes:notes.data.listNotes.items});
323 | }
324 |
325 | render() {
326 | const data = [].concat(this.state.notes)
327 | .map((item,i)=>
328 |
368 | );
369 | }
370 | }
371 | export default withAuthenticator(App, { includeGreetings: true });
372 | ```
373 | Theirs a lot going on here so lets break down the changes we just made:
374 | * Lines 1-5 we've added a couple of extra parts we need brought in from the Amplify libraries.
375 | * line 6 we've added our bootstrap.css to add some pretty to our application.
376 | * lines 10-19 is just a CSS block to clean up the menu. We've also removed the reference to our App.css.
377 | * lines 21-60 are the GraphQL queries that we are going to need. These are the same as the queries we ran in the previous steps.
378 | * lines 63-112 adds some GraphQL logic and state handling. This is mainly to refresh the page and notes are added/updated or removed.
379 | * lines 115-156 is just HTML used to display the page.
380 |
381 | And that's it, we've just added all of the code we need to interact with our GraphQL API.
382 |
383 | 7. Time to test it. Like earlier, all we need to do is to just run "Amplify serve" which will start a local development instance that you can use.
384 | ```bash
385 | amplify serve
386 | ```
387 | 
388 |
389 | either follow the same process we used before to open the preview window, or refresh it if it's still open. Once you've logged in, you should be presented with a list of the notes we created using AppSync.
390 | 
391 |
392 | 8. To finish off this section, lets make sure that nobody else can access our notes. Click the "SIGN OUT" button at the top of the application and create a second user account using the same process we followed earlier. When you sign in, you should be presented with no notes.
393 | 
394 |
395 | But where did we define this? Well, back in our GraphQL schema, we defined the "allow: owner" parameter as shown below
396 | ```
397 | type Note @model @auth(rules: [{allow: owner}]){
398 | id: ID!
399 | note: String!
400 | }
401 | ```
402 | This automatically ensures that users can only see the notes that they created. What's not clear from our schema file is that AppSync is adding an "owner" field to every record it creates and this is what's it's checking as a part of the authentication against the API. We can confirm this by taking a look at the records, AppSync has written to the DynamoDB table.
403 | 
404 |
405 | ## Committing our Code
406 | The final step is to commit our dev branch back to our repository.
407 |
408 | 1. we can simply go a "git add ." to stage all of the files we've created ready for a commit.
409 | ```bash
410 | git add .
411 | ```
412 |
413 | 2. Next we can commit our code to the branch
414 | ```bash
415 | git commit -m "Added Authentication and API"
416 | ```
417 |
418 | 3. And then a git push, to upload it back to our repository. Note that we'll need to set the up stream endpoint.
419 | ```bash
420 | git push -u origin dev
421 | ```
422 | Our branch has now been uploaded back to our git repository ready for use.
423 |
424 | 
425 |
426 | ## Next Steps
427 | And there we go. We've added some authentication to our application and integrated a GraphQL endpoint to it. We are now ready to move onto the next step [here](/TriggerDeployment.md) where we will merge the code back to our "test" branch and trigger the automated deployment.
428 |
--------------------------------------------------------------------------------