diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-01-07 17:25:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-07 17:25:34 +0100 |
commit | fac64478157ee563b185edb5734688e4523df3a1 (patch) | |
tree | 888d562982e1fc37dfb9a4459928bcec84d55dfc /cli | |
parent | 82e930726ee5dbac8e6eae0962c07c72daf9843c (diff) |
refactor(permissions): add PermissionsContainer struct for internal mutability (#17134)
Turns out we were cloning permissions which after prompting were discarded,
so the state of permissions was never preserved. To handle that we need to store
all permissions behind "Arc<Mutex<>>" (because there are situations where we
need to send them to other thread).
Testing and benching code still uses "Permissions" in most places - it's undesirable
to share the same permission set between various test/bench files - otherwise
granting or revoking permissions in one file would influence behavior of other test
files.
Diffstat (limited to 'cli')
-rw-r--r-- | cli/build.rs | 18 | ||||
-rw-r--r-- | cli/cache/mod.rs | 14 | ||||
-rw-r--r-- | cli/file_fetcher.rs | 69 | ||||
-rw-r--r-- | cli/graph_util.rs | 6 | ||||
-rw-r--r-- | cli/lsp/registries.rs | 12 | ||||
-rw-r--r-- | cli/lsp/testing/execution.rs | 6 | ||||
-rw-r--r-- | cli/module_loader.rs | 13 | ||||
-rw-r--r-- | cli/ops/bench.rs | 16 | ||||
-rw-r--r-- | cli/ops/testing.rs | 16 | ||||
-rw-r--r-- | cli/proc_state.rs | 16 | ||||
-rw-r--r-- | cli/standalone.rs | 5 | ||||
-rw-r--r-- | cli/tests/run_tests.rs | 17 | ||||
-rw-r--r-- | cli/tools/bench.rs | 13 | ||||
-rw-r--r-- | cli/tools/repl/mod.rs | 7 | ||||
-rw-r--r-- | cli/tools/run.rs | 20 | ||||
-rw-r--r-- | cli/tools/standalone.rs | 4 | ||||
-rw-r--r-- | cli/tools/test.rs | 26 | ||||
-rw-r--r-- | cli/worker.rs | 11 |
18 files changed, 172 insertions, 117 deletions
diff --git a/cli/build.rs b/cli/build.rs index faeaed073..b4acc0d1d 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use deno_core::snapshot_util::*; use deno_core::Extension; use deno_runtime::deno_cache::SqliteBackedCache; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use deno_runtime::*; mod ts { @@ -294,13 +294,13 @@ fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) { deno_console::init(), deno_url::init(), deno_tls::init(), - deno_web::init::<Permissions>( + deno_web::init::<PermissionsContainer>( deno_web::BlobStore::default(), Default::default(), ), - deno_fetch::init::<Permissions>(Default::default()), + deno_fetch::init::<PermissionsContainer>(Default::default()), deno_cache::init::<SqliteBackedCache>(None), - deno_websocket::init::<Permissions>("".to_owned(), None, None), + deno_websocket::init::<PermissionsContainer>("".to_owned(), None, None), deno_webstorage::init(None), deno_crypto::init(None), deno_webgpu::init(false), @@ -308,15 +308,15 @@ fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) { deno_broadcast_channel::InMemoryBroadcastChannel::default(), false, // No --unstable. ), - deno_node::init::<Permissions>(None), // No --unstable. - deno_ffi::init::<Permissions>(false), - deno_net::init::<Permissions>( + deno_node::init::<PermissionsContainer>(None), // No --unstable. + deno_ffi::init::<PermissionsContainer>(false), + deno_net::init::<PermissionsContainer>( None, false, // No --unstable. None, ), - deno_napi::init::<Permissions>(false), + deno_napi::init::<PermissionsContainer>(false), deno_http::init(), - deno_flash::init::<Permissions>(false), // No --unstable + deno_flash::init::<PermissionsContainer>(false), // No --unstable ]; create_snapshot(CreateSnapshotOptions { diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs index 68bf1e4c6..d2ad1b20a 100644 --- a/cli/cache/mod.rs +++ b/cli/cache/mod.rs @@ -11,7 +11,7 @@ use deno_graph::source::CacheInfo; use deno_graph::source::LoadFuture; use deno_graph::source::LoadResponse; use deno_graph::source::Loader; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use std::sync::Arc; mod check; @@ -42,17 +42,17 @@ pub const CACHE_PERM: u32 = 0o644; /// a concise interface to the DENO_DIR when building module graphs. pub struct FetchCacher { emit_cache: EmitCache, - dynamic_permissions: Permissions, + dynamic_permissions: PermissionsContainer, file_fetcher: Arc<FileFetcher>, - root_permissions: Permissions, + root_permissions: PermissionsContainer, } impl FetchCacher { pub fn new( emit_cache: EmitCache, file_fetcher: FileFetcher, - root_permissions: Permissions, - dynamic_permissions: Permissions, + root_permissions: PermissionsContainer, + dynamic_permissions: PermissionsContainer, ) -> Self { let file_fetcher = Arc::new(file_fetcher); @@ -104,7 +104,7 @@ impl Loader for FetchCacher { } let specifier = specifier.clone(); - let mut permissions = if is_dynamic { + let permissions = if is_dynamic { self.dynamic_permissions.clone() } else { self.root_permissions.clone() @@ -113,7 +113,7 @@ impl Loader for FetchCacher { async move { file_fetcher - .fetch(&specifier, &mut permissions) + .fetch(&specifier, permissions) .await .map_or_else( |err| { diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index cc83e6f5f..2376133f5 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -31,7 +31,7 @@ use deno_runtime::deno_fetch::reqwest::header::AUTHORIZATION; use deno_runtime::deno_fetch::reqwest::header::IF_NONE_MATCH; use deno_runtime::deno_fetch::reqwest::StatusCode; use deno_runtime::deno_web::BlobStore; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use log::debug; use std::borrow::Borrow; use std::collections::HashMap; @@ -406,7 +406,7 @@ impl FileFetcher { fn fetch_remote( &self, specifier: &ModuleSpecifier, - permissions: &mut Permissions, + permissions: PermissionsContainer, redirect_limit: i64, maybe_accept: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<File, AnyError>> + Send>> { @@ -461,7 +461,6 @@ impl FileFetcher { }; let maybe_auth_token = self.auth_tokens.get(specifier); let specifier = specifier.clone(); - let mut permissions = permissions.clone(); let client = self.http_client.clone(); let file_fetcher = self.clone(); // A single pass of fetch either yields code or yields a redirect. @@ -487,7 +486,7 @@ impl FileFetcher { file_fetcher .fetch_remote( &redirect_url, - &mut permissions, + permissions, redirect_limit - 1, maybe_accept, ) @@ -547,7 +546,7 @@ impl FileFetcher { pub async fn fetch( &self, specifier: &ModuleSpecifier, - permissions: &mut Permissions, + permissions: PermissionsContainer, ) -> Result<File, AnyError> { debug!("FileFetcher::fetch() - specifier: {}", specifier); self.fetch_with_accept(specifier, permissions, None).await @@ -556,7 +555,7 @@ impl FileFetcher { pub async fn fetch_with_accept( &self, specifier: &ModuleSpecifier, - permissions: &mut Permissions, + permissions: PermissionsContainer, maybe_accept: Option<&str>, ) -> Result<File, AnyError> { let scheme = get_validated_scheme(specifier)?; @@ -797,7 +796,7 @@ mod tests { async fn test_fetch(specifier: &ModuleSpecifier) -> (File, FileFetcher) { let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None); let result = file_fetcher - .fetch(specifier, &mut Permissions::allow_all()) + .fetch(specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); (result.unwrap(), file_fetcher) @@ -809,7 +808,7 @@ mod tests { let _http_server_guard = test_util::http_server(); let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None); let result: Result<File, AnyError> = file_fetcher - .fetch_remote(specifier, &mut Permissions::allow_all(), 1, None) + .fetch_remote(specifier, PermissionsContainer::allow_all(), 1, None) .await; assert!(result.is_ok()); let (_, headers, _) = file_fetcher.http_cache.get(specifier).unwrap(); @@ -1053,7 +1052,7 @@ mod tests { file_fetcher.insert_cached(file.clone()); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let result_file = result.unwrap(); @@ -1069,7 +1068,7 @@ mod tests { .unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); @@ -1098,7 +1097,7 @@ mod tests { let specifier = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1130,7 +1129,7 @@ mod tests { ); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1153,7 +1152,7 @@ mod tests { resolve_url_or_path("http://localhost:4545/subdir/mod2.ts").unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1175,7 +1174,7 @@ mod tests { metadata.write(&cache_filename).unwrap(); let result = file_fetcher_01 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1196,7 +1195,7 @@ mod tests { metadata.write(&cache_filename).unwrap(); let result = file_fetcher_02 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1219,7 +1218,7 @@ mod tests { ) .unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1252,7 +1251,7 @@ mod tests { .unwrap(); let result = file_fetcher_01 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); @@ -1271,7 +1270,7 @@ mod tests { ) .unwrap(); let result = file_fetcher_02 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); @@ -1303,7 +1302,7 @@ mod tests { .unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1356,7 +1355,7 @@ mod tests { .unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1422,7 +1421,7 @@ mod tests { .unwrap(); let result = file_fetcher_01 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); @@ -1442,7 +1441,7 @@ mod tests { ) .unwrap(); let result = file_fetcher_02 - .fetch(&redirected_specifier, &mut Permissions::allow_all()) + .fetch(&redirected_specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); @@ -1464,12 +1463,12 @@ mod tests { .unwrap(); let result = file_fetcher - .fetch_remote(&specifier, &mut Permissions::allow_all(), 2, None) + .fetch_remote(&specifier, PermissionsContainer::allow_all(), 2, None) .await; assert!(result.is_ok()); let result = file_fetcher - .fetch_remote(&specifier, &mut Permissions::allow_all(), 1, None) + .fetch_remote(&specifier, PermissionsContainer::allow_all(), 1, None) .await; assert!(result.is_err()); @@ -1501,7 +1500,7 @@ mod tests { .unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1545,7 +1544,7 @@ mod tests { resolve_url("http://localhost:4545/run/002_hello.ts").unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_err()); let err = result.unwrap_err(); @@ -1580,7 +1579,7 @@ mod tests { resolve_url("http://localhost:4545/run/002_hello.ts").unwrap(); let result = file_fetcher_01 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_err()); let err = result.unwrap_err(); @@ -1588,12 +1587,12 @@ mod tests { assert_eq!(err.to_string(), "Specifier not found in cache: \"http://localhost:4545/run/002_hello.ts\", --cached-only is specified."); let result = file_fetcher_02 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let result = file_fetcher_01 - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); } @@ -1606,7 +1605,7 @@ mod tests { resolve_url_or_path(&fixture_path.to_string_lossy()).unwrap(); fs::write(fixture_path.clone(), r#"console.log("hello deno");"#).unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1614,7 +1613,7 @@ mod tests { fs::write(fixture_path, r#"console.log("goodbye deno");"#).unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1630,7 +1629,7 @@ mod tests { let specifier = ModuleSpecifier::parse("http://localhost:4545/dynamic").unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1639,7 +1638,7 @@ mod tests { let (file_fetcher, _) = setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1657,7 +1656,7 @@ mod tests { let specifier = ModuleSpecifier::parse("http://localhost:4545/dynamic_cache").unwrap(); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); @@ -1666,7 +1665,7 @@ mod tests { let (file_fetcher, _) = setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); let result = file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await; assert!(result.is_ok()); let file = result.unwrap(); diff --git a/cli/graph_util.rs b/cli/graph_util.rs index d815e3311..812701892 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -28,7 +28,7 @@ use deno_graph::ModuleGraphError; use deno_graph::ModuleKind; use deno_graph::Range; use deno_graph::Resolved; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::HashSet; @@ -514,8 +514,8 @@ pub async fn create_graph_and_maybe_check( let mut cache = cache::FetchCacher::new( ps.emit_cache.clone(), ps.file_fetcher.clone(), - Permissions::allow_all(), - Permissions::allow_all(), + PermissionsContainer::allow_all(), + PermissionsContainer::allow_all(), ); let maybe_imports = ps.options.to_maybe_imports()?; let maybe_cli_resolver = CliResolver::maybe_new( diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index 81e2552c0..c8e5dad60 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -30,7 +30,7 @@ use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::Dependency; use deno_runtime::deno_web::BlobStore; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use log::error; use once_cell::sync::Lazy; use regex::Regex; @@ -519,7 +519,7 @@ impl ModuleRegistry { .file_fetcher .fetch_with_accept( specifier, - &mut Permissions::allow_all(), + PermissionsContainer::allow_all(), Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"), ) .await; @@ -617,7 +617,7 @@ impl ModuleRegistry { .ok()?; let file = self .file_fetcher - .fetch(&endpoint, &mut Permissions::allow_all()) + .fetch(&endpoint, PermissionsContainer::allow_all()) .await .ok()?; let documentation: lsp::Documentation = @@ -973,7 +973,7 @@ impl ModuleRegistry { let specifier = Url::parse(url).ok()?; let file = self .file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await .ok()?; serde_json::from_str(&file.source).ok() @@ -1030,7 +1030,7 @@ impl ModuleRegistry { let specifier = ModuleSpecifier::parse(url).ok()?; let file = self .file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await .map_err(|err| { error!( @@ -1066,7 +1066,7 @@ impl ModuleRegistry { .ok()?; let file = self .file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await .map_err(|err| { error!( diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index 722f06e2c..a498df857 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -30,6 +30,7 @@ use deno_core::ModuleSpecifier; use deno_runtime::ops::io::Stdio; use deno_runtime::ops::io::StdioPipe; use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use deno_runtime::tokio_util::run_local; use indexmap::IndexMap; use std::collections::HashMap; @@ -162,7 +163,7 @@ async fn test_specifier( let mut worker = create_main_worker_for_test_or_bench( &ps, specifier.clone(), - permissions, + PermissionsContainer::new(permissions), vec![ops::testing::init(sender, fail_fast_tracker, filter)], Stdio { stdin: StdioPipe::Inherit, @@ -254,6 +255,9 @@ impl TestRun { lsp_log!("Executing test run with arguments: {}", args.join(" ")); let flags = flags_from_vec(args.into_iter().map(String::from).collect())?; let ps = proc_state::ProcState::build(flags).await?; + // Various test files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. let permissions = Permissions::from_options(&ps.options.permissions_options())?; test::check_specifiers( diff --git a/cli/module_loader.rs b/cli/module_loader.rs index edc89be77..d452c30cf 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -21,7 +21,7 @@ use deno_core::ModuleSpecifier; use deno_core::ModuleType; use deno_core::OpState; use deno_core::SourceMapGetter; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use std::cell::RefCell; use std::pin::Pin; use std::rc::Rc; @@ -38,7 +38,7 @@ pub struct CliModuleLoader { /// The initial set of permissions used to resolve the static imports in the /// worker. They are decoupled from the worker (dynamic) permissions since /// read access errors must be raised based on the parent thread permissions. - pub root_permissions: Permissions, + pub root_permissions: PermissionsContainer, pub ps: ProcState, } @@ -46,12 +46,15 @@ impl CliModuleLoader { pub fn new(ps: ProcState) -> Rc<Self> { Rc::new(CliModuleLoader { lib: ps.options.ts_type_lib_window(), - root_permissions: Permissions::allow_all(), + root_permissions: PermissionsContainer::allow_all(), ps, }) } - pub fn new_for_worker(ps: ProcState, permissions: Permissions) -> Rc<Self> { + pub fn new_for_worker( + ps: ProcState, + permissions: PermissionsContainer, + ) -> Rc<Self> { Rc::new(CliModuleLoader { lib: ps.options.ts_type_lib_worker(), root_permissions: permissions, @@ -235,7 +238,7 @@ impl ModuleLoader for CliModuleLoader { let ps = self.ps.clone(); let state = op_state.borrow(); - let dynamic_permissions = state.borrow::<Permissions>().clone(); + let dynamic_permissions = state.borrow::<PermissionsContainer>().clone(); let root_permissions = if is_dynamic { dynamic_permissions.clone() } else { diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs index 6fc881f61..3b27ffa7e 100644 --- a/cli/ops/bench.rs +++ b/cli/ops/bench.rs @@ -9,7 +9,7 @@ use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::permissions::create_child_permissions; use deno_runtime::permissions::ChildPermissionsArg; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use serde::Deserialize; use serde::Serialize; use std::sync::atomic::AtomicUsize; @@ -40,7 +40,7 @@ pub fn init( } #[derive(Clone)] -struct PermissionsHolder(Uuid, Permissions); +struct PermissionsHolder(Uuid, PermissionsContainer); #[op] pub fn op_pledge_test_permissions( @@ -48,8 +48,12 @@ pub fn op_pledge_test_permissions( args: ChildPermissionsArg, ) -> Result<Uuid, AnyError> { let token = Uuid::new_v4(); - let parent_permissions = state.borrow_mut::<Permissions>(); - let worker_permissions = create_child_permissions(parent_permissions, args)?; + let parent_permissions = state.borrow_mut::<PermissionsContainer>(); + let worker_permissions = { + let mut parent_permissions = parent_permissions.0.lock(); + let perms = create_child_permissions(&mut parent_permissions, args)?; + PermissionsContainer::new(perms) + }; let parent_permissions = parent_permissions.clone(); if state.try_take::<PermissionsHolder>().is_some() { @@ -59,7 +63,7 @@ pub fn op_pledge_test_permissions( state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions)); // NOTE: This call overrides current permission set for the worker - state.put::<Permissions>(worker_permissions); + state.put::<PermissionsContainer>(worker_permissions); Ok(token) } @@ -75,7 +79,7 @@ pub fn op_restore_test_permissions( } let permissions = permissions_holder.1; - state.put::<Permissions>(permissions); + state.put::<PermissionsContainer>(permissions); Ok(()) } else { Err(generic_error("no permissions to restore")) diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index b6fd29fc7..e5c0a2b99 100644 --- a/cli/ops/testing.rs +++ b/cli/ops/testing.rs @@ -17,7 +17,7 @@ use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::permissions::create_child_permissions; use deno_runtime::permissions::ChildPermissionsArg; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use serde::Deserialize; use serde::Deserializer; use serde::Serialize; @@ -50,7 +50,7 @@ pub fn init( } #[derive(Clone)] -struct PermissionsHolder(Uuid, Permissions); +struct PermissionsHolder(Uuid, PermissionsContainer); #[op] pub fn op_pledge_test_permissions( @@ -58,8 +58,12 @@ pub fn op_pledge_test_permissions( args: ChildPermissionsArg, ) -> Result<Uuid, AnyError> { let token = Uuid::new_v4(); - let parent_permissions = state.borrow_mut::<Permissions>(); - let worker_permissions = create_child_permissions(parent_permissions, args)?; + let parent_permissions = state.borrow_mut::<PermissionsContainer>(); + let worker_permissions = { + let mut parent_permissions = parent_permissions.0.lock(); + let perms = create_child_permissions(&mut parent_permissions, args)?; + PermissionsContainer::new(perms) + }; let parent_permissions = parent_permissions.clone(); if state.try_take::<PermissionsHolder>().is_some() { @@ -68,7 +72,7 @@ pub fn op_pledge_test_permissions( state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions)); // NOTE: This call overrides current permission set for the worker - state.put::<Permissions>(worker_permissions); + state.put::<PermissionsContainer>(worker_permissions); Ok(token) } @@ -84,7 +88,7 @@ pub fn op_restore_test_permissions( } let permissions = permissions_holder.1; - state.put::<Permissions>(permissions); + state.put::<PermissionsContainer>(permissions); Ok(()) } else { Err(generic_error("no permissions to restore")) diff --git a/cli/proc_state.rs b/cli/proc_state.rs index eb672d8d0..0dd97b5e3 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -59,7 +59,7 @@ use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_web::BlobStore; use deno_runtime::inspector_server::InspectorServer; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use import_map::ImportMap; use log::warn; use std::collections::HashSet; @@ -181,7 +181,7 @@ impl ProcState { let maybe_import_map = if let Some(import_map_specifier) = maybe_import_map_specifier { let file = file_fetcher - .fetch(&import_map_specifier, &mut Permissions::allow_all()) + .fetch(&import_map_specifier, PermissionsContainer::allow_all()) .await .context(format!( "Unable to load '{}' import map", @@ -289,8 +289,8 @@ impl ProcState { roots: Vec<ModuleSpecifier>, is_dynamic: bool, lib: TsTypeLib, - root_permissions: Permissions, - dynamic_permissions: Permissions, + root_permissions: PermissionsContainer, + dynamic_permissions: PermissionsContainer, reload_on_watch: bool, ) -> Result<(), AnyError> { log::debug!("Preparing module load."); @@ -490,8 +490,8 @@ impl ProcState { specifiers, false, lib, - Permissions::allow_all(), - Permissions::allow_all(), + PermissionsContainer::allow_all(), + PermissionsContainer::allow_all(), false, ) .await @@ -668,8 +668,8 @@ impl ProcState { cache::FetchCacher::new( self.emit_cache.clone(), self.file_fetcher.clone(), - Permissions::allow_all(), - Permissions::allow_all(), + PermissionsContainer::allow_all(), + PermissionsContainer::allow_all(), ) } diff --git a/cli/standalone.rs b/cli/standalone.rs index c93631327..2b0a77e18 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -29,6 +29,7 @@ use deno_runtime::deno_tls::rustls_pemfile; use deno_runtime::deno_web::BlobStore; use deno_runtime::fmt_errors::format_js_error; use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use deno_runtime::permissions::PermissionsOptions; use deno_runtime::worker::MainWorker; use deno_runtime::worker::WorkerOptions; @@ -226,7 +227,9 @@ pub async fn run( let flags = metadata_to_flags(&metadata); let main_module = &metadata.entrypoint; let ps = ProcState::build(flags).await?; - let permissions = Permissions::from_options(&metadata.permissions)?; + let permissions = PermissionsContainer::new(Permissions::from_options( + &metadata.permissions, + )?); let blob_store = BlobStore::default(); let broadcast_channel = InMemoryBroadcastChannel::default(); let module_loader = Rc::new(EmbeddedModuleLoader { diff --git a/cli/tests/run_tests.rs b/cli/tests/run_tests.rs index dfe95d9a8..8460d3f8f 100644 --- a/cli/tests/run_tests.rs +++ b/cli/tests/run_tests.rs @@ -3725,4 +3725,21 @@ console.log("finish"); args: "run --quiet run/001_hello.js --allow-net", output: "run/001_hello.js.out", }); + + // Regression test for https://github.com/denoland/deno/issues/16772 + #[test] + fn file_fetcher_preserves_permissions() { + let _guard = util::http_server(); + util::with_pty(&["repl"], |mut console| { + console.write_text( + "const a = import('http://127.0.0.1:4545/run/019_media_types.ts');", + ); + console.write_text("y"); + console.write_line(""); + console.write_line("close();"); + let output = console.read_all_output(); + assert_contains!(output, "success"); + assert_contains!(output, "true"); + }); + } } diff --git a/cli/tools/bench.rs b/cli/tools/bench.rs index 24fb07919..2d54b260d 100644 --- a/cli/tools/bench.rs +++ b/cli/tools/bench.rs @@ -28,6 +28,7 @@ use deno_core::futures::StreamExt; use deno_core::ModuleSpecifier; use deno_graph::ModuleKind; use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use deno_runtime::tokio_util::run_local; use indexmap::IndexMap; use log::Level; @@ -337,8 +338,8 @@ async fn check_specifiers( specifiers, false, lib, - Permissions::allow_all(), - permissions, + PermissionsContainer::allow_all(), + PermissionsContainer::new(permissions), true, ) .await?; @@ -358,7 +359,7 @@ async fn bench_specifier( let mut worker = create_main_worker_for_test_or_bench( &ps, specifier.clone(), - permissions, + PermissionsContainer::new(permissions), vec![ops::bench::init(channel.clone(), filter)], Default::default(), ) @@ -490,6 +491,9 @@ pub async fn run_benchmarks( bench_flags: BenchFlags, ) -> Result<(), AnyError> { let ps = ProcState::build(flags).await?; + // Various bench files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. let permissions = Permissions::from_options(&ps.options.permissions_options())?; @@ -527,6 +531,9 @@ pub async fn run_benchmarks_with_watch( bench_flags: BenchFlags, ) -> Result<(), AnyError> { let ps = ProcState::build(flags).await?; + // Various bench files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. let permissions = Permissions::from_options(&ps.options.permissions_options())?; diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index fc03dee2f..00f10b7d6 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -8,6 +8,7 @@ use crate::worker::create_main_worker; use deno_core::error::AnyError; use deno_core::resolve_url_or_path; use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use rustyline::error::ReadlineError; mod cdp; @@ -72,7 +73,7 @@ async fn read_eval_file( let file = ps .file_fetcher - .fetch(&specifier, &mut Permissions::allow_all()) + .fetch(&specifier, PermissionsContainer::allow_all()) .await?; Ok((*file.source).to_string()) @@ -84,7 +85,9 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> { let mut worker = create_main_worker( &ps, main_module.clone(), - Permissions::from_options(&ps.options.permissions_options())?, + PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?), ) .await?; worker.setup_repl().await?; diff --git a/cli/tools/run.rs b/cli/tools/run.rs index af982e483..3830affed 100644 --- a/cli/tools/run.rs +++ b/cli/tools/run.rs @@ -9,6 +9,7 @@ use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; use deno_core::resolve_url_or_path; use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use crate::args::EvalFlags; use crate::args::Flags; @@ -56,8 +57,9 @@ To grant permissions, set them before the script argument. For example: } else { resolve_url_or_path(&run_flags.script)? }; - let permissions = - Permissions::from_options(&ps.options.permissions_options())?; + let permissions = PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?); let mut worker = create_main_worker(&ps, main_module.clone(), permissions).await?; @@ -71,7 +73,9 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> { let mut worker = create_main_worker( &ps.clone(), main_module.clone(), - Permissions::from_options(&ps.options.permissions_options())?, + PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?), ) .await?; @@ -110,8 +114,9 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> { let ps = ProcState::build_for_file_watcher((*flags).clone(), sender.clone()) .await?; - let permissions = - Permissions::from_options(&ps.options.permissions_options())?; + let permissions = PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?); let worker = create_main_worker(&ps, main_module.clone(), permissions).await?; worker.run_for_watcher().await?; @@ -143,8 +148,9 @@ pub async fn eval_command( let main_module = resolve_url_or_path(&format!("./$deno$eval.{}", eval_flags.ext))?; let ps = ProcState::build(flags).await?; - let permissions = - Permissions::from_options(&ps.options.permissions_options())?; + let permissions = PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?); let mut worker = create_main_worker(&ps, main_module.clone(), permissions).await?; // Create a dummy source file. diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs index 471c9605d..07baecc05 100644 --- a/cli/tools/standalone.rs +++ b/cli/tools/standalone.rs @@ -21,7 +21,7 @@ use deno_core::serde_json; use deno_core::url::Url; use deno_graph::ModuleSpecifier; use deno_runtime::colors; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use std::env; use std::fs; use std::fs::File; @@ -170,7 +170,7 @@ async fn create_standalone_binary( Some(import_map_specifier) => { let file = ps .file_fetcher - .fetch(&import_map_specifier, &mut Permissions::allow_all()) + .fetch(&import_map_specifier, PermissionsContainer::allow_all()) .await .context(format!( "Unable to load '{}' import map", diff --git a/cli/tools/test.rs b/cli/tools/test.rs index 35c0ea079..9d1774fff 100644 --- a/cli/tools/test.rs +++ b/cli/tools/test.rs @@ -37,6 +37,7 @@ use deno_runtime::fmt_errors::format_js_error; use deno_runtime::ops::io::Stdio; use deno_runtime::ops::io::StdioPipe; use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use deno_runtime::tokio_util::run_local; use indexmap::IndexMap; use log::Level; @@ -723,7 +724,7 @@ async fn test_specifier( let mut worker = create_main_worker_for_test_or_bench( &ps, specifier.clone(), - permissions, + PermissionsContainer::new(permissions), vec![ops::testing::init( sender, fail_fast_tracker, @@ -895,11 +896,8 @@ async fn fetch_inline_files( ) -> Result<Vec<File>, AnyError> { let mut files = Vec::new(); for specifier in specifiers { - let mut fetch_permissions = Permissions::allow_all(); - let file = ps - .file_fetcher - .fetch(&specifier, &mut fetch_permissions) - .await?; + let fetch_permissions = PermissionsContainer::allow_all(); + let file = ps.file_fetcher.fetch(&specifier, fetch_permissions).await?; let inline_files = if file.media_type == MediaType::Unknown { extract_files_from_fenced_blocks( @@ -957,8 +955,8 @@ pub async fn check_specifiers( specifiers, false, lib, - Permissions::allow_all(), - permissions.clone(), + PermissionsContainer::new(Permissions::allow_all()), + PermissionsContainer::new(permissions.clone()), false, ) .await?; @@ -979,8 +977,8 @@ pub async fn check_specifiers( module_specifiers, false, lib, - Permissions::allow_all(), - permissions, + PermissionsContainer::allow_all(), + PermissionsContainer::new(permissions), true, ) .await?; @@ -1324,7 +1322,7 @@ async fn fetch_specifiers_with_test_mode( for (specifier, mode) in &mut specifiers_with_mode { let file = ps .file_fetcher - .fetch(specifier, &mut Permissions::allow_all()) + .fetch(specifier, PermissionsContainer::allow_all()) .await?; if file.media_type == MediaType::Unknown @@ -1342,6 +1340,9 @@ pub async fn run_tests( test_flags: TestFlags, ) -> Result<(), AnyError> { let ps = ProcState::build(flags).await?; + // Various test files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. let permissions = Permissions::from_options(&ps.options.permissions_options())?; let specifiers_with_mode = fetch_specifiers_with_test_mode( @@ -1383,6 +1384,9 @@ pub async fn run_tests_with_watch( test_flags: TestFlags, ) -> Result<(), AnyError> { let ps = ProcState::build(flags).await?; + // Various test files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. let permissions = Permissions::from_options(&ps.options.permissions_options())?; diff --git a/cli/worker.rs b/cli/worker.rs index ea50966f4..2d29a7a53 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -16,7 +16,7 @@ use deno_runtime::colors; use deno_runtime::fmt_errors::format_js_error; use deno_runtime::ops::worker_host::CreateWebWorkerCb; use deno_runtime::ops::worker_host::WorkerEventCb; -use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsContainer; use deno_runtime::web_worker::WebWorker; use deno_runtime::web_worker::WebWorkerOptions; use deno_runtime::worker::MainWorker; @@ -410,7 +410,7 @@ impl CliMainWorker { pub async fn create_main_worker( ps: &ProcState, main_module: ModuleSpecifier, - permissions: Permissions, + permissions: PermissionsContainer, ) -> Result<CliMainWorker, AnyError> { create_main_worker_internal( ps, @@ -426,7 +426,7 @@ pub async fn create_main_worker( pub async fn create_main_worker_for_test_or_bench( ps: &ProcState, main_module: ModuleSpecifier, - permissions: Permissions, + permissions: PermissionsContainer, custom_extensions: Vec<Extension>, stdio: deno_runtime::ops::io::Stdio, ) -> Result<CliMainWorker, AnyError> { @@ -444,7 +444,7 @@ pub async fn create_main_worker_for_test_or_bench( async fn create_main_worker_internal( ps: &ProcState, main_module: ModuleSpecifier, - permissions: Permissions, + permissions: PermissionsContainer, mut custom_extensions: Vec<Extension>, stdio: deno_runtime::ops::io::Stdio, bench_or_test: bool, @@ -731,10 +731,11 @@ mod tests { use deno_core::{resolve_url_or_path, FsModuleLoader}; use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; use deno_runtime::deno_web::BlobStore; + use deno_runtime::permissions::Permissions; fn create_test_worker() -> MainWorker { let main_module = resolve_url_or_path("./hello.js").unwrap(); - let permissions = Permissions::default(); + let permissions = PermissionsContainer::new(Permissions::default()); let options = WorkerOptions { bootstrap: BootstrapOptions { |