Skip to content

Commit 668cfe3

Browse files
authored
Don't overwrite stored netrc credentials on download (#27, #13) (#28)
* Don't overwrite stored netrc credentials on download (#27, #13) edl_download() (and a bare edl_netrc()) unconditionally rewrote the .netrc file with the bundled default credentials, clobbering credentials a user had already set with edl_netrc() and causing 401 errors. Only (re)write the netrc when credentials are supplied explicitly or when no earthdata netrc exists yet. The guard uses missing() + file existence, so it behaves deterministically in headless/non-interactive sessions too. * Extend netrc no-overwrite guard to edl_search() (#27)
1 parent 800f8ed commit 668cfe3

5 files changed

Lines changed: 87 additions & 17 deletions

File tree

‎NEWS.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# earthdatalogin 0.0.4
22

3+
* `edl_download()`, `edl_search()`, and `edl_netrc()` no longer overwrite
4+
stored credentials. Previously, calling these without arguments rewrote the
5+
`.netrc` file with the bundled default credentials, clobbering credentials a
6+
user had already set and causing 401 errors. Now the netrc is only
7+
(re)written when credentials are supplied explicitly or when no earthdata
8+
netrc exists yet (#27, #13).
9+
310
* Tests no longer attempt network access on CRAN. The `netcdf access` test now
411
skips on CRAN and when offline, and the `get_nasa_stac_url()` error-path test
512
is mocked so it runs without network access. This resolves the CRAN check

‎R/edl_download.R‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,17 @@ edl_download <- function(href,
3636

3737
} else {
3838

39-
edl_netrc(username = username,
40-
password = password,
41-
netrc_path = netrc_path,
42-
cookie_path = cookie_path,
43-
cloud_config = FALSE)
39+
# Only (re)write the netrc when the caller explicitly supplies
40+
# credentials, or when no earthdata netrc exists yet. Downloading must
41+
# never clobber credentials a user already stored with edl_netrc() (#27).
42+
if (!missing(username) || !missing(password) ||
43+
!has_edl_netrc(netrc_path)) {
44+
edl_netrc(username = username,
45+
password = password,
46+
netrc_path = netrc_path,
47+
cookie_path = cookie_path,
48+
cloud_config = FALSE)
49+
}
4450

4551

4652
if (method == "httr") {

‎R/edl_netrc.R‎

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,26 @@ edl_netrc <- function(username = default("user"),
4040
# Bearer auth can conflict
4141
edl_unset_token()
4242

43-
# Create a .netrc for earthdatalogin
44-
contents <- paste("machine urs.earthdata.nasa.gov login",
45-
username, "password", password)
46-
writeLines(contents, netrc_path)
43+
# Don't clobber stored credentials. If the caller did not explicitly
44+
# supply a username/password and the netrc file already holds earthdata
45+
# credentials, keep them rather than overwriting with the bundled
46+
# defaults (#13, #27).
47+
if (!missing(username) || !missing(password) ||
48+
!has_edl_netrc(netrc_path)) {
49+
50+
# Create a .netrc for earthdatalogin
51+
contents <- paste("machine urs.earthdata.nasa.gov login",
52+
username, "password", password)
53+
writeLines(contents, netrc_path)
54+
55+
# GDAL < 3.7 cannot use an alternative location for .netrc
56+
old_gdal_compatibility(netrc_path, contents)
57+
}
4758

4859
# set GDAL env vars to use this netrc
4960
Sys.setenv("GDAL_HTTP_NETRC" = "YES")
5061
Sys.setenv("GDAL_HTTP_NETRC_FILE" = netrc_path) # GDAL >= 3.7.0
5162

52-
# GDAL < 3.7 cannot use an alternative location for .netrc
53-
old_gdal_compatibility(netrc_path, contents)
54-
5563
# Set cookie paths as GDAL env vars
5664
Sys.setenv("GDAL_HTTP_COOKIEFILE" = cookie_path)
5765
Sys.setenv("GDAL_HTTP_COOKIEJAR" = cookie_path)
@@ -60,6 +68,15 @@ edl_netrc <- function(username = default("user"),
6068
gdal_cloud_config()
6169
}
6270

71+
invisible(TRUE)
72+
}
73+
74+
#' Does an earthdata .netrc file already exist at this path?
75+
#' @noRd
76+
has_edl_netrc <- function(netrc_path = edl_netrc_path()) {
77+
file.exists(netrc_path) &&
78+
any(grepl("machine urs.earthdata.nasa.gov",
79+
readLines(netrc_path, warn = FALSE)))
6380
}
6481

6582
#' edl_unset_netrc

‎R/edl_search.R‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,17 @@ edl_search <- function(short_name = NULL,
6262
# prompt_for_netrc = FALSE)
6363

6464

65-
edl_netrc(username = username,
66-
password = password,
67-
netrc_path = netrc_path,
68-
cookie_path = cookie_path,
69-
cloud_config = FALSE)
65+
# Only (re)write the netrc when the caller explicitly supplies
66+
# credentials, or when no earthdata netrc exists yet, so searching never
67+
# clobbers credentials a user already stored with edl_netrc() (#27).
68+
if (!missing(username) || !missing(password) ||
69+
!has_edl_netrc(netrc_path)) {
70+
edl_netrc(username = username,
71+
password = password,
72+
netrc_path = netrc_path,
73+
cookie_path = cookie_path,
74+
cloud_config = FALSE)
75+
}
7076
netrc_config <-
7177
httr::config(netrc = TRUE,
7278
netrc_file = netrc_path,

‎tests/testthat/test-edl_netrc.R‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
test_that("edl_netrc and edl_download do not overwrite stored credentials", {
2+
# No network needed: we only check what gets written to the netrc file.
3+
netrc <- tempfile()
4+
cookie <- tempfile()
5+
on.exit(unlink(c(netrc, cookie)), add = TRUE)
6+
7+
# explicit credentials are written
8+
edl_netrc(username = "alice", password = "secret",
9+
netrc_path = netrc, cookie_path = cookie, cloud_config = FALSE)
10+
expect_match(readLines(netrc), "login alice password secret")
11+
12+
# a bare call must NOT overwrite the stored credentials with the defaults
13+
edl_netrc(netrc_path = netrc, cookie_path = cookie, cloud_config = FALSE)
14+
expect_match(readLines(netrc), "login alice password secret")
15+
16+
# a download without credentials must also leave the netrc intact
17+
tryCatch(
18+
edl_download("https://urs.earthdata.nasa.gov/nonexistent",
19+
dest = tempfile(), netrc_path = netrc,
20+
cookie_path = cookie, quiet = TRUE),
21+
error = function(e) NULL, warning = function(w) NULL
22+
)
23+
expect_match(readLines(netrc), "login alice password secret")
24+
25+
# but explicit credentials at download time are honored
26+
tryCatch(
27+
edl_download("https://urs.earthdata.nasa.gov/nonexistent",
28+
dest = tempfile(), username = "bob", password = "pw2",
29+
netrc_path = netrc, cookie_path = cookie, quiet = TRUE),
30+
error = function(e) NULL, warning = function(w) NULL
31+
)
32+
expect_match(readLines(netrc), "login bob password pw2")
33+
})
34+
135
test_that("edl_netrc", {
236
skip_on_cran()
337
skip_if_offline()

0 commit comments

Comments
 (0)