diff --git a/DESCRIPTION b/DESCRIPTION index 0b0eaab..ebcee03 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: iassetR Title: Use the iAsset API in R -Version: 0.0.0.9000 +Version: 0.0.1.9000 Authors@R: c( person("Pieter", "Huybrechts", , "pieter.huybrechts@inbo.be", role = "aut", comment = c(ORCID = "0000-0002-6658-6062")), @@ -19,6 +19,7 @@ Imports: glue, httr2, janitor, + keyring, magrittr, openssl, purrr, @@ -26,5 +27,5 @@ Imports: stringr Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 BugReports: https://github.com/inbo/iassetR/issues diff --git a/NAMESPACE b/NAMESPACE index cca531a..bff2f42 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,5 +4,6 @@ export("%>%") export(get_access_token) export(get_fields) export(get_records) +export(get_username) importFrom(magrittr,"%>%") importFrom(rlang,.data) diff --git a/R/get_access_token.R b/R/get_access_token.R index 54b2907..8dbf661 100644 --- a/R/get_access_token.R +++ b/R/get_access_token.R @@ -6,30 +6,88 @@ #' @return Invisibily, an access token upon succes #' @export #' -#' @examples \dontrun{get_access_token("my_username")} +#' @details +#' This function uses keyring to retrieve the password. If no password has been +#' set using keyring you'll be prompted to enter your password using askpass. +#' This password - username combination will then be stored in the system +#' credential store. +#' Keyring uses secret environment variables on GitHub Actions. +#' +#' @examples \dontrun{ +#' get_access_token("my_username") +#' } get_access_token <- - function(username, quiet = FALSE) { + function(username = get_username(), quiet = FALSE) { # check input params - assertthat::assert_that(assertthat::is.string(username)) + assertthat::assert_that(assertthat::is.flag(quiet)) + + # check for keyring support + assertthat::assert_that(keyring::has_keyring_support()) + + # check if a keyring exists + iasset_keyring_exists <- + "iasset_password" %in% dplyr::pull(keyring::key_list(), "service") + + ## check if a username is set + iasset_username_missing <- !rlang::is_string(get_username()) + + # check that only one keyring is set + number_of_keyrings <- nrow(keyring::key_list(service = "iasset_password")) + assertthat::assert_that(number_of_keyrings <= 1, + msg = paste( + "iassetR currently only supports storing one iAsset account at a time.", + "Delete any other accounts using", + 'keyring::key_list(service = "iasset_password")$username', + "to get a list of linked usernames &", + 'keyring::key_delete(service = "iasset_password",', + 'username = "username_to_delete")', + "to delete the unneeded username" + ) + ) + + # prompt user for credentials if password or username is missing + if(!iasset_keyring_exists | iasset_username_missing){ + message( + paste( + "iasset credentials are missing, please enter your credentials or", + "if you don't have any contact your domain admin." + ) + ) + keyring::key_set( + service = "iasset_password", + username = + askpass::askpass(prompt = "Please enter your iasset username: "), + prompt = "Please enter your iasset password: " + ) + } + + # fetch the username, we'll fetch the password in line to avoid storing it + username <- get_username() + + # check that the fetched username is a string + assertthat::assert_that(assertthat::is.string(username)) + # build a request and perform it login_request <- httr2::request(base_url = "https://api.iasset.nl/login/") - hash <- askpass::askpass() %>% - openssl::md5() + login_response <- login_request %>% httr2::req_body_form( username = username, - password = hash, + password = openssl::md5(keyring::key_get("iasset_password", + username = username)), domain = "riparias", version = "9.7" ) %>% httr2::req_perform() %>% httr2::resp_body_json(check_type = FALSE) + # print success if (!quiet) { message(login_response$returndata[[1]]$success_msg) } + # return access token invisible(purrr::chuck(login_response, "returndata", 1, "access_token")) } diff --git a/R/get_username.R b/R/get_username.R new file mode 100644 index 0000000..03266b5 --- /dev/null +++ b/R/get_username.R @@ -0,0 +1,25 @@ +#' Get the username associated with the iAsset credentials in the system credentials store. +#' +#' @param service Character. The keyring service to fetch the stored username for. +#' +#' @return A character vector of stored usernames for the service. NA if none. +#' +#' @export +#' +#' @examples +#' \dontrun{get_username("iasset_password")} +get_username <- function(service = "iasset_password") { + # check input params + assertthat::assert_that(assertthat::is.string(service)) + + # check that the system supports keyring + assertthat::assert_that(keyring::has_keyring_support()) + + # check that the queried service is in the keyring + assertthat::validate_that(service %in% keyring::key_list()$service, + msg = glue::glue("{service} not found in keyring") + ) + + # fetch the associated usernames + keyring::key_list(service = service)$username +} diff --git a/man/get_access_token.Rd b/man/get_access_token.Rd index a502bbb..7c8347c 100644 --- a/man/get_access_token.Rd +++ b/man/get_access_token.Rd @@ -4,7 +4,7 @@ \alias{get_access_token} \title{Login to iAsset and retreive access token} \usage{ -get_access_token(username, quiet = FALSE) +get_access_token(username = get_username(), quiet = FALSE) } \arguments{ \item{username}{the iAsset username} @@ -17,6 +17,15 @@ Invisibily, an access token upon succes \description{ Login to iAsset and retreive access token } +\details{ +This function uses keyring to retrieve the password. If no password has been +set using keyring you'll be prompted to enter your password using askpass. +This password - username combination will then be stored in the system +credential store. +Keyring uses secret environment variables on GitHub Actions. +} \examples{ -\dontrun{get_access_token("my_username")} +\dontrun{ +get_access_token("my_username") +} } diff --git a/man/get_username.Rd b/man/get_username.Rd new file mode 100644 index 0000000..0df5b08 --- /dev/null +++ b/man/get_username.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_username.R +\name{get_username} +\alias{get_username} +\title{Get the username associated with the iAsset credentials in the system credentials store.} +\usage{ +get_username(service = "iasset_password") +} +\arguments{ +\item{service}{Character. The keyring service to fetch the stored username for.} +} +\value{ +A character vector of stored usernames for the service. NA if none. +} +\description{ +Get the username associated with the iAsset credentials in the system credentials store. +} +\examples{ +\dontrun{get_username("iasset_password")} +}