From dadfd8bf67dd0da54aa668fc73d3ae4ff9ec6a67 Mon Sep 17 00:00:00 2001 From: Sam Perman Date: Tue, 7 Apr 2026 14:12:25 -0400 Subject: [PATCH 1/3] feat: support POSIT_PRODUCT env var and Connect Cloud for OAuth apps Add POSIT_PRODUCT as an alternative to RSTUDIO_PRODUCT for detecting Connect, and add on_connect_cloud() to support apps running in Connect Cloud (POSIT_PRODUCT="CONNECT_CLOUD"). --- R/connect.R | 2 +- R/utils.R | 11 ++++++-- tests/testthat/test-connect.R | 50 +++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/R/connect.R b/R/connect.R index 0701d6706..d6ae120c0 100644 --- a/R/connect.R +++ b/R/connect.R @@ -1007,7 +1007,7 @@ connect <- function( if (!missing(token)) { error_if_less_than(con$version, "2025.01.0") - if (on_connect()) { + if (on_connect() || on_connect_cloud()) { visitor_creds <- get_oauth_credentials( con, user_session_token = token, diff --git a/R/utils.R b/R/utils.R index 85e89b4e2..eecf06536 100644 --- a/R/utils.R +++ b/R/utils.R @@ -239,9 +239,16 @@ error_code <- function(res) { } # Returns `TRUE` if we're running on Connect as determined by the -# `RSTUDIO_PRODUCT` env var, else `FALSE`. +# `RSTUDIO_PRODUCT` or `POSIT_PRODUCT` env var, else `FALSE`. on_connect <- function() { - Sys.getenv("RSTUDIO_PRODUCT") == "CONNECT" + Sys.getenv("RSTUDIO_PRODUCT") == "CONNECT" || + Sys.getenv("POSIT_PRODUCT") == "CONNECT" +} + +# Returns `TRUE` if we're running on Connect Cloud as determined by the +# `POSIT_PRODUCT` env var, else `FALSE`. +on_connect_cloud <- function() { + Sys.getenv("POSIT_PRODUCT") == "CONNECT_CLOUD" } # Returns `TRUE` if running via testthat diff --git a/tests/testthat/test-connect.R b/tests/testthat/test-connect.R index 972dc6530..802262b53 100644 --- a/tests/testthat/test-connect.R +++ b/tests/testthat/test-connect.R @@ -265,6 +265,56 @@ test_that("Visitor client can successfully be created running on Connect", { }) }) +test_that("Visitor client can successfully be created running on Connect (POSIT_PRODUCT)", { + with_mock_api({ + withr::local_options(list(rlib_warning_verbosity = "verbose")) + withr::local_envvar( + CONNECT_SERVER = "https://connect.example", + CONNECT_API_KEY = "fake", + POSIT_PRODUCT = "CONNECT" + ) + + expect_warning( + client <- connect(token = "my-token"), + "This feature requires Posit Connect version" + ) + + expect_equal( + client$server, + "https://connect.example" + ) + expect_equal( + client$api_key, + "visitor-api-key" + ) + }) +}) + +test_that("Visitor client can successfully be created running on Connect Cloud", { + with_mock_api({ + withr::local_options(list(rlib_warning_verbosity = "verbose")) + withr::local_envvar( + CONNECT_SERVER = "https://connect.example", + CONNECT_API_KEY = "fake", + POSIT_PRODUCT = "CONNECT_CLOUD" + ) + + expect_warning( + client <- connect(token = "my-token"), + "This feature requires Posit Connect version" + ) + + expect_equal( + client$server, + "https://connect.example" + ) + expect_equal( + client$api_key, + "visitor-api-key" + ) + }) +}) + test_that("Visitor client can successfully be created running on Connect with audience", { with_mock_dir("2025.07.0", { withr::local_options(list(rlib_warning_verbosity = "verbose")) From ef4ca246ebef667b61fac1396c53eb5bca79d9ab Mon Sep 17 00:00:00 2001 From: Sam Perman Date: Thu, 9 Apr 2026 13:14:34 -0400 Subject: [PATCH 2/3] update error message, and NEWS.md --- NEWS.md | 3 +++ R/connect.R | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 9d151c5a1..c79f06822 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # connectapi (development version) +- Apps running on Connect Cloud are now supported for OAuth integrations via the + new `on_connect_cloud()` helper. The `POSIT_PRODUCT` environment variable is + now recognized as an alternative to `RSTUDIO_PRODUCT` for detecting Connect. - When using integrations, prefer to read from `CONNECT_CONTENT_SESSION_TOKEN_FILE` to find the session token. This helps long-running processes ensure that they can maintain fresh credentials. # connectapi 0.11.1 diff --git a/R/connect.R b/R/connect.R index d6ae120c0..bb7671f97 100644 --- a/R/connect.R +++ b/R/connect.R @@ -1018,7 +1018,7 @@ connect <- function( } else { con <- connect(server = server, api_key = token_local_testing_key) message(paste0( - "Called with `token` but not running on Connect. ", + "Called with `token` but not running on Connect or Connect Cloud. ", "Continuing with fallback API key." )) } From 8fa0a372cb1d3a6cd4ec6d722ec2e5a6f7e5d2d8 Mon Sep 17 00:00:00 2001 From: Sam Perman Date: Thu, 9 Apr 2026 13:42:38 -0400 Subject: [PATCH 3/3] Fix test to match new error message --- tests/testthat/test-connect.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-connect.R b/tests/testthat/test-connect.R index 802262b53..1549ded10 100644 --- a/tests/testthat/test-connect.R +++ b/tests/testthat/test-connect.R @@ -349,7 +349,7 @@ test_that("Visitor client uses fallback api key when running locally", { expect_warning( expect_message( client <- connect(token = NULL), - "Called with `token` but not running on Connect. Continuing with fallback API key." + "Called with `token` but not running on Connect or Connect Cloud. Continuing with fallback API key." ), "the server version is not exposed by this Posit Connect instance" ) @@ -370,7 +370,7 @@ test_that("Visitor client uses fallback api key when running locally", { token = NULL, token_local_testing_key = "fallback_fake" ), - "Called with `token` but not running on Connect. Continuing with fallback API key." + "Called with `token` but not running on Connect or Connect Cloud. Continuing with fallback API key." ), "the server version is not exposed by this Posit Connect instance" )