Skip to content

Commit

Permalink
version 0.6.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Edmondson authored and cran-robot committed Nov 14, 2017
1 parent 1794215 commit 4995981
Show file tree
Hide file tree
Showing 31 changed files with 736 additions and 322 deletions.
9 changes: 5 additions & 4 deletions DESCRIPTION
@@ -1,8 +1,9 @@
Package: googleAuthR
Type: Package
Version: 0.6.1
Version: 0.6.2
Title: Authenticate and Create Google APIs
Description: Create R functions that interact with OAuth2 Google APIs easily,
Description: Create R functions that interact with OAuth2 Google APIs
<https://developers.google.com/apis-explorer/> easily,
with auto-refresh and Shiny compatibility.
Authors@R: c(person("Mark", "Edmondson",email = "m@sunholo.com",
role = c("aut", "cre"),
Expand All @@ -23,11 +24,11 @@ LazyData: true
VignetteBuilder: knitr
RoxygenNote: 6.0.1
NeedsCompilation: no
Packaged: 2017-11-12 19:48:43 UTC; mark
Packaged: 2017-11-14 21:26:42 UTC; mark
Author: Mark Edmondson [aut, cre] (0000-0002-8434-3881),
Jennifer Bryan [ctb],
Johann deBoer [ctb],
Neal Richardson [ctb]
Maintainer: Mark Edmondson <m@sunholo.com>
Repository: CRAN
Date/Publication: 2017-11-13 00:05:10 UTC
Date/Publication: 2017-11-14 21:45:36 UTC
55 changes: 30 additions & 25 deletions MD5
@@ -1,36 +1,37 @@
2335142ea99e733da9c63b4bba6cc92c *DESCRIPTION
5762e47c1f1944c5e3a40a9ca3c89e9c *DESCRIPTION
1a7dd189ced65f0849efcebc9c2be3ca *LICENSE
f5302407a3bd82e01232740bebedb58e *NAMESPACE
065337838e6ced4ef5cee383ec4944d1 *NEWS.md
51418adf04e86a24b743182f38399ffe *R/auth.R
0d15cc26aeea8286c7baa512b0ba45b6 *NAMESPACE
0f42de0e53c8b02e20c761accdf6d85d *NEWS.md
1f15ab5122f6ed43c32b19a19a35d47f *R/auth.R
31aa65d0281502a87cc21b2453572b78 *R/auto_auth.R
8ea8cafa855df89a64a6021fc22477b4 *R/batch.R
ae7532f977f13c6308a7c9ae04e81edb *R/checks.R
c0bb809acc31ec4c0efb92c2ab968837 *R/batch.R
0fbe7696cf09c7b8912400782e425868 *R/checks.R
5dacaa8d3a11144903b039586e0f8636 *R/deprecated.R
8b43e5daad8317cea84fa617eb95fef2 *R/discovery.R
f2ef72c2656914d292e8b13be1356401 *R/discovery_build.R
60fac3804327d694f75a15e31ad7f2b7 *R/discovery_utilities.R
ef129e7f705a87082fdd784fa4a1119f *R/gadget.R
426cf88eef0b645601407c7d4bfa2a1e *R/gce.R
e01f0ea43ade00c493e16ee9d7c71bd6 *R/generator.R
5795434ce6af3974f3098cd15e59a20d *R/generator.R
c8e880bcbb8481de8df859434542528e *R/googleAuthR.R
a2cdb006d035c68198eb4548a62ad86b *R/memoise.R
9ec03ab986d2dcbdfa9b08847b76608d *R/memoise.R
ef51b565063c64d1ee439d95e049638e *R/options.R
e79a78647aee8ea30ba5a3aeab145a12 *R/set_client.R
e69b9f6e7eb2d2960e7f992a525b20e5 *R/shiny.R
5840bed076148953b7c4ae41212c9d4b *R/test-helpers.R
7f7ab7eb8e70c89089089d1b90bcf9c9 *R/utility.R
f36b9c1a84f78f03b9f1a68cc52e1ec6 *README.md
bc5e8cb25d0a68cf04523efcdb50cc72 *build/vignette.rds
7c64d8ed6ca22d72b295d3f9942f2834 *inst/doc/advanced-building.Rmd
a773b4614be98d4e7a491321f06b64e8 *inst/doc/advanced-building.html
58fa181e8c4fa38001a647d07b2cc360 *build/vignette.rds
40271dae50961d64dc18d8dbbeaefb97 *inst/doc/advanced-building.Rmd
08e9fb8fe55d736df0eb172379c29cc1 *inst/doc/advanced-building.html
da206d00aaad0fecd05820cfaab12f93 *inst/doc/building.Rmd
4db48a783f3f09647cb997370f017213 *inst/doc/building.html
d8fbc23581e3ced257b2367527e959e2 *inst/doc/google-authentication-types.Rmd
fa7639f90b87095db07eb546a3a8c204 *inst/doc/google-authentication-types.html
d8a821c432f29bf2c4e65ffff46bd538 *inst/doc/building.html
541025ad476dc571c84b3a3ad9c22a65 *inst/doc/google-authentication-types.Rmd
f4dacbce6f7e17f77fccef2c4f082114 *inst/doc/google-authentication-types.html
57f58c6779eba2463a7d8a13459abb8f *inst/doc/setup.Rmd
744fa3d3072f56d28a21d0015f5415ef *inst/doc/setup.html
c5d3640c1b969159fd21f58c2de44fc1 *inst/doc/troubleshooting.Rmd
b1985df6b3bdcf7f1f4461efd6457663 *inst/doc/troubleshooting.html
cd16b0b933556639cb8dd3bf49fa8fc1 *inst/doc/setup.html
0021260c0fde674108a44024aca1d74d *inst/doc/troubleshooting.Rmd
ad982c7b64f9d32f07a36965631fdcb2 *inst/doc/troubleshooting.html
a8d0d381a2e9300734726552aaf37667 *inst/drive/listGoogleDrive/app.R
ed95cd1767f9fc4a0f96f74e541e9857 *inst/embed/server.R
8abf6dffaf053622f0e747dd75eefb97 *inst/embed/ui.R
Expand All @@ -55,7 +56,7 @@ a58ea666a12cfa44a67c272b6e60be5a *man/gar_auth_service.Rd
15997439a8d793fb7e467b577c5f653c *man/gar_auto_auth.Rd
208520c01260f1218c61deb09841fcea *man/gar_batch.Rd
e6f878708103802eba8e3df789389ef5 *man/gar_batch_walk.Rd
38a6fb20dfc1018f21b9f6588121434d *man/gar_cache_setup.Rd
53ccbe903f32b79ac165708321cfd68b *man/gar_cache_setup.Rd
b3786daff04d1041f4d2ee2b0ffb94b4 *man/gar_check_existing_token.Rd
c5f2b21cdb2248604d8311af36611f9d *man/gar_create_api_objects.Rd
50d3bcc286b1bc35d7bdbe50402f6291 *man/gar_create_api_skeleton.Rd
Expand All @@ -64,6 +65,7 @@ bda695259944040784590a0dca53b826 *man/gar_create_package.Rd
9b1a491ef479e732afd9a775f518cd16 *man/gar_discovery_apis_list.Rd
040a6e068f69e37b51d04843a5557ffc *man/gar_gce_auth.Rd
9cf44d160d7bfd74b1703d3acf8d1465 *man/gar_gce_auth_email.Rd
5cd105282aa92488e0c1c5cefe801df1 *man/gar_set_client.Rd
508819727f3d8d2063870087ba9dddad *man/gar_shiny_getAuthUrl.Rd
4ca3d2503c56f326da88e44d841e3de0 *man/gar_shiny_getToken.Rd
8cf41f61d42c18d2af797c87adb6f31f *man/gar_shiny_getUrl.Rd
Expand All @@ -81,18 +83,21 @@ c659165619e07515dc629f7a03f9e22e *man/skip_if_no_env_auth.Rd
b16645b5fa790c51c628accae098ed6d *man/token_exists.Rd
74c0ecca71dfea9b31d2f4ec02435ca7 *man/with_shiny.Rd
a204c7579a63de5e59a937603e0aee78 *tests/testthat.R
6f2382617e20bacd2d8d0a44c691b421 *tests/testthat/gdrive.oauth
28e456d35c101f285d7a097da76c7b27 *tests/testthat/googleAuthR_tests.httr-oauth
94e5da23d5c0999e8a28320b9829f512 *tests/testthat/mock/24a0d02b587bc246
0b1aceeacdab70330561fd759706384a *tests/testthat/mock/54ed4ff2b2693090
ed6fc4d3cca6b342e4f7a9d810dba4a8 *tests/testthat/mock/85460cd6cee1de4a
f999768909313d680bd98d589177025e *tests/testthat/mock/90dd9a77247710c6
587fc64f111d19eb821fd8c85daf4e15 *tests/testthat/test-batch.R
055fcd4a0b45e12cf2cfdc22b18de742 *tests/testthat/test-discovery.R
c280059abce523ba8248b75f415346e3 *tests/testthat/test-integration.R
c3818b447723cc5379bbffa1b207869a *tests/testthat/test-integration.R
010dfaedc966009b06889b22a5b2dccf *tests/testthat/test-unit.R
b4fc6ddc1cb440a310cde1c9c82748e6 *tests/www.googleapis.com/discovery/v1/apis.json
85a52503530de9a295bfd7952d78bced *tests/www.googleapis.com/discovery/v1/apis/acceleratedmobilepageurl/v1/rest.json
985d4b31c36a9da41f01d735d80b27ab *tests/www.googleapis.com/urlshortener/v1/url-bd4cc3-POST.json
7c64d8ed6ca22d72b295d3f9942f2834 *vignettes/advanced-building.Rmd
c51e740df336b388292807202ae17186 *tests/www.googleapis.com/discovery/v1/apis.json
0c315b27da71e0e1a84c3bef7f22390f *tests/www.googleapis.com/discovery/v1/apis/acceleratedmobilepageurl/v1/rest.json
a6fab8709272bfbeb460fa15682d4713 *tests/www.googleapis.com/urlshortener/v1/url-bd4cc3-POST.json
40271dae50961d64dc18d8dbbeaefb97 *vignettes/advanced-building.Rmd
da206d00aaad0fecd05820cfaab12f93 *vignettes/building.Rmd
d8fbc23581e3ced257b2367527e959e2 *vignettes/google-authentication-types.Rmd
541025ad476dc571c84b3a3ad9c22a65 *vignettes/google-authentication-types.Rmd
57f58c6779eba2463a7d8a13459abb8f *vignettes/setup.Rmd
c5d3640c1b969159fd21f58c2de44fc1 *vignettes/troubleshooting.Rmd
0021260c0fde674108a44024aca1d74d *vignettes/troubleshooting.Rmd
1 change: 1 addition & 0 deletions NAMESPACE
Expand Up @@ -21,6 +21,7 @@ export(gar_discovery_api)
export(gar_discovery_apis_list)
export(gar_gce_auth)
export(gar_gce_auth_email)
export(gar_set_client)
export(gar_token_info)
export(googleAuth)
export(googleAuthUI)
Expand Down
6 changes: 6 additions & 0 deletions NEWS.md
@@ -1,3 +1,9 @@
# googleAuthR v0.6.2

* Encoding fixed as it broke some functions downstream (#101)
* Fix batching with caching options (#106)
* Add `gar_set_client` to load client id/secret from JSON (Idea via @jennybc / @jimhester at `gargle`/`gmailr`)

# googleAuthR v0.6.1

* Fix bug with batching that didn't parse data (#103)
Expand Down
3 changes: 2 additions & 1 deletion R/auth.R
Expand Up @@ -335,6 +335,7 @@ is.token2.0 <- function(x){
#'
#' @keywords internal
#' @family authentication functions
#' @importFrom httr config
get_google_token <- function(shiny_return_token=NULL) {

if(any(which(grepl("with_mock_API", as.character(sys.calls()))))){
Expand All @@ -356,7 +357,7 @@ get_google_token <- function(shiny_return_token=NULL) {

}

httr::config(token = token)
config(token = token)

}

Expand Down
36 changes: 7 additions & 29 deletions R/batch.R
Expand Up @@ -37,10 +37,7 @@ gar_batch <- function(call_list, ...){
## call doHttrRequest with batched together functions
cached_call <- !is.null(gar_cache_get_loc())
if(cached_call){
req <- memDoBatchRequest(l,
function_list = function_list,
applyDataParseFunction = applyDataParseFunction,
...)
req <- memDoBatchRequest(l)
} else {
req <- doBatchRequest(l)
}
Expand All @@ -56,9 +53,13 @@ gar_batch <- function(call_list, ...){
}

## now only one function allowed, this is shortcut to use only first function's data_parse
applyDataParseFunction(function_list, batch_content, ...)

f <- function_list[[1]]$data_parse_function

batch_content_content <- lapply(batch_content, function(x) x$content[[1]])

## apply data parse function from function_list$data_parse_function
lapply(batch_content_content, f, ... = ...)

}


Expand Down Expand Up @@ -158,29 +159,6 @@ gar_batch_walk <- function(f,

the_data
}




#' Apply parsing function if a good response
#'
#' @param function_entry a Google API function generated by \code{gar_api_generator}
#' @param the content returned from a batch call
#'
#' @keywords internal
#' @family batch functions
#' @noRd
applyDataParseFunction <- function(function_list, batch_content, ...){

## we only need first data_parse_function as all the same
f <- function_list[[1]]$data_parse_function

batch_content_content <- lapply(batch_content, function(x) x$content[[1]])

## apply data parse function from function_list$data_parse_function
lapply(batch_content_content, f, ... = ...)

}


#' Parse batch request
Expand Down
2 changes: 1 addition & 1 deletion R/checks.R
Expand Up @@ -37,7 +37,7 @@ gar_check_existing_token <- function(token = Authentication$public_fields$token)
}

is.different <- function(token_element, option_name){
if(!any(token_element %in% getOption(option_name))){
if(!all(token_element %in% getOption(option_name))){
myMessage(sprintf("Token %s != getOption('%s') \n#>Token: %s \n#>Option: %s\n",
deparse(substitute(token_element)),
option_name,
Expand Down
6 changes: 4 additions & 2 deletions R/generator.R
Expand Up @@ -94,10 +94,12 @@ gar_api_generator <- function(baseURI,
}

if(!is.null(pars_args)){
## it has to be a character for pars
pars_args <- vapply(pars_args, as.character, character(1))
pars <-
paste(names(pars_args),
vapply(pars_args, URLencode, reserved = TRUE, names(pars_args)),
sep='=', collapse='&')
vapply(pars_args, URLencode, reserved = TRUE, character(1)),
sep='=', collapse='&')

}

Expand Down
15 changes: 6 additions & 9 deletions R/memoise.R
@@ -1,7 +1,9 @@
# cache global
.gar_cache <- new.env(parent = emptyenv())
.gar_cache$cache <- NULL # what type of caching
.gar_cache$invalid <- function(req){req$status_code == 200} # whether to invalidate when passed req

# whether to invalidate when passed req
.gar_cache$invalid <- function(req){tryCatch(req$status_code == 200, error = function(x) FALSE)}



Expand Down Expand Up @@ -87,7 +89,7 @@ gar_cache_empty <- function(){
#' @export
#' @family cache functions
gar_cache_setup <- function(mcache=memoise::cache_memory(),
invalid_func = function(req){req$status_code == 200}){
invalid_func = function(req){tryCatch(req$status_code == 200, error = function(x) FALSE)}){

if(is.null(mcache)){
return(gar_cache_empty())
Expand Down Expand Up @@ -155,10 +157,7 @@ memDoHttrRequest <- function(req_url,
#' @noRd
#' @import memoise
#' @family cache functions
memDoBatchRequest <- function(l,
function_list,
applyDataParseFunction,
...){
memDoBatchRequest <- function(l){

cachedBatchedRequest <- memoise(doBatchRequest, cache = gar_cache_get_loc())

Expand All @@ -172,13 +171,11 @@ memDoBatchRequest <- function(l,

req <- cachedBatchedRequest(l)

batch_content <- parseBatchResponse(req)
parsed_batch_content <- lapply(function_list, applyDataParseFunction, batch_content, ...)
## check request against cache_function to see whether to cache result is TRUE
cache_function <- .gar_cache$invalid

cache_result <- tryCatch({
cache_function(parsed_batch_content)
cache_function(req)
}, error = function(ex){
warning("Error in batch cache function", call. = FALSE)
FALSE
Expand Down
73 changes: 73 additions & 0 deletions R/set_client.R
@@ -0,0 +1,73 @@
#' Setup the clientId, clientSecret and scopes
#'
#' Help setup the client ID and secret with the OAuth 2.0 clientID.
#' Do not confuse with Service account keys.
#'
#' @param json The file location of an OAuth 2.0 client ID json file
#' @param scopes A character vector of scopes to set
#'
#' @details
#'
#' This function helps set the \code{options(googleAuthR.client_id)},
#' \code{options(googleAuthR.client_secret)} and
#' \code{options(googleAuthR.scopes.selected)} for you.
#' Note that if you authenticate with a cache token with different values it
#' will overwrite them.
#'
#' For successful authentication, the API scopes can be browsed via the
#' googleAuthR RStudio addin or the Google API documentation.
#'
#' Do not confuse this JSON file with the service account keys, that are
#' used to authenticate a service email. This JSON only sets up which
#' app you are going to authenticate with - use \link{gar_auth_service} with
#' the Service account keys JSON to perform the actual authentication.
#'
#' By default the JSON file will be looked for in the location specified by the
#' \code{"GAR_CLIENT_JSON"} environment argument.
#'
#' @author Idea via @jennybc and @jimhester from \code{gargle and gmailr} libraries.
#'
#' @return The \code{project-id} the app has been set for
#'
#' @seealso \url{https://console.cloud.google.com/apis/credentials}
#'
#' @export
#'
#' @examples
#' \dontrun{
#'
#' gar_set_client("google-client.json", scopes = "http://www.googleapis.com/auth/webmasters")
#' gar_auth_service("google-service-auth.json")
#' }
#'
#' @importFrom jsonlite fromJSON
#' @import assertthat
gar_set_client <- function(json = Sys.getenv("GAR_CLIENT_JSON"),
scopes = NULL){

assert_that(is.readable(json))

the_json <- fromJSON(json)

if(is.null(the_json$installed)){
stop("$installed not found in JSON - have you downloaded the correct JSON file?
(Service account client, not Service Account Keys)")
}

if(!is.null(scopes)){
assert_that(is.character(scopes))
options(googleAuthR.scopes.selected = scopes)
}

options(googleAuthR.client_id = the_json$installed$client_id,
googleAuthR.client_secret = the_json$installed$client_secret)

myMessage("\noptions(googleAuthR.scopes.selected=c('",
paste(getOption("googleAuthR.scopes.selected"), collapse = "','"),"'))",
"\noptions(googleAuthR.client_id='", getOption("googleAuthR.client_id"),"')",
"\noptions(googleAuthR.client_secret=' ", getOption("googleAuthR.client_secret"),"')",
level = 3)

the_json$installed$project_id

}
Binary file modified build/vignette.rds
Binary file not shown.
22 changes: 20 additions & 2 deletions inst/doc/advanced-building.Rmd
Expand Up @@ -231,9 +231,27 @@ shorten_url_cache("http://blahblah.com")

#### Batching and caching

If you are caching a batched call, your cache invalidation function will need to take account that it will recieve a list of responses, each parsed with their respective parsing function, that was passed via the `data_parse_function` argument.
If you are caching a batched call, your cache invalidation function will need to take account that it will recieve a response which is a `multipart/mixed; boundary=batch_{random_string}` as its content-type header. This response will need to be parsed into JSON first, before applying your data parsing functions and/or deciding to cache. To get you started here is a cache function:

This differs from the normal caching which deals with the raw response, but batch responses are raw bytes so its been judged easier to deal with.

```r
batched_caching <- function(req){

## if a batched response
if(grepl(""multipart/mixed; boundary=batch",req$headers)){
## find content that indicates a successful request ('kind:analytics#gaData')
is_ga <- grepl('"kind":"analytics#gaData', (httr::content(req, as = "text", encoding = "UTF-8")))
if(is_ga){
## is a response you want, cache me
return(TRUE)
}
}

FALSE
}

```

### Using caching

Expand Down

0 comments on commit 4995981

Please sign in to comment.