Skip to contents

Getting Started

To filter content by permissions, you first need a “baseline set of content.” This could be all content on the server, all content in a particular tag, etc.

NOTE: performance will depend heavily on the size of this baseline set of content, because the permissions API today requires enumeration. To improve performance for large sets of content, you can use pins or caching on disk to reduce how often the requests must be re-executed.

We will start by deploying a few pieces of test content, two test users, set access controls, and tags:

bnd <- bundle_static(system.file("logo.png", package = "connectapi"))
## Error in get(paste0(generic, ".", class), envir = get_method_env()) : 
##   object 'type_sum.accel' not found
## Bundling directory (/tmp/RtmpoOqtnm/bundledir2ecc6cee3297)
content_1 <- deploy(client, bnd, title = "App 1")
## Getting content endpoint
## Found EXISTING content 057ae2e5-203a-4e11-a8f2-39982d3b2db1 with name mwlefoodfieexombwkkeulbfd on http://localhost:32768
## Uploading bundle
## Deploying bundle
content_2 <- deploy(client, bnd, title = "App 2")
## Getting content endpoint
## Found EXISTING content e818d49a-c198-4be0-b647-372f5c8fba5c with name pbcyvkgufivjubqtxvafbsnay on http://localhost:32768
## Uploading bundle
## Deploying bundle
user_restricted <- client$users_create("example_restricted", "restricted@example.com", password = create_random_name())
user_all <- client$users_create("example_all", "all@example.com", password = create_random_name())

invisible(create_tag_tree(client, "Example", "Permissions"))
## Posit Connect Tag Tree (filtered)
## └── Example
##    └── Permissions
tags <- get_tags(client)
tag_1 <- tags$Example$Permissions

set_content_tags(content_1, tag_1)
## Posit Connect Tag Tree (content)
## └── Example
##    └── Permissions
## Posit Connect Content Task: 
##   Content GUID: 057ae2e5-203a-4e11-a8f2-39982d3b2db1
##   URL: http://localhost:32768/connect/#/apps/057ae2e5-203a-4e11-a8f2-39982d3b2db1/
##   Task ID: H9VxhLBK6RIZvPa0
set_content_tags(content_2, tag_1)
## Posit Connect Tag Tree (content)
## └── Example
##    └── Permissions
## Posit Connect Content Task: 
##   Content GUID: e818d49a-c198-4be0-b647-372f5c8fba5c
##   URL: http://localhost:32768/connect/#/apps/e818d49a-c198-4be0-b647-372f5c8fba5c/
##   Task ID: IpDqN1Mwlfk6u5L4
content_add_user(content_1, user_restricted$guid, role = "viewer")
## Adding permission for user 'e97b7bac-7d07-408a-a210-4a344622235c' with role 'viewer'
## Posit Connect Content Task: 
##   Content GUID: 057ae2e5-203a-4e11-a8f2-39982d3b2db1
##   URL: http://localhost:32768/connect/#/apps/057ae2e5-203a-4e11-a8f2-39982d3b2db1/
##   Task ID: H9VxhLBK6RIZvPa0
content_add_user(content_1, user_all$guid, "viewer")
## Adding permission for user 'b2f8ba87-d8ed-483e-8585-340d475ae3fd' with role 'viewer'
## Posit Connect Content Task: 
##   Content GUID: 057ae2e5-203a-4e11-a8f2-39982d3b2db1
##   URL: http://localhost:32768/connect/#/apps/057ae2e5-203a-4e11-a8f2-39982d3b2db1/
##   Task ID: H9VxhLBK6RIZvPa0
content_add_user(content_2, user_all$guid, "viewer")
## Adding permission for user 'b2f8ba87-d8ed-483e-8585-340d475ae3fd' with role 'viewer'
## Posit Connect Content Task: 
##   Content GUID: e818d49a-c198-4be0-b647-372f5c8fba5c
##   URL: http://localhost:32768/connect/#/apps/e818d49a-c198-4be0-b647-372f5c8fba5c/
##   Task ID: IpDqN1Mwlfk6u5L4

Retrieve the Content List

The content_list_with_permissions() function is the core of what we want. However, it defaults to return all content on the server. For some servers, this is very expensive (and can take 30 minutes or more).

Instead, we recommend using the .p argument to define a “predicate” function (in the style of purrr::keep()) that determines which records to keep. Since all this predicate has access to is the “content list” itself, we will retrieve a list of Content GUIDs first.

my_tag_content <- content_list_by_tag(client, tag_1)
content_guids <- my_tag_content$guid

c_with_p <- content_list_with_permissions(client, .p = ~ .x$guid %in% content_guids)
## Getting content list
## Getting permission list
# another approach, with a function
c_with_p <- content_list_with_permissions(client, .p = function(.x) {
  .x$guid %in% content_guids
})
## Getting content list
## Getting permission list
# notice the "permission" column:
c_with_p$permission
## [[1]]
## # A tibble: 2 × 5
##   id    content_guid                         principal_guid principal_type role 
##   <chr> <chr>                                <chr>          <chr>          <chr>
## 1 3     e818d49a-c198-4be0-b647-372f5c8fba5c b2f8ba87-d8ed… user           view…
## 2 NA    e818d49a-c198-4be0-b647-372f5c8fba5c 720e1e01-4095… user           owner
## 
## [[2]]
## # A tibble: 3 × 5
##   id    content_guid                         principal_guid principal_type role 
##   <chr> <chr>                                <chr>          <chr>          <chr>
## 1 1     057ae2e5-203a-4e11-a8f2-39982d3b2db1 e97b7bac-7d07… user           view…
## 2 2     057ae2e5-203a-4e11-a8f2-39982d3b2db1 b2f8ba87-d8ed… user           view…
## 3 NA    057ae2e5-203a-4e11-a8f2-39982d3b2db1 720e1e01-4095… user           owner

Filter the Content List

We added a helper function to the package that should filter the content list for you: content_list_guid_has_access()

In a Shiny application or other personalized context (i.e. using session$user), you then filter the content list to only what a user should see (using the permissions column returned above)

# restricted has access
content_list_guid_has_access(c_with_p, user_restricted$guid) %>% .$title
## [1] "mwlefoodfieexombwkkeulbfd"
# "all" has access
content_list_guid_has_access(c_with_p, user_all$guid) %>% .$title
## [1] "pbcyvkgufivjubqtxvafbsnay" "mwlefoodfieexombwkkeulbfd"

Display the Content List

We plan to build a full example in Shiny (and to show example code below). However, suffice it to say that for RStudio Connect version 1.9.0 or newer, connectwidgets is a great way to plan to display your data, and provides several helpers for doing so!