Skip to content

Commit f91b547

Browse files
committed
Add support for viewer-based credentials on Posit Connect.
This commit brings support for Posit Connect's "viewer-based credentials" feature [0] to `gh`. Checks for viewer-based credentials are designed to fall back gracefully to existing authentication methods. This is intended to allow users to -- for example -- develop and test a Shiny app that uses GitHub credentials in desktop Positron/RStudio or Posit Workbench and deploy it with no code changes to Connect. Most of the actual work is outsourced to a new shared package, `connectcreds` [1]. Unit tests are included. [0]: https://docs.posit.co/connect/user/oauth-integrations/ [1]: https://github.com/posit-dev/connectcreds/ Signed-off-by: Aaron Jacobs <[email protected]>
1 parent f391c2b commit f91b547

File tree

4 files changed

+23
-10
lines changed

4 files changed

+23
-10
lines changed

DESCRIPTION

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Imports:
2323
lifecycle,
2424
rlang (>= 1.0.0)
2525
Suggests:
26+
connectcreds,
2627
covr,
2728
knitr,
2829
rmarkdown,
@@ -39,4 +40,5 @@ Language: en-US
3940
Roxygen: list(markdown = TRUE)
4041
RoxygenNote: 7.3.2
4142
Remotes:
43+
posit-dev/connectcreds,
4244
r-lib/httr2

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* `gh()` now uses a cache provided by httr2. This cache lives in `tools::R_user_dir("gh", "cache")`, maxes out at 100 MB, and can be disabled by setting `options(gh_cache = FALSE)` (#203).
55
* Removes usage of mockery (@tanho63, #197)
66

7+
* `gh_token()` can now pick up on GitHub credentials from the current Shiny
8+
session when running on Posit Connect (@atheriel, #217).
9+
710
# gh 1.4.1
811

912
* `gh_next()`, `gh_prev()`, `gh_first()` and `gh_last()`

R/gh_token.R

+10-10
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,16 @@
4646
gh_token <- function(api_url = NULL) {
4747
api_url <- api_url %||% default_api_url()
4848
stopifnot(is.character(api_url), length(api_url) == 1)
49+
host_url <- get_hosturl(api_url)
50+
# Check for credentials supplied by Posit Connect.
51+
if (is_installed("connectcreds")) {
52+
if (connectcreds::has_viewer_token(host_url)) {
53+
token <- connectcreds::connect_viewer_token(host_url)
54+
return(gh_pat(token$access_token))
55+
}
56+
}
4957
token <- tryCatch(
50-
gitcreds::gitcreds_get(get_hosturl(api_url)),
58+
gitcreds::gitcreds_get(host_url),
5159
error = function(e) NULL
5260
)
5361
gh_pat(token$password %||% "")
@@ -56,15 +64,7 @@ gh_token <- function(api_url = NULL) {
5664
#' @export
5765
#' @rdname gh_token
5866
gh_token_exists <- function(api_url = NULL) {
59-
api_url <- api_url %||% default_api_url()
60-
tryCatch(
61-
{
62-
token <- gitcreds::gitcreds_get(get_hosturl(api_url))
63-
gh_pat(token$password)
64-
TRUE
65-
} ,
66-
error = function(e) FALSE
67-
)
67+
tryCatch(nzchar(gh_token(api_url)), error = function(e) FALSE)
6868
}
6969

7070
gh_auth <- function(token) {

tests/testthat/test-gh_token.R

+8
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,11 @@ test_that("get_apiurl() works", {
163163
expect_equal(get_apiurl("https://github.acme.com/OWNER/REPO"), x)
164164
expect_equal(get_apiurl("https://github.acme.com/api/v3"), x)
165165
})
166+
167+
test_that("tokens can be requested from a Connect server", {
168+
skip_if_not_installed("connectcreds")
169+
170+
token <- strrep("a", 40)
171+
connectcreds::local_mocked_connect_responses(token = token)
172+
expect_equal(gh_token(), gh_pat(token))
173+
})

0 commit comments

Comments
 (0)