R/ocsManager.R

#' ocsManager
#' @docType class
#' @export
#' @keywords ocs manager
#' @return Object of \code{\link{R6Class}} for modelling an ocsManager
#' @format \code{\link{R6Class}} object.
#' @section General Methods:
#' \describe{
#'  \item{\code{new(url, user, pwd, logger, keyring_backend)}}{
#'    This method is used to instantiate an ocsManager. The user/pwd are
#'    mandatory in order to connect to 'ocs'. 
#'    
#'    The logger can be either NULL, "INFO" (with minimum logs), or "DEBUG" 
#'    (for complete curl http calls logs).
#'    
#'    The \code{keyring_backend} can be set to use a different backend for storing 
#'    the user password with \pkg{keyring} (Default value is 'env').
#'   
#'  }
#'  \item{\code{connect()}}{
#'    A method to connect to 'ocs' and set version/capabilities
#'  }
#'  \item{\code{getVersion()}}{
#'    Get the 'ocs' server version
#'  }
#'  \item{\code{getCapabilities()}}{
#'    Get the 'ocs' server capabilities
#'  }
#'  \item{\code{getWebdavRoot()}}{
#'    Get the 'ocs' WebDAV root URL
#'  }
#' }
#'
#' @section WebDAV methods:
#' \describe{
#'  \item{\code{listFiles(relPath)}}{
#'    WebDAV method to list folders/files given a relative path. The relative path is set
#'    to \code{"/"} by default, which corresponds to the root of the 'ocs' repository.
#'  }
#'  \item{\code{makeCollection(name, relPath)}}{
#'    WebDAV method to make a collection. By default \code{relPath} is set to \code{"/"} (root).
#'    The \code{name} is the name of the new collection to be created. The function is recursive
#'    in the sense that a \code{name} can be provided as relative path of a collection tree 
#'    (eg \code{newfolder1/newfolder2/newfolder3}), the function will create recursively as 
#'    many collections are handled in the name. 
#'  }
#'  \item{\code{uploadFile(filename, relPath)}}{
#'    WebDAV method to upload a file. By default \code{relPath} is set to \code{"/"} (root).
#'  }
#' }
#' 
#' @section 'OCS' Share API methods:
#' \describe{
#'  \item{\code{getShares(path, reshares, shared_with_me, state, subfiles, pretty)}}{
#'    Get list of shares as \code{list}. To return as \code{data.frame}, set 
#'    \code{pretty = TRUE}. The method accepts additional parameters. 
#'  }
#'  \item{\code{createShare(path, name, shareType, shareWith, publicUpload, password, 
#'  permissions = NULL, expireDate = NULL)}}{
#'    Creates a share for the path (file or folder), given a name. The \code{shareType} should be among
#'    values 'user','group','publiclink' or 'federated'.The \code{shareWith} is required for \code{shareType} 
#'    'user' and 'group' and corresponds to the username or groupname. The \code{permissions} can be set among
#'    values 'read', 'update', 'create', 'delete', 'read-write', 'share', 'all'. By default the permissions will 
#'    be the default permissions set by the ocs server (by default 'all').
#'  }
#'  \item{\code{shareWithUser(path, name, username, permissions, pretty)}}{
#'   Shares a resource (file or folder) with a user given its username handled with argument \code{username}. 
#'   The \code{permissions} can be set among values 'read', 'update', 'create', 'delete', 'read-write', 'share', 
#'   'all'. By default the permissions will be the default permissions set by the ocs server (by default 'all').
#'   Returns the share properties as \code{list} (or as\code{data.frame} if \code{pretty} is set to TRUE).
#'  }
#'  \item{\code{shareWithGroup(path, name, group, permissions, pretty)}}{
#'   Shares a resource (file or folder) with a group given its name handled with argument \code{group}. 
#'   The \code{permissions} can be set among values 'read', 'update', 'create', 'delete', 'read-write', 'share', 
#'   'all'. By default the permissions will be the default permissions set by the ocs server (by default 'all').
#'   Returns the share properties as \code{list} (or as\code{data.frame} if \code{pretty} is set to TRUE).
#'  }
#'  \item{\code{shareAsPublicLink(path, name, publicUpload, password, permissions, expireDate)}}{
#'   Shares a resource (file or folder) as public link. The function returns the public link generated by ocs.
#'  }
#' }
#'  
#' @examples
#' \dontrun{
#'    #Not Run:
#'    #Connect to an OCS API
#'    OCS <- ocsManager$new(url = ocs_url, user = ocs_user, pwd = ocs_pwd, logger = "DEBUG")
#'    version <- OCS$getVersion()
#'    caps <- OCS$getCapabilities()
#'    
#'    #OCS User Provisioning API
#'    #-------------------------------------
#'    #users
#'    users <- OCS$getUsers() #get users
#'    user <- OCS$getUser("admin") #get a user
#'    user.df <- OCS$getUser("admin", TRUE) #the same user as data.frame
#'    added <- OCS$addUser("john.doe", password = "ocs4john") #add a user
#'    disabled <- OCS$disableUser("john.doe") #disable a user
#'    enabled <- OCS$enableUser("john.doe") #enable auser
#'    edited <- OCS$editUser("john.doe", key = "display", value = "John Doe") #edit user
#'    #edit some user field
#'    edited2 <- OCS$editUserDisplayName("john.doe", displayName = "John Doe Jr.") 
#'    deleted <- OCS$deleteUser("john.doe")
#'    
#'    #groups
#'    admingroups <- OCS$getUserGroups("admin")
#'    groups <- OCS$getGroups()
#'    added <- OCS$addGroup("scientists") #add a new group
#'    sc_group <- OCS$getGroup("scientists") #get group details
#'    added <- OCS$addToGroup("john.doe", "scientists") #add user to group
#'    removed <- OCS$removeFromGroup("john.doe", "scientists") #remove user from group
#'    deleted <- OCS$deleteGroup("scientists")
#'    
#'    #OCS Webdav API
#'    #-------------------------------------
#'    #list files
#'    files <- OCS$listFiles()
#'    subfiles <- OCS$listFiles("Documents")
#'    #make collection
#'    OCS$makeCollection("myfolder")
#'    subfiles <- OCS$listFiles("myfolder")
#'    #upload a file?
#'    filename <- "magic.txt"
#'    file.create(filename); writeLines("ocs4R is great", filename)
#'    #we upload the file in 'Documents' folder
#'    OCS$uploadFile(filename, "/Documents")
#'    #check if file is uploaded
#'    OCS$listFiles('Documents')
#'    
#'    #OCS Sharing API
#'    #-------------------------------------
#'    #let's add a user with User provisioning API
#'    added <- OCS$addUser("john.doe", password = "ocs4john") #add a user
#'    #let's share the previously uploaded file with John Doe
#'    OCS$shareWithUser("/Documents", filename, "john.doe")
#' }
#' 
#' @author Emmanuel Blondel <emmanuel.blondel1@@gmail.com>
#' 
ocsManager <-  R6Class("ocsManager",
  inherit = ocs4RLogger,
  lock_objects = FALSE,
  private = list(
    url = NULL,
    user = NULL,
    cookies = NULL,
    version = NULL,
    capabilities = NULL,
    
    keyring_backend = NULL,
    keyring_service = NULL,
    
    #getToken (if existing)
    getToken = function(){
      token <- NULL
      if(!is.null(private$keyring_service)){
        keyring_token <- suppressWarnings(try(private$keyring_backend$get(service = private$keyring_service, username = paste0(private$user, "_token")), silent = TRUE))
        if(!is(keyring_token, "try-error")) token <- keyring_token
      }
      return(token)
    },
    
    #checkAPIAvailability
    checkAPIAvailability = function(name, element){
      if(!private$capabilities[[element]]$api_enabled){
        errMsg <- sprintf("This method requires the 'OCS' REST API %s to be enabled.", name)
        errMsg <- paste(errMsg, "Please get in touch with your administrator")
        self$ERROR(errMsg)
        stop(errMsg)
      }
    },
    
    #check
    checkSharingAPIAvailability = function(){
      private$checkAPIAvailability("OCS Sharing API", "files_sharing")
    }
  ),
  public = list(
    apis = list(),
    initialize = function(url, user, pwd, logger = NULL,
                          keyring_backend = 'env'){
      super$initialize(logger = logger)
      private$url = url
      private$user <- user
      if(!keyring_backend %in% names(keyring:::known_backends)){
        errMsg <- sprintf("Backend '%s' is not a known keyring backend!", keyring_backend)
        self$ERROR(errMsg)
        stop(errMsg)
      }
      private$keyring_backend <- keyring:::known_backends[[keyring_backend]]$new()
      private$keyring_service <- paste0("ocs4R@", url)
      private$keyring_backend$set_with_value(private$keyring_service, username = paste0(user,"_pwd"), password = pwd)
      
      #try to connect
      if(!startsWith(self$getClassName(), "ocsApi")){
        
        #test connection
        self$connect()
        
        #inherit managers methods (experimenting)
        list_of_classes <- rev(ls("package:ocs4R"))
        supportedManagers <- list_of_classes[regexpr("ocsApi.+Manager", list_of_classes)>0]
        for(manager in supportedManagers){
          class <- eval(parse(text=manager))
          man <- class$new(url, user, pwd, logger, keyring_backend)
          api_name <- tolower(unlist(strsplit(unlist(strsplit(manager, "ocsApi"))[2],"Manager"))[1])
          self$apis[[api_name]] <- man
          list_of_methods <- rev(names(man))
          for(method in list_of_methods){
            methodObj <- man[[method]]
            if(!(method %in% names(self)) && class(methodObj) == "function"){1
              self[[method]] <- methodObj
              environment(self[[method]]) <- environment(self$connect)
            } 
          }
        }
      }
      invisible(self)
    },
    
    #connect
    connect = function(){
      caps_req <- ocsRequest$new(
        type = "HTTP_GET", private$url, "ocs/v1.php/cloud/capabilities",
        private$user, pwd = private$keyring_backend$get(service = private$keyring_service, username = paste0(private$user,"_pwd")), 
        logger = self$loggerType
      )
      caps_req$execute()
      caps_resp <- caps_req$getResponse()
      
      req_cookies <- caps_resp$cookies
      cookies <- as.list(req_cookies$value)
      names(cookies) <- req_cookies$name
      if(length(cookies[names(cookies)=="XSRF-TOKEN"])>0){
        token <- cookies[names(cookies)=="XSRF-TOKEN"][[1]]
        private$keyring_backend$set_with_value(private$keyring_service, username = paste0(private$user,"_token"), password = token)
      }
      cookies <- unlist(cookies[names(cookies)!="XSRF-TOKEN"])
      private$cookies <- paste0(sapply(names(cookies), function(cookiename){paste0(cookiename,"=",cookies[[cookiename]])}),collapse=";")
      
      keyring_token <- private$getToken()
      if(!is.null(keyring_token)){
        caps_req <- ocsRequest$new(
          type = "HTTP_GET", private$url, "ocs/v1.php/cloud/capabilities",
          private$user, token = keyring_token, cookies = private$cookies, 
          logger = self$loggerType
        )
        caps_req$execute()
        caps_resp <- caps_req$getResponse()
      }
      
      if(caps_resp$ocs$meta$status == "failure"){
        errMsg <- sprintf("Could not connect to ocs '%s': %s", private$url, caps_resp$ocs$meta$message)
        self$ERROR(errMsg)
        stop(errMsg)
      }
      if(caps_resp$ocs$meta$status == "ok"){
        self$INFO(sprintf("Successful connection to ocs '%s'!", private$url))
        private$version = caps_resp$ocs$data$version
        private$capabilities = caps_resp$ocs$data$capabilities
      }
    },
    
    #getVersion
    getVersion = function(){
      return(private$version)
    },
    
    #getCapabilities
    getCapabilities = function(){
      return(private$capabilities)
    },
    
    #getAPIWebdavManager
    getAPIWebdavManager = function(){
      return(self$apis[["webdav"]])
    },
    
    #getAPISharingManager
    getAPISharingManager = function(){
      return(self$apis[["sharing"]])
    },
    
    #getAPIUserProvisioningManager
    getAPIUserProvisioningManager = function(){
      return(self$apis[["userprovisioning"]])
    }
    
  )
)

Try the ocs4R package in your browser

Any scripts or data that you put into this service are public.

ocs4R documentation built on March 18, 2022, 6:31 p.m.