From 1d546f157af244e06195a3c7ac4b7787b255a2d0 Mon Sep 17 00:00:00 2001 From: David Blodgett Date: Wed, 16 Apr 2025 09:41:30 -0500 Subject: [PATCH 1/4] pull username from token_stache directory --- R/authenticate_sb.R | 20 +++++++++++--- man/initialize_sciencebase_session.Rd | 3 ++- tests/testthat/setup_utils.R | 13 +++++++++ tests/testthat/test-auth-item.R | 6 +---- tests/testthat/test-auth-item2.R | 6 +---- tests/testthat/test-auth-rm.R | 8 ++---- tests/testthat/test-auth.R | 38 +++------------------------ 7 files changed, 40 insertions(+), 54 deletions(-) create mode 100644 tests/testthat/setup_utils.R diff --git a/R/authenticate_sb.R b/R/authenticate_sb.R index c30d231..385620e 100644 --- a/R/authenticate_sb.R +++ b/R/authenticate_sb.R @@ -98,6 +98,17 @@ get_username <- function(username = NULL) { return(username) } + username_file <- file.path(dirname(token_stache_path()), "username") + + if(file.exists(username_file)) { + username <- readLines(username_file, 1) + } + + if(username != "") { + pkg.env$username <- username + return(username) + } + if(interactive()) { username = readline('Please enter your username:') @@ -148,7 +159,9 @@ set_keycloak_env <- function(token_resp) { #' If the token text is provided as input, no popup prompt will be raised. #' #' @param username email address of sciencebase user. Will be retrieved from the -#' `sb_user` environment variable if set. A prompt will be raised if not provided. +#' `sb_user` environment variable if set or retrieved from a `username` file cached +#' in the `token_text` directory. A prompt will be raised if not provided. +#' #' @export #' initialize_sciencebase_session <- function(username = NULL, token_text = NULL) { @@ -184,7 +197,7 @@ initialize_sciencebase_session <- function(username = NULL, token_text = NULL) { worked <- try(initialize_keycloack_env(token_text)) if(!inherits(worked, "try-error")) { - stache_token(token_text) + stache_token(username, token_text) return(invisible(TRUE)) } else { return(invisible(FALSE)) @@ -242,9 +255,10 @@ token_stache_path <- function(dir = NULL) { } -stache_token <- function(token_text) { +stache_token <- function(username, token_text) { dir.create(dirname(token_stache_path()), recursive = TRUE, showWarnings = FALSE) + write(username, file = file.path(dirname(token_stache_path()), "username")) write(token_text, file = token_stache_path()) } diff --git a/man/initialize_sciencebase_session.Rd b/man/initialize_sciencebase_session.Rd index 4580006..255cfad 100644 --- a/man/initialize_sciencebase_session.Rd +++ b/man/initialize_sciencebase_session.Rd @@ -8,7 +8,8 @@ initialize_sciencebase_session(username = NULL, token_text = NULL) } \arguments{ \item{username}{email address of sciencebase user. Will be retrieved from the -`sb_user` environment variable if set. A prompt will be raised if not provided.} +`sb_user` environment variable if set or retrieved from a `username` file cached +in the `token_text` directory. A prompt will be raised if not provided.} \item{token_text}{character json formatted token text. `token_text` is stashed in \link[tools]{R_user_dir} and does not need to be re-entered unless diff --git a/tests/testthat/setup_utils.R b/tests/testthat/setup_utils.R new file mode 100644 index 0000000..fcb1a0f --- /dev/null +++ b/tests/testthat/setup_utils.R @@ -0,0 +1,13 @@ +try_auth <- function() { + skipit <- TRUE + + user <- try(sbtools:::get_username()) + + if(!inherits(user, "try-error")) { + skipit <- !initialize_sciencebase_session() + } + + if(skipit) { + skip("Authenticated tests skipped due to lack of login info") + } +} diff --git a/tests/testthat/test-auth-item.R b/tests/testthat/test-auth-item.R index 575d370..9de6966 100644 --- a/tests/testthat/test-auth-item.R +++ b/tests/testthat/test-auth-item.R @@ -1,11 +1,7 @@ test_that("item creation, identifiers, and file upload works", { skip_on_cran() - if(is.na(Sys.getenv("sb_user", unset=NA))){ - skip("Authenticated tests skipped due to lack of login info") - } - - initialize_sciencebase_session() + try_auth() on.exit(sbtools:::clean_session()) diff --git a/tests/testthat/test-auth-item2.R b/tests/testthat/test-auth-item2.R index a2e89df..1d34da7 100644 --- a/tests/testthat/test-auth-item2.R +++ b/tests/testthat/test-auth-item2.R @@ -1,11 +1,7 @@ test_that("items", { skip_on_cran() - if(is.na(Sys.getenv("sb_user", unset=NA))){ - skip("Authenticated tests skipped due to lack of login info") - } - - initialize_sciencebase_session() + try_auth() on.exit(sbtools:::clean_session()) diff --git a/tests/testthat/test-auth-rm.R b/tests/testthat/test-auth-rm.R index a11827c..6a02b4a 100644 --- a/tests/testthat/test-auth-rm.R +++ b/tests/testthat/test-auth-rm.R @@ -2,12 +2,8 @@ test_that("Test that surgical item rm", { skip_on_cran() - if(is.na(Sys.getenv("sb_user", unset=NA))){ - skip("Authenticated tests skipped due to lack of login info") - } - - initialize_sciencebase_session() - + try_auth() + on.exit(sbtools:::clean_session()) item = item_create(title="file add rm test item") diff --git a/tests/testthat/test-auth.R b/tests/testthat/test-auth.R index 492d752..f2cea20 100644 --- a/tests/testthat/test-auth.R +++ b/tests/testthat/test-auth.R @@ -1,39 +1,8 @@ -user <- Sys.getenv("sb_user", unset=NA) - -test_that("not_logged in tests", { - skip("retired pattern") - expect_error(sbtools:::get_access_token(), "no token found, must call authenticate_sb()") - expect_error(sbtools:::get_refresh_token(), "no token found, must call authenticate_sb()") - - if(!interactive()) - expect_error(authenticate_sb(), 'username required for authentication') - - if(!interactive()) - expect_error(authenticate_sb("dummy"), 'No password supplied to authenticate_sciencebase in a non-interactive session.') -}) - -test_that("authenticate_sb errors", { - skip("retired pattern") - - if(is.na(user)){ - skip("Authenticated tests skipped due to lack of login info") - } - - keyring::key_set_with_value("sciencebase", "test-user@usgs.gov", "broken") - - on.exit(keyring::key_delete("sciencebase", "test-user@usgs.gov")) - - expect_error(authenticate_sb("test-user@usgs.gov"), - "Sciencebase login failed with stored password?") - -}) test_that("initialize_scienbase_session login results in valid session and renew works", { skip_on_cran() - if(is.na(Sys.getenv("sb_user", unset=NA))){ - skip("Authenticated tests skipped due to lack of login info") - } + try_auth() initialize_sciencebase_session() @@ -67,14 +36,15 @@ test_that("login results in valid session and renew works (new)", { sbtools:::clean_session() token <- sbtools:::grab_token() + user <- try(sbtools:::get_username()) - if(token == "" | is.na(Sys.getenv("sb_user"))){ + if(token == "" | inherits(user, "try-error")) { skip("Authenticated tests skipped due to lack of login info") } unlink(sbtools:::token_stache_path(), force = TRUE) - if(!initialize_sciencebase_session(Sys.getenv("sb_user"), token)) { + if(!initialize_sciencebase_session(user, token)) { sbtools:::clean_session() skip("token didn't work, refresh it?") From e4bf7005e2e0bd4f2a4ccceced4b662b01799e4d Mon Sep 17 00:00:00 2001 From: David Blodgett Date: Wed, 16 Apr 2025 10:34:27 -0500 Subject: [PATCH 2/4] export additional functions --- DESCRIPTION | 2 +- NAMESPACE | 3 ++ NEWS.md | 3 ++ R/authenticate_sb.R | 57 +++++++++++++++++++++++++++--------- _pkgdown.yml | 3 ++ man/authenticate_sb.Rd | 5 +++- man/get_cached_token.Rd | 14 +++++++++ man/get_username.Rd | 23 +++++++++++++++ man/token_stache_path.Rd | 21 +++++++++++++ tests/testthat/setup_utils.R | 2 +- tests/testthat/test-auth.R | 4 +-- 11 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 man/get_cached_token.Rd create mode 100644 man/get_username.Rd create mode 100644 man/token_stache_path.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 778a186..444685c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -37,6 +37,6 @@ URL: https://github.com/DOI-USGS/sbtools, https://doi-usgs.github.io/sbtools/ BugReports: https://github.com/DOI-USGS/sbtools/issues RoxygenNote: 7.3.2 VignetteBuilder: knitr -Config/testthat/parallel: true +Config/testthat/parallel: false Config/testthat/edition: 3 Encoding: UTF-8 diff --git a/NAMESPACE b/NAMESPACE index 9eac835..9b08d19 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,6 +10,8 @@ export(as.sbitem) export(authenticate_sb) export(current_session) export(folder_create) +export(get_cached_token) +export(get_username) export(identifier_exists) export(initialize_sciencebase_session) export(is.sbitem) @@ -54,6 +56,7 @@ export(session_expired) export(session_renew) export(session_validate) export(set_endpoint) +export(token_stache_path) export(user_id) import(httr) import(jsonlite) diff --git a/NEWS.md b/NEWS.md index 829d636..9cf8e20 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,9 @@ - removed `items_create()`, `items_upsert()`, and `items_update()` as they are no longer supported by sciencebase. - Fixed bugs related to sciencebase updates. +- added `get_username()` as exported function. +- added `get_cached_token()` as exported function. +- added `token_stache_path()` as exported function. # version 1.3.2 diff --git a/R/authenticate_sb.R b/R/authenticate_sb.R index 385620e..1ca0922 100644 --- a/R/authenticate_sb.R +++ b/R/authenticate_sb.R @@ -1,5 +1,7 @@ -#' Authenticate to SB for subsequent calls +#' Authenticate to SB for subsequent calls [DEPRECATED] +#' +#' THIS AUTHENTICATION METHOD NO LONGER WORKS FOR INDIVIDUAL LOGIN SESSIONS #' #' This connects to SB, authenticates and gets a session token for communicating #' with SB. If you do not supply a username or password, you will be prompted to @@ -88,6 +90,20 @@ authenticate_sb = function(username, password){ return(invisible(TRUE)) } +#' get or set sciencebase username +#' @description +#' Used to retrieve the current user name. Will request the username be entered +#' if no user is provided and `interactive()` is TRUE. +#' +#' This is largely an internal function, but is exported for awareness and +#' use in automated pipelines. +#' +#' @param username character if NULL, will be retrieved from the `sb_user` +#' environment variable or the `username` file stored at `token_stache_path()` +#' @return character string containing a username. Throws an error if no +#' username is found and `interactive()` is FALSE +#' @export +#' get_username <- function(username = NULL) { if(is.null(username)) { @@ -117,11 +133,11 @@ get_username <- function(username = NULL) { stop('Empty username supplied, stopping') } - }else { + } else { stop("username required for authentication") + } - # username <- try(session_details()$username) } pkg.env$username <- username @@ -170,7 +186,7 @@ initialize_sciencebase_session <- function(username = NULL, token_text = NULL) { if(is.null(token_text)) { - token <- gsub("[\r\n]", "", grab_token()) + token <- get_cached_token() if(token != "") { check_current <- try( @@ -226,19 +242,26 @@ clean_session <- function() { } #' Get or set token stache data directory -#' @description if left unset, will return the user data dir -#' as returned by `tools::R_user_dir` for this package. -#' @param dir path of desired token stache file +#' @description Will check the `SBTOOLS_TOKEN_STACHE` environment variable +#' and will check if the `token_stache_path` has been set durring the current +#' session previously. If the environment variable or session-variable are not +#' found, returns `file.path(tools::R_user_dir(package = "sbtools"), "token")`. +#' @param dir path of desired token stache file. See description for behavior +#' if left unset. #' @return character path of data directory (silent when setting) #' @importFrom tools R_user_dir -#' @noRd +#' @export #' token_stache_path <- function(dir = NULL) { if(is.null(dir)) { - token_stache <- try(get("token_stache", envir = pkg.env), silent = TRUE) - - if(inherits(token_stache, "try-error")) { + token_stache <- Sys.getenv("SBTOOLS_TOKEN_STACHE") + + if(token_stache == "") { + token_stache <- try(get("token_stache", envir = pkg.env), silent = TRUE) + } + + if(inherits(token_stache, "try-error") | token_stache == "") { assign("token_stache", file.path(tools::R_user_dir(package = "sbtools"), "token"), envir = pkg.env) @@ -252,7 +275,6 @@ token_stache_path <- function(dir = NULL) { return(invisible(get("token_stache", envir = pkg.env))) } - } stache_token <- function(username, token_text) { @@ -262,10 +284,17 @@ stache_token <- function(username, token_text) { write(token_text, file = token_stache_path()) } -grab_token <- function() { + +#' get cached sciencebase token +#' @description +#' tries to retrieve a cached token from `token_stache_path()` +#' @return character containing the token (which may be stale) or an empty string +#' @export +get_cached_token <- function() { if(file.exists(token_stache_path())) { - readChar(token_stache_path(), file.info(token_stache_path())$size) + gsub("[\r\n]", "", + readChar(token_stache_path(), file.info(token_stache_path())$size)) } else { "" } diff --git a/_pkgdown.yml b/_pkgdown.yml index 8c8660e..0479385 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -16,6 +16,9 @@ reference: - '`set_endpoint`' - '`user_id`' - '`is_logged_in`' + - '`get_username`' + - '`get_cached_token`' + - '`token_stache_path`' - title: Item Operations - contents: - '`sbitem`' diff --git a/man/authenticate_sb.Rd b/man/authenticate_sb.Rd index b7feed3..8d5a50d 100644 --- a/man/authenticate_sb.Rd +++ b/man/authenticate_sb.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/authenticate_sb.R \name{authenticate_sb} \alias{authenticate_sb} -\title{Authenticate to SB for subsequent calls} +\title{Authenticate to SB for subsequent calls [DEPRECATED]} \usage{ authenticate_sb(username, password) } @@ -14,6 +14,9 @@ no password is returned by `keyring::key_get("sciencebase", username)`. See \code{\link[keyring]{keyring-package}} documentation for more details.} } \description{ +THIS AUTHENTICATION METHOD NO LONGER WORKS FOR INDIVIDUAL LOGIN SESSIONS +} +\details{ This connects to SB, authenticates and gets a session token for communicating with SB. If you do not supply a username or password, you will be prompted to enter them. diff --git a/man/get_cached_token.Rd b/man/get_cached_token.Rd new file mode 100644 index 0000000..1d0a5d7 --- /dev/null +++ b/man/get_cached_token.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/authenticate_sb.R +\name{get_cached_token} +\alias{get_cached_token} +\title{get cached sciencebase token} +\usage{ +get_cached_token() +} +\value{ +character containing the token (which may be stale) or an empty string +} +\description{ +tries to retrieve a cached token from `token_stache_path()` +} diff --git a/man/get_username.Rd b/man/get_username.Rd new file mode 100644 index 0000000..72c6b48 --- /dev/null +++ b/man/get_username.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/authenticate_sb.R +\name{get_username} +\alias{get_username} +\title{get or set sciencebase username} +\usage{ +get_username(username = NULL) +} +\arguments{ +\item{username}{character if NULL, will be retrieved from the `sb_user` +environment variable or the `username` file stored at `token_stache_path()`} +} +\value{ +character string containing a username. Throws an error if no +username is found and `interactive()` is FALSE +} +\description{ +Used to retrieve the current user name. Will request the username be entered +if no user is provided and `interactive()` is TRUE. + +This is largely an internal function, but is exported for awareness and +use in automated pipelines. +} diff --git a/man/token_stache_path.Rd b/man/token_stache_path.Rd new file mode 100644 index 0000000..a093cd7 --- /dev/null +++ b/man/token_stache_path.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/authenticate_sb.R +\name{token_stache_path} +\alias{token_stache_path} +\title{Get or set token stache data directory} +\usage{ +token_stache_path(dir = NULL) +} +\arguments{ +\item{dir}{path of desired token stache file. See description for behavior +if left unset.} +} +\value{ +character path of data directory (silent when setting) +} +\description{ +Will check the `SBTOOLS_TOKEN_STACHE` environment variable +and will check if the `token_stache_path` has been set durring the current +session previously. If the environment variable or session-variable are not +found, returns `file.path(tools::R_user_dir(package = "sbtools"), "token")`. +} diff --git a/tests/testthat/setup_utils.R b/tests/testthat/setup_utils.R index fcb1a0f..aa4fb37 100644 --- a/tests/testthat/setup_utils.R +++ b/tests/testthat/setup_utils.R @@ -1,7 +1,7 @@ try_auth <- function() { skipit <- TRUE - user <- try(sbtools:::get_username()) + user <- try(get_username()) if(!inherits(user, "try-error")) { skipit <- !initialize_sciencebase_session() diff --git a/tests/testthat/test-auth.R b/tests/testthat/test-auth.R index f2cea20..29d80ce 100644 --- a/tests/testthat/test-auth.R +++ b/tests/testthat/test-auth.R @@ -35,8 +35,8 @@ test_that("login results in valid session and renew works (new)", { sbtools:::clean_session() - token <- sbtools:::grab_token() - user <- try(sbtools:::get_username()) + token <- get_cached_token() + user <- try(get_username()) if(token == "" | inherits(user, "try-error")) { skip("Authenticated tests skipped due to lack of login info") From 4b9a64c4b9f37ef1f36eb18ae82053ab776bbb46 Mon Sep 17 00:00:00 2001 From: David Blodgett Date: Wed, 16 Apr 2025 10:57:32 -0500 Subject: [PATCH 3/4] pkgown --- docs/404.html | 2 +- docs/DISCLAIMER.html | 2 +- docs/LICENSE.html | 2 +- docs/articles/index.html | 2 +- docs/articles/sbtools.html | 8 +- docs/authors.html | 2 +- docs/index.html | 2 +- docs/news/index.html | 5 +- docs/pkgdown.yml | 2 +- docs/reference/authenticate_sb.html | 20 ++--- docs/reference/current_session.html | 2 +- docs/reference/folder_create.html | 2 +- docs/reference/get_cached_token.html | 70 +++++++++++++++ docs/reference/get_username.html | 89 +++++++++++++++++++ docs/reference/identifier_exists.html | 2 +- docs/reference/index.html | 22 ++++- .../initialize_sciencebase_session.html | 5 +- docs/reference/is_logged_in.html | 2 +- docs/reference/item_append_files.html | 2 +- docs/reference/item_create.html | 2 +- docs/reference/item_exists.html | 2 +- docs/reference/item_file_download.html | 2 +- docs/reference/item_get.html | 2 +- docs/reference/item_get_fields.html | 2 +- docs/reference/item_get_parent.html | 2 +- docs/reference/item_list_children.html | 2 +- docs/reference/item_list_files.html | 2 +- docs/reference/item_move.html | 2 +- docs/reference/item_publish_cloud.html | 2 +- docs/reference/item_rename_files.html | 2 +- docs/reference/item_replace_files.html | 2 +- docs/reference/item_rm.html | 2 +- docs/reference/item_rm_files.html | 2 +- docs/reference/item_rm_recursive.html | 2 +- docs/reference/item_update.html | 2 +- docs/reference/item_update_identifier.html | 2 +- docs/reference/item_upload_cloud.html | 2 +- docs/reference/item_upload_create.html | 2 +- docs/reference/item_upsert.html | 2 +- docs/reference/query_item_identifier.html | 2 +- docs/reference/query_item_in_folder.html | 2 +- docs/reference/query_items.html | 2 +- docs/reference/query_sb.html | 2 +- docs/reference/query_sb_datatype.html | 2 +- docs/reference/query_sb_date.html | 2 +- docs/reference/query_sb_doi.html | 2 +- docs/reference/query_sb_spatial.html | 2 +- docs/reference/query_sb_text.html | 2 +- docs/reference/readPassword.html | 2 +- docs/reference/sb_datatypes.html | 2 +- docs/reference/sb_ping.html | 2 +- docs/reference/sbitem.html | 2 +- docs/reference/sbtools-package.html | 2 +- docs/reference/sbtools_GET.html | 2 +- docs/reference/sbtools_POST.html | 2 +- docs/reference/sbtools_PUT.html | 2 +- docs/reference/session_age.html | 2 +- docs/reference/session_details.html | 2 +- docs/reference/session_expired.html | 2 +- docs/reference/session_renew.html | 2 +- docs/reference/session_validate.html | 2 +- docs/reference/set_endpoint.html | 2 +- docs/reference/token_stache_path.html | 88 ++++++++++++++++++ docs/reference/user_id.html | 2 +- docs/search.json | 2 +- docs/sitemap.xml | 3 + vignettes/sbtools.Rmd | 2 +- 67 files changed, 349 insertions(+), 77 deletions(-) create mode 100644 docs/reference/get_cached_token.html create mode 100644 docs/reference/get_username.html create mode 100644 docs/reference/token_stache_path.html diff --git a/docs/404.html b/docs/404.html index 981ddce..5cc837e 100644 --- a/docs/404.html +++ b/docs/404.html @@ -20,7 +20,7 @@ sbtools - 1.3.2 + 1.4.0 + + + + + +
+
+
+ +
+

tries to retrieve a cached token from `token_stache_path()`

+
+ +
+

Usage

+
get_cached_token()
+
+ +
+

Value

+

character containing the token (which may be stale) or an empty string

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/get_username.html b/docs/reference/get_username.html new file mode 100644 index 0000000..2837165 --- /dev/null +++ b/docs/reference/get_username.html @@ -0,0 +1,89 @@ + +get or set sciencebase username — get_username • sbtools + Skip to contents + + +
+
+
+ +
+

Used to retrieve the current user name. Will request the username be entered +if no user is provided and `interactive()` is TRUE.

+

This is largely an internal function, but is exported for awareness and +use in automated pipelines.

+
+ +
+

Usage

+
get_username(username = NULL)
+
+ +
+

Arguments

+ + +
username
+

character if NULL, will be retrieved from the `sb_user` +environment variable or the `username` file stored at `token_stache_path()`

+ +
+
+

Value

+

character string containing a username. Throws an error if no +username is found and `interactive()` is FALSE

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/identifier_exists.html b/docs/reference/identifier_exists.html index e650291..5e00716 100644 --- a/docs/reference/identifier_exists.html +++ b/docs/reference/identifier_exists.html @@ -13,7 +13,7 @@ sbtools - 1.3.2 + 1.4.0 + + + + + +
+
+
+ +
+

Will check the `SBTOOLS_TOKEN_STACHE` environment variable +and will check if the `token_stache_path` has been set durring the current +session previously. If the environment variable or session-variable are not +found, returns `file.path(tools::R_user_dir(package = "sbtools"), "token")`.

+
+ +
+

Usage

+
token_stache_path(dir = NULL)
+
+ +
+

Arguments

+ + +
dir
+

path of desired token stache file. See description for behavior +if left unset.

+ +
+
+

Value

+

character path of data directory (silent when setting)

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/user_id.html b/docs/reference/user_id.html index 6c1241c..8229f88 100644 --- a/docs/reference/user_id.html +++ b/docs/reference/user_id.html @@ -7,7 +7,7 @@ sbtools - 1.3.2 + 1.4.0