Skip to content

Commit

Permalink
Merge pull request #13 from kennedymwavu/11-docs-explain-usage-of-exa…
Browse files Browse the repository at this point in the history
…mple-09_goals

docs: explain usage of example 09 goals
  • Loading branch information
kennedymwavu authored Jul 21, 2024
2 parents 454f367 + 58427ee commit 37795d9
Show file tree
Hide file tree
Showing 29 changed files with 687 additions and 42 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions 09_goals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Here's what's covered:

## Run API

1. `cd` into the `09_goals/backend/` dir:
1. `cd` into the `09_goals/` dir:

```bash
cd 09_goals/backend/
cd 09_goals/
```

1. Fire up R and restore package dependencies:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ <h5 class="no-anchor card-title listing-title">
</div>
</a>
</div>
<div class="g-col-1" data-index="9" data-categories="09_goals" data-listing-date-sort="1720558800000" data-listing-file-modified-sort="1721079945606" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="2" data-listing-word-count-sort="258">
<div class="g-col-1" data-index="9" data-categories="09_goals" data-listing-date-sort="1720558800000" data-listing-file-modified-sort="1721531177242" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="7" data-listing-word-count-sort="1256">
<a href="./posts/09_goals/index.html" class="quarto-grid-link">
<div class="quarto-grid-item card h-100 card-left">
<div class="card-body post-contents">
Expand Down Expand Up @@ -469,7 +469,7 @@ <h5 class="no-anchor card-title listing-title">
</div>
</a>
</div>
<div class="g-col-1" data-index="11" data-categories="11_csv_xlsx_upload" data-listing-date-sort="1721336400000" data-listing-file-modified-sort="1721346735647" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="7" data-listing-word-count-sort="1235">
<div class="g-col-1" data-index="11" data-categories="11_csv_xlsx_upload" data-listing-date-sort="1721336400000" data-listing-file-modified-sort="1721348353455" data-listing-date-modified-sort="NaN" data-listing-reading-time-sort="7" data-listing-word-count-sort="1235">
<a href="./posts/11_csv_xlsx_upload/index.html" class="quarto-grid-link">
<div class="quarto-grid-item card h-100 card-left">
<div class="card-body post-contents">
Expand Down
320 changes: 310 additions & 10 deletions docs/posts/09_goals/index.html

Large diffs are not rendered by default.

30 changes: 8 additions & 22 deletions docs/search.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,32 +385,18 @@
"text": "An installation of the community edition of MongoDB\nThe mongolite R pkg"
},
{
"objectID": "posts/09_goals/index.html#prerequisites",
"href": "posts/09_goals/index.html#prerequisites",
"objectID": "posts/09_goals/index.html#apiusers",
"href": "posts/09_goals/index.html#apiusers",
"title": "09: goals",
"section": "",
"text": "An installation of the community edition of MongoDB\nThe mongolite R pkg"
},
{
"objectID": "posts/09_goals/index.html#run-app",
"href": "posts/09_goals/index.html#run-app",
"title": "09: goals",
"section": "Run app",
"text": "Run app\n\ncd into the 09_goals/backend/ dir:\ncd 09_goals/backend/\nFire up R:\nR\nRestore package dependencies:\nrenv::restore()\nOnce done, exit R.\nserver.R is the entry point. To start the app, run this on the terminal:\nRscript server.R"
},
{
"objectID": "posts/09_goals/index.html#explanation",
"href": "posts/09_goals/index.html#explanation",
"title": "09: goals",
"section": "Explanation",
"text": "Explanation\nThis app starts a server and listens on port 5000 for connections.\nIn this example, we build a CRUD application backend: Goals.\nHere are the defined routes:\n\n/api:\n\nGET /goals: Get all user goals\nPOST /goals: Create a goal\nPUT /goals/:id: Update a goal\nDELETE /goals/:id: Delete a goal\n/users:\n\nPOST /: Register new user\nPOST /login: Login user\nGET /me: Get user data\n\n\n\nYou will be able to Create, Read, Update & Delete Goals.\nHere’s what’s covered:\n\nAmbiorix + MongoDB\nWorking with middleware:\n\nAuth middleware: You will learn how you can use JSON Web Tokens (JWT) to protect routes\nError handling middleware"
"section": "/api/users*",
"text": "/api/users*\n\nRegisterLoginDetails\n\n\nSince the API requires JWT auth, you first need to create an account. To do that, make a POST request to /api/users:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# registration details:\nuser_details &lt;- list(\n name = \"mwavu\",\n email = \"[email protected]\",\n password = \"test123\"\n)\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/users\") |&gt;\n req_body_multipart(!!!user_details)\n\n# use `tryCatch()` in case an error occurs while performing the request:\ntryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nIf that’s successful, you get back a list containing a named list of 4 items: - _id - name - email - token: A JWT token\nHere is an example:\n[[1]]\n[[1]]$`_id`\n[1] \"669c6ee4ddfa7be6a10f07e1\"\n\n[[1]]$name\n[1] \"mwavu\"\n\n[[1]]$email\n[1] \"[email protected]\"\n\n[[1]]$token\n[1] \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY0MzcsImlhdCI6MTcyMTUyODAzNywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.ebhkSXwJChW4iqLDRRoLOGrX3hb7NevRW4vZncjm5MY\"\n\n\nTo login a user, we make a POST request to /api/users/login:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# login details:\nuser_details &lt;- list(\n email = \"[email protected]\",\n password = \"test123\"\n)\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/users/login\") |&gt;\n req_body_multipart(!!!user_details)\n\n# use `tryCatch()` in case an error occurs while performing the request:\ntryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nAgain, on successful login, you get back a list containing a named list of 4 items:\n\n_id\nname\nemail\ntoken: A JWT token\n\n[[1]]\n[[1]]$`_id`\n[1] \"669c6ee4ddfa7be6a10f07e1\"\n\n[[1]]$name\n[1] \"mwavu\"\n\n[[1]]$email\n[1] \"[email protected]\"\n\n[[1]]$token\n[1] \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY5NDcsImlhdCI6MTcyMTUyODU0NywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.rpSOL0LynYm2BBP60Ikpz-GNIY6mR_ZKKzH9Tai2IS4\"\n\n\nTo get details of a specific user, you need the JWT token returned during register or login. The token is verified by the auth middleware.\nMake a GET request to /api/users/me and include the JWT as an auth bearer token:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# the JWT token from signup/login:\ntoken &lt;- \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY5NDcsImlhdCI6MTcyMTUyODU0NywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.rpSOL0LynYm2BBP60Ikpz-GNIY6mR_ZKKzH9Tai2IS4\"\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/users/me\") |&gt;\n req_auth_bearer_token(token = token)\n\n# use `tryCatch()` in case an error occurs while performing the request:\ntryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nIf successful, that returns a named list of 3:\n\n_id\nname\nemail"
},
{
"objectID": "posts/09_goals/index.html#live-reloading",
"href": "posts/09_goals/index.html#live-reloading",
"objectID": "posts/09_goals/index.html#apigoals",
"href": "posts/09_goals/index.html#apigoals",
"title": "09: goals",
"section": "Live reloading",
"text": "Live reloading\nSee how you can enable ✨live reloading✨."
"section": "/api/goals*",
"text": "/api/goals*\nEvery route in /api/goals* is protected, meaning they can only be accessed by an authenticated user. Also, each user only has access to the goals they set, not anyone elses.\nIn other words, send the JWT as an auth bearer token in your requests.\n\nCreateReadUpdateDelete\n\n\nLet’s set a goal by sending a POST request to /api/goals:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# the JWT token from signup/login:\ntoken &lt;- \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY5NDcsImlhdCI6MTcyMTUyODU0NywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.rpSOL0LynYm2BBP60Ikpz-GNIY6mR_ZKKzH9Tai2IS4\"\n\n# your goal:\ntext &lt;- \"Learn Rust\"\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/goals\") |&gt;\n req_auth_bearer_token(token = token) |&gt;\n req_body_multipart(text = text)\n\n# use `tryCatch()` in case an error occurs while performing the request:\ntryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nIf successful, that should return a list containing a named list of 3:\n\n_id\nuser_id\ntext\n\nFor example:\n[[1]]\n[[1]]$`_id`\n[1] \"669c74e6ddfa7be6a10f07e2\"\n\n[[1]]$user_id\n[1] \"669c6ee4ddfa7be6a10f07e1\"\n\n[[1]]$text\n[1] \"Learn Rust\"\n\n\nTo get all goals a user has set, send a GET request to /api/goals:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# the JWT token from signup/login:\ntoken &lt;- \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY5NDcsImlhdCI6MTcyMTUyODU0NywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.rpSOL0LynYm2BBP60Ikpz-GNIY6mR_ZKKzH9Tai2IS4\"\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/goals\") |&gt;\n req_auth_bearer_token(token = token)\n\n# use `tryCatch()` in case an error occurs while performing the request:\nres &lt;- tryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nIf successful, that should return a list of named lists. Each of the nested lists has 2 items:\n\n_id: Id of the goal\ntext: The goal\n\nFor example:\nstr(res)\n# List of 1\n# $ :List of 2\n# ..$ _id : chr \"669c74e6ddfa7be6a10f07e2\"\n# ..$ text: chr \"Learn Rust\"\n\n\nTo update a goal, send a PUT request to /api/users/:id:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# the JWT token from signup/login:\ntoken &lt;- \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY5NDcsImlhdCI6MTcyMTUyODU0NywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.rpSOL0LynYm2BBP60Ikpz-GNIY6mR_ZKKzH9Tai2IS4\"\n\nupdated_goal &lt;- \"Learn Rust & Postgres\"\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/goals/669c74e6ddfa7be6a10f07e2\") |&gt;\n req_auth_bearer_token(token = token) |&gt;\n req_method(method = \"PUT\") |&gt;\n req_body_multipart(text = updated_goal)\n\n# use `tryCatch()` in case an error occurs while performing the request:\nres &lt;- tryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nIf successful, you should get back a named list of 2:\nstr(res)\n# List of 2\n# $ msg : chr \"Goal updated successfully\"\n# $ goal:List of 1\n# ..$ :List of 2\n# .. ..$ _id : chr \"669c74e6ddfa7be6a10f07e2\"\n# .. ..$ text: chr \"Learn Rust & Postgres\"\n\n\nTo delete a goal, send a, well, DELETE request to /api/goals/:id:\nbase_url &lt;- \"http://127.0.0.1:5000\"\n\n# the JWT token from signup/login:\ntoken &lt;- \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MjQyMDY5NDcsImlhdCI6MTcyMTUyODU0NywidXNlcl9pZCI6IjY2OWM2ZWU0ZGRmYTdiZTZhMTBmMDdlMSJ9.rpSOL0LynYm2BBP60Ikpz-GNIY6mR_ZKKzH9Tai2IS4\"\n\nreq &lt;- request(base_url = base_url) |&gt;\n req_url_path(\"/api/goals/669c74e6ddfa7be6a10f07e2\") |&gt;\n req_auth_bearer_token(token = token) |&gt;\n req_method(method = \"DELETE\")\n\n# use `tryCatch()` in case an error occurs while performing the request:\nres &lt;- tryCatch(\n expr = req |&gt;\n req_perform() |&gt;\n resp_body_json(),\n error = \\(e) {\n print(\"An error occurred!\")\n error &lt;- last_response() |&gt; resp_body_json()\n print(error)\n }\n)\nIf successful, you will again get back a named list of 2:\nstr(res)\n# List of 2\n# $ msg : chr \"Goal deleted successfully\"\n# $ goal:List of 1\n# ..$ :List of 2\n# .. ..$ _id : chr \"669c74e6ddfa7be6a10f07e2\"\n# .. ..$ text: chr \"Learn Rust & Postgres\""
},
{
"objectID": "posts/07_dynamic_rendering/index.html",
Expand Down
Loading

0 comments on commit 37795d9

Please sign in to comment.