Skip to content

Commit

Permalink
Merge pull request #5 from ScotGovAnalysis/vignettes
Browse files Browse the repository at this point in the history
Add vignettes for authentication and example workflow
  • Loading branch information
alice-hannah authored May 17, 2024
2 parents 57e04be + f58e876 commit 91431e3
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 2 deletions.
23 changes: 23 additions & 0 deletions R/random_uuid.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#' Generate random UUID
#'
#' @param seed Integer to set seed for random sampling. Default value is NULL.
#'
#' @return A single character value in the format of eight blocks of four
#' letters/integers separated by dashes.
#'
#' @noRd

random_uuid <- function(seed = NULL) {

options <- c(letters, 0:9)

# There should be equal probability of a letter or integer being sampled
prob_weights <- c(rep(1/26, 26), rep(1/10, 10))

set.seed(seed)

replicate(8, paste0(sample(options, 4, replace = TRUE, prob = prob_weights),
collapse = "")) |>
paste0(collapse = "-")

}
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

<!-- badges: end -->

objectiveR is an R package wrapper for the [Objective Connect API](https://secure.objectiveconnect.co.uk/publicapi/1/swagger-ui/index.html?configUrl=/publicapi/1/v3/api-docs/swagger-config#/).

objectiveR aims to provide a convenient method of interacting with [Objective Connect](https://secure.objectiveconnect.co.uk) using R, making use of the [Objective Connect API](https://secure.objectiveconnect.co.uk/publicapi/1/swagger-ui/index.html).

## Installation

Expand Down
5 changes: 5 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
url: https://scotgovanalysis.github.io/objectiveR

development:
mode: auto

template:
bootstrap: 5
bslib:
base_font: {google: "Roboto"}

home:
sidebar:
Expand Down
34 changes: 34 additions & 0 deletions tests/testthat/test-random_uuid.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

test_that("Single character value returned", {

expect_type(random_uuid(), "character")

expect_length(random_uuid(), 1)

})

test_that("Returned value format correct", {

pattern_exp <- paste(rep("[a-z0-9]{4}", 8), collapse = "-")

expect_true(grepl(pattern = pattern_exp, x = random_uuid()))

})

test_that("Not setting seed returns random value", {

sample_5 <- replicate(5, random_uuid())

expect_true(length(unique(sample_5)) == 5)

})

test_that("Setting seed returns consistent value", {

expect_identical(
random_uuid(1234),
random_uuid(1234)
)

})

Binary file added vignettes/auth_prompt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions vignettes/authentication.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: "Authentication"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Authentication}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
eval = FALSE
)
```

## How authentication works

The first time you send a request, the API requires your Objective Connect user email address and password to authenticate.

Each successful response from the API includes a token. This token can then be used to authenticate subsequent requests in your session, negating the need to repeatedly supply your email address and password.

The rest of this article details how to manage authentication when using the `objectiveR` package.


## First request

You will need your Objective Connect user email address and password to make a first request to the API. These can be provided in two ways.

### R Environment variables

Add two variables to your `.Renviron` file to define your email address and password.

* Open your `.Renviron` file to edit:

```{r open_renviron}
usethis::edit_r_environ()
```

* Add two variables as follows:

```{r add_vars}
OBJECTIVER_USR = "XXX"
OBJECTIVER_PWD = "XXX"
```

* Save and close the `.Renviron` file.

* To check this has worked as expected, first restart your R session then:

```{r check_vars}
Sys.getenv("OBJECTIVER_USR")
Sys.getenv("OBJECTIVER_PWD")
```

Your credentials should be printed in the console.

Note: For this reason, it is important not to save your R session workspace on close as your console may contain your Objective Connect credentials.

The benefit of this method is that you can leave this information in your `.Renviron` file and `objectiveR` will automatically find them here each time you use the package.


### Supply credentials when prompted

If you don't have these variables defined in your `.Renviron` file, `objectiveR` will prompt you to supply them if you're working in an interactive session.

<br>

```{r}
#| eval: true
#| echo: false
#| fig-align: "center"
#| fig-alt: >
#| A small pop-up window with prompt 'Enter email registered with Objective
#| Connect' followed by a text input box and buttons to select 'OK' or
#| 'Cancel'.
knitr::include_graphics("auth_prompt.png", dpi = "retina")
```


## Subsequent requests

Each successful API response includes a token that can be used for subsequent requests. `objectiveR` functions automatically parse this token from the API response and store it in your R session's global environment.

Where this object exists, `objectiveR` will automatically use it to authenticate subsequent requests.

If this object doesn't exist, `objectiveR` will resort to using your username and password, as it did for your [first request](#first-request).

143 changes: 143 additions & 0 deletions vignettes/objectiveR.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: "Introduction to objectiveR"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Introduction to objectiveR}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
eval = FALSE
)
```

objectiveR aims to provide a convenient method of interacting with [Objective Connect](https://secure.objectiveconnect.co.uk) using R, making use of the [Objective Connect API](https://secure.objectiveconnect.co.uk/publicapi/1/swagger-ui/index.html).

This article demonstrates a simple workflow for using the package, with the ultimate aim of downloading or uploading a file to an Objective Connect workspace.

Start by loading the package in your R session:

```{r setup}
library(objectiveR)
```


## Universally Unique Identifiers

It is useful to be aware that everything on Objective Connect is associated with a Universally Unique Identifier (UUID). This includes users, workgroups, workspaces, participants in a workspace and assets in a workspace.

Objective Connect UUIDs take the form of a string of eight chunks of four lower case letters and numbers, separated by dashes. For example:

```
84op-9qdu-c692-t4z1-wa4z-h9k3-8454-i71f
```

Use of the API and the objectiveR package depends on these UUIDs. UUIDs are mostly findable using the functions in objectiveR (as demonstrated in this article), however you can often also find relevant UUIDs in the webpage URLs. For example, this is an example URL when viewing a workspace:

```
https://secure.objectiveconnect.co.uk/share/2vo2-dd3s-1nn9-y20r-b906-u4s2-
7134-b352?workgroupUuid=2j47-ff38-lcgg-mnis-3vq8-9536-9jfp-oy44
```

The UUID for the workspace is `2vo2-dd3s-1nn9-y20r-b906-u4s2-7134-b352` and the UUID for the workgroup is `2j47-ff38-lcgg-mnis-3vq8-9536-9jfp-oy44`.


## Test your authentication

To interact with the Objective Connect API, you must provide valid authentication. This is explained in more detail in `vignette("authentication")`.

It might be a good idea to test your authentication, especially if it's your first time using the package. There is no specific function for this, but the following simple function to get your own user ID requires no input and is an easy way to test that you can get a successful response from the API.

```{r user}
me <- my_user_id()
```


## Workspaces

To see workspaces you are a member of:

```{r workspaces}
workspaces <- my_workspaces()
```

This returns a data frame with a row for each workspace you are a member of. Among other things, there will be a column containing the workspace name and another containing the workspace UUID. For example:

```{r workspaces-output, eval = TRUE, echo = FALSE}
data.frame(
workspace_name = c("Project 1", "Project 2"),
workspace_uuid = sapply(1:2, objectiveR:::random_uuid)
)
```


## Assets

Maybe you would like to download a file from one of your workspaces. In Objective Connect, files are also known as 'assets'. To download an asset, you'll need its UUID.

Use the workspace UUID from `workspaces` to get a data frame of assets in the workspace:

```{r assets}
assets <- workspace_assets("84op-9qdu-c692-t4z1-wa4z-h9k3-8454-i71f")
```

This returns a data frame with a row for each asset in the workspace. Among other things, there will be a column containing the asset name and another containing the asset UUID.

```{r assets-output, eval = TRUE, echo = FALSE}
data.frame(
uuid = sapply(3:4, objectiveR:::random_uuid),
name = c("asset1", "asset2")
)
```


## Download file

To download a document, use its UUID and the file path of the folder you'd like the downloaded file to be saved to:

```{r download}
download_file(document_uuid = "2j47-ff38-lcgg-mnis-3vq8-9536-9jfp-oy44",
folder = here::here("data"))
```

This function doesn't return anything but will display a message in the R console to indicate the download has been a success and to confirm the location of the file:

```{r download-output, eval = TRUE, echo = FALSE, message = TRUE}
cli::cli_alert_success(
"File downloaded: project-1/data/file1.csv."
)
```


## Upload file

To upload a file to a workspace, use the UUID of the workspace and the file path of the file to upload:

```{r upload}
new_document(here::here("data", "file2.csv"),
workspace_uuid = "84op-9qdu-c692-t4z1-wa4z-h9k3-8454-i71f")
```

This function doesn't return anything but will display a message in the R console to indicate the upload has been a success and to confirm the name of the file.

```{r upload-output, eval = TRUE, echo = FALSE, message = TRUE}
cli::cli_alert_success(
"New document created: file2.csv."
)
```

Now, if you rerun the previous step to get a data frame of workspace assets, you should see an additional row for the file you've just uploaded.

```{r assets2}
assets <- workspace_assets("84op-9qdu-c692-t4z1-wa4z-h9k3-8454-i71f")
```

```{r assets2-output, eval = TRUE, echo = FALSE}
data.frame(
uuid = sapply(3:5, objectiveR:::random_uuid),
name = c("Asset 1", "Asset 2", "file2")
)
```

0 comments on commit 91431e3

Please sign in to comment.