- 
                Notifications
    You must be signed in to change notification settings 
- Fork 26
          feat: connect_user S3 class
          #462
        
          New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d22fbf6
              fa37692
              7b8ef60
              61b5388
              d561a02
              a211710
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -13,8 +13,8 @@ | |
| #' value (boolean OR). When `NULL` (the default), results are not filtered. | ||
|  | ||
| #' | ||
| #' @return | ||
| #' A tibble with the following columns: | ||
| #' @return For `get_users_list`, a list of objects of type `"connect_user"` which | ||
| #' contain the following information: | ||
| #' | ||
| #' * `email`: The user's email | ||
| #' * `username`: The user's username | ||
|  | @@ -33,6 +33,10 @@ | |
| #' * `locked`: Whether or not the user is locked | ||
| #' * `guid`: The user's GUID, or unique identifier, in UUID RFC4122 format | ||
| #' | ||
| #' For `get_users`, a data frame with the same fields as `get_users_list`. | ||
| #' | ||
| #' For `get_user`, a single `"connect_user"` object. | ||
| #' | ||
| #' @details | ||
| #' Please see https://docs.posit.co/connect/api/#get-/v1/users for more information. | ||
| #' | ||
|  | @@ -41,18 +45,41 @@ | |
| #' library(connectapi) | ||
| #' client <- connect() | ||
| #' | ||
| #' # Get all users | ||
| #' # Get all users as a data frame | ||
| #' get_users(client) | ||
| #' | ||
| #' # Get all licensed users | ||
| #' get_users(client, account_status = "licensed") | ||
| #' | ||
| #' # Get all users who are administrators or publishers | ||
| #' get_users(client, user_role = c("administrator", "publisher")) | ||
| #' | ||
| #' # Get users as a list | ||
| #' users_list <- get_users_list(client) | ||
| #' } | ||
| #' | ||
| #' @export | ||
| get_users <- function( | ||
| get_users <- function(src, | ||
| page_size = 500, | ||
| prefix = NULL, | ||
| limit = Inf, | ||
| user_role = NULL, | ||
| account_status = NULL) { | ||
| as.data.frame( | ||
| get_users_list( | ||
| src, | ||
| page_size, | ||
| prefix, | ||
| limit, | ||
| user_role, | ||
| account_status | ||
| ) | ||
| ) | ||
| } | ||
|  | ||
| #' @rdname get_users | ||
| #' @export | ||
| get_users_list <- function( | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming! @karawoo and I talked about this yesterday and there are a few options available, including what's used here, just calling it  I was thinking back to a similar discussion with @jonkeane at the start of the year about job-related functions, particularly during #356 (the comment threads are hard to follow and not particularly worth mining). If we wanted to follow the pattern used with  I also think it would be fine to call it  Calling it  Calling it  | ||
| src, | ||
| page_size = 500, | ||
| prefix = NULL, | ||
|  | @@ -72,10 +99,23 @@ get_users <- function( | |
| ), | ||
| limit = limit | ||
| ) | ||
| return(prepend_class(res, "connect_users")) | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a note — the list-of-integrations object's class is  Not saying that that's a better paradigm, and these class names are internal — there isn't much sunk cost here, so if  | ||
| } | ||
|  | ||
| out <- parse_connectapi_typed(res, connectapi_ptypes$users) | ||
| #' @param guid user GUID | ||
| #' @rdname get_users | ||
| get_user <- function(src, guid) { | ||
| src$user(guid) | ||
| } | ||
|  | ||
| return(out) | ||
| #' @export | ||
| as.data.frame.connect_users <- function(x, ...) { | ||
| parse_connectapi_typed(x, connectapi_ptypes$users) | ||
| } | ||
|  | ||
| #' @export | ||
| as_tibble.connect_users <- function(x, ...) { | ||
| parse_connectapi_typed(x, connectapi_ptypes$users) | ||
| } | ||
|  | ||
| #' Get information about content on the Posit Connect server | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -32,3 +32,28 @@ user_guid_from_username <- function(client, username) { | |
| return(res[[1]]$guid) | ||
| } | ||
| } | ||
|  | ||
| #' Extract User GUID | ||
| #' | ||
| #' Helper function to extract a user GUID from either a character string or a | ||
| #' `connect_user` object. | ||
| #' | ||
| #' @param user Either a character string containing a user GUID or a | ||
| #' `connect_user` object (as returned by `Connect$user()` or `Connect$users()`) | ||
| #' | ||
| #' @return A character string containing the user GUID | ||
| #' | ||
| #' @keywords internal | ||
| 
      Comment on lines
    
      +36
     to 
      +46
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💟 | ||
| get_user_guid <- function(user) { | ||
| if (is.character(user)) { | ||
| return(user) | ||
| } else if (inherits(user, "connect_user")) { | ||
| if (!is.null(user$guid)) { | ||
| return(user$guid) | ||
| } else { | ||
| stop("connect_user object does not contain a guid field") | ||
| } | ||
| } else { | ||
| stop("user must be either a character string (GUID) or a connect_user object") | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking ahead in this line of work to functions that act on a single user. We'd like to be able to something like
lock_user(user), without having to also pass in the client as the first argument.Different objects in the package achieve this in different ways. The R6 classes have the client as a property. The jobs (just a list, no class) have the client as an added list item. Integrations (an S3 class, which is the most similar to what we're doing here) have the client as an attribute — the thing I like about that is that it keeps the list fields as the data returned by the server, which feels neat and tidy to me.
That doesn't need to happen in this PR — it looks like most of the user-facing functions that are being updated are ones that also operate on content, and so already have access to a client.