From 92201e171fb929550a5e00967ac9a9cf24ad6285 Mon Sep 17 00:00:00 2001 From: Colin Gillespie Date: Mon, 24 Jun 2024 18:05:52 +0100 Subject: [PATCH 1/3] feat: Automatically extract Posit versions --- R/posit_versions.R | 4 +- R/rvest.R | 45 +++++ inst/extdata/versions/connect.csv | 296 ++++++++++++++++++++-------- inst/extdata/versions/drivers.csv | 12 +- inst/extdata/versions/workbench.csv | 42 ++-- 5 files changed, 299 insertions(+), 100 deletions(-) create mode 100644 R/rvest.R diff --git a/R/posit_versions.R b/R/posit_versions.R index cafc20f..4e5822f 100644 --- a/R/posit_versions.R +++ b/R/posit_versions.R @@ -12,8 +12,8 @@ get_posit_versions = function(type = c("connect", "workbench", "drivers")) { fname = system.file("extdata", "versions", paste0(type, ".csv"), mustWork = TRUE, package = "audit.base" ) - versions = readr::read_csv(fname, comment = "#", col_types = c("c", "D", "c")) - versions = dplyr::arrange(versions, dplyr::desc(date)) + versions = readr::read_csv(fname, comment = "#", col_types = c("c", "c")) + versions = dplyr::arrange(versions, dplyr::desc(name)) return(versions) } diff --git a/R/rvest.R b/R/rvest.R new file mode 100644 index 0000000..000e32e --- /dev/null +++ b/R/rvest.R @@ -0,0 +1,45 @@ +extract_cves = function(url) { + page = rvest::read_html(url) + sections = rvest::html_elements(page, "section") + v_tibbles = purrr::map_df(sections, extract_components) + all_v = get_all_versions(page) |> + dplyr::filter(!.data$name %in% v_tibbles$name) %>% + dplyr::bind_rows(v_tibbles) %>% + dplyr::arrange(dplyr::desc(name)) + all_v +} + +extract_components = function(section) { + posit_name = rvest::html_attrs(section) + posit_name = as.vector(posit_name["id"]) + posit_id = stringr::str_extract(posit_name, "[0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2}") + + li = section %>% + rvest::html_elements("li") %>% + rvest::html_text2() + + cves = stringr::str_extract(li, "^CVE-[0-9]{4}-[0-9]*") + cves = cves[!is.na(cves)] + + if (length(cves) == 0L || is.na(posit_id)) { + NULL + } else { + tibble::tibble(name = posit_id, cve = cves) + } + } + +get_all_versions = function(page) { + versions = page %>% + rvest::html_nodes('h2') %>% + rvest::html_text() + v = stringr::str_extract(versions, "202[0-9]\\.[0-9]{2}\\.[0-9]{1,2}") + tibble::tibble(name = v[!is.na(v)], cve = "") +} + +update_posit_versions = function() { + readr::write_csv(extract_cves("https://docs.posit.co/connect/news/"), + file = "inst/extdata/versions/connect.csv") + + readr::write_csv(extract_cves("https://docs.posit.co/ide/news/"), + file = "inst/extdata/versions/workbench.csv") +} \ No newline at end of file diff --git a/inst/extdata/versions/connect.csv b/inst/extdata/versions/connect.csv index 9e6a8d3..3921e8d 100644 --- a/inst/extdata/versions/connect.csv +++ b/inst/extdata/versions/connect.csv @@ -1,78 +1,218 @@ -#https://docs.posit.co/connect/news/ -version,date,cve -2024.05.0,2024-05-31,CVE-2024-24787 -2024.05.0,2024-05-31,CVE-2024-24788 -2024.04.1,2024-05-07, -2024.04.0,2024-04-29,CVE-2023-39320 -2024.04.0,2024-04-29,CVE-2023-39320 -2024.04.0,2024-04-29,CVE-2023-39319 -2024.04.0,2024-04-29,CVE-2023-39321 -2024.04.0,2024-04-29,CVE-2023-45288 -2024.04.0,2024-04-29,CVE-2023-45857 -2024.04.0,2024-04-29,CVE-2024-31207 -2024.03.0,2024-03-28, -2024.02.0,2024-02-27,CVE-2023-7104 -2024.01.0,2024-01-25,CVE-2023-48795 -2024.01.0,2024-01-25,CVE-2023-45683 -2023.12.0,2023-12-18,CVE-2023-45283 -2023.12.0,2023-12-18,CVE-2023-45284 -2023.12.0,2023-12-18,CVE-2023-39326 -2023.12.0,2023-12-18,CVE-2023-45285 -2023.10.0,2023-10-31,CVE-2023-39323 -2023.10.0,2023-10-31,CVE-2023-39325 -2023.10.0,2023-10-31,CVE-2023-44487 -2023.09.0,2023-09-23,CVE-2023-29409 -2023.09.0,2023-09-23,CVE-2023-39318 -2023.09.0,2023-09-23,CVE-2023-39319 -2023.09.0,2023-09-23,CVE-2023-39320 -2023.09.0,2023-09-23,CVE-2023-39321 -2023.09.0,2023-09-23,CVE-2023-39322 -2023.09.0,2023-09-23,CVE-2023-26117 -2023.09.0,2023-09-23,CVE-2023-26116 -2023.09.0,2023-09-23,CVE-2023-26118 -2023.07.0,2023-07-27,CVE-2023-29406 -2023.06.0,2023-06-26,CVE-2023-29401 -2023.06.0,2023-06-26,CVE-2023-29402 -2023.06.0,2023-06-26,CVE-2023-29403 -2023.06.0,2023-06-26,CVE-2023-29404 -2023.06.0,2023-06-26,CVE-2023-29405 -2023.05.0,2023-05-10,CVE-2023-24537 -2023.05.0,2023-05-10,CVE-2023-24538 -2023.05.0,2023-05-10,CVE-2023-24534 -2023.05.0,2023-05-10,CVE-2023-24536 -2023.05.0,2023-05-10,CVE-2023-28119 -2023.05.0,2023-05-10,CVE-2022-41912 -2023.05.0,2023-05-10,CVE-2023-24539 -2023.05.0,2023-05-10,CVE-2023-24540 -2023.05.0,2023-05-10,CVE-2023-29400 -2023.05.0,2023-05-10,CVE-2023-26125 -2023.03.0,2023-03-13,CVE-2022-41722 -2023.03.0,2023-03-13,CVE-2022-41725 -2023.03.0,2023-03-13,CVE-2022-41724 -2023.03.0,2023-03-13,CVE-2022-41723 -2023.03.0,2023-03-13,CVE-2023-24532 -2023.01.0,2023-01-25,CVE-2022-35737 -2022.12.0,2022-12-10,CVE-2022-0536 -2022.12.0,2022-12-10,CVE-2022-41720 -2022.12.0,2022-12-10,CVE-2022-41717 -2022.11.0,2022-11-16,CVE-2022-25844 -2022.11.0,2022-11-16,CVE-2022-25869 -2022.11.0,2022-11-16,CVE-2022-41716 -2022.10.0,2022-10-26,CVE-2022-2879 -2022.10.0,2022-10-26,CVE-2022-2879 -2022.10.0,2022-10-26,CVE-2022-41715 -2022.10.0,2022-10-26,CVE-2022-32149 -2022.09.0,2022-09-13,CVE-2022-28948 -2022.09.0,2022-09-13,CVE-2022-28948 -2022.09.0,2022-09-13,CVE-2022-32190 -2022.08.1,2022-08-25, -2022.08.0,2022-08-17,CVE-2022-32189 -2022.07.0,2022-07-21,CVE-2022-1705 -2022.07.0,2022-07-21,CVE-2022-32148 -2022.07.0,2022-07-21,CVE-2022-30631 -2022.07.0,2022-07-21,CVE-2022-30633 -2022.07.0,2022-07-21,CVE-2022-28131 -2022.07.0,2022-07-21,CVE-2022-30635 -2022.07.0,2022-07-21,CVE-2022-30632 -2022.07.0,2022-07-21,CVE-2022-30630 -2022.07.0,2022-07-21,CVE-2022-1962 +name,cve +2024.05.0,CVE-2024-24787 +2024.05.0,CVE-2024-24788 +2024.05.0,CVE-2024-24787 +2024.05.0,CVE-2024-24788 +2024.04.1, +2024.04.0,CVE-2023-39320 +2024.04.0,CVE-2023-39320 +2024.04.0,CVE-2023-39319 +2024.04.0,CVE-2023-39321 +2024.04.0,CVE-2023-45288 +2024.04.0,CVE-2023-45857 +2024.04.0,CVE-2024-31207 +2024.04.0,CVE-2023-39320 +2024.04.0,CVE-2023-39320 +2024.04.0,CVE-2023-39319 +2024.04.0,CVE-2023-39321 +2024.04.0,CVE-2023-45288 +2024.04.0,CVE-2023-45857 +2024.04.0,CVE-2024-31207 +2024.03.0, +2024.02.0,CVE-2023-7104 +2024.02.0,CVE-2023-7104 +2024.01.0,CVE-2023-48795 +2024.01.0,CVE-2023-45683 +2024.01.0,CVE-2023-48795 +2024.01.0,CVE-2023-45683 +2023.12.0,CVE-2023-45283 +2023.12.0,CVE-2023-45284 +2023.12.0,CVE-2023-39326 +2023.12.0,CVE-2023-45285 +2023.12.0,CVE-2023-45283 +2023.12.0,CVE-2023-45284 +2023.12.0,CVE-2023-39326 +2023.12.0,CVE-2023-45285 +2023.10.0,CVE-2023-39323 +2023.10.0,CVE-2023-39325 +2023.10.0,CVE-2023-44487 +2023.10.0,CVE-2023-39323 +2023.10.0,CVE-2023-39325 +2023.10.0,CVE-2023-44487 +2023.09.0,CVE-2023-29409 +2023.09.0,CVE-2023-39318 +2023.09.0,CVE-2023-39319 +2023.09.0,CVE-2023-39320 +2023.09.0,CVE-2023-39321 +2023.09.0,CVE-2023-39322 +2023.09.0,CVE-2023-26117 +2023.09.0,CVE-2023-26116 +2023.09.0,CVE-2023-26118 +2023.09.0,CVE-2023-29409 +2023.09.0,CVE-2023-39318 +2023.09.0,CVE-2023-39319 +2023.09.0,CVE-2023-39320 +2023.09.0,CVE-2023-39321 +2023.09.0,CVE-2023-39322 +2023.09.0,CVE-2023-26117 +2023.09.0,CVE-2023-26116 +2023.09.0,CVE-2023-26118 +2023.07.0,CVE-2023-29406 +2023.07.0,CVE-2023-29406 +2023.06.0,CVE-2023-29401 +2023.06.0,CVE-2023-29402 +2023.06.0,CVE-2023-29403 +2023.06.0,CVE-2023-29404 +2023.06.0,CVE-2023-29405 +2023.06.0,CVE-2023-29401 +2023.06.0,CVE-2023-29402 +2023.06.0,CVE-2023-29403 +2023.06.0,CVE-2023-29404 +2023.06.0,CVE-2023-29405 +2023.05.0,CVE-2023-24537 +2023.05.0,CVE-2023-24538 +2023.05.0,CVE-2023-24534 +2023.05.0,CVE-2023-24536 +2023.05.0,CVE-2023-28119 +2023.05.0,CVE-2022-41912 +2023.05.0,CVE-2023-24539 +2023.05.0,CVE-2023-24540 +2023.05.0,CVE-2023-29400 +2023.05.0,CVE-2023-26125 +2023.05.0,CVE-2022-38131 +2023.05.0,CVE-2023-24537 +2023.05.0,CVE-2023-24538 +2023.05.0,CVE-2023-24534 +2023.05.0,CVE-2023-24536 +2023.05.0,CVE-2023-28119 +2023.05.0,CVE-2022-41912 +2023.05.0,CVE-2023-24539 +2023.05.0,CVE-2023-24540 +2023.05.0,CVE-2023-29400 +2023.05.0,CVE-2023-26125 +2023.05.0,CVE-2022-38131 +2023.03.0,CVE-2022-41722 +2023.03.0,CVE-2022-41725 +2023.03.0,CVE-2022-41724 +2023.03.0,CVE-2022-41723 +2023.03.0,CVE-2023-24532 +2023.03.0,CVE-2022-41722 +2023.03.0,CVE-2022-41725 +2023.03.0,CVE-2022-41724 +2023.03.0,CVE-2022-41723 +2023.03.0,CVE-2023-24532 +2023.01.1, +2023.01.0, +2022.12.0,CVE-2022-0536 +2022.12.0,CVE-2022-41720 +2022.12.0,CVE-2022-41717 +2022.12.0,CVE-2022-0536 +2022.12.0,CVE-2022-41720 +2022.12.0,CVE-2022-41717 +2022.11.0,CVE-2022-25844 +2022.11.0,CVE-2022-25869 +2022.11.0,CVE-2022-41716 +2022.11.0,CVE-2022-25844 +2022.11.0,CVE-2022-25869 +2022.11.0,CVE-2022-41716 +2022.10.0,CVE-2022-2879 +2022.10.0,CVE-2022-2880 +2022.10.0,CVE-2022-41715 +2022.10.0,CVE-2022-32149 +2022.10.0,CVE-2022-2879 +2022.10.0,CVE-2022-2880 +2022.10.0,CVE-2022-41715 +2022.10.0,CVE-2022-32149 +2022.09.0,CVE-2022-28948 +2022.09.0,CVE-2022-27664 +2022.09.0,CVE-2022-32190 +2022.09.0,CVE-2022-28948 +2022.09.0,CVE-2022-27664 +2022.09.0,CVE-2022-32190 +2022.08.1, +2022.08.0,CVE-2022-32189 +2022.08.0,CVE-2022-32189 +2022.07.0,CVE-2022-1705 +2022.07.0,CVE-2022-32148 +2022.07.0,CVE-2022-30631 +2022.07.0,CVE-2022-30633 +2022.07.0,CVE-2022-28131 +2022.07.0,CVE-2022-30635 +2022.07.0,CVE-2022-30632 +2022.07.0,CVE-2022-30630 +2022.07.0,CVE-2022-1962 +2022.07.0,CVE-2022-1705 +2022.07.0,CVE-2022-32148 +2022.07.0,CVE-2022-30631 +2022.07.0,CVE-2022-30633 +2022.07.0,CVE-2022-28131 +2022.07.0,CVE-2022-30635 +2022.07.0,CVE-2022-30632 +2022.07.0,CVE-2022-30630 +2022.07.0,CVE-2022-1962 +2022.06.2, +2022.06.0,CVE-2022-30634 +2022.06.0,CVE-2022-30629 +2022.06.0,CVE-2022-30580 +2022.06.0,CVE-2022-29804 +2022.06.0,CVE-2022-30634 +2022.06.0,CVE-2022-30629 +2022.06.0,CVE-2022-30580 +2022.06.0,CVE-2022-29804 +2022.05.1, +2022.05.0,CVE-2022-21698 +2022.05.0,CVE-2020-28483 +2022.05.0,CVE-2022-29526 +2022.05.0,CVE-2022-21698 +2022.05.0,CVE-2020-28483 +2022.05.0,CVE-2022-29526 +2022.04.3, +2022.04.2, +2022.04.1, +2022.04.0,CVE-2022-24675 +2022.04.0,CVE-2022-28327 +2022.04.0,CVE-2022-27536 +2022.04.0,CVE-2022-24675 +2022.04.0,CVE-2022-28327 +2022.04.0,CVE-2022-27536 +2022.03.3, +2022.03.2, +2022.03.1, +2022.03.0,CVE-2022-24921 +2022.03.0,CVE-2022-27191 +2022.03.0,CVE-2022-24921 +2022.03.0,CVE-2022-27191 +2022.02.4, +2022.02.3, +2022.02.2, +2022.02.0,CVE-2020-7676 +2022.02.0,CVE-2019-10768 +2022.02.0,CVE-2022-23806 +2022.02.0,CVE-2022-23772 +2022.02.0,CVE-2022-23773 +2022.02.0,CVE-2020-7676 +2022.02.0,CVE-2019-10768 +2022.02.0,CVE-2022-23806 +2022.02.0,CVE-2022-23772 +2022.02.0,CVE-2022-23773 +2021.12.1, +2021.12.0,CVE-2021-43565 +2021.12.0,CVE-2021-44716 +2021.12.0,CVE-2021-44717 +2021.12.0,CVE-2021-43565 +2021.12.0,CVE-2021-44716 +2021.12.0,CVE-2021-44717 +2021.11.1, +2021.11.0,CVE-2021-41772 +2021.11.0,CVE-2021-41771 +2021.11.0,CVE-2021-41772 +2021.11.0,CVE-2021-41771 +2021.10.0,CVE-2021-38297 +2021.10.0,CVE-2021-39293 +2021.10.0,CVE-2021-38297 +2021.10.0,CVE-2021-39293 +2021.09.0, +2021.08.2, +2021.08.1,CVE-2021-3664 +2021.08.1,CVE-2021-27515 +2021.08.0,CVE-2021-36221 diff --git a/inst/extdata/versions/drivers.csv b/inst/extdata/versions/drivers.csv index b7fd76b..236897c 100644 --- a/inst/extdata/versions/drivers.csv +++ b/inst/extdata/versions/drivers.csv @@ -1,8 +1,8 @@ # https://docs.posit.co/pro-drivers/documentation/ -version,date,cve -2024.03.0,2024-03-01, -2023.12.1,2023-11-03, -2023.05.0,2023-05-01, -2022.11.0,2022-11-01, -2021.10.0,2021-10-01, +version,cve +2024.03.0, +2023.12.1, +2023.05.0, +2022.11.0, +2021.10.0, diff --git a/inst/extdata/versions/workbench.csv b/inst/extdata/versions/workbench.csv index 66337fc..fd18644 100644 --- a/inst/extdata/versions/workbench.csv +++ b/inst/extdata/versions/workbench.csv @@ -1,14 +1,28 @@ -# https://docs.posit.co/ide/news/ -version,date,cve -2024.04.1,2024-05-13, -2024.04.0,2024-04-29, -2023.12.1,2024-01-29, -2023.12.0,2023-12-15, -2023.09.1,2023-10-17, -2023.09.0,2023-09-25, -2023.06.2,2023-08-24, -2023.06.1,2023-07-07, -2023.06.0,2023-06-08, -2023.03.2,2023-06-12, -2023.03.1,2023-05-12, -2023.03.0,2023-03-16, +name,cve +2024.04.2, +2024.04.1, +2024.04.0, +2023.12.1, +2023.12.0, +2023.09.1, +2023.09.0, +2023.06.2, +2023.06.1, +2023.06.0, +2023.03.2, +2023.03.1, +2023.03.0, +2022.12.0, +2022.07.2, +2022.07.1, +2022.07.0, +2022.02.4, +2022.02.3, +2022.02.2, +2022.02.1, +2022.02.0, +2021.09.4, +2021.09.3, +2021.09.2, +2021.09.1, +2021.09.0, From db1e50f6c1a6b7fab10226ad734b74d9a97ec418 Mon Sep 17 00:00:00 2001 From: Colin Gillespie Date: Mon, 24 Jun 2024 18:09:29 +0100 Subject: [PATCH 2/3] fix: Update --- R/rvest.R | 2 +- inst/extdata/versions/software.csv | 5 ++--- tests/testthat/test-posit_versions.R | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/R/rvest.R b/R/rvest.R index 000e32e..b13e89e 100644 --- a/R/rvest.R +++ b/R/rvest.R @@ -36,7 +36,7 @@ get_all_versions = function(page) { tibble::tibble(name = v[!is.na(v)], cve = "") } -update_posit_versions = function() { +update_posit_csv = function() { readr::write_csv(extract_cves("https://docs.posit.co/connect/news/"), file = "inst/extdata/versions/connect.csv") diff --git a/inst/extdata/versions/software.csv b/inst/extdata/versions/software.csv index b7fcad4..68dba49 100644 --- a/inst/extdata/versions/software.csv +++ b/inst/extdata/versions/software.csv @@ -1,15 +1,14 @@ software,version -python,3.12.3 +python,3.12.4 python,3.11.9 python,3.10.14 python,3.9.19 python,3.8.19 -python,3.7.17 quarto,1.4.555 quarto,1.2.475 quarto,1.1.189 quarto,1.0.38 -r,4.4.0 +r,4.4.1 r,4.3.3 r,4.2.3 r,4.1.3 diff --git a/tests/testthat/test-posit_versions.R b/tests/testthat/test-posit_versions.R index 5a7650c..6d1ea53 100644 --- a/tests/testthat/test-posit_versions.R +++ b/tests/testthat/test-posit_versions.R @@ -2,7 +2,7 @@ test_that("Testing check server", { types = c("workbench", "connect", "drivers") for (type in types) { versions = get_posit_versions(type) - expect_equal(ncol(versions), 3) + expect_equal(ncol(versions), 2) expect_gt(nrow(versions), 2) } type = "connect" From 05118bdb67209fbb685c39ab1becae90c9fff4d0 Mon Sep 17 00:00:00 2001 From: Colin Gillespie Date: Mon, 24 Jun 2024 19:23:25 +0100 Subject: [PATCH 3/3] feat: Automatically extract connect/workbench versions --- DESCRIPTION | 3 +- NAMESPACE | 2 +- NEWS.md | 4 +++ R/create_software_tibble.R | 11 ------ R/get_posit_cves.R | 40 ++++++++++++++++++++++ R/posit_versions.R | 10 ++++-- R/rvest.R | 45 ------------------------- R/update_all_versions.R | 20 +++++++++++ inst/extdata/versions/connect.csv | 2 +- inst/extdata/versions/workbench.csv | 2 +- man/update_all_versions.Rd | 12 +++++++ man/update_software_csv.Rd | 12 ------- tests/testthat/test-posit_versions.R | 14 ++++++++ tests/testthat/test-quarto-helpers.R | 2 +- tests/testthat/test-software-versions.R | 3 +- 15 files changed, 105 insertions(+), 77 deletions(-) create mode 100644 R/get_posit_cves.R delete mode 100644 R/rvest.R create mode 100644 R/update_all_versions.R create mode 100644 man/update_all_versions.Rd delete mode 100644 man/update_software_csv.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 7afbf6c..5f660a9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: audit.base Title: Base package for Posit Checks -Version: 0.6.16 +Version: 0.6.17 Authors@R: person("Jumping", "Rivers", , "info@jumpingrivers.com", role = c("aut", "cre")) Description: Base package for sharing classes between posit audit @@ -25,6 +25,7 @@ Imports: yaml Suggests: jsonlite, + rvest, testthat (>= 3.0.0) Remotes: jumpingrivers/serverHeaders diff --git a/NAMESPACE b/NAMESPACE index 7f04430..23dc9d5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -20,7 +20,7 @@ export(init_r6_check) export(init_r6_checks) export(logger) export(print_colour_versions) -export(update_software_csv) +export(update_all_versions) import(R6) importFrom(dplyr,"%>%") importFrom(rlang,.data) diff --git a/NEWS.md b/NEWS.md index 7c7a1cd..a820388 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# audit.base 0.6.17 _2024-06-24_ +- chore: Software bump +- feat: Automatically extract connect/workbench versions + # audit.base 0.6.16 _2024-06-24_ - chore: Use jrStyling diff --git a/R/create_software_tibble.R b/R/create_software_tibble.R index 41fe0b1..1af76e4 100644 --- a/R/create_software_tibble.R +++ b/R/create_software_tibble.R @@ -1,14 +1,3 @@ -#' Helper function for updating R/Py/Quarto versions -#' -#' Currently this function would only be called by the package author, as it -#' updates inst/extdata/versions/software.csv -#' @export -update_software_csv = function() { - software = create_software_tibble() - readr::write_csv(software, file = "inst/extdata/versions/software.csv") - return(invisible(software)) -} - # https://gitlab.com/jumpingrivers/services/de/spd/infrastructure-template/-/blob/5c584fced32a6fc8fd7b25b3ea78f6fb7a8bd7ca/template/ansible/scripts/versions.sh create_software_tibble = function() { r = get_latest_versions_from_posit("r") diff --git a/R/get_posit_cves.R b/R/get_posit_cves.R new file mode 100644 index 0000000..df8ea82 --- /dev/null +++ b/R/get_posit_cves.R @@ -0,0 +1,40 @@ +get_posit_remote_versions = function(type = c("connect", "workbench")) { + type = match.arg(type) + url = if (type == "connect") "https://docs.posit.co/connect/news/" + else "https://docs.posit.co/ide/news/" + page = rvest::read_html(url) + sections = rvest::html_elements(page, "section") + v_tibbles = purrr::map_df(sections, extract_posit_cves) + all_v = get_all_remote_versions(page) |> + dplyr::filter(!.data$version %in% v_tibbles$version) %>% + dplyr::bind_rows(v_tibbles) %>% + dplyr::arrange(dplyr::desc(.data$version)) + all_v +} + +extract_posit_cves = function(section) { + posit_name = rvest::html_attrs(section) + posit_name = as.vector(posit_name["id"]) + posit_version = stringr::str_extract(posit_name, "[0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2}") + + li = section %>% + rvest::html_elements("li") %>% + rvest::html_text2() + + cves = stringr::str_extract(li, "^CVE-[0-9]{4}-[0-9]*") + cves = cves[!is.na(cves)] + + if (length(cves) == 0L || is.na(posit_version)) { + tibble::tibble(version = character(0), cve = character(0)) + } else { + tibble::tibble(version = posit_version, cve = cves) + } +} + +get_all_remote_versions = function(page) { + versions = page %>% + rvest::html_nodes("h2") %>% + rvest::html_text() + v = stringr::str_extract(versions, "202[0-9]\\.[0-9]{2}\\.[0-9]{1,2}") + tibble::tibble(version = v[!is.na(v)], cve = "") +} diff --git a/R/posit_versions.R b/R/posit_versions.R index 4e5822f..845d452 100644 --- a/R/posit_versions.R +++ b/R/posit_versions.R @@ -13,7 +13,7 @@ get_posit_versions = function(type = c("connect", "workbench", "drivers")) { mustWork = TRUE, package = "audit.base" ) versions = readr::read_csv(fname, comment = "#", col_types = c("c", "c")) - versions = dplyr::arrange(versions, dplyr::desc(name)) + versions = dplyr::arrange(versions, dplyr::desc(.data$version)) return(versions) } @@ -45,13 +45,17 @@ audit_posit_version = function(posit_version, type = c("connect", "workbench", " return(invisible(NULL)) } + + lookup_version = function(posit_version, type) { versions = get_posit_versions(type = type) version_as_date = version_to_date(posit_version) - if (is.na(version_as_date) || version_as_date < min(versions$date)) { + all_dates = unlist(purrr::map(versions$version, version_to_date)) + + if (is.na(version_as_date) || version_as_date < min(all_dates)) { # Older than DB row_number = NA_integer_ - } else if (version_as_date > max(versions$date)) { + } else if (version_as_date > max(all_dates)) { # Newer than DB row_number = 1L } else { diff --git a/R/rvest.R b/R/rvest.R deleted file mode 100644 index b13e89e..0000000 --- a/R/rvest.R +++ /dev/null @@ -1,45 +0,0 @@ -extract_cves = function(url) { - page = rvest::read_html(url) - sections = rvest::html_elements(page, "section") - v_tibbles = purrr::map_df(sections, extract_components) - all_v = get_all_versions(page) |> - dplyr::filter(!.data$name %in% v_tibbles$name) %>% - dplyr::bind_rows(v_tibbles) %>% - dplyr::arrange(dplyr::desc(name)) - all_v -} - -extract_components = function(section) { - posit_name = rvest::html_attrs(section) - posit_name = as.vector(posit_name["id"]) - posit_id = stringr::str_extract(posit_name, "[0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2}") - - li = section %>% - rvest::html_elements("li") %>% - rvest::html_text2() - - cves = stringr::str_extract(li, "^CVE-[0-9]{4}-[0-9]*") - cves = cves[!is.na(cves)] - - if (length(cves) == 0L || is.na(posit_id)) { - NULL - } else { - tibble::tibble(name = posit_id, cve = cves) - } - } - -get_all_versions = function(page) { - versions = page %>% - rvest::html_nodes('h2') %>% - rvest::html_text() - v = stringr::str_extract(versions, "202[0-9]\\.[0-9]{2}\\.[0-9]{1,2}") - tibble::tibble(name = v[!is.na(v)], cve = "") -} - -update_posit_csv = function() { - readr::write_csv(extract_cves("https://docs.posit.co/connect/news/"), - file = "inst/extdata/versions/connect.csv") - - readr::write_csv(extract_cves("https://docs.posit.co/ide/news/"), - file = "inst/extdata/versions/workbench.csv") -} \ No newline at end of file diff --git a/R/update_all_versions.R b/R/update_all_versions.R new file mode 100644 index 0000000..04efb3f --- /dev/null +++ b/R/update_all_versions.R @@ -0,0 +1,20 @@ +#' Helper functions for updating R/Py/Quarto/Posit versions +#' +#' Currently this function would only be called by the package author, as it +#' updates inst/extdata/versions/*.csv +#' @export +update_all_versions = function() { + readr::write_csv( + get_posit_remote_versions(type = "connect"), + file = "inst/extdata/versions/connect.csv" + ) + + readr::write_csv( + get_posit_remote_versions(type = "workbench"), + file = "inst/extdata/versions/workbench.csv" + ) + + software = create_software_tibble() + readr::write_csv(software, file = "inst/extdata/versions/software.csv") + return(invisible(NULL)) +} diff --git a/inst/extdata/versions/connect.csv b/inst/extdata/versions/connect.csv index 3921e8d..ab8bc0d 100644 --- a/inst/extdata/versions/connect.csv +++ b/inst/extdata/versions/connect.csv @@ -1,4 +1,4 @@ -name,cve +version,cve 2024.05.0,CVE-2024-24787 2024.05.0,CVE-2024-24788 2024.05.0,CVE-2024-24787 diff --git a/inst/extdata/versions/workbench.csv b/inst/extdata/versions/workbench.csv index fd18644..8284975 100644 --- a/inst/extdata/versions/workbench.csv +++ b/inst/extdata/versions/workbench.csv @@ -1,4 +1,4 @@ -name,cve +version,cve 2024.04.2, 2024.04.1, 2024.04.0, diff --git a/man/update_all_versions.Rd b/man/update_all_versions.Rd new file mode 100644 index 0000000..18d9e4b --- /dev/null +++ b/man/update_all_versions.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/update_all_versions.R +\name{update_all_versions} +\alias{update_all_versions} +\title{Helper functions for updating R/Py/Quarto/Posit versions} +\usage{ +update_all_versions() +} +\description{ +Currently this function would only be called by the package author, as it +updates inst/extdata/versions/*.csv +} diff --git a/man/update_software_csv.Rd b/man/update_software_csv.Rd deleted file mode 100644 index bcb4a47..0000000 --- a/man/update_software_csv.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/create_software_tibble.R -\name{update_software_csv} -\alias{update_software_csv} -\title{Helper function for updating R/Py/Quarto versions} -\usage{ -update_software_csv() -} -\description{ -Currently this function would only be called by the package author, as it -updates inst/extdata/versions/software.csv -} diff --git a/tests/testthat/test-posit_versions.R b/tests/testthat/test-posit_versions.R index 6d1ea53..6382307 100644 --- a/tests/testthat/test-posit_versions.R +++ b/tests/testthat/test-posit_versions.R @@ -39,3 +39,17 @@ test_that("Testing check server", { regexp = "out of date" ) }) + +test_that("Testing check Posit versions", { + type = "connect" + remote = get_posit_remote_versions(type) + local = get_posit_versions(type) + expect_true(all(remote$version %in% local$version), + info = "Try running update_all_versions()") + type = "workbench" + remote = get_posit_remote_versions(type) + local = get_posit_versions(type) + expect_true(all(remote$version %in% local$version), + info = "Try running update_all_versions()") +} +) \ No newline at end of file diff --git a/tests/testthat/test-quarto-helpers.R b/tests/testthat/test-quarto-helpers.R index d80d3f3..a6bc170 100644 --- a/tests/testthat/test-quarto-helpers.R +++ b/tests/testthat/test-quarto-helpers.R @@ -1,7 +1,7 @@ test_that("Quarto Outputs", { out = list() out$posit_version = "2022.10.0" - msg = get_quarto_posit_version_msg(out, "connect") + msg = get_quarto_posit_version_msg(out, type = "connect") expect_true(stringr::str_detect(msg, "CVEs")) out$posit_version = "2012.10.0" diff --git a/tests/testthat/test-software-versions.R b/tests/testthat/test-software-versions.R index 7f87b48..ec2f7c6 100644 --- a/tests/testthat/test-software-versions.R +++ b/tests/testthat/test-software-versions.R @@ -48,5 +48,6 @@ test_that("Ensure that software versions are up to date", { versions = get_latest_versions() latest = create_software_tibble() # If this test files, try running update_software_csv() first - expect_true(all(latest$version %in% versions$version)) + expect_true(all(latest$version %in% versions$version), + info = "Try running update_all_versions()") })