Content Permissions
Cole Arendt
8/9/2021
Source:vignettes/articles/content_permissions.Rmd
content_permissions.Rmd
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"))
## Bundling directory (/tmp/RtmpEtHDTH/bundledir2c872a50390)
content_1 <- deploy(client, bnd, title = "App 1")
## Getting content endpoint
## Found EXISTING content 801a214d-2563-4f35-be9f-4ed321a2b949 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 034dc441-46b7-4e66-9d70-3af7ded96d63 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: 801a214d-2563-4f35-be9f-4ed321a2b949
## URL: http://localhost:32768/connect/#/apps/801a214d-2563-4f35-be9f-4ed321a2b949
## Task ID: iz4MxND62D2pQOdM
set_content_tags(content_2, tag_1)
## Posit Connect Tag Tree (content)
## └── Example
## └── Permissions
## Posit Connect Content Task:
## Content GUID: 034dc441-46b7-4e66-9d70-3af7ded96d63
## URL: http://localhost:32768/connect/#/apps/034dc441-46b7-4e66-9d70-3af7ded96d63
## Task ID: W2OxxNtlGUCMbXYJ
content_add_user(content_1, user_restricted$guid, role = "viewer")
## Adding permission for user 'ba422724-0d64-4d83-81be-a21f02a24841' with role 'viewer'
## Posit Connect Content Task:
## Content GUID: 801a214d-2563-4f35-be9f-4ed321a2b949
## URL: http://localhost:32768/connect/#/apps/801a214d-2563-4f35-be9f-4ed321a2b949
## Task ID: iz4MxND62D2pQOdM
content_add_user(content_1, user_all$guid, "viewer")
## Adding permission for user '64d004a7-2592-4484-871c-bd5df2d2cf14' with role 'viewer'
## Posit Connect Content Task:
## Content GUID: 801a214d-2563-4f35-be9f-4ed321a2b949
## URL: http://localhost:32768/connect/#/apps/801a214d-2563-4f35-be9f-4ed321a2b949
## Task ID: iz4MxND62D2pQOdM
content_add_user(content_2, user_all$guid, "viewer")
## Adding permission for user '64d004a7-2592-4484-871c-bd5df2d2cf14' with role 'viewer'
## Posit Connect Content Task:
## Content GUID: 034dc441-46b7-4e66-9d70-3af7ded96d63
## URL: http://localhost:32768/connect/#/apps/034dc441-46b7-4e66-9d70-3af7ded96d63
## Task ID: W2OxxNtlGUCMbXYJ
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 034dc441-46b7-4e66-9d70-3af7ded96d63 64d004a7-2592… user view…
## 2 NA 034dc441-46b7-4e66-9d70-3af7ded96d63 4199c36d-45bc… user owner
##
## [[2]]
## # A tibble: 3 × 5
## id content_guid principal_guid principal_type role
## <chr> <chr> <chr> <chr> <chr>
## 1 1 801a214d-2563-4f35-be9f-4ed321a2b949 ba422724-0d64… user view…
## 2 2 801a214d-2563-4f35-be9f-4ed321a2b949 64d004a7-2592… user view…
## 3 NA 801a214d-2563-4f35-be9f-4ed321a2b949 4199c36d-45bc… 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!