From 415624755759c200a49c644ccbb99452e855b812 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Thu, 31 Jul 2025 18:24:42 -0400 Subject: [PATCH 01/12] add class to represent oauth integrations --- NAMESPACE | 3 + R/integrations.R | 60 ++++++++++++++++- ...as.data.frame.connect_list_integrations.Rd | 2 +- man/as_integration.Rd | 19 ++++++ man/as_tibble.connect_list_integrations.Rd | 2 +- tests/testthat/test-integrations.R | 64 ++++++++++++++++++- 6 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 man/as_integration.Rd diff --git a/NAMESPACE b/NAMESPACE index 340e5a15..d2195979 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ S3method(api_build,op_head) S3method(as.data.frame,connect_list_hits) S3method(as.data.frame,connect_list_integrations) S3method(as.data.frame,tbl_connect) +S3method(as_integration,default) S3method(as_tibble,connect_list_hits) S3method(as_tibble,connect_list_integrations) S3method(connect_vars,op_base) @@ -16,6 +17,7 @@ S3method(connect_vars,tbl_connect) S3method(dim,tbl_connect) S3method(dimnames,tbl_connect) S3method(head,tbl_connect) +S3method(print,connect_integration) S3method(print,connect_tag_tree) S3method(print,tbl_connect) export("%>%") @@ -28,6 +30,7 @@ export(Task) export(Vanity) export(Variant) export(VariantSchedule) +export(as_integration) export(audit_access_open) export(audit_r_versions) export(audit_runas) diff --git a/R/integrations.R b/R/integrations.R index b39122a0..5c28712f 100644 --- a/R/integrations.R +++ b/R/integrations.R @@ -60,11 +60,12 @@ get_integrations <- function(client) { error_if_less_than(client$version, "2024.12.0") integrations <- client$GET(v1_url("oauth", "integrations")) + integrations <- lapply(integrations, as_integration) class(integrations) <- c("connect_list_integrations", class(integrations)) integrations } -#' Convert integrations data to a data frame +#' Convert integrations list to a data frame #' #' @description #' Converts an list returned by [get_integrations()] into a data frame. @@ -91,7 +92,7 @@ as.data.frame.connect_list_integrations <- function( ) } -#' Convert integrations data to a tibble +#' Convert integrations list to a tibble #' #' @description #' Converts a list returned by [get_integrations()] to a tibble. @@ -104,3 +105,58 @@ as.data.frame.connect_list_integrations <- function( as_tibble.connect_list_integrations <- function(x, ...) { parse_connectapi_typed(x, connectapi_ptypes$integrations) } + +# Integration class ---- + +validate_integration <- function(x) { + fields <- c( + "id", + "guid", + "created_time", + "updated_time", + "name", + "description", + "template", + "auth_type", + "config" + ) + missing_fields <- setdiff(fields, names(x)) + if (length(missing_fields) > 0) { + stop("Missing required fields: ", paste(missing_fields, collapse = ",")) + } +} + +#' Convert objects to integration class +#' +#' @param x An object to convert to an integration +#' @param ... Additional arguments passed to methods +#' +#' @return An integration object +#' @export +as_integration <- function(x, ...) { + UseMethod("as_integration") +} + +#' @export +as_integration.default <- function(x, ...) { + stop( + "Cannot convert object of class '", + class(x)[1], + "' to an integration" + ) +} + +#' @method as_integration list +as_integration.list <- function(x) { + y <- structure(x, class = c("connect_integration", "list")) + validate_integration(y) + y +} + +#' @export +print.connect_integration <- function(x, ...) { + cat("Integration:", x$name, "\n") + cat("GUID:", x$guid, "\n") + cat("Template:", x$template, "\n") + invisible(x) +} diff --git a/man/as.data.frame.connect_list_integrations.Rd b/man/as.data.frame.connect_list_integrations.Rd index 8f54ff5b..86258a78 100644 --- a/man/as.data.frame.connect_list_integrations.Rd +++ b/man/as.data.frame.connect_list_integrations.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/integrations.R \name{as.data.frame.connect_list_integrations} \alias{as.data.frame.connect_list_integrations} -\title{Convert integrations data to a data frame} +\title{Convert integrations list to a data frame} \usage{ \method{as.data.frame}{connect_list_integrations}(x, row.names = NULL, optional = FALSE, ...) } diff --git a/man/as_integration.Rd b/man/as_integration.Rd new file mode 100644 index 00000000..c4b75448 --- /dev/null +++ b/man/as_integration.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/integrations.R +\name{as_integration} +\alias{as_integration} +\title{Convert objects to integration class} +\usage{ +as_integration(x, ...) +} +\arguments{ +\item{x}{An object to convert to an integration} + +\item{...}{Additional arguments passed to methods} +} +\value{ +An integration object +} +\description{ +Convert objects to integration class +} diff --git a/man/as_tibble.connect_list_integrations.Rd b/man/as_tibble.connect_list_integrations.Rd index a060b497..3d3397bd 100644 --- a/man/as_tibble.connect_list_integrations.Rd +++ b/man/as_tibble.connect_list_integrations.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/integrations.R \name{as_tibble.connect_list_integrations} \alias{as_tibble.connect_list_integrations} -\title{Convert integrations data to a tibble} +\title{Convert integrations list to a tibble} \usage{ \method{as_tibble}{connect_list_integrations}(x, ...) } diff --git a/tests/testthat/test-integrations.R b/tests/testthat/test-integrations.R index 30127a2d..88e7db1e 100644 --- a/tests/testthat/test-integrations.R +++ b/tests/testthat/test-integrations.R @@ -2,12 +2,13 @@ with_mock_dir("2024.12.0", { test_that("get_integrations() gets integrations", { client <- Connect$new(server = "https://connect.example", api_key = "fake") integrations <- get_integrations(client) - expect_true(inherits(integrations, "connect_list_integrations")) + expect_s3_class(integrations, "connect_list_integrations") # Check a few fields expect_equal(integrations[[1]]$name, "GitHub Integration") expect_equal(integrations[[2]]$updated_time, "2025-03-25T19:07:01Z") expect_equal(integrations[[1]]$config$client_id, "client_id_123") + expect_s3_class(integrations[[1]], "connect_integration") }) test_that("get_integrations() can be converted to a data frame correctly", { @@ -46,3 +47,64 @@ test_that("get_integrations() errs on older Connect versions", { "This feature requires Posit Connect version 2024.12.0 but you are using 2024.11.1" ) }) + +test_that("as_integration correctly converts lists to integration + objects", { + valid_integration <- list( + id = "123", + guid = "abc-123", + created_time = Sys.time(), + updated_time = Sys.time(), + name = "Test Integration", + description = "A test integration", + template = "github", + auth_type = "oauth2", + config = list(client_id = "client_id") + ) + + result <- as_integration(valid_integration) + expect_s3_class(result, "connect_integration") + expect_identical(result$guid, valid_integration$guid) +}) + +test_that("as_integration validates required fields", { + invalid_integration <- list( + id = "123", + name = "Incomplete Integration" + ) + + expect_error( + as_integration(invalid_integration), + "Missing required fields" + ) +}) + +test_that("as_integration.default errors on non-list input", { + expect_error(as_integration(42), "Cannot convert object of class") + expect_error( + as_integration("string"), + "Cannot convert object of class" + ) +}) + +test_that("print.integration produces expected output", { + test_int <- structure( + list( + name = "Test Integration", + guid = "abc-123", + template = "github" + ), + class = c("connect_integration", "list") + ) + + # Capture print output + output <- capture.output(result <- print(test_int)) + + # Check output contains expected text + expect_match(output[1], "Integration: Test Integration") + expect_match(output[2], "GUID: abc-123") + expect_match(output[3], "Template: github") + + # Check it returns invisibly + expect_identical(result, test_int) +}) From 0a9c5772c3a858b2777e428d96732809a286b88d Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Thu, 31 Jul 2025 18:26:02 -0400 Subject: [PATCH 02/12] clean up --- tests/testthat/test-integrations.R | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/testthat/test-integrations.R b/tests/testthat/test-integrations.R index 88e7db1e..d06d533f 100644 --- a/tests/testthat/test-integrations.R +++ b/tests/testthat/test-integrations.R @@ -4,7 +4,6 @@ with_mock_dir("2024.12.0", { integrations <- get_integrations(client) expect_s3_class(integrations, "connect_list_integrations") - # Check a few fields expect_equal(integrations[[1]]$name, "GitHub Integration") expect_equal(integrations[[2]]$updated_time, "2025-03-25T19:07:01Z") expect_equal(integrations[[1]]$config$client_id, "client_id_123") @@ -97,14 +96,10 @@ test_that("print.integration produces expected output", { class = c("connect_integration", "list") ) - # Capture print output output <- capture.output(result <- print(test_int)) - # Check output contains expected text expect_match(output[1], "Integration: Test Integration") expect_match(output[2], "GUID: abc-123") expect_match(output[3], "Template: github") - - # Check it returns invisibly expect_identical(result, test_int) }) From d784d9055636b799346b3a0cfc489374522947e7 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Fri, 1 Aug 2025 19:26:17 -0400 Subject: [PATCH 03/12] add function to set oauth integrations of a content item --- NAMESPACE | 3 + R/content.R | 72 +++++++++++++++++ R/integrations.R | 49 +++++++++++- _pkgdown.yml | 10 +++ man/content_delete.Rd | 1 + man/content_item.Rd | 1 + man/content_set_all_integrations.Rd | 79 +++++++++++++++++++ man/content_title.Rd | 1 + man/content_update.Rd | 1 + man/create_random_name.Rd | 1 + man/dashboard_url.Rd | 1 + man/delete_thumbnail.Rd | 1 + man/delete_vanity_url.Rd | 1 + man/deploy_repo.Rd | 1 + man/environment.Rd | 1 + man/get_bundles.Rd | 2 + man/get_image.Rd | 1 + man/get_integrations.Rd | 9 ++- man/get_job.Rd | 1 + man/get_jobs.Rd | 1 + man/get_log.Rd | 1 + man/get_thumbnail.Rd | 1 + man/get_vanity_url.Rd | 1 + man/git.Rd | 1 + man/has_thumbnail.Rd | 1 + man/integration.Rd | 52 ++++++++++++ man/permissions.Rd | 1 + man/set_image.Rd | 1 + man/set_run_as.Rd | 1 + man/set_thumbnail.Rd | 1 + man/set_vanity_url.Rd | 1 + man/swap_vanity_url.Rd | 1 + man/swap_vanity_urls.Rd | 1 + man/terminate_jobs.Rd | 1 + man/verify_content_name.Rd | 1 + .../__api__/v1/content/12345678-064d19.json | 69 ++++++++++++++++ .../v1/oauth/integrations/f8688548.json | 20 +++++ tests/testthat/test-content.R | 30 +++++++ tests/testthat/test-integrations.R | 10 +++ 39 files changed, 427 insertions(+), 5 deletions(-) create mode 100644 man/content_set_all_integrations.Rd create mode 100644 man/integration.Rd create mode 100644 tests/testthat/2024.12.0/__api__/v1/content/12345678-064d19.json create mode 100644 tests/testthat/2024.12.0/__api__/v1/oauth/integrations/f8688548.json diff --git a/NAMESPACE b/NAMESPACE index d2195979..96c96eca 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,7 @@ S3method(as.data.frame,connect_list_hits) S3method(as.data.frame,connect_list_integrations) S3method(as.data.frame,tbl_connect) S3method(as_integration,default) +S3method(as_integration,list) S3method(as_tibble,connect_list_hits) S3method(as_tibble,connect_list_integrations) S3method(connect_vars,op_base) @@ -53,6 +54,7 @@ export(content_list_guid_has_access) export(content_list_with_permissions) export(content_render) export(content_restart) +export(content_set_all_integrations) export(content_title) export(content_update) export(content_update_access_type) @@ -120,6 +122,7 @@ export(get_variants) export(groups_create_remote) export(has_image) export(has_thumbnail) +export(integration) export(page_cursor) export(page_offset) export(poll_task) diff --git a/R/content.R b/R/content.R index c2dca338..09a369b4 100644 --- a/R/content.R +++ b/R/content.R @@ -1434,3 +1434,75 @@ get_content_packages <- function(content) { res <- content$packages() parse_connectapi_typed(res, connectapi_ptypes$content_packages) } + +# Integrations ---- + +#' Set all OAuth integration associations for a content item +#' +#' @description +#' Removes any existing OAuth integration associations for a content item, and +#' creates associations with the integrations provided. You must have +#' administrator or publisher privileges to perform this action. +#' +#' @param content A `Content` R6 object representing the content item to modify. +#' @param integrations A single `connect_integration` object or a list of +#' `connect_integration` objects to associate with this content. +#' +#' @return Invisibly returns `NULL`. A message is printed on success. +#' +#' @seealso +#' [get_integrations()], [integration()], [content_item()] +#' +#' @examples +#' \dontrun{ +#' client <- connect() +#' +#' content <- content_item(client, "12345678-90ab-cdef-1234-567890abcdef") +#' +#' integrations <- get_integrations(client) +#' +#' # Associate a single integration +#' github_integration <- purrr::keep(integrations, \(x) x$template == "github")[[1]] +#' content_set_all_integrations(content, github_integration) +#' +#' # Associate multiple integrations at once +#' selected_integrations <- integrations[1:2] +#' content_set_all_integrations(content, selected_integrations) +#' } +#' +#' @family oauth integration functions +#' @family content functions +#' @export +content_set_all_integrations <- function(content, integrations) { + validate_R6_class(content, "Content") + # Handle a single integration + if (inherits(integrations, "connect_integration")) { + integrations <- list(integrations) + } else if (!inherits(integrations, "list")) { + stop( + "`integrations` must be a `connect_integration` class object or a list ", + "of `connect_integration` objects." + ) + } + # Ensure that all the items we've been passed are integrations + if (!all(vapply(integrations, inherits, logical(1), "connect_integration"))) { + stop("All items must be `connect_integration` objects") + } + + json_payload <- jsonlite::toJSON( + lapply(integrations, \(x) list(oauth_integration_guid = x$guid)), + auto_unbox = TRUE + ) + content$connect$PUT( + v1_url( + "content", + content$content$guid, + "oauth", + "integrations", + "associations" + ), + body = json_payload + ) + print("Successfully set the associations for the content item.") + invisible(NULL) +} diff --git a/R/integrations.R b/R/integrations.R index 5c28712f..a6de59d5 100644 --- a/R/integrations.R +++ b/R/integrations.R @@ -20,7 +20,7 @@ #' * `template`: The template used to configure this OAuth integration. #' * `auth_type`: The authentication type indicates which OAuth flow is used by #' this integration. -#' * `config`: A sub-list list with the OAuth integration configuration. Fields +#' * `config`: A list with the OAuth integration configuration. Fields #' differ between integrations. #' #' Use [as.data.frame()] or [tibble::as_tibble()] to convert to a data frame with @@ -29,7 +29,7 @@ #' * `created_time` and `updated_time` are parsed to `POSIXct`. #' * `config` remains as a list-column. #' -#' @seealso [get_oauth_credentials()], [get_oauth_content_credentials()] +#' @seealso [get_oauth_credentials()], [get_oauth_content_credentials()], [integration()] #' #' @examples #' \dontrun{ @@ -56,6 +56,7 @@ #' integrations_df <- tibble::as_tibble(integrations) #' } #' +#' @family oauth integration functions #' @export get_integrations <- function(client) { error_if_less_than(client$version, "2024.12.0") @@ -146,7 +147,7 @@ as_integration.default <- function(x, ...) { ) } -#' @method as_integration list +#' @export as_integration.list <- function(x) { y <- structure(x, class = c("connect_integration", "list")) validate_integration(y) @@ -160,3 +161,45 @@ print.connect_integration <- function(x, ...) { cat("Template:", x$template, "\n") invisible(x) } + +#' Get the details of an OAuth integration +#' +#' @description +#' Given the GUID of an OAuth integration available on a Connect server, retrieve +#' its details. You must have administrator or publisher privileges to perform +#' this action. +#' +#' @param client A `Connect` R6 client object. +#' @param guid The GUID of an integration available on the Connect server. +#' +#' @return A `connect_integration` object representing an OAuth integration, +#' which has the following fields: +#' +#' * `id`: The internal identifier of this OAuth integration. +#' * `guid`: The GUID of this OAuth integration. +#' * `created_time`: The timestamp (RFC3339) indicating when this integration +#' was created. +#' * `updated_time`: The timestamp (RFC3339) indicating when this integration +#' was last updated +#' * `name`: A descriptive name to identify the OAuth integration. +#' * `description`: A brief text to describe the OAuth integration. +#' * `template`: The template used to configure this OAuth integration. +#' * `auth_type`: The authentication type indicates which OAuth flow is used by +#' this integration. +#' * `config`: A list with the OAuth integration configuration. Fields +#' differ between integrations. +#' +#' @seealso [get_oauth_credentials()], [get_oauth_content_credentials()], [get_integrations()] +#' +#' @examples +#' \dontrun{ +#' client <- connect() +#' x <- integration(client, guid) +#' } +#' +#' @family oauth integration functions +#' @export +integration <- function(client, guid) { + validate_R6_class(client, "Connect") + as_integration(client$GET(v1_url("oauth", "integrations", guid))) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index ae9f6d7d..0a020c2e 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -62,6 +62,16 @@ reference: contents: - matches("repo") + - title: "OAuth Integrations" + desc: > + Functions to work with OAuth integrations + contents: + - matches("integration") + - content_set_all_integrations + - get_integrations + - get_oauth_credentials + - get_oauth_content_credentials + - title: "Reporting" desc: > Helpers to "get" data out of Connect diff --git a/man/content_delete.Rd b/man/content_delete.Rd index 58a21cf4..7279c38f 100644 --- a/man/content_delete.Rd +++ b/man/content_delete.Rd @@ -21,6 +21,7 @@ logs, and resources about a content item. It \emph{cannot} be undone. \seealso{ Other content functions: \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/content_item.Rd b/man/content_item.Rd index aabc8aac..e96557b2 100644 --- a/man/content_item.Rd +++ b/man/content_item.Rd @@ -27,6 +27,7 @@ connect() \%>\% \seealso{ Other content functions: \code{\link{content_delete}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/content_set_all_integrations.Rd b/man/content_set_all_integrations.Rd new file mode 100644 index 00000000..99b51c5c --- /dev/null +++ b/man/content_set_all_integrations.Rd @@ -0,0 +1,79 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/content.R +\name{content_set_all_integrations} +\alias{content_set_all_integrations} +\title{Set all OAuth integration associations for a content item} +\usage{ +content_set_all_integrations(content, integrations) +} +\arguments{ +\item{content}{A \code{Content} R6 object representing the content item to modify.} + +\item{integrations}{A single \code{connect_integration} object or a list of +\code{connect_integration} objects to associate with this content.} +} +\value{ +Invisibly returns \code{NULL}. A message is printed on success. +} +\description{ +Removes any existing OAuth integration associations for a content item, and +creates associations with the integrations provided. You must have +administrator or publisher privileges to perform this action. +} +\examples{ +\dontrun{ +client <- connect() + +content <- content_item(client, "12345678-90ab-cdef-1234-567890abcdef") + +integrations <- get_integrations(client) + +# Associate a single integration +github_integration <- purrr::keep(integrations, \(x) x$template == "github")[[1]] +content_set_all_integrations(content, github_integration) + +# Associate multiple integrations at once +selected_integrations <- integrations[1:2] +content_set_all_integrations(content, selected_integrations) +} + +} +\seealso{ +\code{\link[=get_integrations]{get_integrations()}}, \code{\link[=integration]{integration()}}, \code{\link[=content_item]{content_item()}} + +Other oauth integration functions: +\code{\link{get_integrations}()}, +\code{\link{integration}()} + +Other content functions: +\code{\link{content_delete}()}, +\code{\link{content_item}()}, +\code{\link{content_title}()}, +\code{\link{content_update}()}, +\code{\link{create_random_name}()}, +\code{\link{dashboard_url}()}, +\code{\link{delete_thumbnail}()}, +\code{\link{delete_vanity_url}()}, +\code{\link{deploy_repo}()}, +\code{\link{get_bundles}()}, +\code{\link{get_environment}()}, +\code{\link{get_image}()}, +\code{\link{get_job}()}, +\code{\link{get_jobs}()}, +\code{\link{get_log}()}, +\code{\link{get_thumbnail}()}, +\code{\link{get_vanity_url}()}, +\code{\link{git}}, +\code{\link{has_thumbnail}()}, +\code{\link{permissions}}, +\code{\link{set_image_path}()}, +\code{\link{set_run_as}()}, +\code{\link{set_thumbnail}()}, +\code{\link{set_vanity_url}()}, +\code{\link{swap_vanity_url}()}, +\code{\link{swap_vanity_urls}()}, +\code{\link{terminate_jobs}()}, +\code{\link{verify_content_name}()} +} +\concept{content functions} +\concept{oauth integration functions} diff --git a/man/content_title.Rd b/man/content_title.Rd index 9d74b6b1..cfd978ac 100644 --- a/man/content_title.Rd +++ b/man/content_title.Rd @@ -24,6 +24,7 @@ is missing (deleted) or not visible, then returns the \code{default} Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, diff --git a/man/content_update.Rd b/man/content_update.Rd index 29cef5e3..d488adb5 100644 --- a/man/content_update.Rd +++ b/man/content_update.Rd @@ -44,6 +44,7 @@ etc. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, diff --git a/man/create_random_name.Rd b/man/create_random_name.Rd index e4103ed8..d6300073 100644 --- a/man/create_random_name.Rd +++ b/man/create_random_name.Rd @@ -21,6 +21,7 @@ connectapi::verify_content_name Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{dashboard_url}()}, diff --git a/man/dashboard_url.Rd b/man/dashboard_url.Rd index b86e53a2..74599561 100644 --- a/man/dashboard_url.Rd +++ b/man/dashboard_url.Rd @@ -21,6 +21,7 @@ Returns the URL for the content dashboard (opened to the selected pane). Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/delete_thumbnail.Rd b/man/delete_thumbnail.Rd index 87a30706..ca1b4f1b 100644 --- a/man/delete_thumbnail.Rd +++ b/man/delete_thumbnail.Rd @@ -32,6 +32,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/delete_vanity_url.Rd b/man/delete_vanity_url.Rd index c30dbcbc..3c1adeca 100644 --- a/man/delete_vanity_url.Rd +++ b/man/delete_vanity_url.Rd @@ -16,6 +16,7 @@ Delete the vanity URL for a piece of content. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/deploy_repo.Rd b/man/deploy_repo.Rd index 5cc312c0..4d958376 100644 --- a/man/deploy_repo.Rd +++ b/man/deploy_repo.Rd @@ -59,6 +59,7 @@ connectapi::poll_task, connectapi::repo_check_branches, connectapi::repo_check_m Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/environment.Rd b/man/environment.Rd index 704906f2..239e3f9a 100644 --- a/man/environment.Rd +++ b/man/environment.Rd @@ -41,6 +41,7 @@ variables not specified) Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_bundles.Rd b/man/get_bundles.Rd index 16146f87..dd432544 100644 --- a/man/get_bundles.Rd +++ b/man/get_bundles.Rd @@ -21,6 +21,7 @@ Lists bundles for a content item Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, @@ -50,6 +51,7 @@ Other content functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_image.Rd b/man/get_image.Rd index 2bced5af..27efbc3a 100644 --- a/man/get_image.Rd +++ b/man/get_image.Rd @@ -31,6 +31,7 @@ Please use \code{\link{get_thumbnail}}, Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_integrations.Rd b/man/get_integrations.Rd index 26dad24c..22ea2df4 100644 --- a/man/get_integrations.Rd +++ b/man/get_integrations.Rd @@ -24,7 +24,7 @@ was last updated \item \code{template}: The template used to configure this OAuth integration. \item \code{auth_type}: The authentication type indicates which OAuth flow is used by this integration. -\item \code{config}: A sub-list list with the OAuth integration configuration. Fields +\item \code{config}: A list with the OAuth integration configuration. Fields differ between integrations. } @@ -66,5 +66,10 @@ integrations_df <- tibble::as_tibble(integrations) } \seealso{ -\code{\link[=get_oauth_credentials]{get_oauth_credentials()}}, \code{\link[=get_oauth_content_credentials]{get_oauth_content_credentials()}} +\code{\link[=get_oauth_credentials]{get_oauth_credentials()}}, \code{\link[=get_oauth_content_credentials]{get_oauth_content_credentials()}}, \code{\link[=integration]{integration()}} + +Other oauth integration functions: +\code{\link{content_set_all_integrations}()}, +\code{\link{integration}()} } +\concept{oauth integration functions} diff --git a/man/get_job.Rd b/man/get_job.Rd index 48588c3e..2411aed5 100644 --- a/man/get_job.Rd +++ b/man/get_job.Rd @@ -25,6 +25,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_jobs.Rd b/man/get_jobs.Rd index ba9a2959..2df1185d 100644 --- a/man/get_jobs.Rd +++ b/man/get_jobs.Rd @@ -100,6 +100,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_log.Rd b/man/get_log.Rd index 28a1f272..88eb407c 100644 --- a/man/get_log.Rd +++ b/man/get_log.Rd @@ -47,6 +47,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_thumbnail.Rd b/man/get_thumbnail.Rd index bc4c1d42..34ba2869 100644 --- a/man/get_thumbnail.Rd +++ b/man/get_thumbnail.Rd @@ -37,6 +37,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_vanity_url.Rd b/man/get_vanity_url.Rd index fe582453..c2fd8a7f 100644 --- a/man/get_vanity_url.Rd +++ b/man/get_vanity_url.Rd @@ -19,6 +19,7 @@ Get the vanity URL for a piece of content. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/git.Rd b/man/git.Rd index 6d379c29..46aa6926 100644 --- a/man/git.Rd +++ b/man/git.Rd @@ -44,6 +44,7 @@ connectapi::deploy_repo Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/has_thumbnail.Rd b/man/has_thumbnail.Rd index fa1e78fa..10d921d7 100644 --- a/man/has_thumbnail.Rd +++ b/man/has_thumbnail.Rd @@ -33,6 +33,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/integration.Rd b/man/integration.Rd new file mode 100644 index 00000000..2dba8739 --- /dev/null +++ b/man/integration.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/integrations.R +\name{integration} +\alias{integration} +\title{Get the details of an OAuth integration} +\usage{ +integration(client, guid) +} +\arguments{ +\item{client}{A \code{Connect} R6 client object.} + +\item{guid}{The GUID of an integration available on the Connect server.} +} +\value{ +A \code{connect_integration} object representing an OAuth integration, +which has the following fields: +\itemize{ +\item \code{id}: The internal identifier of this OAuth integration. +\item \code{guid}: The GUID of this OAuth integration. +\item \code{created_time}: The timestamp (RFC3339) indicating when this integration +was created. +\item \code{updated_time}: The timestamp (RFC3339) indicating when this integration +was last updated +\item \code{name}: A descriptive name to identify the OAuth integration. +\item \code{description}: A brief text to describe the OAuth integration. +\item \code{template}: The template used to configure this OAuth integration. +\item \code{auth_type}: The authentication type indicates which OAuth flow is used by +this integration. +\item \code{config}: A list with the OAuth integration configuration. Fields +differ between integrations. +} +} +\description{ +Given the GUID of an OAuth integration available on a Connect server, retrieve +its details. You must have administrator or publisher privileges to perform +this action. +} +\examples{ +\dontrun{ +client <- connect() +x <- integration(client, guid) +} + +} +\seealso{ +\code{\link[=get_oauth_credentials]{get_oauth_credentials()}}, \code{\link[=get_oauth_content_credentials]{get_oauth_content_credentials()}}, \code{\link[=get_integrations]{get_integrations()}} + +Other oauth integration functions: +\code{\link{content_set_all_integrations}()}, +\code{\link{get_integrations}()} +} +\concept{oauth integration functions} diff --git a/man/permissions.Rd b/man/permissions.Rd index 8eb3e05d..013b4149 100644 --- a/man/permissions.Rd +++ b/man/permissions.Rd @@ -66,6 +66,7 @@ This makes it easier to find / isolate this record. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_image.Rd b/man/set_image.Rd index a35e284b..66a1d223 100644 --- a/man/set_image.Rd +++ b/man/set_image.Rd @@ -37,6 +37,7 @@ skips and warns for any content that requires authentication until the Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_run_as.Rd b/man/set_run_as.Rd index 43593146..8921496e 100644 --- a/man/set_run_as.Rd +++ b/man/set_run_as.Rd @@ -39,6 +39,7 @@ connectapi::content_update Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_thumbnail.Rd b/man/set_thumbnail.Rd index 63e2360e..4974f2b1 100644 --- a/man/set_thumbnail.Rd +++ b/man/set_thumbnail.Rd @@ -36,6 +36,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_vanity_url.Rd b/man/set_vanity_url.Rd index 7bd9c776..85e02fc2 100644 --- a/man/set_vanity_url.Rd +++ b/man/set_vanity_url.Rd @@ -32,6 +32,7 @@ connect() \%>\% Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/swap_vanity_url.Rd b/man/swap_vanity_url.Rd index c9854ef0..ba3fbce2 100644 --- a/man/swap_vanity_url.Rd +++ b/man/swap_vanity_url.Rd @@ -22,6 +22,7 @@ This function is deprecated; please use \code{\link{swap_vanity_urls}}. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/swap_vanity_urls.Rd b/man/swap_vanity_urls.Rd index c95957b0..20686dcb 100644 --- a/man/swap_vanity_urls.Rd +++ b/man/swap_vanity_urls.Rd @@ -21,6 +21,7 @@ Swap the vanity URLs of two pieces of content. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/terminate_jobs.Rd b/man/terminate_jobs.Rd index b3245828..af55fec1 100644 --- a/man/terminate_jobs.Rd +++ b/man/terminate_jobs.Rd @@ -49,6 +49,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/verify_content_name.Rd b/man/verify_content_name.Rd index f26d3b5d..fd992602 100644 --- a/man/verify_content_name.Rd +++ b/man/verify_content_name.Rd @@ -24,6 +24,7 @@ connectapi::create_random_name Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, +\code{\link{content_set_all_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/tests/testthat/2024.12.0/__api__/v1/content/12345678-064d19.json b/tests/testthat/2024.12.0/__api__/v1/content/12345678-064d19.json new file mode 100644 index 00000000..6101474e --- /dev/null +++ b/tests/testthat/2024.12.0/__api__/v1/content/12345678-064d19.json @@ -0,0 +1,69 @@ +{ + "guid": "12345678", + "name": "fake-app-2000", + "title": "fake-app-2000", + "description": "", + "access_type": "acl", + "locked": false, + "locked_message": "", + "connection_timeout": null, + "read_timeout": null, + "init_timeout": null, + "idle_timeout": null, + "max_processes": null, + "min_processes": null, + "max_conns_per_process": null, + "load_factor": null, + "memory_request": null, + "memory_limit": null, + "cpu_request": null, + "cpu_limit": null, + "amd_gpu_limit": null, + "nvidia_gpu_limit": null, + "service_account_name": null, + "default_image_name": null, + "created_time": "2024-08-22T15:44:48Z", + "last_deployed_time": "2024-08-22T15:44:49Z", + "bundle_id": "142621", + "app_mode": "shiny", + "content_category": "", + "parameterized": false, + "cluster_name": "Local", + "image_name": null, + "r_version": "4.4.0", + "py_version": null, + "quarto_version": null, + "r_environment_management": true, + "default_r_environment_management": null, + "py_environment_management": null, + "default_py_environment_management": null, + "run_as": null, + "run_as_current_user": false, + "owner_guid": "fe07bf64", + "content_url": "https://connect.example/content/12345678/", + "dashboard_url": "https://connect.example/connect/#/apps/12345678", + "app_role": "owner", + "id": "56746", + "tags": [ + { + "id": "2", + "name": "tag1", + "parent_id": "1", + "created_time": "2017-04-18T19:54:24Z", + "updated_time": "2017-05-19T18:15:39Z" + }, + { + "id": "3", + "name": "tag2", + "parent_id": "2", + "created_time": "2017-04-18T19:54:32Z", + "updated_time": "2017-05-03T20:15:27Z" + } + ], + "owner": { + "guid": "2bdffba4-2efd-436c-a30d-6dc5b5e2bb99", + "username": "a_user", + "first_name": "A", + "last_name": "User" + } +} diff --git a/tests/testthat/2024.12.0/__api__/v1/oauth/integrations/f8688548.json b/tests/testthat/2024.12.0/__api__/v1/oauth/integrations/f8688548.json new file mode 100644 index 00000000..a61babb1 --- /dev/null +++ b/tests/testthat/2024.12.0/__api__/v1/oauth/integrations/f8688548.json @@ -0,0 +1,20 @@ +{ + "id": "4", + "guid": "f8688548", + "created_time": "2024-08-01T20:14:31Z", + "updated_time": "2025-03-25T19:08:26Z", + "name": "GitHub Integration", + "description": "with refresh support ", + "template": "custom", + "auth_type": "Viewer", + "config": { + "auth_mode": "Confidential", + "auth_type": "Viewer", + "authorization_uri": "https://github.com/login/oauth/authorize", + "client_id": "client_id_123", + "scopes": "offline_access openid profile email repo read:user", + "token_endpoint_auth_method": "client_secret_post", + "token_uri": "https://github.com/login/oauth/access_token", + "use_pkce": true + } +} diff --git a/tests/testthat/test-content.R b/tests/testthat/test-content.R index eb29015e..cb6dda3a 100644 --- a/tests/testthat/test-content.R +++ b/tests/testthat/test-content.R @@ -466,3 +466,33 @@ test_that("get_content_packages() gets packages", { ) }) }) + +test_that("content_set_all_integrations() sends expected request", { + with_mock_dir("2024.12.0", { + client <- Connect$new(server = "https://connect.example", api_key = "fake") + x <- content_item(client, "12345678") + y <- integration(client, "f8688548") + }) + without_internet( + expect_PUT( + content_set_all_integrations(x, y), + url = "https://connect.example/__api__/v1/content/12345678/oauth/integrations/associations", + '[{"oauth_integration_guid":"f8688548"}]' + ) + ) +}) + +test_that("content_set_all_integrations() fails when provided the wrong class", { + with_mock_dir("2024.12.0", { + client <- Connect$new(server = "https://connect.example", api_key = "fake") + x <- content_item(client, "12345678") + }) + expect_error( + content_set_all_integrations(x, "string"), + "`integrations` must be a `connect_integration` class object or a list" + ) + expect_error( + content_set_all_integrations(x, list("string")), + "All items must be `connect_integration` objects" + ) +}) diff --git a/tests/testthat/test-integrations.R b/tests/testthat/test-integrations.R index d06d533f..2cdaf497 100644 --- a/tests/testthat/test-integrations.R +++ b/tests/testthat/test-integrations.R @@ -103,3 +103,13 @@ test_that("print.integration produces expected output", { expect_match(output[3], "Template: github") expect_identical(result, test_int) }) + +with_mock_dir("2024.12.0", { + test_that("integration creates a single integration", { + client <- Connect$new(server = "https://connect.example", api_key = "fake") + x <- integration(client, "f8688548") + expect_s3_class(x, "connect_integration") + expect_equal(x$template, "custom") + expect_equal(x$guid, "f8688548") + }) +}) From fc8b95776abfa77c1b3b0028a61148630319b0a9 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Fri, 1 Aug 2025 19:29:29 -0400 Subject: [PATCH 04/12] update news --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 3857b0de..1772835d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,10 @@ # connectapi (development version) +- New `content_set_all_integrations()` function to set the OAuth integration + associations for a content item. (#414) +- New `integration()` function to retrieve details of a specific OAuth integration + from a Connect server. (#431) + # connectapi 0.8.0 ## Breaking changes From ea08ded71aed22dd923b01c761212aca52398ec4 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Fri, 1 Aug 2025 19:41:35 -0400 Subject: [PATCH 05/12] align methods --- R/integrations.R | 5 ++--- man/as_integration.Rd | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/R/integrations.R b/R/integrations.R index a6de59d5..80bd569a 100644 --- a/R/integrations.R +++ b/R/integrations.R @@ -130,16 +130,15 @@ validate_integration <- function(x) { #' Convert objects to integration class #' #' @param x An object to convert to an integration -#' @param ... Additional arguments passed to methods #' #' @return An integration object #' @export -as_integration <- function(x, ...) { +as_integration <- function(x) { UseMethod("as_integration") } #' @export -as_integration.default <- function(x, ...) { +as_integration.default <- function(x) { stop( "Cannot convert object of class '", class(x)[1], diff --git a/man/as_integration.Rd b/man/as_integration.Rd index c4b75448..c042cebe 100644 --- a/man/as_integration.Rd +++ b/man/as_integration.Rd @@ -4,12 +4,10 @@ \alias{as_integration} \title{Convert objects to integration class} \usage{ -as_integration(x, ...) +as_integration(x) } \arguments{ \item{x}{An object to convert to an integration} - -\item{...}{Additional arguments passed to methods} } \value{ An integration object From 842a473618b8eb8ad3994353dd7aea50918fbe45 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 10:59:17 -0400 Subject: [PATCH 06/12] Update R/content.R Co-authored-by: Neal Richardson --- R/content.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/content.R b/R/content.R index 09a369b4..f967c83b 100644 --- a/R/content.R +++ b/R/content.R @@ -1503,6 +1503,5 @@ content_set_all_integrations <- function(content, integrations) { ), body = json_payload ) - print("Successfully set the associations for the content item.") invisible(NULL) } From e66e3f54bc2273e37cebc4b924f4b82b3171d633 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 12:02:00 -0400 Subject: [PATCH 07/12] respond to feedback --- NAMESPACE | 4 ++-- NEWS.md | 4 ++-- R/content.R | 18 +++++++--------- R/integrations.R | 21 ++++++------------- _pkgdown.yml | 2 +- man/content_delete.Rd | 2 +- man/content_item.Rd | 2 +- ...rations.Rd => content_set_integrations.Rd} | 16 +++++++------- man/content_title.Rd | 2 +- man/content_update.Rd | 2 +- man/create_random_name.Rd | 2 +- man/dashboard_url.Rd | 2 +- man/delete_thumbnail.Rd | 2 +- man/delete_vanity_url.Rd | 2 +- man/deploy_repo.Rd | 2 +- man/environment.Rd | 2 +- man/get_bundles.Rd | 4 ++-- man/get_image.Rd | 2 +- man/{integration.Rd => get_integration.Rd} | 10 ++++----- man/get_integrations.Rd | 7 ++++--- man/get_job.Rd | 2 +- man/get_jobs.Rd | 2 +- man/get_log.Rd | 2 +- man/get_thumbnail.Rd | 2 +- man/get_vanity_url.Rd | 2 +- man/git.Rd | 2 +- man/has_thumbnail.Rd | 2 +- man/permissions.Rd | 2 +- man/set_image.Rd | 2 +- man/set_run_as.Rd | 2 +- man/set_thumbnail.Rd | 2 +- man/set_vanity_url.Rd | 2 +- man/swap_vanity_url.Rd | 2 +- man/swap_vanity_urls.Rd | 2 +- man/terminate_jobs.Rd | 2 +- man/verify_content_name.Rd | 2 +- tests/testthat/test-content.R | 12 +++++------ tests/testthat/test-integrations.R | 2 +- 38 files changed, 72 insertions(+), 82 deletions(-) rename man/{content_set_all_integrations.Rd => content_set_integrations.Rd} (84%) rename man/{integration.Rd => get_integration.Rd} (91%) diff --git a/NAMESPACE b/NAMESPACE index 96c96eca..c83e086c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -54,7 +54,7 @@ export(content_list_guid_has_access) export(content_list_with_permissions) export(content_render) export(content_restart) -export(content_set_all_integrations) +export(content_set_integrations) export(content_title) export(content_update) export(content_update_access_type) @@ -91,6 +91,7 @@ export(get_group_members) export(get_group_permission) export(get_groups) export(get_image) +export(get_integration) export(get_integrations) export(get_job) export(get_job_list) @@ -122,7 +123,6 @@ export(get_variants) export(groups_create_remote) export(has_image) export(has_thumbnail) -export(integration) export(page_cursor) export(page_offset) export(poll_task) diff --git a/NEWS.md b/NEWS.md index 1772835d..9222c718 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,8 @@ # connectapi (development version) -- New `content_set_all_integrations()` function to set the OAuth integration +- New `content_set_integrations()` function to set the OAuth integration associations for a content item. (#414) -- New `integration()` function to retrieve details of a specific OAuth integration +- New `get_integration()` function to retrieve details of a specific OAuth integration from a Connect server. (#431) # connectapi 0.8.0 diff --git a/R/content.R b/R/content.R index f967c83b..64cae9b0 100644 --- a/R/content.R +++ b/R/content.R @@ -1451,7 +1451,7 @@ get_content_packages <- function(content) { #' @return Invisibly returns `NULL`. A message is printed on success. #' #' @seealso -#' [get_integrations()], [integration()], [content_item()] +#' [get_integrations()], [get_integration()], [content_item()] #' #' @examples #' \dontrun{ @@ -1463,17 +1463,17 @@ get_content_packages <- function(content) { #' #' # Associate a single integration #' github_integration <- purrr::keep(integrations, \(x) x$template == "github")[[1]] -#' content_set_all_integrations(content, github_integration) +#' content_set_integrations(content, github_integration) #' #' # Associate multiple integrations at once #' selected_integrations <- integrations[1:2] -#' content_set_all_integrations(content, selected_integrations) +#' content_set_integrations(content, selected_integrations) #' } #' #' @family oauth integration functions #' @family content functions #' @export -content_set_all_integrations <- function(content, integrations) { +content_set_integrations <- function(content, integrations) { validate_R6_class(content, "Content") # Handle a single integration if (inherits(integrations, "connect_integration")) { @@ -1485,14 +1485,12 @@ content_set_all_integrations <- function(content, integrations) { ) } # Ensure that all the items we've been passed are integrations - if (!all(vapply(integrations, inherits, logical(1), "connect_integration"))) { + if (!purrr::every(integrations, \(x) inherits(x, "connect_integration"))) { stop("All items must be `connect_integration` objects") } - json_payload <- jsonlite::toJSON( - lapply(integrations, \(x) list(oauth_integration_guid = x$guid)), - auto_unbox = TRUE - ) + payload <- purrr::map(integrations, \(x) list(oauth_integration_guid = x$guid)) + content$connect$PUT( v1_url( "content", @@ -1501,7 +1499,7 @@ content_set_all_integrations <- function(content, integrations) { "integrations", "associations" ), - body = json_payload + body = payload ) invisible(NULL) } diff --git a/R/integrations.R b/R/integrations.R index 80bd569a..06437a2e 100644 --- a/R/integrations.R +++ b/R/integrations.R @@ -29,7 +29,8 @@ #' * `created_time` and `updated_time` are parsed to `POSIXct`. #' * `config` remains as a list-column. #' -#' @seealso [get_oauth_credentials()], [get_oauth_content_credentials()], [integration()] +#' @seealso [get_oauth_credentials()], [get_oauth_content_credentials()], +#' [get_integration()] #' #' @examples #' \dontrun{ @@ -59,6 +60,7 @@ #' @family oauth integration functions #' @export get_integrations <- function(client) { + validate_R6_class(client, "Connect") error_if_less_than(client$version, "2024.12.0") integrations <- client$GET(v1_url("oauth", "integrations")) integrations <- lapply(integrations, as_integration) @@ -110,18 +112,7 @@ as_tibble.connect_list_integrations <- function(x, ...) { # Integration class ---- validate_integration <- function(x) { - fields <- c( - "id", - "guid", - "created_time", - "updated_time", - "name", - "description", - "template", - "auth_type", - "config" - ) - missing_fields <- setdiff(fields, names(x)) + missing_fields <- setdiff(names(connectapi_ptypes$integrations), names(x)) if (length(missing_fields) > 0) { stop("Missing required fields: ", paste(missing_fields, collapse = ",")) } @@ -193,12 +184,12 @@ print.connect_integration <- function(x, ...) { #' @examples #' \dontrun{ #' client <- connect() -#' x <- integration(client, guid) +#' x <- get_integration(client, guid) #' } #' #' @family oauth integration functions #' @export -integration <- function(client, guid) { +get_integration <- function(client, guid) { validate_R6_class(client, "Connect") as_integration(client$GET(v1_url("oauth", "integrations", guid))) } diff --git a/_pkgdown.yml b/_pkgdown.yml index 0a020c2e..38da9515 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -67,7 +67,7 @@ reference: Functions to work with OAuth integrations contents: - matches("integration") - - content_set_all_integrations + - content_set_integrations - get_integrations - get_oauth_credentials - get_oauth_content_credentials diff --git a/man/content_delete.Rd b/man/content_delete.Rd index 7279c38f..4c9da7a5 100644 --- a/man/content_delete.Rd +++ b/man/content_delete.Rd @@ -21,7 +21,7 @@ logs, and resources about a content item. It \emph{cannot} be undone. \seealso{ Other content functions: \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/content_item.Rd b/man/content_item.Rd index e96557b2..43f73cf8 100644 --- a/man/content_item.Rd +++ b/man/content_item.Rd @@ -27,7 +27,7 @@ connect() \%>\% \seealso{ Other content functions: \code{\link{content_delete}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/content_set_all_integrations.Rd b/man/content_set_integrations.Rd similarity index 84% rename from man/content_set_all_integrations.Rd rename to man/content_set_integrations.Rd index 99b51c5c..0ba6e622 100644 --- a/man/content_set_all_integrations.Rd +++ b/man/content_set_integrations.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/content.R -\name{content_set_all_integrations} -\alias{content_set_all_integrations} +\name{content_set_integrations} +\alias{content_set_integrations} \title{Set all OAuth integration associations for a content item} \usage{ -content_set_all_integrations(content, integrations) +content_set_integrations(content, integrations) } \arguments{ \item{content}{A \code{Content} R6 object representing the content item to modify.} @@ -30,20 +30,20 @@ integrations <- get_integrations(client) # Associate a single integration github_integration <- purrr::keep(integrations, \(x) x$template == "github")[[1]] -content_set_all_integrations(content, github_integration) +content_set_integrations(content, github_integration) # Associate multiple integrations at once selected_integrations <- integrations[1:2] -content_set_all_integrations(content, selected_integrations) +content_set_integrations(content, selected_integrations) } } \seealso{ -\code{\link[=get_integrations]{get_integrations()}}, \code{\link[=integration]{integration()}}, \code{\link[=content_item]{content_item()}} +\code{\link[=get_integrations]{get_integrations()}}, \code{\link[=get_integration]{get_integration()}}, \code{\link[=content_item]{content_item()}} Other oauth integration functions: -\code{\link{get_integrations}()}, -\code{\link{integration}()} +\code{\link{get_integration}()}, +\code{\link{get_integrations}()} Other content functions: \code{\link{content_delete}()}, diff --git a/man/content_title.Rd b/man/content_title.Rd index cfd978ac..dc9e96eb 100644 --- a/man/content_title.Rd +++ b/man/content_title.Rd @@ -24,7 +24,7 @@ is missing (deleted) or not visible, then returns the \code{default} Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, diff --git a/man/content_update.Rd b/man/content_update.Rd index d488adb5..40c5a863 100644 --- a/man/content_update.Rd +++ b/man/content_update.Rd @@ -44,7 +44,7 @@ etc. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{create_random_name}()}, \code{\link{dashboard_url}()}, diff --git a/man/create_random_name.Rd b/man/create_random_name.Rd index d6300073..6eaec236 100644 --- a/man/create_random_name.Rd +++ b/man/create_random_name.Rd @@ -21,7 +21,7 @@ connectapi::verify_content_name Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{dashboard_url}()}, diff --git a/man/dashboard_url.Rd b/man/dashboard_url.Rd index 74599561..89fff4c4 100644 --- a/man/dashboard_url.Rd +++ b/man/dashboard_url.Rd @@ -21,7 +21,7 @@ Returns the URL for the content dashboard (opened to the selected pane). Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/delete_thumbnail.Rd b/man/delete_thumbnail.Rd index ca1b4f1b..88b01a76 100644 --- a/man/delete_thumbnail.Rd +++ b/man/delete_thumbnail.Rd @@ -32,7 +32,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/delete_vanity_url.Rd b/man/delete_vanity_url.Rd index 3c1adeca..f156d517 100644 --- a/man/delete_vanity_url.Rd +++ b/man/delete_vanity_url.Rd @@ -16,7 +16,7 @@ Delete the vanity URL for a piece of content. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/deploy_repo.Rd b/man/deploy_repo.Rd index 4d958376..7558379c 100644 --- a/man/deploy_repo.Rd +++ b/man/deploy_repo.Rd @@ -59,7 +59,7 @@ connectapi::poll_task, connectapi::repo_check_branches, connectapi::repo_check_m Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/environment.Rd b/man/environment.Rd index 239e3f9a..f86437fb 100644 --- a/man/environment.Rd +++ b/man/environment.Rd @@ -41,7 +41,7 @@ variables not specified) Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_bundles.Rd b/man/get_bundles.Rd index dd432544..523055e0 100644 --- a/man/get_bundles.Rd +++ b/man/get_bundles.Rd @@ -21,7 +21,7 @@ Lists bundles for a content item Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, @@ -51,7 +51,7 @@ Other content functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_image.Rd b/man/get_image.Rd index 27efbc3a..0de4ef2b 100644 --- a/man/get_image.Rd +++ b/man/get_image.Rd @@ -31,7 +31,7 @@ Please use \code{\link{get_thumbnail}}, Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/integration.Rd b/man/get_integration.Rd similarity index 91% rename from man/integration.Rd rename to man/get_integration.Rd index 2dba8739..7d31d416 100644 --- a/man/integration.Rd +++ b/man/get_integration.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/integrations.R -\name{integration} -\alias{integration} +\name{get_integration} +\alias{get_integration} \title{Get the details of an OAuth integration} \usage{ -integration(client, guid) +get_integration(client, guid) } \arguments{ \item{client}{A \code{Connect} R6 client object.} @@ -38,7 +38,7 @@ this action. \examples{ \dontrun{ client <- connect() -x <- integration(client, guid) +x <- get_integration(client, guid) } } @@ -46,7 +46,7 @@ x <- integration(client, guid) \code{\link[=get_oauth_credentials]{get_oauth_credentials()}}, \code{\link[=get_oauth_content_credentials]{get_oauth_content_credentials()}}, \code{\link[=get_integrations]{get_integrations()}} Other oauth integration functions: -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{get_integrations}()} } \concept{oauth integration functions} diff --git a/man/get_integrations.Rd b/man/get_integrations.Rd index 22ea2df4..75eca010 100644 --- a/man/get_integrations.Rd +++ b/man/get_integrations.Rd @@ -66,10 +66,11 @@ integrations_df <- tibble::as_tibble(integrations) } \seealso{ -\code{\link[=get_oauth_credentials]{get_oauth_credentials()}}, \code{\link[=get_oauth_content_credentials]{get_oauth_content_credentials()}}, \code{\link[=integration]{integration()}} +\code{\link[=get_oauth_credentials]{get_oauth_credentials()}}, \code{\link[=get_oauth_content_credentials]{get_oauth_content_credentials()}}, +\code{\link[=get_integration]{get_integration()}} Other oauth integration functions: -\code{\link{content_set_all_integrations}()}, -\code{\link{integration}()} +\code{\link{content_set_integrations}()}, +\code{\link{get_integration}()} } \concept{oauth integration functions} diff --git a/man/get_job.Rd b/man/get_job.Rd index 2411aed5..6d5cea7c 100644 --- a/man/get_job.Rd +++ b/man/get_job.Rd @@ -25,7 +25,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_jobs.Rd b/man/get_jobs.Rd index 2df1185d..f685a2f3 100644 --- a/man/get_jobs.Rd +++ b/man/get_jobs.Rd @@ -100,7 +100,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_log.Rd b/man/get_log.Rd index 88eb407c..3c399fd5 100644 --- a/man/get_log.Rd +++ b/man/get_log.Rd @@ -47,7 +47,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_thumbnail.Rd b/man/get_thumbnail.Rd index 34ba2869..194c230d 100644 --- a/man/get_thumbnail.Rd +++ b/man/get_thumbnail.Rd @@ -37,7 +37,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/get_vanity_url.Rd b/man/get_vanity_url.Rd index c2fd8a7f..84e3d148 100644 --- a/man/get_vanity_url.Rd +++ b/man/get_vanity_url.Rd @@ -19,7 +19,7 @@ Get the vanity URL for a piece of content. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/git.Rd b/man/git.Rd index 46aa6926..e69533fe 100644 --- a/man/git.Rd +++ b/man/git.Rd @@ -44,7 +44,7 @@ connectapi::deploy_repo Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/has_thumbnail.Rd b/man/has_thumbnail.Rd index 10d921d7..ed83fe45 100644 --- a/man/has_thumbnail.Rd +++ b/man/has_thumbnail.Rd @@ -33,7 +33,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/permissions.Rd b/man/permissions.Rd index 013b4149..48d581a5 100644 --- a/man/permissions.Rd +++ b/man/permissions.Rd @@ -66,7 +66,7 @@ This makes it easier to find / isolate this record. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_image.Rd b/man/set_image.Rd index 66a1d223..ec5036fa 100644 --- a/man/set_image.Rd +++ b/man/set_image.Rd @@ -37,7 +37,7 @@ skips and warns for any content that requires authentication until the Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_run_as.Rd b/man/set_run_as.Rd index 8921496e..cc26419b 100644 --- a/man/set_run_as.Rd +++ b/man/set_run_as.Rd @@ -39,7 +39,7 @@ connectapi::content_update Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_thumbnail.Rd b/man/set_thumbnail.Rd index 4974f2b1..df0f54bc 100644 --- a/man/set_thumbnail.Rd +++ b/man/set_thumbnail.Rd @@ -36,7 +36,7 @@ Other thumbnail functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/set_vanity_url.Rd b/man/set_vanity_url.Rd index 85e02fc2..0f5caea5 100644 --- a/man/set_vanity_url.Rd +++ b/man/set_vanity_url.Rd @@ -32,7 +32,7 @@ connect() \%>\% Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/swap_vanity_url.Rd b/man/swap_vanity_url.Rd index ba3fbce2..30a2cae5 100644 --- a/man/swap_vanity_url.Rd +++ b/man/swap_vanity_url.Rd @@ -22,7 +22,7 @@ This function is deprecated; please use \code{\link{swap_vanity_urls}}. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/swap_vanity_urls.Rd b/man/swap_vanity_urls.Rd index 20686dcb..0ab2d923 100644 --- a/man/swap_vanity_urls.Rd +++ b/man/swap_vanity_urls.Rd @@ -21,7 +21,7 @@ Swap the vanity URLs of two pieces of content. Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/terminate_jobs.Rd b/man/terminate_jobs.Rd index af55fec1..6c7c349b 100644 --- a/man/terminate_jobs.Rd +++ b/man/terminate_jobs.Rd @@ -49,7 +49,7 @@ Other job functions: Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/man/verify_content_name.Rd b/man/verify_content_name.Rd index fd992602..53414d4b 100644 --- a/man/verify_content_name.Rd +++ b/man/verify_content_name.Rd @@ -24,7 +24,7 @@ connectapi::create_random_name Other content functions: \code{\link{content_delete}()}, \code{\link{content_item}()}, -\code{\link{content_set_all_integrations}()}, +\code{\link{content_set_integrations}()}, \code{\link{content_title}()}, \code{\link{content_update}()}, \code{\link{create_random_name}()}, diff --git a/tests/testthat/test-content.R b/tests/testthat/test-content.R index cb6dda3a..cb9aa873 100644 --- a/tests/testthat/test-content.R +++ b/tests/testthat/test-content.R @@ -467,32 +467,32 @@ test_that("get_content_packages() gets packages", { }) }) -test_that("content_set_all_integrations() sends expected request", { +test_that("content_set_integrations() sends expected request", { with_mock_dir("2024.12.0", { client <- Connect$new(server = "https://connect.example", api_key = "fake") x <- content_item(client, "12345678") - y <- integration(client, "f8688548") + y <- get_integration(client, "f8688548") }) without_internet( expect_PUT( - content_set_all_integrations(x, y), + content_set_integrations(x, y), url = "https://connect.example/__api__/v1/content/12345678/oauth/integrations/associations", '[{"oauth_integration_guid":"f8688548"}]' ) ) }) -test_that("content_set_all_integrations() fails when provided the wrong class", { +test_that("content_set_integrations() fails when provided the wrong class", { with_mock_dir("2024.12.0", { client <- Connect$new(server = "https://connect.example", api_key = "fake") x <- content_item(client, "12345678") }) expect_error( - content_set_all_integrations(x, "string"), + content_set_integrations(x, "string"), "`integrations` must be a `connect_integration` class object or a list" ) expect_error( - content_set_all_integrations(x, list("string")), + content_set_integrations(x, list("string")), "All items must be `connect_integration` objects" ) }) diff --git a/tests/testthat/test-integrations.R b/tests/testthat/test-integrations.R index 2cdaf497..ed5c46d8 100644 --- a/tests/testthat/test-integrations.R +++ b/tests/testthat/test-integrations.R @@ -107,7 +107,7 @@ test_that("print.integration produces expected output", { with_mock_dir("2024.12.0", { test_that("integration creates a single integration", { client <- Connect$new(server = "https://connect.example", api_key = "fake") - x <- integration(client, "f8688548") + x <- get_integration(client, "f8688548") expect_s3_class(x, "connect_integration") expect_equal(x$template, "custom") expect_equal(x$guid, "f8688548") From a91373d092e4c2d9782e493959aaa351385a3f50 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 12:04:12 -0400 Subject: [PATCH 08/12] Replace anonymous function with tilde for older version compat --- R/content.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/content.R b/R/content.R index 64cae9b0..131a2f2c 100644 --- a/R/content.R +++ b/R/content.R @@ -1485,11 +1485,11 @@ content_set_integrations <- function(content, integrations) { ) } # Ensure that all the items we've been passed are integrations - if (!purrr::every(integrations, \(x) inherits(x, "connect_integration"))) { + if (!purrr::every(integrations, ~ inherits(x, "connect_integration"))) { stop("All items must be `connect_integration` objects") } - payload <- purrr::map(integrations, \(x) list(oauth_integration_guid = x$guid)) + payload <- purrr::map(integrations, ~ list(oauth_integration_guid = x$guid)) content$connect$PUT( v1_url( From c423d97a7b03edb4c304d3f4fd9fcf628be23cd0 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 12:11:49 -0400 Subject: [PATCH 09/12] Fix linting, hopefully --- tests/testthat/test-content.R | 2 +- tests/testthat/test-integrations.R | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-content.R b/tests/testthat/test-content.R index cb9aa873..16c8ba71 100644 --- a/tests/testthat/test-content.R +++ b/tests/testthat/test-content.R @@ -491,7 +491,7 @@ test_that("content_set_integrations() fails when provided the wrong class", { content_set_integrations(x, "string"), "`integrations` must be a `connect_integration` class object or a list" ) - expect_error( + expect_error( content_set_integrations(x, list("string")), "All items must be `connect_integration` objects" ) diff --git a/tests/testthat/test-integrations.R b/tests/testthat/test-integrations.R index ed5c46d8..952405cd 100644 --- a/tests/testthat/test-integrations.R +++ b/tests/testthat/test-integrations.R @@ -47,8 +47,7 @@ test_that("get_integrations() errs on older Connect versions", { ) }) -test_that("as_integration correctly converts lists to integration - objects", { +test_that("as_integration correctly converts lists to integration objects", { valid_integration <- list( id = "123", guid = "abc-123", From 95904ce5fe575680da9408fb5bb3b7cb5fc4508c Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 16:27:26 -0400 Subject: [PATCH 10/12] fix a recent purrr change --- R/content.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/content.R b/R/content.R index 131a2f2c..e9278d90 100644 --- a/R/content.R +++ b/R/content.R @@ -1485,11 +1485,11 @@ content_set_integrations <- function(content, integrations) { ) } # Ensure that all the items we've been passed are integrations - if (!purrr::every(integrations, ~ inherits(x, "connect_integration"))) { + if (!purrr::every(integrations, ~ inherits(.x, "connect_integration"))) { stop("All items must be `connect_integration` objects") } - payload <- purrr::map(integrations, ~ list(oauth_integration_guid = x$guid)) + payload <- purrr::map(integrations, ~ list(oauth_integration_guid = .x$guid)) content$connect$PUT( v1_url( From 47a976db91d2f8e3d03d279c887789da928f5730 Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 16:37:18 -0400 Subject: [PATCH 11/12] do not export as_integration() --- NAMESPACE | 1 - R/integrations.R | 12 +----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index c83e086c..f7d575a7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -31,7 +31,6 @@ export(Task) export(Vanity) export(Variant) export(VariantSchedule) -export(as_integration) export(audit_access_open) export(audit_r_versions) export(audit_runas) diff --git a/R/integrations.R b/R/integrations.R index 06437a2e..ef8aa74e 100644 --- a/R/integrations.R +++ b/R/integrations.R @@ -111,19 +111,11 @@ as_tibble.connect_list_integrations <- function(x, ...) { # Integration class ---- -validate_integration <- function(x) { - missing_fields <- setdiff(names(connectapi_ptypes$integrations), names(x)) - if (length(missing_fields) > 0) { - stop("Missing required fields: ", paste(missing_fields, collapse = ",")) - } -} - #' Convert objects to integration class #' #' @param x An object to convert to an integration #' #' @return An integration object -#' @export as_integration <- function(x) { UseMethod("as_integration") } @@ -139,9 +131,7 @@ as_integration.default <- function(x) { #' @export as_integration.list <- function(x) { - y <- structure(x, class = c("connect_integration", "list")) - validate_integration(y) - y + structure(x, class = c("connect_integration", "list")) } #' @export From 2d4fd9b3a77a09e41f749144860c91623796c38c Mon Sep 17 00:00:00 2001 From: Toph Allen Date: Mon, 4 Aug 2025 16:40:13 -0400 Subject: [PATCH 12/12] remove test for validation --- tests/testthat/test-integrations.R | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/testthat/test-integrations.R b/tests/testthat/test-integrations.R index 952405cd..71c039e4 100644 --- a/tests/testthat/test-integrations.R +++ b/tests/testthat/test-integrations.R @@ -65,18 +65,6 @@ test_that("as_integration correctly converts lists to integration objects", { expect_identical(result$guid, valid_integration$guid) }) -test_that("as_integration validates required fields", { - invalid_integration <- list( - id = "123", - name = "Incomplete Integration" - ) - - expect_error( - as_integration(invalid_integration), - "Missing required fields" - ) -}) - test_that("as_integration.default errors on non-list input", { expect_error(as_integration(42), "Cannot convert object of class") expect_error(