r-lib / keyring

:closed_lock_with_key: Access the system credential store from R
https://keyring.r-lib.org/
Other
196 stars 28 forks source link

backend_file doesn't handle entries without a username #78

Closed sz-cgt closed 3 years ago

sz-cgt commented 4 years ago

The documentation for the backend$set() method says that the username field is optional. However, the file backend does not handle situations where the username is not supplied when setting an entry.

kr <- keyring::backend_file$new()
kr$keyring_unlock(password = "test")
kr$list()
#> [1] service  username
#> <0 rows> (or 0-length row.names)
kr$set_with_value("test",password = "test")
kr$list()
#> Error in vapply(all_items, `[[`, character(1L), "user_name"): values must be length 1,
#>  but FUN(X[[1]]) result is length 0

Created on 2020-01-15 by the reprex package (v0.3.0)

sessionInfo()
R version 3.6.0 (2019-04-26)
Platform: x86_64-redhat-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS/LAPACK: /usr/lib64/R/lib/libRblas.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages:
 [1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.3       ps_1.3.0         getPass_0.2-2    withr_2.1.2      digest_0.6.23    assertthat_0.2.1
 [7] rappdirs_0.3.1   R6_2.4.1         reprex_0.3.0     evaluate_0.14    rlang_0.4.2      rstudioapi_0.10
[13] fs_1.3.1         callr_3.4.0      whisker_0.4      filelock_1.0.2   keyring_1.1.0    rmarkdown_2.0
[19] tools_3.6.0      processx_3.4.1   xfun_0.12        yaml_2.2.0       compiler_3.6.0   sodium_1.1
[25] clipr_0.7.0      htmltools_0.4.0  knitr_1.26
jeanetteclark commented 4 years ago

I ran into the same issue when trying to set a second key in a keyring when using a file backend, as below:

library(keyring)
options(keyring_backend = "file")

keyring_create("test_keyring")

key_set_with_value(service = "foo",
                   password = "bar",
                   keyring = "test_keyring")

key_set_with_value(service = "foo2",
                   password = "bar2",
                   keyring = "test_keyring")

I found a workaround that uses unlist() and lapply() unstead of [[ and vapply(), which seems to handle the NULL that shows up in user_name if none has been set previously. The solution is not particularly elegant, and I'm not sure it covers all cases. All of the tests that run are passing on my Mac at least. I'll create a PR which you can take or leave.

gaborcsardi commented 3 years ago

Fixed in db90922 (#95).