---
title: "Content Permissions"
author: "Cole Arendt"
date: "8/9/2021"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(connectapi)
client <- connect()
options("connectapi_disable_experimental_warnings" = TRUE)
```

# 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:

```{r deploy_baseline}
bnd <- bundle_static(system.file("logo.png", package = "connectapi"))

content_1 <- deploy(client, bnd, title = "App 1")
content_2 <- deploy(client, bnd, title = "App 2")

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"))
tags <- get_tags(client)
tag_1 <- tags$Example$Permissions

set_content_tags(content_1, tag_1)
set_content_tags(content_2, tag_1)

content_add_user(content_1, user_restricted$guid, role = "viewer")
content_add_user(content_1, user_all$guid, "viewer")
content_add_user(content_2, user_all$guid, "viewer")
```


# 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.

```{r list}
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)

# another approach, with a function
c_with_p <- content_list_with_permissions(client, .p = function(.x) {
  .x$guid %in% content_guids
})

# notice the "permission" column:
c_with_p$permission
```

# 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)
```{r filter}
# restricted has access
content_list_guid_has_access(c_with_p, user_restricted$guid) %>% .$title

# "all" has access
content_list_guid_has_access(c_with_p, user_all$guid) %>% .$title
```

# 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`](https://pkgs.rstudio.com/connectwidgets/) is a great way to
plan to display your data, and provides several helpers for doing so!
