Public Content
Identifying public content
This recipe contains Quarto documents in Python and R that present tables showing how much content hosted by Posit Connect uses each access type and enumerates the content that does not require login.
The document uses the GET /v1/content
endpoint to obtain information about content. This API call returns every content item visible to your API key.
---
title: "Content Report: Public Access"
---
This document analyzes the access types granted to content items
hosted by Posit Connect. It presents a summary according to each
type of access and enumerates all content that allows access
without login.
```{python libraries}
#| echo: false
#| message: false
import os
import requests
import pandas as pd
from IPython.display import Markdown
from tabulate import tabulate
```
```{python configuration}
#| echo: false
# Confirm that environment variables are available.
connect_server = os.environ["CONNECT_SERVER"]
connect_api_key = os.environ["CONNECT_API_KEY"]
```
```{python fetch}
#| echo: false
#| warning: false
# Fetch all content items from Posit Connect.
resp = requests.get(
f"{connect_server}__api__/v1/content",
headers = {
"Authorization": f"Key {connect_api_key}",
},
)
payload = resp.json()
content = pd.DataFrame.from_dict(payload)
```
## Access type frequency
```{python frequency}
#| echo: false
# Summarize by access type with cleaned names and order by
# restriction.
types = {
"all": "All (public)",
"logged_in": "Logged-in",
"acl": "Access Control List",
}
content["access_type"] = pd.Categorical(
content["access_type"],
["all", "logged_in", "acl"],
)
counts = content.groupby(
'access_type', observed = True,
)['access_type'].count().reset_index(name="N")
counts["Type"] = counts["access_type"].transform(
lambda t: types.get(t,t),
)
counts = counts[["Type","N"]]
Markdown(tabulate(
counts,
headers=["Title", "N"],
showindex=False,
))
```
## Public content
```{python report}
#| echo: false
# Select public content and present the title and link.
public = content.copy()
public["title"] = public["title"].fillna(public["name"])
public["dashboard_url"] = public["dashboard_url"].transform(
lambda u: f"[{u}](u){{target='_blank'}}",
)
public = public.loc[content["access_type"] == "all"]
public = public[["title", "dashboard_url"]]
Markdown(tabulate(
public,
headers=["Title", "URL"],
showindex = False,
))
```
---
title: "Content Report: Public Access"
---
This document analyzes the access types granted to content items
hosted by Posit Connect. It presents a summary according to each
type of access and enumerates all content that allows access
without login.
```{r libraries}
#| echo: false
#| message: false
library(httr)
library(jsonlite)
library(magrittr)
library(dplyr)
library(knitr)
```
```{r configuration}
#| echo: false
# Confirm that environment variables are available.
connect_server <- Sys.getenv("CONNECT_SERVER")
if (nchar(connect_server) == 0) {
stop("Set the CONNECT_SERVER environment variable.")
}
connect_api_key <- Sys.getenv("CONNECT_API_KEY")
if (nchar(connect_api_key) == 0) {
stop("Set the CONNECT_API_KEY environment variable.")
}
```
```{r fetch}
#| echo: false
# Fetch all content items from Posit Connect.
res <- httr::GET(
paste0(connect_server, "/__api__/v1/content"),
httr::add_headers(Authorization = paste("Key", connect_api_key)),
httr::write_memory()
)
if (httr::http_error(res)) {
err <- sprintf(
"%s request failed with %s",
res$request$url,
httr::http_status(res)$message
)
message(capture.output(str(httr::content(res))))
stop(err)
}
content <- httr::content(
res, as = "parsed", simplifyDataFrame = TRUE
)
```
## Access type frequency
```{r frequency}
#| echo: false
# Summarize by access type with cleaned names and order by
# restriction.
access_types <- content %>%
mutate(Type = access_type) %>%
select(Type) %>%
group_by(Type) %>%
summarise(N = n()) %>%
arrange(match(Type, c('all', 'logged_in', 'all'))) %>%
mutate(Type = case_when(
Type == "all" ~ "All (public)",
Type == "logged_in" ~ "Logged-in",
Type == "acl" ~ "Access Control List"))
kable(access_types)
```
## Public content
```{r report}
#| echo: false
# Select public content and present the title and link.
public_content <- content %>%
filter(access_type == "all") %>%
mutate(
Title = ifelse(is.na(title), name, title),
URL = paste0("[", dashboard_url, "](", dashboard_url, "){target='_blank'}"),
) %>%
select(Title, URL)
kable(public_content)
```