Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
Package: EDIutils
Title: An API Client for the Environmental Data Initiative Repository
Version: 1.0.3
Version: 2.0.0
Authors@R:
c(person("Colin", "Smith", email = "colin.smith@wisc.edu", role = c("aut", "cre"), comment = "https://orcid.org/0000-0003-2261-9931"),
person("Corinna", "Gries", role = "ctb", comment = "https://orcid.org/0000-0002-9091-6543"),
person("Jasmine", "Lai", role = "rev", comment = "https://orcid.org/0000-0001-8888-547X"),
person("Rodrigo", "Pires", role = "rev", comment = "https://orcid.org/0000-0001-7384-6849"))
c(person("Colin", "Smith", email = "colin.smith@wisc.edu", role = c("aut", "cre"), comment = "0000-0003-2261-9931"),
person("Corinna", "Gries", role = "ctb", comment = "0000-0002-9091-6543"),
person("Jasmine", "Lai", role = "rev", comment = "0000-0001-8888-547X"),
person("Rodrigo", "Pires", role = "rev", comment = "0000-0001-7384-6849"))
Description: A client for the Environmental Data Initiative repository REST API. The 'EDI' data repository <https://portal.edirepository.org/nis/home.jsp> is for publication and reuse of ecological data with emphasis on metadata accuracy and completeness. It is built upon the 'PASTA+' software stack <https://pastaplus-core.readthedocs.io/en/latest/index.html#> and was developed in collaboration with the US 'LTER' Network <https://lternet.edu/>. 'EDIutils' includes functions to search and access existing data, evaluate and upload new data, and assist other data management tasks common to repository users.
Imports: curl, httr, jsonlite, xml2
Imports: curl, httr, jsonlite, xml2, utils
License: MIT + file LICENSE
Encoding: UTF-8
RoxygenNote: 7.2.3
RoxygenNote: 7.3.3
Suggests: knitr, readr, vcr, rmarkdown, roxygen2, testthat
URL: https://github.com/ropensci/EDIutils, https://docs.ropensci.org/EDIutils/
BugReports: https://github.com/ropensci/EDIutils/issues
Expand Down
1 change: 1 addition & 0 deletions EDIutils.Rproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Version: 1.0
ProjectId: cad0fc9a-82d4-4af8-b8ce-a598f5372c69

RestoreWorkspace: Default
SaveWorkspace: Default
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export(delete_reservation)
export(evaluate_data_package)
export(execute_event_subscription)
export(get_audit_count)
export(get_audit_csv_report)
export(get_audit_record)
export(get_audit_report)
export(get_docid_reads)
Expand Down Expand Up @@ -72,3 +73,4 @@ export(read_metadata_format)
export(read_metadata_resource_metadata)
export(search_data_packages)
export(update_data_package)
importFrom(utils,read.csv)
16 changes: 16 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
EDIutils 2.2.0 (2026-01-09)
===========================

### DEPRECATED AND DEFUNCT
* Deprecate `get_audit_report()` in favor of `get_audit_csv_report()` (#62)
* Defunct `create_dn()`. This introduces a breaking change for
`list_principal_owner_citations()` and `list_user_data_packages()`,
which now require an EDI-ID instead of a Distinguished Name (DN). Users can
obtain their EDI-ID by logging into the
[EDI Identity and Access Manager](https://auth.edirepository.org/auth/ui/signin)
and copying the "EDI-ID" from their profile home page. (#65)

### MINOR IMPROVEMENTS

* Update authentication to support new EDI IAM system (#60)

EDIutils 1.0.3 (2023-10-10)
===========================

Expand Down
10 changes: 9 additions & 1 deletion R/create_dn.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#' Create a users distinguished name
#' Create a users distinguished name (defunct)
#'
#' This function is defunct. Distinguished names are deprecated in favor of EDI
#' IDs. An EDI ID can be obtained from the EDI Identity and Access
#' Manager (\url{https://auth.edirepository.org/auth/ui/signin}).
#'
#' @param userId (character) User identifier of an EDI data repository account
#' @param ou (character) Organizational unit in which \code{userId} belongs.
Expand All @@ -12,14 +16,18 @@
#' @export
#'
#' @examples
#' \dontrun{
#' # For an EDI account
#' dn <- create_dn(userId = "my_userid", ou = "EDI")
#' dn
#'
#' # For an LTER account
#' dn <- create_dn(userId = "my_userid", ou = "LTER")
#' dn
#' }
create_dn <- function(userId, ou = "EDI") {
.Defunct(msg = "'create_dn()' is defunct. Distinguished names are no longer
used in EDI authentication. Use an EDI ID token instead.")
ou <- toupper(ou)
res <- paste0("uid=", userId, ",o=", ou, ",")
if (ou == "EDI") {
Expand Down
73 changes: 73 additions & 0 deletions R/get_audit_csv_report.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#' Get audit csv report
#'
#' @param query (character) Query (see details below)
#' @param env (character) Repository environment. Can be: "production",
#' "staging", or "development".
#'
#' @return (data.frame or xml_document) Zero or more audit records matching
#' the query parameters as specified in the request (see details below) and
#' streams back a comma separated values result set.
#'
#' @details Query parameters are specified as key=value pairs, multiple pairs
#' must be delimited with ampersands (&), and only a single value should be
#' specified for a particular key. The following query parameter keys are
#' allowed:
#'
#' \itemize{
#' \item category - Can be: debug, info, error, warn
#' \item service - Any of the EDI data repository services
#' \item serviceMethod - Any of the EDI data repository service Resource
#' class JAX-RS methods
#' \item user - Any user
#' \item group - Any group
#' \item authSystem - A valid auth system identifier
#' \item status - A valid HTTP Response Code
#' \item resourceId - An EDI data repository resource identifier, e.g.
#' https://pasta.lternet.edu/package/eml/knb-lter-and/2719/6, or a thereof
#' (see details below)
#' \item fromTime - An ISO8601 timestamp
#' \item toTime - An ISO8601 timestamp
#' \item limit - A positive whole number
#' }
#'
#' The query parameters fromTime and optionally toTime should be used to
#' indicate a time span. When toTime is absent, the report will consist of all
#' matching records up to the current time. Either of these parameters may only
#' be used once. The query parameter limit sets an upper limit on the number of
#' audit records returned. For example, "limit=1000". The query parameter
#' resourceId will match any audit log entry whose resourceId value contains
#' the specified string value. Thus, a query parameter of
#' "resourceId=knb-lter-and" will match any audit log entry whose resourceId
#' value contains the substring "knb-lter-and", while a query parameter of
#' "resourceId=knb-lter-and/2719/6" will match any audit log entry whose
#' resourceId value contains the substring "knb-lter-and/2719/6".
#'
#' @note User authentication is required (see \code{login()})
#'
#' @family Audit Manager Services
#'
#' @importFrom utils read.csv
#'
#' @export
#'
#' @examples
#' \dontrun{
#'
#' login()
#'
#' # Get audit report for data reads between 2021-12-01 and 2021-12-02
#' query <- "serviceMethod=readDataEntity&fromTime=2021-12-01&toTime=2021-12-02"
#' auditReport <- get_audit_csv_report(query)
#'
#' logout()
#' }
#'
get_audit_csv_report <- function(query, env = "production") {
url <- paste0(base_url(env), "/audit/csvreport?", query)
cookie <- bake_cookie()
resp <- httr::GET(url, set_user_agent(), cookie, handle = httr::handle(""))
res <- httr::content(resp, as = "text", encoding = "UTF-8")
httr::stop_for_status(resp, res)
res <- read.csv(text = res, stringsAsFactors = FALSE)
return(res)
}
5 changes: 4 additions & 1 deletion R/get_audit_report.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#' Get audit report
#' Get audit report (deprecated)
#'
#' This function is deprecated. Please use get_audit_csv_report() instead.
#'
#' @param query (character) Query (see details below)
#' @param as (character) Format of the returned object. Can be: "data.frame"
Expand Down Expand Up @@ -62,6 +64,7 @@
#' }
#'
get_audit_report <- function(query, as = "data.frame", env = "production") {
.Deprecated("get_audit_csv_report")
url <- paste0(base_url(env), "/audit/report?", query)
cookie <- bake_cookie()
resp <- httr::GET(url, set_user_agent(), cookie, handle = httr::handle(""))
Expand Down
9 changes: 5 additions & 4 deletions R/list_principal_owner_citations.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#' List principal owner citations
#'
#' @param principalOwner (character) Principal owner in the format returned by
#' \code{create_dn()}
#' @param principalOwner (character) The EDI ID of the principal owner.
#' EDI IDs can be obtained from the EDI Identity and Access
#' Manager (\url{https://auth.edirepository.org/auth/ui/signin}).
#' @param as (character) Format of the returned object. Can be: "data.frame"
#' or "xml".
#' @param env (character) Repository environment. Can be: "production",
Expand All @@ -18,8 +19,8 @@
#' \dontrun{
#'
#' # List citations
#' dn <- create_dn(userId = "FCE", ou = "EDI")
#' journalCitations <- list_principal_owner_citations(principalOwner = dn)
#' edi_id <- "EDI-543afa80c859825d35d37d9111c24a4a65a0ff9e"
#' journalCitations <- list_principal_owner_citations(principalOwner = edi_id)
#' }
list_principal_owner_citations <- function(principalOwner,
as = "data.frame",
Expand Down
16 changes: 9 additions & 7 deletions R/list_user_data_packages.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
#' distinguished name. Data packages that were uploaded by the specified user
#' but have since been deleted are excluded from the list.
#'
#' @param dn (character) Distinguished name of user. Create with
#' \code{create_dn()}.
#' @param edi_id (character) The EDI ID of the user. An EDI ID can be obtained
#' from the EDI Identity and Access Manager
#' (\url{https://auth.edirepository.org/auth/ui/signin}).
#' @param env (character) Repository environment. Can be: "production",
#' "staging", or "development".
#'
#' @return (character) Data package identifiers belonging to a \code{dn}
#' @return (character) Data package identifiers belonging to a
#' \code{edi_id}
#'
#' @family Listing
#'
Expand All @@ -20,13 +22,13 @@
#' \dontrun{
#'
#' # List user data packages
#' dn <- create_dn(userId = "dbjourneynorth")
#' packageIds <- list_user_data_packages(dn)
#' edi_id <- "EDI-543afa80c859825d35d37d9111c24a4a65a0ff9e"
#' packageIds <- list_user_data_packages(edi_id)
#' packageIds
#' #> [1] "edi.948.1" "edi.949.1"
#' }
list_user_data_packages <- function(dn, env = "production") {
url <- paste0(base_url(env), "/package/user/", dn)
list_user_data_packages <- function(edi_id, env = "production") {
url <- paste0(base_url(env), "/package/user/", edi_id)
resp <- httr::GET(url, set_user_agent(), handle = httr::handle(""))
res <- httr::content(resp, as = "text", encoding = "UTF-8")
httr::stop_for_status(resp, res)
Expand Down
24 changes: 19 additions & 5 deletions R/login.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#' @param config (character) Path to config.txt, which contains \code{userId}
#' and \code{userPass} (see details below)
#'
#' @return (character) A temporary (~10 hour) authentication token written to
#' the system variable "EDI_TOKEN".
#' @return (character) Temporary (~10 hour) authentication tokens written to
#' the system variables "EDI_TOKEN" and "AUTH_TOKEN".
#'
#' @note Only works when authenticating with EDI credentials. Does not work
#' when authenticating with ORCiD, GitHub, or Google credentials.
Expand Down Expand Up @@ -72,13 +72,27 @@ login <- function(userId = NULL, userPass = NULL, config = NULL) {
regmatches(txt[i], regexpr(pattern, txt[i], perl = TRUE))
)
}
dn <- create_dn(userId, "EDI")
dn <- .create_dn(userId, "EDI")
resp <- httr::GET(
url = paste0(base_url("production"), "/package/eml"),
config = httr::authenticate(dn, userPass, type = "basic"),
handle = httr::handle("")
)
httr::stop_for_status(resp)
token <- httr::cookies(resp)$value
Sys.setenv(EDI_TOKEN = token)
token_name <- httr::cookies(resp)$name
token_value <- httr::cookies(resp)$value
Sys.setenv(EDI_TOKEN = token_value[token_name == "edi-token"])
Sys.setenv(AUTH_TOKEN = token_value[token_name == "auth-token"])
}


.create_dn <- function(userId, ou = "EDI") {
ou <- toupper(ou)
res <- paste0("uid=", userId, ",o=", ou, ",")
if (ou == "EDI") {
res <- paste0(res, "dc=edirepository,dc=org")
} else {
res <- paste0(res, "dc=ecoinformatics,dc=org")
}
return(res)
}
5 changes: 3 additions & 2 deletions R/logout.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#' Logout of the EDI repository
#'
#' @details Removes the temporary authentication token system variable
#' "EDI_TOKEN".
#' @details Removes the temporary authentication token system variables
#' "EDI_TOKEN" and "AUTH_TOKEN".
#'
#' @return (NULL) No return value.
#'
Expand All @@ -16,4 +16,5 @@
#'
logout <- function() {
suppressWarnings(Sys.unsetenv("EDI_TOKEN"))
suppressWarnings(Sys.unsetenv("AUTH_TOKEN"))
}
18 changes: 12 additions & 6 deletions R/utilities.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
#' @noRd
#'
bake_cookie <- function() {
token <- Sys.getenv("EDI_TOKEN")
if (token == "") {
edi_token <- Sys.getenv("EDI_TOKEN")
auth_token <- Sys.getenv("AUTH_TOKEN")
if (edi_token == "" || auth_token == "") {
stop("Authentication token not found. Run 'login()' then try again.",
call. = FALSE
)
}
cookie <- httr::set_cookies(`auth-token` = token)
cookie <- httr::set_cookies(
`edi-token` = edi_token,
`auth-token` = auth_token
)
cookie$options$cookie <- curl::curl_unescape(cookie$options$cookie)
return(cookie)
}
Expand Down Expand Up @@ -119,6 +123,9 @@ config_test_eml <- function(userId, url) {
#' written to file
#' @param packageId (character) Package identifier, of the form
#' "scope.identifier.revision", for the new EML file
#' @param edi_id (character) The EDI ID of the user creating the test EML.
#' An EDI ID can be obtained from the EDI Identity and Access
#' Manager (\url{https://auth.edirepository.org/auth/ui/signin}).
#'
#' @return (character) Full path to EML file written by this function to
#' \code{path}. Should be \code{tempdir()} if executed in a testthat context.
Expand All @@ -128,16 +135,15 @@ config_test_eml <- function(userId, url) {
#'
#' @noRd
#'
create_test_eml <- function(path, packageId) {
create_test_eml <- function(path, packageId, edi_id) {
# Read EML template
eml <- system.file("extdata", "eml.xml", package = "EDIutils")
eml <- xml2::read_xml(eml)
# Add packageId
xml2::xml_attr(eml, "packageId") <- packageId
# Add principal
dn <- create_dn(Sys.getenv("EDI_USERID"))
principal <- xml2::xml_find_first(eml, ".//principal")
xml2::xml_text(principal) <- dn
xml2::xml_text(principal) <- edi_id
# Add URL
url <- xml2::xml_find_first(eml, ".//online/url")
xml2::xml_text(url) <- Sys.getenv("EDI_TEST_URL")
Expand Down
Loading
Loading