-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use gitcreds for managing github PAT #96
base: master
Are you sure you want to change the base?
Changes from all commits
fe62328
e0ce731
6111dfb
986d28b
c69d78c
f0bf8ef
ca9c281
a685fff
62caffd
ee26685
f50c173
fd71d51
72ba060
5bbb5fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,12 +12,12 @@ Description: Work with 'GitHub' 'gists' from 'R' (e.g., | |
<https://gist.github.com/>. | ||
Version: 0.9.0.93 | ||
Authors@R: c( | ||
person("Scott", "Chamberlain", role = c("aut", "cre"), | ||
email = "[email protected]", | ||
comment = c(ORCID="0000-0003-1444-9135")), | ||
person("Scott", "Chamberlain", , "[email protected]", role = "aut", | ||
comment = c(ORCID = "0000-0003-1444-9135")), | ||
person("Ramnath", "Vaidyanathan", role = "aut"), | ||
person("Karthik", "Ram", role = "aut"), | ||
person("Milgram", "Eric", role = "aut") | ||
person("Milgram", "Eric", role = c("aut", "cre")), | ||
person("Eric R.", "Scott", role = "ctb") | ||
) | ||
License: MIT + file LICENSE | ||
URL: https://github.com/ropensci/gistr (devel), | ||
|
@@ -35,11 +35,12 @@ Imports: | |
assertthat, | ||
knitr, | ||
rmarkdown, | ||
dplyr | ||
dplyr, | ||
gitcreds | ||
Suggests: | ||
git2r, | ||
testthat | ||
RoxygenNote: 7.1.1 | ||
RoxygenNote: 7.3.2 | ||
X-schema.org-applicationCategory: Web | ||
X-schema.org-keywords: http, https, API, web-services, GitHub, GitHub API, gist, gists, code, script, snippet | ||
X-schema.org-isPartOf: https://ropensci.org |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,22 @@ | ||
#' Authorize with GitHub. | ||
#' | ||
#' This function is run automatically to allow gistr to access your GitHub | ||
#' This function is run automatically to allow gistr to access your GitHub | ||
#' account. | ||
#' | ||
#' There are two ways to authorise gistr to work with your GitHub account: | ||
#' | ||
#' - Generate a personal access token with the gist scope selected, and set it | ||
#' as the `GITHUB_PAT` environment variable per session using `Sys.setenv` | ||
#' or across sessions by adding it to your `.Renviron` file or similar. | ||
#' See | ||
#' | ||
#' - Generate a personal access token with the gist scope selected, and store it | ||
#' with `gitcreds::gitcreds_set()`. Alternatively you can set it as the | ||
#' `GITHUB_PAT` environment variable per session using `Sys.setenv()` or across | ||
#' sessions by adding it to your `.Renviron` file or similar. See | ||
#' https://help.github.com/articles/creating-an-access-token-for-command-line-use | ||
#' for help | ||
#' - Interactively login into your GitHub account and authorise with OAuth. | ||
#' for help or use `usethis::create_github_token()`. | ||
#' - Interactively log in into your GitHub account and authorise with OAuth. | ||
#' | ||
#' Using `GITHUB_PAT` is recommended. | ||
#' Using `gitcreds::gitcreds_set()` is recommended. | ||
#' | ||
#' @export | ||
#' @param app An [httr::oauth_app()] for GitHub. The default uses an | ||
#' @param app An [httr::oauth_app()] for GitHub. The default uses an | ||
#' application `gistr_oauth` created by Scott Chamberlain. | ||
#' @param reauth (logical) Force re-authorization? | ||
#' @return a named list, with a single slot for `Authorization`, with a single | ||
|
@@ -27,24 +27,40 @@ | |
#' } | ||
|
||
gist_auth <- function(app = gistr_app, reauth = FALSE) { | ||
|
||
|
||
#if there is a token cached, use that | ||
if (exists("auth_config", envir = cache) && !reauth) { | ||
return(auth_header(cache$auth_config$auth_token$credentials$access_token)) | ||
return(auth_header(cache$auth_config$auth_token)) | ||
} | ||
pat <- Sys.getenv("GITHUB_PAT", "") | ||
if (!identical(pat, "")) { | ||
auth_config <- list(auth_token=list(credentials=list(access_token=pat))) | ||
} else if (!interactive()) { | ||
stop("In non-interactive environments, please set GITHUB_PAT env to a GitHub", | ||
" access token (https://help.github.com/articles/creating-an-access-token-for-command-line-use)", | ||
call. = FALSE) | ||
} else { | ||
endpt <- httr::oauth_endpoints("github") | ||
token <- httr::oauth2.0_token(endpt, app, scope = "gist", cache = !reauth) | ||
auth_config <- httr::config(token = token) | ||
#if nothing cached, use gitcreds to retrieve PAT stored as an GITHUB_PAT | ||
#environment variable or set with gitcreds::gitcreds_set(). gitcreds_get() | ||
#errors when no PAT is found, but we want to try one more method, so silence | ||
#this error and return NULL. | ||
creds <- tryCatch( | ||
error = function(cnd) { | ||
return(NULL) | ||
}, | ||
gitcreds::gitcreds_get() | ||
) | ||
token <- creds$password | ||
#TODO would be great to check here that token has "gist" scope | ||
#if no token, or invalid token and interactive, try direct oauth | ||
if ((is.null(token) | !valid_gh_pat(token))) { | ||
if (interactive()) { | ||
endpt <- httr::oauth_endpoints("github") | ||
auth <- httr::oauth2.0_token(endpt, app, scope = "gist", cache = !reauth) | ||
token <- auth$credentials$access_token | ||
} else { | ||
stop("In non-interactive environments, please set GITHUB_PAT env to a GitHub", | ||
" access token (https://help.github.com/articles/creating-an-access-token-for-command-line-use)", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this could also point to https://usethis.r-lib.org/reference/github-token.html as the functions are quite handy |
||
call. = FALSE) | ||
} | ||
} | ||
|
||
#cache auth config | ||
auth_config <- httr::config(token = token) | ||
cache$auth_config <- auth_config | ||
auth_header(auth_config$auth_token$credentials$access_token) | ||
return(auth_header(auth_config$auth_token)) | ||
} | ||
|
||
auth_header <- function(x) list(Authorization = paste0("token ", x)) | ||
|
@@ -56,3 +72,11 @@ gistr_app <- httr::oauth_app( | |
"89ecf04527f70e0f9730", | ||
"77b5970cdeda925513b2cdec40c309ea384b74b7" | ||
) | ||
|
||
# inspired by https://github.com/r-lib/gh/blob/main/R/gh_token.R | ||
valid_gh_pat <- function(x) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead, why not directly test it works, using a call to https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user |
||
!is.null(x) & ( | ||
grepl("^(gh[pousr]_[A-Za-z0-9_]{36,251}|github_pat_[A-Za-z0-9_]{36,244})$", x) || | ||
grepl("^[[:xdigit:]]{40}$", x) | ||
) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.httr-oauth |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
test_that("gitcreds finds PAT", { | ||
expect_equal(gitcreds::gitcreds_get()$password, Sys.getenv("GITHUB_PAT")) | ||
}) | ||
|
||
|
||
test_that("gist_auth finds PAT", { | ||
skip_on_cran() | ||
auth <- gist_auth(reauth = TRUE) | ||
expect_equal( | ||
auth$Authorization, | ||
paste0("token ", gitcreds::gitcreds_get()$password) | ||
) | ||
}) | ||
|
||
#can't (easily) test PAT stored with gitcreds::gitcreds_set() or interactive oauth | ||
|
||
test_that("valid_gh_pat() works", { | ||
expect_false(valid_gh_pat("hello")) | ||
expect_false(valid_gh_pat("")) | ||
expect_false(valid_gh_pat(NULL)) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see what usethis does https://github.com/r-lib/usethis/blob/50dcb10cf5fc69d456176cfb66b4d19f81e12bf4/R/github_token.R#L254