test_that("private invitations require delivery, expire, and cannot be replayed", { skip_if_not_installed("openssl") path<-tempfile(); queue<-tempfile(); on.exit(unlink(c(path,queue),recursive=TRUE)) configure_reviewer_access(path,"owner@example.org") old_opts<-options(alsdownloader.reviewer_credentials=path,alsdownloader.submission_mail=NULL);on.exit(options(old_opts),add=TRUE) p<-zenodo_build(zenodo_fixture(),zenodo_shape(),"2018","ALS") id<-submit_zenodo(p,queue); clock<-1000 key<-reviewer_invitation(queue,id,"owner@example.org",clock) access<-reviewer_access_controller(queue,now=function()clock) expect_null(access$login(id,key)) zenodo_write(list(status="sent"),file.path(queue,"notifications",paste0(id,".json"))) expect_null(access$login(id,paste(rep("0",64),collapse=""))) expect_null(access$login("../escape",key)) token<-access$login(id,key) expect_true(access$valid(token)); expect_null(access$login(id,key)) clock<-2801; expect_false(access$valid(token)) key<-reviewer_invitation(queue,id,"owner@example.org",clock) clock<-clock+30*86400; expect_null(access$login(id,key)) key<-reviewer_invitation(queue,id,"owner@example.org",clock) configure_reviewer_access(path,"owner@example.org") expect_null(access$login(id,key)) expect_error(reviewer_invitation(queue,id,"outsider@example.org"),"recipient") }) test_that("forged inputs and a different proposal cannot use an emailed invitation", { skip_if_not_installed("openssl") path<-tempfile(); queue<-tempfile(); on.exit(unlink(c(path,queue),recursive=TRUE)) configure_reviewer_access(path,"owner@example.org") old_opts<-options(alsdownloader.reviewer_credentials=path,alsdownloader.submission_mail=NULL);on.exit(options(old_opts),add=TRUE) p<-zenodo_build(zenodo_fixture(),zenodo_shape(),"2018","ALS","private@example.org") id<-submit_zenodo(p,queue) other<-submit_zenodo(zenodo_build(zenodo_fixture(),zenodo_shape(),"2019","ALS"),queue) key<-reviewer_invitation(queue,id,"owner@example.org") zenodo_write(list(status="sent"),file.path(queue,"notifications",paste0(id,".json"))) access<-reviewer_access_controller(queue) local_mocked_bindings(inspect_zenodo=function(...)zenodo_fixture(),.package="alsdownloader") shiny::testServer(function(input,output,session){reviewer<-"Maintainer";eval(body(zenodo_submission_server),envir=environment())},{ session$setInputs(zenodo_review_id=id,zenodo_review_confirm=TRUE,zenodo_review_approve=1) expect_true(all(zenodo_submissions(queue)$status=="pending")) expect_error(output$zenodo_review_details,class="shiny.silent.error") # Test the same exchange used by the explicit Open private review action. requested(id); invitation(key) session$setInputs(review_login=1,zenodo_review_id=id) expect_match(output$zenodo_review_details,"private@example.org",fixed=TRUE) session$setInputs(zenodo_review_id=other,zenodo_review_confirm=TRUE,zenodo_review_approve=2) expect_true(all(zenodo_submissions(queue)$status=="pending")) expect_error(output$zenodo_review_details,class="shiny.silent.error") session$setInputs(zenodo_review_id=id) session$setInputs(zenodo_review_confirm=TRUE,zenodo_review_approve=3) rows<-zenodo_submissions(queue) expect_identical(rows$status[rows$id==id],"approve") expect_identical(rows$status[rows$id==other],"pending") expect_match(jsonlite::fromJSON(file.path(queue,"decisions",paste0(id,".json")))$reviewer,"owner@example.org",fixed=TRUE) expect_error(output$zenodo_review_details,class="shiny.silent.error") }) })