R/LinkItEngine.R

#' Business logic of the LinkIt application
#' @description An R6 object with methods for use in the Shiny application `ede_linkt_app`, 
#' and `ede-izm_frontend`. 
#' @importsFrom shintobag shinto_db_connection
#' @importsFrom pool dbPool poolClose
#' @importsFrom R6 R6Class
#' @importsFrom safer encrypt_string decrypt_string
#' @export
LinkItEngine <- R6::R6Class(
  lock_objects = FALSE,
  inherit = shintodb::databaseClass,
  
  public = list(
    
    sel = NULL,
    gemeente = NULL,
    gebruikers = NULL,
    
    initialize = function(gemeente = NULL, schema, pool, config_file = "conf/config.yml", what = NULL){
      
      self$gemeente <- gemeente
      
      # LinkIt default: config entry = 'ede'
      if(is.null(what)){
        what <- tolower(gemeente)  
      }
      
      
      super$initialize(what = what, config_file = config_file, pool = pool, schema = schema)
      
      dossierkenmerktype <- self$read_table("dossierkenmerktype")
      objectkenmerktype <- self$read_table("objectkenmerktype")
      
      self$sel <- list(

        dossierkenmerktypes =  self$make_choices(values_from = "typeid",
                                                 names_from = "naam",
                                                 data = dossierkenmerktype),
        objectkenmerktypes =  self$make_choices(values_from = "typeid",
                                                names_from = "naam",
                                                data = objectkenmerktype)
      )
      
    },
    
    #----- User methods (via shintousers) ---
    store_user_object = function(.user){
      
      stopifnot(inherits(.user, "ShintoUsers"))
      
      self$.user <- .user
      
    },
    
    save_coordinatoren_list = function(){
      
      self$gebruikers <- self$.user$list_application_users(ignore_groups = "ontwikkelaar")
      
      self$sel$coordinatoren <- self$make_choices(values_from = "userid",
                                        names_from = "username",
                                        data = self$gebruikers)
      
    },
    
    username_from_userid = function(userid){
      
      self$.user$get_name(userid)
      
    },
    
    
    # ---- algemene DB methodes niet in shintodb (of wel maar dan net anders, deze heeft voorrang!)
    delete_rows_where = function(table, col_compare, val_compare){
      
      query <- glue("delete from {self$schema}.{table} where {col_compare}= ?val")
      query <- sqlInterpolate(DBI::ANSI(), query, val = val_compare)
      flog.info(query, name = "DBR6")
      
      tm <- try(
        dbExecute(self$con, query)   
      )
      
      return(invisible(!inherits(tm, "try-error")))
    },
    
    delete_rows_where2 = function(table, col_compare, val_compare, col_compare2, val_compare2){
      
      query <- glue("delete from {self$schema}.{table} where {col_compare}= ?val and {col_compare2}= ?val2")
      query <- sqlInterpolate(DBI::ANSI(), query, val = val_compare, val2 = val_compare2)
      flog.info(query, name = "DBR6")
      
      tm <- try(
        dbExecute(self$con, query)   
      )
      
      return(invisible(!inherits(tm, "try-error")))
    },
    


    
    #---- Algemene niet DB methodes -----
    make_choices = function(values_from, names_from = values_from, data = NULL){
      
      data <- data %>%
        distinct(!!sym(values_from), !!sym(names_from))
      
      out <- data[[values_from]] %>% 
        setNames(data[[names_from]])
      
      # Sorteer op labels, niet op waardes
      out[order(names(out))]
      
    },
    
    
    #------- LinkIt methodes -----

    get_favorites = function(userid, lazy = FALSE){
      
      fav <- self$read_table("favorieten", lazy = TRUE) %>%
        filter(userid == !!userid) %>%
        collect
      
      out <- self$read_table("dossiers", lazy = TRUE) %>% 
        filter(dossierid %in% !!fav$dossierid)
      
      if(lazy){
        return(out)
      } else {
        return(collect(out))
      }
      
    },
    
    is_favorite = function(userid, dossierid){
      
      fav_dos <- self$read_table("favorieten", lazy = TRUE) %>%
        filter(userid == !!userid, dossierid == !!dossierid) %>%
        collect
      
      nrow(fav_dos) > 0
    },
    
    format_dossierid = function(id){
      
      stringr::str_pad(as.character(id), 4, "left", "0")
      
    },
    
    
    add_favorite = function(userid, dossierid){
      
      if(!self$is_favorite(userid, dossierid)){
        
        self$log_audit(userid, dossierid, actie = glue("Dossier {dossierid} gevolgd"))
        
        self$append_data("favorieten",
                         tibble(
                           id = uuid::UUIDgenerate(),
                           dossierid = dossierid,
                           userid = userid
                         ))
      } else {
        return(FALSE)
      }
      
      
    },
    
    delete_favorite = function(userid, dossierid){
      
      self$log_audit(userid, dossierid, actie = glue("Dossier {dossierid} ontvolgd"))
      
      self$delete_rows_where2("favorieten", 
                              col_compare = "dossierid", 
                              val_compare = dossierid, 
                              col_compare2 = "userid", 
                              val_compare2 = userid
      )
      
      
    },
    
    #' @description Toggle favorie dossier for a user
    #' @details Delete the favorite if the dossier is a favorite, otherwise add it.
    #' @return TRUE if successful.
    toggle_favorite = function(userid, dossierid){
      
      if(self$is_favorite(userid, dossierid)){
        self$delete_favorite(userid, dossierid)
      } else {
        self$add_favorite(userid, dossierid)
      }
      
    },
    
    
    next_dossier_id = function(){
      
      maxid <- self$query("select max(dossierid) from linkit.dossiers")
      
      out <- maxid$max + 1
      if(is.na(out))out <- 1
      
      out
      
    },
    
    #' @description Make a new dossier, write to DB
    #' @param dossiername Name of the dossier (char)
    #' @param userid Current user (char)
    #' @param aanmaakdatum Creation date (posixct)
    #' @param verloopdatum Expiry date (posixct)
    #' @param betrokkeninstanties (char)
    #' @return The (usually new) ID of the dossier.
    add_dossier = function(dossiername, 
                           userid, 
                           aanmaakdatum, 
                           verloopdatum, 
                           betrokkeninstanties,
                           aanmelder,
                           id = NULL){
      
      if(is.null(id)){
        id <- self$next_dossier_id()
      }
      
      self$append_data("dossiers", 
                       tibble(
                         dossierid = id,
                         dossiername = dossiername,
                         aanmaker = userid,
                         aanmaakdatum = aanmaakdatum,
                         verloopdatum = verloopdatum,
                         #archiefdatum = 
                         #hoofdadresid =
                         actuele_status = "Actief",
                         betrokkeninstanties = paste(betrokkeninstanties, collapse=";"),
                         aanmelder = aanmelder
                       ))
      
      return(id)
      
    },
    
    #' @description Get a dossier based on its ID
    #' @param dossierid Dossier ID's (can be a vector)
    get_dossier = function(dossierid){
      
      self$read_table("dossiers", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierid) %>%
        collect
      
    },
    
    #' @description Retrieves dossiers for a user 'Actief' or 'Volgen' status for 
    get_my_active_dossiers = function(userid){
      
      dossierids <- self$get_dossierid_coordinatoren(userid)
      
      self$read_table("dossiers", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierids, actuele_status %in%  c("Actief","Volgen")) %>%
        collect
      
    },

    #' @description Find all dossiers with 'Actief' or 'Volgen' status
    get_all_active_dossiers = function(){
      
      self$read_table("dossiers", lazy = TRUE) %>%
        filter(actuele_status %in%  c("Actief","Volgen")) %>%
        collect
      
    },
    
    #' @description Find all dossiers with 'Verwijderd' status
    get_verwijderde_dossiers = function(){
      
      self$read_table("dossiers", lazy = TRUE) %>%
        filter(actuele_status == "Verwijderd") %>%
        collect
      
    },
    
    #' Retrieve all pseudo-BSNs of all persons in active dossiers for the current user.
    #' @return Vector of pseudo-BSNs
    get_personen_active_dossiers = function(userid = NULL, method = c("current_user", "all")){
      
      method <- match.arg(method)
      
      if(method == "current_user"){
        dosid <- self$get_my_active_dossiers(userid) %>%
          pull(dossierid)
      } else {
        dosid <- self$get_all_active_dossiers() %>%
          pull(dossierid)
      }
      
      if(length(dosid) == 0)return(NULL)
      
      self$get_objects(dosid) %>%
        filter(objecttype == "bsn_persoon") %>%
        pull(objectinstance)
      
    },
    
    get_objecten_objectinstance = function(ids){
      
      self$read_table("objecten", lazy = TRUE) %>% 
        filter(objectinstance %in% !!ids) %>%
        collect
      
    },
    
    get_dossierid_personen = function(pseudoid){
      
      doss_ids <- self$get_objecten_objectinstance(pseudoid) %>% 
        pull(dossierid) %>%
        unique
      
      doss_nms <-self$dossier_naam_from_id(doss_ids)
      
      tibble(dossierid = doss_ids, dossiername = doss_nms)
      
    },
    
    
    
    #' @description Find the name of a dossier based on its ID
    dossier_naam_from_id = function(dossierid){
      
      self$get_dossier(dossierid) %>% pull(dossiername)
      
    },
    
    #' @description Really delete a dossier.
    delete_dossier = function(dossierid){
      
      self$delete_rows_where("dossiers", "dossierid", dossierid)
      self$delete_rows_where("favorieten", "dossierid", dossierid)
      self$delete_rows_where("dossierkenmerk", "dossierid", dossierid)
      self$delete_rows_where("coordinatoren", "dossierid", dossierid)
      self$delete_rows_where("objecten", "dossierid", dossierid)
      self$delete_rows_where("persoon_kenmerken", "dossierid", dossierid)
      
    },
    
    #' @description Set status dossier to 'Verwijderd'
    verwijder_dossier = function(dossierid){
      
      tm_now <- Sys.time()
      tm_10yr <- tm_now + lubridate::years(10)
      
      dbExecute(self$con, glue("update {self$schema}.dossiers set",
                               " actuele_status = 'Verwijderd' where dossierid = {dossierid}"))
      dbExecute(self$con, glue("update {self$schema}.dossiers set",
                               " archiefdatum = '{format(tm_now)}' where dossierid = {dossierid}"))
      dbExecute(self$con, glue("update {self$schema}.dossiers set",
                               " verloopdatum = '{format(tm_10yr)}' where dossierid = {dossierid}"))
      
    },
    
    #' @description Undo verwijder_dossier
    undo_verwijder_dossier = function(dossierid){
      
      dbExecute(self$con, glue("update {self$schema}.dossiers set",
                               " actuele_status = 'Actief' where dossierid = {dossierid}"))
      dbExecute(self$con, glue("update {self$schema}.dossiers set",
                               " archiefdatum = NULL where dossierid = {dossierid}"))
      dbExecute(self$con, glue("update {self$schema}.dossiers set",
                               " verloopdatum = NULL where dossierid = {dossierid}"))
    },
    
    
    #' @description Does the given Dossier ID actually exist?
    dossier_exists = function(dossierid){
      
      self$has_value("dossiers", "dossierid", dossierid)  
      
    },
    
    
    #' @description Betrokken instantie toevoegen
    add_instantie = function(instantie, properties = ""){
      
      
      data_have <- self$read_table("instanties", lazy = TRUE) %>% 
        filter(instantie == !!instantie) %>%
        collect
      
      id_max <- self$query("select max(id) from linkit.instanties")[[1]]
      
      n_have <- nrow(data_have)
      
      if(n_have == 0){
        self$append_data(
          "instanties",
          tibble(
            id = id_max + 1,
            instantie = instantie,
            properties = properties
          )
        ) 
        
        return(1)
        
      } else {
        return(-1)
      }
      
      
    },
    
    list_instanties = function(){
      
      self$read_table("instanties") %>% 
        pull(instantie) %>%
        stringr::str_sort()
      
    },
    
    
    #' @description Log an audit action
    log_audit = function(userid, dossierid, actie, pseudo_bsn = ""){
      
      self$append_data("audittrail", 
                       tibble(
                         auditid = uuid::UUIDgenerate(),
                         userid = userid,
                         dossierid = dossierid,
                         actie = actie,
                         tijdstip = Sys.time(),
                         pseudo_bsn = pseudo_bsn
                       ))
      
      
    },
    
    #' @description Get dossier kenmerken for a dossierid
    get_audit = function(dossierid){
      
      self$read_table("audittrail", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierid) %>%
        collect
      
    },
    
    
    #' @description Is this objectinstance a member of dossier?
    #' @return TRUE if object is in the dossier, FALSE otherwise.
    is_object_in_dossier = function(objectinstance, dossierid){
      
      out <- self$read_table("objecten", lazy = TRUE) %>%
        filter(dossierid == !!dossierid, objectinstance == !!objectinstance) %>%
        collect
      
      nrow(out) > 0
    },
    
    
    #' @description Add person(s) (who has a BSN) to a dossier
    #' @param ids Vector of pseudo-BSNs, or persoon-IDs (in case of unknown persons)
    #' @param dossierid Dossier ID (char)
    #' @param userid The current user (for audit trail)
    #' @return TRUE if successful, FALSE if object already added to dossier.
    add_object_to_dossier = function(ids, dossierid, userid,
                                     type = c("bsn_persoon","onbekend_persoon",
                                              "bag_locatie","onbekend_locatie"),
                                     dossierid_check = TRUE){  
      
      
      type <- match.arg(type)
      
      if(dossierid_check && !self$dossier_exists(dossierid)){
        warning(glue("Trying to add object to non-existent Dossier ID: {dossierid}"))
        return(FALSE)
      }
      
      
      # current objects in dossier
      cur_ids <- self$get_objects(dossierid) %>% pull(objectinstance)
      
      ids_exist <- intersect(ids, cur_ids)
      if(length(ids_exist)){
        
        if(length(ids_exist) == length(ids)){
          
          # object already in dossier
          return(FALSE)
          
        } else {
          
          # some objects already in dossier, add only the ones that are not.
          ids <- setdiff(ids, cur_ids)
          
        }
        
      }
      
      self$append_data("objecten", tibble(
        objectid = uuid::UUIDgenerate(n = length(ids)),
        dossierid = dossierid,
        objecttype = type,
        objectinstance = as.character(ids),  # pseudo_bsn's, adresseerbaarobject, etc.
        toevoegdatum = Sys.time(),
        verwijderdatum = as.POSIXct(NA)
      ))
      
      if(type == "bsn_persoon"){
        pids <- paste(ids, collapse=';')
        self$log_audit(userid, dossierid, actie = glue("Object type {type} toegevoegd aan Dossier {dossierid},",
                                                       " pseudo-BSN: {pids}"),
                       pseudo_bsn = pids)
      } else {
        self$log_audit(userid, dossierid, actie = glue("Object type {type} toegevoegd aan Dossier {dossierid}."))
      }
      
    },
    
    #' @description Remove an object from a dossier
    remove_object_from_dossier = function(ids, dossierid, userid){
      
      for(id in ids){
        self$log_audit(userid, dossierid, actie = glue("Verwijder object: {id} uit dossier: {dossierid}"))  
        self$delete_rows_where2("objecten", "objectinstance", id, "dossierid", dossierid)
      }
      
    },
    
    #' @description Add kenmerken to a persoon
    add_persoon_kenmerken = function(dossierid,
                                     id,
                                     geboortedatum = "",
                                     geslacht = ""){
      
      ts <- format(Sys.time())
      
      leeftijd <- floor(as.numeric(difftime(Sys.Date(), as.Date(geboortedatum),
                           units = "weeks")) / 52)
      
      self$append_data("persoon_kenmerken", tibble(
        timestamp = ts,
        dossierid = dossierid,
        pseudo_bsn = id,
        leeftijd = leeftijd,
        geslacht = geslacht
      ))
      
    },
    
    
    #' @description Register a new 'unknown' person
    #' @param name
    #' @param adresseerbaarobject
    #' @param woonadresomschrijving
    #' @return The new ID of the person
    add_unknown_person = function(name, 
                                  adresseerbaarobject = NULL, 
                                  locatieid = "",
                                  woonadresomschrijving = ""){
      
      persoon_id <- uuid::UUIDgenerate()
      
      if(is.null(adresseerbaarobject)){
        woonadres_type <- "locatie"
        woonadres_id <- locatieid
      } else {
        woonadres_type <- "adresseerbaarobject"
        woonadres_id <- adresseerbaarobject
      }
      
      # Onbekend persoon op onbekend adres
      self$append_data("persoon", 
                       tibble(
                         persoonid = persoon_id,
                         persoonname = name,
                         woonadrestype = woonadres_type,
                         woonadresid = woonadres_id,
                         woonadresomschrijving = woonadresomschrijving,  # 'extra' veld (?)
                         gekoppeldbsn = ""  # kan later ingevuld worden
                       ))
      
      
      return(persoon_id) 
    },
    
    #' @description Get a person (an unknown person) by ID
    get_persoon = function(id){
      
      self$read_table("persoon", lazy = TRUE) %>%
        filter(persoonid %in% !!id) %>%
        collect
      
    },
    
    #' @description Update name, BSN of an unknown person
    edit_unknown_persoon = function(id, naam, bsn){
      
      if(!is.null(naam)){
        self$replace_value_where("persoon", col_replace = "persoonname", val_replace = naam,
                                 col_compare = "persoonid", val_compare = id)  
      }
      if(!is.null(bsn)){
        self$replace_value_where("persoon", col_replace = "gekoppeldbsn", val_replace = bsn,
                                 col_compare = "persoonid", val_compare = id)  
      }
      
      
    },
    
    #' @description Register an 'unknown' location
    #' @param locatieomschrijving Description of the location - mandatory
    #' @param wijk Optional
    #' @param buurt Optional
    #' @param postcode Optional
    #' @param straatnaam Optional
    #' @return The new ID of the location
    add_unknown_location = function(locatieomschrijving, 
                                    wijk = "", 
                                    buurt = "", 
                                    postcode = "", 
                                    straatnaam = "",
                                    huisnummer = "",
                                    huisnummertoevoeging = "",
                                    plaatsnaam = ""
    ){
      
      
      location_id <- uuid::UUIDgenerate()
      
      self$append_data("locatie", 
                       tibble(
                         locatieid = location_id,
                         locatieomschrijving = locatieomschrijving, 
                         wijk = wijk, 
                         buurt = buurt, 
                         postcode = postcode, 
                         straatnaam = straatnaam,
                         huisnummer = huisnummer,
                         huisnummertoevoeging = huisnummertoevoeging,
                         plaatsnaam = plaatsnaam
                       ))
      
      return(location_id)
    },
    
    delete_unknown_location = function(id){
      
      self$delete_rows_where("locatie", "locatieid", id)
      
    },
    
    get_unknown_location = function(id){
      
      self$read_table("locatie", lazy = TRUE) %>%
        filter(locatieid %in% !!id) %>%
        collect
      
    },
    
    
    #' @description Make an adres the hoofdadres of the dossier
    #' @param dossierid
    #' @param objectinstance
    set_adres_as_hoofdadres = function(dossierid, objectinstance){
      
      query <- glue("update {self$schema}.dossiers set hoofdadresid = '{objectinstance}' where ",
                    "dossierid = {dossierid}") %>% as.character()
      
      dbExecute(self$con, query)
      
    },
    

    
    #'@description Fill 'relation' and 'related_to' column for an object (typically, person) 
    #'in a dossier.
    #'@param dossierid
    #'@param objectinstance
    #'@param relation
    #'@param related_to
    set_object_relations = function(dossierid, objectinstance, relation, related_to){
      
      query <- glue("update {self$schema}.objecten set relation = '{relation}', related_to = '{related_to}' ",
                    "where dossierid = {dossierid} and objectinstance = '{objectinstance}'") %>% 
        as.character()
      
      dbExecute(self$con, query)
      
    },
    
    #' @description Get kenmerk column for an object in a dossier. 
    #' @param dossierid The dossier ID (integer)
    #' @param objectinstance The object ID instance.
    get_object_kenmerk = function(dossierid, objectinstance){
      
      self$read_table("objecten", lazy = TRUE) %>%
        filter(dossierid == !!dossierid, objectinstance == !!objectinstance) %>%
        collect %>%
        pull(kenmerk)
      
    },
    
    #'@description Fill 'kenmerk' column for an object in a dossier.
    #'@param dossierid
    #'@param objectinstance
    #'@param kenmerk Text field (no validation)
    set_object_kenmerk = function(dossierid, objectinstance, kenmerk){
      
      if(is.null(kenmerk))kenmerk <- " "
      query <- glue("update {self$schema}.objecten set kenmerk = '{kenmerk}' where ",
                    "dossierid = {dossierid} and objectinstance = '{objectinstance}'") %>% 
        as.character()
      
      dbExecute(self$con, query)
      
    },
    
    #' @description Get all objects in a dossier
    #' @param dossierid The dossier ID (integer)
    get_objects = function(dossierid, type = NULL){
      
      query <- self$read_table("objecten", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierid)
      
      if(!is.null(type)){
        query <- filter(query, objecttype %in% !!type)
      }
      
      collect(query)
      
    },
    
    n_personen_dossier = function(dossierid){
      
      out <- self$read_table("objecten", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierid,
               objecttype %in% c("bsn_persoon","onbekend_persoon")) %>%
        summarize(n()) %>%
        collect
      
      as.integer(out[[1]])
      
    },
    
    #' @description Save kenmerktypes for a dossier
    #' @param dossierid The dossier ID
    #' @param A vector of kenmerktypes
    add_dossier_kenmerken = function(dossierid, kenmerktypeid, userid){
      
      n_kenm <- length(kenmerktypeid)
      
      self$append_data("dossierkenmerk", tibble(
        
        dossierid = dossierid,
        kenmerktypeid = kenmerktypeid,
        creation_time = Sys.time(),
        userid = userid
      ))
      
      
    },
    
    #' @description Get dossier kenmerken for a dossierid
    get_dossier_kenmerken = function(dossierid){
      
      self$read_table("dossierkenmerk", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierid) %>%
        collect
      
    },
    
    #' @description Replace kenmerken for a dossier
    replace_dossier_kenmerken = function(dossierid, kenmerktypeid, userid){
      
      kenm <- paste(kenmerktypeid, collapse =", ")
      self$log_audit(userid, dossierid, actie = glue("Kenmerken dossier toegewezen: {kenm} voor dossier: {dossierid}"))
      
      self$delete_rows_where("dossierkenmerk", "dossierid", dossierid)
      
      if(length(kenmerktypeid) > 0){
        self$add_dossier_kenmerken(dossierid, kenmerktypeid, userid)  
      }
      
      
    },
    
    
    #' @description Get dossierid's for given dossierkenmerken
    #' @param coordinatoren A vector of coordinatoren userid's.
    #' @return A vector of dossierid's
    get_dossierid_dossier_kenmerken = function(kenmerken){
      
      self$read_table("dossierkenmerk", lazy = TRUE) %>%
        filter(kenmerktypeid %in% !!kenmerken) %>%
        collect %>%
        pull(dossierid) %>%
        unique
      
    },
    
    
    #' @description Write coordinatoren for a dossier.
    add_coordinatoren = function(dossierid, userid){
      
      n_coor <- length(userid)
      
      self$append_data("coordinatoren", tibble(
        id = uuid::UUIDgenerate(n = n_coor),
        dossierid = dossierid,
        userid = userid
      ))
      
    },
    
    delete_dossier_coordinatoren = function(dossierid){
      
      self$delete_rows_where("coordinatoren",col_compare = "dossierid",val_compare = dossierid)
      
    },
    
    replace_dossier_coordinatoren = function(dossierid, userid){
      
      self$delete_dossier_coordinatoren(dossierid)
      self$add_coordinatoren(dossierid, userid)
      
    },
    
    #' @description Get coordinatoren for a dossierid
    get_coordinatoren = function(dossierid){
      
      self$read_table("coordinatoren", lazy = TRUE) %>%
        filter(dossierid %in% !!dossierid) %>%
        collect
      
    },
    
    #' @description Get dossierid's for given coordinatoren
    #' @param coordinatoren A vector of coordinatoren userid's.
    #' @return A vector of dossierid's
    get_dossierid_coordinatoren = function(coordinatoren){
      
      self$read_table("coordinatoren", lazy = TRUE) %>%
        filter(userid %in% !!coordinatoren) %>%
        collect %>%
        pull(dossierid) %>%
        unique
      
    },
    
    #' @description Encrypt a value using a secret
    #' @details A vectorized version of `safer::encrypt_string`
    #' @param x A vector of values to encrypt
    #' @param secret The secret to use, set options(linkit_secret = "abc")
    encrypt = function(x, secret = getOption("linkit_secret")){
    
    vapply(x, safer::encrypt_string, key = secret,
           USE.NAMES = FALSE, FUN.VALUE = character(1)
    )
    },
    
    #' @description Decrypt a value using a secret
    #' @details A vectorized version of `safer::decrypt_string`.
    #' Missing values and empty strings are returned unchanged.
    #' @param x A vector of values to decrypt
    #' @param secret The secret to use, set options(linkit_secret = "abc")
    decrypt = function(x, secret = getOption("linkit_secret")){
      
      ii <- which(!is.na(x) & stringr::str_trim(x) != "")
      jj <- setdiff(1:length(x),ii)
      
      d <- vapply(x[ii], 
                  safer::decrypt_string, 
                  key = secret,
                  USE.NAMES = FALSE, FUN.VALUE = character(1)
      )
      
      out <- vector("character", length = length(x))
      out[ii] <- d
      out[jj] <- x[jj]
      
      out
    }
    
    
  ),
  
  private = list(
    to_sql_string = function(x){
      
      paste0(
        "('",
        paste(x, collapse="','"),
        "')"
      )
      
    }
    
  )
) 
moturoa/linkitr documentation built on April 15, 2023, 2 p.m.