diff --git a/R/dialogs.R b/R/dialogs.R index deaf4fb..89ca224 100644 --- a/R/dialogs.R +++ b/R/dialogs.R @@ -73,35 +73,3 @@ showPrompt <- function(title, message, default = NULL) { showQuestion <- function(title, message, ok = NULL, cancel = NULL) { callFun("showQuestion", title, message, ok, cancel) } - - - -#' Prompt user for secret -#' -#' Request a secret from the user. If the `keyring` package is installed, it -#' will be used to cache requested secrets. -#' -#' -#' @param name The name of the secret. -#' -#' @param message A character vector with the contents to display in the main -#' dialog area. -#' -#' @param title The title to display in the dialog box. -#' -#' @note The \code{askForSecret} function was added in version 1.1.419 of -#' RStudio. -#' -#' @export -askForSecret <- function( - name, - message = paste(name, ":", sep = ""), - title = paste(name, "Secret")) { - - if (hasFun("askForSecret") || isChildProcess()) { - callFun("askForSecret", name, title, message) - } else { - askForPassword(message) - } - -} diff --git a/R/secrets.R b/R/secrets.R new file mode 100644 index 0000000..c12bea5 --- /dev/null +++ b/R/secrets.R @@ -0,0 +1,102 @@ + +# returns the secret associated with a getenv 'getenv', or NULL +# if no secret is available +retrieveSecret <- function(getenv, label) { + + if (is.null(getenv)) + return(NULL) + + # build full name of environment variable + name <- paste("RSTUDIOAPI_SECRET", getenv, sep = "_") + + # check for a definition + value <- Sys.getenv(name, unset = NA) + if (!is.na(value)) + return(value) + + # for non-interactive sessions, give a warning; otherwise, + # fall through an attempt to ask for a password + if (!interactive() && !isChildProcess()) { + fmt <- "The %s associated with 'RSTUDIOAPI_SECRET_%s' is not set or could not be retrieved." + msg <- sprintf(fmt, label, getenv) + warning(msg) + } + +} + +#' Ask the user for a password interactively +#' +#' Ask the user for a password interactively. +#' +#' RStudio also sets the global \code{askpass} option to the +#' \code{rstudioapi::askForPassword} function so that it can be invoked in a +#' front-end independent manner. +#' +#' @param prompt The prompt to be shown to the user. +#' +#' @param getenv An optional getenv. When provided, RStudio will check to see if +#' an environment variable of the name `RSTUDIOAPI_SECRET_` is defined; +#' if so, that environment variable will be used to supply the password. +#' If the variable is unset, then (in interactive sessions) the user will +#' be prompted for a password; otherwise, a warning will be shown. +#' +#' @note The \code{askForPassword} function was added in version 0.99.853 of +#' RStudio. +#' +#' @examples +#' +#' \dontrun{ +#' rstudioapi::askForPassword("Please enter your password") +#' } +#' +#' @export askForPassword +askForPassword <- function(prompt = "Please enter your password", + getenv = NULL) +{ + password <- retrieveSecret(getenv, "password") + if (!is.null(password)) + return(password) + + callFun("askForPassword", prompt) +} + +#' Prompt user for secret +#' +#' Request a secret from the user. If the `getenvring` package is installed, it +#' will be used to cache requested secrets. +#' +#' @param name The name of the secret. +#' +#' @param message A character vector with the contents to display in the main +#' dialog area. +#' +#' @param title The title to display in the dialog box. +#' +#' @param getenv An optional getenv. When provided, RStudio will check to see if +#' an environment variable of the name `RSTUDIOAPI_SECRET_` is defined; +#' if so, that environment variable will be used to supply the secret. +#' If the variable is unset, then (in interactive sessions) the user will +#' be prompted for a password; otherwise, a warning will be shown. +#' +#' @note The \code{askForSecret} function was added in version 1.1.419 of +#' RStudio. +#' +#' @export +askForSecret <- function( + name, + message = paste(name, ":", sep = ""), + title = paste(name, "Secret"), + getenv = NULL) { + + secret <- retrieveSecret(getenv, "secret") + if (!is.null(secret)) + return(secret) + + # use 'askForSecret' if available + if (hasFun("askForSecret") || isChildProcess()) + return(callFun("askForSecret", name, title, message)) + + # otherwise, fall back to askForPassword + askForPassword(message) + +} diff --git a/R/stubs.R b/R/stubs.R index 4eb717a..cc7fc55 100644 --- a/R/stubs.R +++ b/R/stubs.R @@ -249,32 +249,6 @@ navigateToFile <- function(file = character(0), } -#' Ask the user for a password interactively -#' -#' Ask the user for a password interactively. -#' -#' RStudio also sets the global \code{askpass} option to the -#' \code{rstudioapi::askForPassword} function so that it can be invoked in a -#' front-end independent manner. -#' -#' @param prompt The prompt to be shown to the user. -#' -#' @note The \code{askForPassword} function was added in version 0.99.853 of -#' RStudio. -#' -#' @examples -#' -#' \dontrun{ -#' rstudioapi::askForPassword("Please enter your password") -#' } -#' -#' @export askForPassword -askForPassword <- function(prompt = "Please enter your password") { - callFun("askForPassword", prompt) -} - - - #' Retrieve path to active RStudio project #' #' Get the path to the active RStudio project (if any). If the path contains diff --git a/man/askForPassword.Rd b/man/askForPassword.Rd index dc280ef..bf7de16 100644 --- a/man/askForPassword.Rd +++ b/man/askForPassword.Rd @@ -1,13 +1,19 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/stubs.R +% Please edit documentation in R/secrets.R \name{askForPassword} \alias{askForPassword} \title{Ask the user for a password interactively} \usage{ -askForPassword(prompt = "Please enter your password") +askForPassword(prompt = "Please enter your password", getenv = NULL) } \arguments{ \item{prompt}{The prompt to be shown to the user.} + +\item{getenv}{An optional getenv. When provided, RStudio will check to see if +an environment variable of the name \verb{RSTUDIOAPI_SECRET_} is defined; +if so, that environment variable will be used to supply the password. +If the variable is unset, then (in interactive sessions) the user will +be prompted for a password; otherwise, a warning will be shown.} } \description{ Ask the user for a password interactively. diff --git a/man/askForSecret.Rd b/man/askForSecret.Rd index bf5dde8..f123b36 100644 --- a/man/askForSecret.Rd +++ b/man/askForSecret.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/dialogs.R +% Please edit documentation in R/secrets.R \name{askForSecret} \alias{askForSecret} \title{Prompt user for secret} @@ -7,7 +7,8 @@ askForSecret( name, message = paste(name, ":", sep = ""), - title = paste(name, "Secret") + title = paste(name, "Secret"), + getenv = NULL ) } \arguments{ @@ -17,9 +18,15 @@ askForSecret( dialog area.} \item{title}{The title to display in the dialog box.} + +\item{getenv}{An optional getenv. When provided, RStudio will check to see if +an environment variable of the name \verb{RSTUDIOAPI_SECRET_} is defined; +if so, that environment variable will be used to supply the secret. +If the variable is unset, then (in interactive sessions) the user will +be prompted for a password; otherwise, a warning will be shown.} } \description{ -Request a secret from the user. If the \code{keyring} package is installed, it +Request a secret from the user. If the \code{getenvring} package is installed, it will be used to cache requested secrets. } \note{