-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
More cleanup (spillover from prev commit)
- Loading branch information
Showing
3 changed files
with
120 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
|
||
#' Parse an RT response in its parts as a list | ||
#' | ||
#' The RT API uses overrides default HTTP behavior with their own set of status | ||
#' codes, messages, and response formats. This function parses that custom | ||
#' implementation and presents it into something that's easier to build a | ||
#' package with. | ||
#' | ||
#' For example, a response like: | ||
#' | ||
#' "RT/4.4.3 200 Ok | ||
#' | ||
#' # Ticket 2 created. | ||
#' | ||
#' " | ||
#' | ||
#' is turned into the list: | ||
#' | ||
#' $status | ||
#' [1] 200 | ||
#' | ||
#' $message | ||
#' [1] "Ok" | ||
#' | ||
#' $body | ||
#' [1] "# Ticket 2 created." | ||
#' | ||
#' @param response (character) Parsed response from \code{\link[httr]{content}} | ||
#' @param verbose (logical) Optional, defaults to \code{TRUE}. Prints more information during parsing. | ||
#' | ||
#' @return (list) List with named elements status, message, and body | ||
parse_rt_response <- function(response, verbose = FALSE) { | ||
split_response <- stringr::str_split(response, "[\\n]+", n = 2) | ||
|
||
# Response should be a single result, with parts for the first line, and rest | ||
stopifnot(length(split_response) == 1 && | ||
length(split_response[[1]] != 2)) | ||
|
||
first <- split_response[[1]][1] | ||
rest <- stringr::str_replace_all(split_response[[1]][2], "[\\n]+$", "") | ||
|
||
# Parse the first line (RT version + HTTP status + custom status messsage) | ||
match <- stringr::str_match(first, "\\ART/[\\d\\.]+ (\\d+) (.+)\\Z") | ||
|
||
# Stop, helpfully, if we failed to get what we expected from the regex | ||
if (!all(dim(match) == c(1, 3))) { | ||
if (verbose) { | ||
message(content) | ||
} | ||
|
||
message("Failed to parse RT response. Returning response directly from httr.") | ||
return(response) | ||
} | ||
|
||
return(list( | ||
status = as.numeric(match[1,2]), | ||
message = match[1,3], | ||
body = rest | ||
)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,85 @@ | ||
#' Log in to RT | ||
#' | ||
#' Use this to log into RT at the start of your session. | ||
#' Use this to log into RT at the start of your session. Once you call this | ||
#' function and successfully log in, calls of other functions within this | ||
#' package will re-use your login information automatically. | ||
#' | ||
#' @param user (character) Your username | ||
#' @param pass (character) Your password | ||
#' @param rt_base (character) The base URL that hosts RT for your organization. Set the base URL in your R session using \code{options(rt_base = "https://server.name/rt/")} | ||
#' The value of \code{rt_base_url} should be the same address you use in your | ||
#' web browser to log into RT (i.e., the address of the log in page). | ||
#' | ||
#' @param user (character) Your username. | ||
#' @param password (character) Your password. | ||
#' @param rt_base_url (character) The address of your RT installation. | ||
#' See details. | ||
#' @export | ||
#' | ||
#' @import stringr | ||
#' | ||
#' @examples | ||
#' \dontrun{ | ||
#' options(rt_base = "https://demo.bestpractical.com") | ||
#' rt_login(user = "guest", pass = "guest") | ||
#' } | ||
|
||
rt_login <- function(user, pass, rt_base = getOption("rt_base")) { | ||
if(!is.character(rt_base)){ | ||
stop('Check your base URL. Set it in your R session using option(rt_base = "https://server.name/rt/")', call. = FALSE) | ||
#' # You can setup the location of your RT installation and the values for | ||
#' # your credentials as environmental variables | ||
#' Sys.setenv("RT_USER" = "user", | ||
#' "RT_PASSWORD" = "password", | ||
#' "RT_BASE_URL" = "https://demo.bestpractical.com") | ||
#' | ||
#' # And then log in directly like | ||
#' rt_login() | ||
#' | ||
#' # Or if you prefer, you can pass the values directly, like | ||
#' rt_login("user", "password", "https://demo.bestpractical.com") | ||
#'} | ||
rt_login <- function(user = Sys.getenv("RT_USER"), | ||
password = Sys.getenv("RT_PASSWORD"), | ||
rt_base_url = Sys.getenv("RT_BASE_URL")) { | ||
if (!is.character(rt_base_url) && nchar(rt_base_url) > 0) { | ||
stop("Check your base URL. ", | ||
"Set it in your R session using ", | ||
"Sys.setenv(RT_BASE_URL = \"https://server.name/rt/\")", | ||
call. = FALSE) | ||
} | ||
|
||
base_api <- paste(stringr::str_replace(rt_base, "\\/$", ""), # removes trailing slash from base URL just in case | ||
"REST", "1.0", sep = "/") | ||
req <- httr::POST(base_api, body = list('user' = user, 'pass' = pass)) | ||
|
||
# Check that login worked | ||
response <- httr::POST(rt_url(rt_base_url), | ||
body = list( | ||
'user' = utils::URLencode(user, | ||
reserved = TRUE), | ||
'pass' = utils::URLencode(password, | ||
reserved = TRUE))) | ||
check_login(response) | ||
} | ||
|
||
if(stringr::str_detect(httr::content(req), "Credentials required")){ | ||
invisible(FALSE) | ||
stop("Your log-in was unsuccessful. Check your username, password, and base URL and try again.", | ||
call. = FALSE) | ||
} else { | ||
message("Successfully logged in.") | ||
invisible(TRUE) | ||
#' Check that the login request was successful or not | ||
#' | ||
#' @param response (httr::response) RT API login response | ||
#' | ||
#' @return (logical) TRUE if login was succesful, errors out otherwise | ||
check_login <- function(response) { | ||
parsed <- parse_rt_response(httr::content(response)) | ||
if (parsed$body != "# Invalid object specification: ''\n\nid: ") { | ||
stop(parsed$message, ": ", parsed$body, call. = FALSE) | ||
} | ||
|
||
message("Successfully logged in.") | ||
invisible(TRUE) | ||
} | ||
|
||
#' Log in to RT interactively | ||
#' | ||
#' Wrapper for \code{\link{rt_login}} to interactively log into RT at the start of your | ||
#' session. Keeps your log-in information private. | ||
#' | ||
#' @param rt_base (character) The base URL that hosts RT for your organization. Set the base URL in your R session using \code{options(rt_base = "https://server.name/rt/")} | ||
#' @param rt_base_url (character) The base URL that hosts RT for your organization. Set the base URL in your R session using \code{Sys.getenv("RT_BASE_URL" = "https://server.name/rt/")} | ||
#' | ||
#' @importFrom getPass getPass | ||
#' | ||
#' @export | ||
#' | ||
#' @examples | ||
#' \dontrun{ | ||
#' options(rt_base = "https://demo.bestpractical.com") | ||
#' Sys.setenv(RT_BASE_URL = "https://demo.bestpractical.com") | ||
#' rt_login_interactive() | ||
#' } | ||
|
||
rt_login_interactive <- function(rt_base = getOption("rt_base")) { | ||
rt_login_interactive <- function(rt_base_url = Sys.getenv("RT_BASE")) { | ||
rt_login(user = readline("Enter username: "), | ||
pass = getPass::getPass(), | ||
rt_base = rt_base) | ||
password = getPass::getPass(), | ||
rt_base_url = rt_base_url) | ||
} |