mirror of
https://github.com/denoland/deno.git
synced 2024-11-27 16:10:57 -05:00
refactor(permissions): split up Descriptor into Allow, Deny, and Query (#25508)
This makes the permission system more versatile.
This commit is contained in:
parent
e0b9c745c1
commit
62e952559f
74 changed files with 3062 additions and 1891 deletions
|
@ -32,7 +32,6 @@ use deno_core::normalize_path;
|
||||||
use deno_core::resolve_url_or_path;
|
use deno_core::resolve_url_or_path;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
use deno_runtime::colors;
|
|
||||||
use deno_runtime::deno_permissions::parse_sys_kind;
|
use deno_runtime::deno_permissions::parse_sys_kind;
|
||||||
use deno_runtime::deno_permissions::PermissionsOptions;
|
use deno_runtime::deno_permissions::PermissionsOptions;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -661,107 +660,25 @@ impl PermissionFlags {
|
||||||
|| self.deny_write.is_some()
|
|| self.deny_write.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_options(
|
pub fn to_options(&self) -> PermissionsOptions {
|
||||||
&self,
|
PermissionsOptions {
|
||||||
// will be None when `deno compile` can't resolve the cwd
|
|
||||||
initial_cwd: Option<&Path>,
|
|
||||||
) -> Result<PermissionsOptions, AnyError> {
|
|
||||||
fn convert_option_str_to_path_buf(
|
|
||||||
flag: &Option<Vec<String>>,
|
|
||||||
initial_cwd: Option<&Path>,
|
|
||||||
) -> Result<Option<Vec<PathBuf>>, AnyError> {
|
|
||||||
let Some(paths) = &flag else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut new_paths = Vec::with_capacity(paths.len());
|
|
||||||
for path in paths {
|
|
||||||
if let Some(initial_cwd) = initial_cwd {
|
|
||||||
new_paths.push(initial_cwd.join(path))
|
|
||||||
} else {
|
|
||||||
let path = PathBuf::from(path);
|
|
||||||
if path.is_absolute() {
|
|
||||||
new_paths.push(path);
|
|
||||||
} else {
|
|
||||||
bail!("Could not resolve relative permission path '{}' when current working directory could not be resolved.", path.display())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Some(new_paths))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_allow_run(
|
|
||||||
allow_run: &[String],
|
|
||||||
) -> Result<Vec<PathBuf>, AnyError> {
|
|
||||||
let mut new_allow_run = Vec::with_capacity(allow_run.len());
|
|
||||||
for command_name in allow_run {
|
|
||||||
if command_name.is_empty() {
|
|
||||||
bail!("Empty command name not allowed in --allow-run=...")
|
|
||||||
}
|
|
||||||
let command_path_result = which::which(command_name);
|
|
||||||
match command_path_result {
|
|
||||||
Ok(command_path) => new_allow_run.push(command_path),
|
|
||||||
Err(err) => {
|
|
||||||
log::info!(
|
|
||||||
"{} Failed to resolve '{}' for allow-run: {}",
|
|
||||||
colors::gray("Info"),
|
|
||||||
command_name,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(new_allow_run)
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut deny_write =
|
|
||||||
convert_option_str_to_path_buf(&self.deny_write, initial_cwd)?;
|
|
||||||
let allow_run = self
|
|
||||||
.allow_run
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|raw_allow_run| match resolve_allow_run(raw_allow_run) {
|
|
||||||
Ok(resolved_allow_run) => {
|
|
||||||
if resolved_allow_run.is_empty() && !raw_allow_run.is_empty() {
|
|
||||||
None // convert to no permissions if now empty
|
|
||||||
} else {
|
|
||||||
Some(Ok(resolved_allow_run))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => Some(Err(err)),
|
|
||||||
})
|
|
||||||
.transpose()?;
|
|
||||||
// add the allow_run list to deno_write
|
|
||||||
if let Some(allow_run_vec) = &allow_run {
|
|
||||||
if !allow_run_vec.is_empty() {
|
|
||||||
let deno_write = deny_write.get_or_insert_with(Vec::new);
|
|
||||||
deno_write.extend(allow_run_vec.iter().cloned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(PermissionsOptions {
|
|
||||||
allow_all: self.allow_all,
|
allow_all: self.allow_all,
|
||||||
allow_env: self.allow_env.clone(),
|
allow_env: self.allow_env.clone(),
|
||||||
deny_env: self.deny_env.clone(),
|
deny_env: self.deny_env.clone(),
|
||||||
allow_net: self.allow_net.clone(),
|
allow_net: self.allow_net.clone(),
|
||||||
deny_net: self.deny_net.clone(),
|
deny_net: self.deny_net.clone(),
|
||||||
allow_ffi: convert_option_str_to_path_buf(&self.allow_ffi, initial_cwd)?,
|
allow_ffi: self.allow_ffi.clone(),
|
||||||
deny_ffi: convert_option_str_to_path_buf(&self.deny_ffi, initial_cwd)?,
|
deny_ffi: self.deny_ffi.clone(),
|
||||||
allow_read: convert_option_str_to_path_buf(
|
allow_read: self.allow_read.clone(),
|
||||||
&self.allow_read,
|
deny_read: self.deny_read.clone(),
|
||||||
initial_cwd,
|
allow_run: self.allow_run.clone(),
|
||||||
)?,
|
|
||||||
deny_read: convert_option_str_to_path_buf(&self.deny_read, initial_cwd)?,
|
|
||||||
allow_run,
|
|
||||||
deny_run: self.deny_run.clone(),
|
deny_run: self.deny_run.clone(),
|
||||||
allow_sys: self.allow_sys.clone(),
|
allow_sys: self.allow_sys.clone(),
|
||||||
deny_sys: self.deny_sys.clone(),
|
deny_sys: self.deny_sys.clone(),
|
||||||
allow_write: convert_option_str_to_path_buf(
|
allow_write: self.allow_write.clone(),
|
||||||
&self.allow_write,
|
deny_write: self.deny_write.clone(),
|
||||||
initial_cwd,
|
|
||||||
)?,
|
|
||||||
deny_write,
|
|
||||||
prompt: !resolve_no_prompt(self),
|
prompt: !resolve_no_prompt(self),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
|
|
||||||
|
@ -17,7 +16,7 @@ pub async fn resolve_import_map_value_from_specifier(
|
||||||
Ok(serde_json::from_str(&data_url_text)?)
|
Ok(serde_json::from_str(&data_url_text)?)
|
||||||
} else {
|
} else {
|
||||||
let file = file_fetcher
|
let file = file_fetcher
|
||||||
.fetch(specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(specifier)
|
||||||
.await?
|
.await?
|
||||||
.into_text_decoded()?;
|
.into_text_decoded()?;
|
||||||
Ok(serde_json::from_str(&file.source)?)
|
Ok(serde_json::from_str(&file.source)?)
|
||||||
|
|
|
@ -27,7 +27,6 @@ use deno_npm::npm_rc::NpmRc;
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use import_map::resolve_import_map_value_from_specifier;
|
use import_map::resolve_import_map_value_from_specifier;
|
||||||
|
|
||||||
|
@ -1082,7 +1081,7 @@ impl CliOptions {
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
async move {
|
async move {
|
||||||
let file = file_fetcher
|
let file = file_fetcher
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await?
|
.await?
|
||||||
.into_text_decoded()?;
|
.into_text_decoded()?;
|
||||||
Ok(file.source.to_string())
|
Ok(file.source.to_string())
|
||||||
|
@ -1501,8 +1500,8 @@ impl CliOptions {
|
||||||
&self.flags.permissions
|
&self.flags.permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn permissions_options(&self) -> Result<PermissionsOptions, AnyError> {
|
pub fn permissions_options(&self) -> PermissionsOptions {
|
||||||
self.flags.permissions.to_options(Some(&self.initial_cwd))
|
self.flags.permissions.to_options()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reload_flag(&self) -> bool {
|
pub fn reload_flag(&self) -> bool {
|
||||||
|
|
8
cli/cache/mod.rs
vendored
8
cli/cache/mod.rs
vendored
|
@ -4,6 +4,7 @@ use crate::args::CacheSetting;
|
||||||
use crate::errors::get_error_class_name;
|
use crate::errors::get_error_class_name;
|
||||||
use crate::file_fetcher::FetchNoFollowOptions;
|
use crate::file_fetcher::FetchNoFollowOptions;
|
||||||
use crate::file_fetcher::FetchOptions;
|
use crate::file_fetcher::FetchOptions;
|
||||||
|
use crate::file_fetcher::FetchPermissionsOption;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
use crate::file_fetcher::FileOrRedirect;
|
use crate::file_fetcher::FileOrRedirect;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
|
@ -18,7 +19,6 @@ use deno_graph::source::CacheInfo;
|
||||||
use deno_graph::source::LoadFuture;
|
use deno_graph::source::LoadFuture;
|
||||||
use deno_graph::source::LoadResponse;
|
use deno_graph::source::LoadResponse;
|
||||||
use deno_graph::source::Loader;
|
use deno_graph::source::Loader;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -112,7 +112,7 @@ pub struct FetchCacher {
|
||||||
global_http_cache: Arc<GlobalHttpCache>,
|
global_http_cache: Arc<GlobalHttpCache>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
permissions: PermissionsContainer,
|
permissions: FetchPermissionsOption,
|
||||||
cache_info_enabled: bool,
|
cache_info_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ impl FetchCacher {
|
||||||
global_http_cache: Arc<GlobalHttpCache>,
|
global_http_cache: Arc<GlobalHttpCache>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
permissions: PermissionsContainer,
|
permissions: FetchPermissionsOption,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
|
@ -230,7 +230,7 @@ impl Loader for FetchCacher {
|
||||||
.fetch_no_follow_with_options(FetchNoFollowOptions {
|
.fetch_no_follow_with_options(FetchNoFollowOptions {
|
||||||
fetch_options: FetchOptions {
|
fetch_options: FetchOptions {
|
||||||
specifier: &specifier,
|
specifier: &specifier,
|
||||||
permissions: &permissions,
|
permissions: permissions.as_ref(),
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_cache_setting: maybe_cache_setting.as_ref(),
|
maybe_cache_setting: maybe_cache_setting.as_ref(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -65,10 +65,13 @@ use deno_core::FeatureChecker;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
use deno_runtime::deno_web::BlobStore;
|
use deno_runtime::deno_web::BlobStore;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use node_resolver::analyze::NodeCodeTranslator;
|
use node_resolver::analyze::NodeCodeTranslator;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
@ -181,6 +184,7 @@ struct CliFactoryServices {
|
||||||
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
||||||
node_resolver: Deferred<Arc<NodeResolver>>,
|
node_resolver: Deferred<Arc<NodeResolver>>,
|
||||||
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
|
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
|
||||||
|
permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>,
|
||||||
sloppy_imports_resolver: Deferred<Option<Arc<SloppyImportsResolver>>>,
|
sloppy_imports_resolver: Deferred<Option<Arc<SloppyImportsResolver>>>,
|
||||||
text_only_progress_bar: Deferred<ProgressBar>,
|
text_only_progress_bar: Deferred<ProgressBar>,
|
||||||
type_checker: Deferred<Arc<TypeChecker>>,
|
type_checker: Deferred<Arc<TypeChecker>>,
|
||||||
|
@ -708,6 +712,15 @@ impl CliFactory {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn permission_desc_parser(
|
||||||
|
&self,
|
||||||
|
) -> Result<&Arc<RuntimePermissionDescriptorParser>, AnyError> {
|
||||||
|
self.services.permission_desc_parser.get_or_try_init(|| {
|
||||||
|
let fs = self.fs().clone();
|
||||||
|
Ok(Arc::new(RuntimePermissionDescriptorParser::new(fs)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn feature_checker(&self) -> Result<&Arc<FeatureChecker>, AnyError> {
|
pub fn feature_checker(&self) -> Result<&Arc<FeatureChecker>, AnyError> {
|
||||||
self.services.feature_checker.get_or_try_init(|| {
|
self.services.feature_checker.get_or_try_init(|| {
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
|
@ -739,6 +752,17 @@ impl CliFactory {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_permissions_container(
|
||||||
|
&self,
|
||||||
|
) -> Result<PermissionsContainer, AnyError> {
|
||||||
|
let desc_parser = self.permission_desc_parser()?.clone();
|
||||||
|
let permissions = Permissions::from_options(
|
||||||
|
desc_parser.as_ref(),
|
||||||
|
&self.cli_options()?.permissions_options(),
|
||||||
|
)?;
|
||||||
|
Ok(PermissionsContainer::new(desc_parser, permissions))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_cli_main_worker_factory(
|
pub async fn create_cli_main_worker_factory(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<CliMainWorkerFactory, AnyError> {
|
) -> Result<CliMainWorkerFactory, AnyError> {
|
||||||
|
@ -754,11 +778,17 @@ impl CliFactory {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(CliMainWorkerFactory::new(
|
Ok(CliMainWorkerFactory::new(
|
||||||
StorageKeyResolver::from_options(cli_options),
|
|
||||||
cli_options.sub_command().clone(),
|
|
||||||
npm_resolver.clone(),
|
|
||||||
node_resolver.clone(),
|
|
||||||
self.blob_store().clone(),
|
self.blob_store().clone(),
|
||||||
|
if cli_options.code_cache_enabled() {
|
||||||
|
Some(self.code_cache()?.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
self.feature_checker()?.clone(),
|
||||||
|
self.fs().clone(),
|
||||||
|
maybe_file_watcher_communicator,
|
||||||
|
self.maybe_inspector_server()?.clone(),
|
||||||
|
cli_options.maybe_lockfile().cloned(),
|
||||||
Box::new(CliModuleLoaderFactory::new(
|
Box::new(CliModuleLoaderFactory::new(
|
||||||
cli_options,
|
cli_options,
|
||||||
if cli_options.code_cache_enabled() {
|
if cli_options.code_cache_enabled() {
|
||||||
|
@ -779,17 +809,12 @@ impl CliFactory {
|
||||||
self.parsed_source_cache().clone(),
|
self.parsed_source_cache().clone(),
|
||||||
self.resolver().await?.clone(),
|
self.resolver().await?.clone(),
|
||||||
)),
|
)),
|
||||||
|
node_resolver.clone(),
|
||||||
|
npm_resolver.clone(),
|
||||||
|
self.permission_desc_parser()?.clone(),
|
||||||
self.root_cert_store_provider().clone(),
|
self.root_cert_store_provider().clone(),
|
||||||
self.fs().clone(),
|
StorageKeyResolver::from_options(cli_options),
|
||||||
maybe_file_watcher_communicator,
|
cli_options.sub_command().clone(),
|
||||||
self.maybe_inspector_server()?.clone(),
|
|
||||||
cli_options.maybe_lockfile().cloned(),
|
|
||||||
self.feature_checker()?.clone(),
|
|
||||||
if cli_options.code_cache_enabled() {
|
|
||||||
Some(self.code_cache()?.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
self.create_cli_main_worker_options()?,
|
self.create_cli_main_worker_options()?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,9 +161,38 @@ fn get_validated_scheme(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum FetchPermissionsOptionRef<'a> {
|
||||||
|
AllowAll,
|
||||||
|
Container(&'a PermissionsContainer),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FetchPermissionsOption {
|
||||||
|
AllowAll,
|
||||||
|
Container(PermissionsContainer),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FetchPermissionsOption {
|
||||||
|
pub fn as_ref(&self) -> FetchPermissionsOptionRef {
|
||||||
|
match self {
|
||||||
|
FetchPermissionsOption::AllowAll => FetchPermissionsOptionRef::AllowAll,
|
||||||
|
FetchPermissionsOption::Container(container) => {
|
||||||
|
FetchPermissionsOptionRef::Container(container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PermissionsContainer> for FetchPermissionsOption {
|
||||||
|
fn from(value: PermissionsContainer) -> Self {
|
||||||
|
Self::Container(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FetchOptions<'a> {
|
pub struct FetchOptions<'a> {
|
||||||
pub specifier: &'a ModuleSpecifier,
|
pub specifier: &'a ModuleSpecifier,
|
||||||
pub permissions: &'a PermissionsContainer,
|
pub permissions: FetchPermissionsOptionRef<'a>,
|
||||||
pub maybe_accept: Option<&'a str>,
|
pub maybe_accept: Option<&'a str>,
|
||||||
pub maybe_cache_setting: Option<&'a CacheSetting>,
|
pub maybe_cache_setting: Option<&'a CacheSetting>,
|
||||||
}
|
}
|
||||||
|
@ -515,11 +544,33 @@ impl FileFetcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub async fn fetch_bypass_permissions(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Result<File, AnyError> {
|
||||||
|
self
|
||||||
|
.fetch_inner(specifier, FetchPermissionsOptionRef::AllowAll)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetch a source file and asynchronously return it.
|
/// Fetch a source file and asynchronously return it.
|
||||||
|
#[allow(dead_code)] // todo(25469): undo when merging
|
||||||
|
#[inline(always)]
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
permissions: &PermissionsContainer,
|
permissions: &PermissionsContainer,
|
||||||
|
) -> Result<File, AnyError> {
|
||||||
|
self
|
||||||
|
.fetch_inner(specifier, FetchPermissionsOptionRef::Container(permissions))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_inner(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
permissions: FetchPermissionsOptionRef<'_>,
|
||||||
) -> Result<File, AnyError> {
|
) -> Result<File, AnyError> {
|
||||||
self
|
self
|
||||||
.fetch_with_options(FetchOptions {
|
.fetch_with_options(FetchOptions {
|
||||||
|
@ -583,7 +634,14 @@ impl FileFetcher {
|
||||||
specifier
|
specifier
|
||||||
);
|
);
|
||||||
let scheme = get_validated_scheme(specifier)?;
|
let scheme = get_validated_scheme(specifier)?;
|
||||||
options.permissions.check_specifier(specifier)?;
|
match options.permissions {
|
||||||
|
FetchPermissionsOptionRef::AllowAll => {
|
||||||
|
// allow
|
||||||
|
}
|
||||||
|
FetchPermissionsOptionRef::Container(permissions) => {
|
||||||
|
permissions.check_specifier(specifier)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(file) = self.memory_files.get(specifier) {
|
if let Some(file) = self.memory_files.get(specifier) {
|
||||||
Ok(FileOrRedirect::File(file))
|
Ok(FileOrRedirect::File(file))
|
||||||
} else if scheme == "file" {
|
} else if scheme == "file" {
|
||||||
|
@ -684,9 +742,7 @@ mod tests {
|
||||||
|
|
||||||
async fn test_fetch(specifier: &ModuleSpecifier) -> (File, FileFetcher) {
|
async fn test_fetch(specifier: &ModuleSpecifier) -> (File, FileFetcher) {
|
||||||
let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None);
|
let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None);
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(specifier).await;
|
||||||
.fetch(specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
(result.unwrap(), file_fetcher)
|
(result.unwrap(), file_fetcher)
|
||||||
}
|
}
|
||||||
|
@ -700,7 +756,7 @@ mod tests {
|
||||||
.fetch_with_options_and_max_redirect(
|
.fetch_with_options_and_max_redirect(
|
||||||
FetchOptions {
|
FetchOptions {
|
||||||
specifier,
|
specifier,
|
||||||
permissions: &PermissionsContainer::allow_all(),
|
permissions: FetchPermissionsOptionRef::AllowAll,
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_cache_setting: Some(&file_fetcher.cache_setting),
|
maybe_cache_setting: Some(&file_fetcher.cache_setting),
|
||||||
},
|
},
|
||||||
|
@ -796,9 +852,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
file_fetcher.insert_memory_files(file.clone());
|
file_fetcher.insert_memory_files(file.clone());
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let result_file = result.unwrap();
|
let result_file = result.unwrap();
|
||||||
assert_eq!(result_file, file);
|
assert_eq!(result_file, file);
|
||||||
|
@ -809,9 +863,7 @@ mod tests {
|
||||||
let (file_fetcher, _) = setup(CacheSetting::Use, None);
|
let (file_fetcher, _) = setup(CacheSetting::Use, None);
|
||||||
let specifier = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap();
|
let specifier = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap();
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -840,9 +892,7 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -862,9 +912,7 @@ mod tests {
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::parse("http://localhost:4545/subdir/mod2.ts").unwrap();
|
ModuleSpecifier::parse("http://localhost:4545/subdir/mod2.ts").unwrap();
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -882,9 +930,7 @@ mod tests {
|
||||||
.set(&specifier, headers.clone(), file.source.as_bytes())
|
.set(&specifier, headers.clone(), file.source.as_bytes())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let result = file_fetcher_01
|
let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -908,9 +954,7 @@ mod tests {
|
||||||
.set(&specifier, headers.clone(), file.source.as_bytes())
|
.set(&specifier, headers.clone(), file.source.as_bytes())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let result = file_fetcher_02
|
let result = file_fetcher_02.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -933,9 +977,7 @@ mod tests {
|
||||||
Default::default(),
|
Default::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -966,9 +1008,7 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let cache_key =
|
let cache_key =
|
||||||
file_fetcher.http_cache.cache_item_key(&specifier).unwrap();
|
file_fetcher.http_cache.cache_item_key(&specifier).unwrap();
|
||||||
|
@ -1002,9 +1042,7 @@ mod tests {
|
||||||
Default::default(),
|
Default::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
let cache_key =
|
let cache_key =
|
||||||
|
@ -1041,9 +1079,7 @@ mod tests {
|
||||||
resolve_url("http://localhost:4545/subdir/redirects/redirect1.js")
|
resolve_url("http://localhost:4545/subdir/redirects/redirect1.js")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
assert_eq!(file.specifier, redirected_specifier);
|
assert_eq!(file.specifier, redirected_specifier);
|
||||||
|
@ -1082,9 +1118,7 @@ mod tests {
|
||||||
resolve_url("http://localhost:4545/subdir/redirects/redirect1.js")
|
resolve_url("http://localhost:4545/subdir/redirects/redirect1.js")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
assert_eq!(file.specifier, redirected_02_specifier);
|
assert_eq!(file.specifier, redirected_02_specifier);
|
||||||
|
@ -1142,9 +1176,7 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
let cache_key = file_fetcher
|
let cache_key = file_fetcher
|
||||||
|
@ -1182,7 +1214,7 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let result = file_fetcher
|
let result = file_fetcher
|
||||||
.fetch(&redirected_specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&redirected_specifier)
|
||||||
.await;
|
.await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
@ -1223,7 +1255,7 @@ mod tests {
|
||||||
.fetch_with_options_and_max_redirect(
|
.fetch_with_options_and_max_redirect(
|
||||||
FetchOptions {
|
FetchOptions {
|
||||||
specifier: &specifier,
|
specifier: &specifier,
|
||||||
permissions: &PermissionsContainer::allow_all(),
|
permissions: FetchPermissionsOptionRef::AllowAll,
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_cache_setting: Some(&file_fetcher.cache_setting),
|
maybe_cache_setting: Some(&file_fetcher.cache_setting),
|
||||||
},
|
},
|
||||||
|
@ -1236,7 +1268,7 @@ mod tests {
|
||||||
.fetch_with_options_and_max_redirect(
|
.fetch_with_options_and_max_redirect(
|
||||||
FetchOptions {
|
FetchOptions {
|
||||||
specifier: &specifier,
|
specifier: &specifier,
|
||||||
permissions: &PermissionsContainer::allow_all(),
|
permissions: FetchPermissionsOptionRef::AllowAll,
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_cache_setting: Some(&file_fetcher.cache_setting),
|
maybe_cache_setting: Some(&file_fetcher.cache_setting),
|
||||||
},
|
},
|
||||||
|
@ -1264,9 +1296,7 @@ mod tests {
|
||||||
resolve_url("http://localhost:4550/subdir/redirects/redirect1.js")
|
resolve_url("http://localhost:4550/subdir/redirects/redirect1.js")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
assert_eq!(file.specifier, redirected_specifier);
|
assert_eq!(file.specifier, redirected_specifier);
|
||||||
|
@ -1310,9 +1340,7 @@ mod tests {
|
||||||
let specifier =
|
let specifier =
|
||||||
resolve_url("http://localhost:4545/run/002_hello.ts").unwrap();
|
resolve_url("http://localhost:4545/run/002_hello.ts").unwrap();
|
||||||
|
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let err = result.unwrap_err();
|
let err = result.unwrap_err();
|
||||||
assert_eq!(get_custom_error_class(&err), Some("NoRemote"));
|
assert_eq!(get_custom_error_class(&err), Some("NoRemote"));
|
||||||
|
@ -1343,22 +1371,16 @@ mod tests {
|
||||||
let specifier =
|
let specifier =
|
||||||
resolve_url("http://localhost:4545/run/002_hello.ts").unwrap();
|
resolve_url("http://localhost:4545/run/002_hello.ts").unwrap();
|
||||||
|
|
||||||
let result = file_fetcher_01
|
let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let err = result.unwrap_err();
|
let err = result.unwrap_err();
|
||||||
assert_eq!(err.to_string(), "Specifier not found in cache: \"http://localhost:4545/run/002_hello.ts\", --cached-only is specified.");
|
assert_eq!(err.to_string(), "Specifier not found in cache: \"http://localhost:4545/run/002_hello.ts\", --cached-only is specified.");
|
||||||
assert_eq!(get_custom_error_class(&err), Some("NotCached"));
|
assert_eq!(get_custom_error_class(&err), Some("NotCached"));
|
||||||
|
|
||||||
let result = file_fetcher_02
|
let result = file_fetcher_02.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
let result = file_fetcher_01
|
let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1368,17 +1390,13 @@ mod tests {
|
||||||
let fixture_path = temp_dir.path().join("mod.ts");
|
let fixture_path = temp_dir.path().join("mod.ts");
|
||||||
let specifier = ModuleSpecifier::from_file_path(&fixture_path).unwrap();
|
let specifier = ModuleSpecifier::from_file_path(&fixture_path).unwrap();
|
||||||
fs::write(fixture_path.clone(), r#"console.log("hello deno");"#).unwrap();
|
fs::write(fixture_path.clone(), r#"console.log("hello deno");"#).unwrap();
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(&*file.source, r#"console.log("hello deno");"#);
|
assert_eq!(&*file.source, r#"console.log("hello deno");"#);
|
||||||
|
|
||||||
fs::write(fixture_path, r#"console.log("goodbye deno");"#).unwrap();
|
fs::write(fixture_path, r#"console.log("goodbye deno");"#).unwrap();
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap().into_text_decoded().unwrap();
|
let file = result.unwrap().into_text_decoded().unwrap();
|
||||||
assert_eq!(&*file.source, r#"console.log("goodbye deno");"#);
|
assert_eq!(&*file.source, r#"console.log("goodbye deno");"#);
|
||||||
|
@ -1392,18 +1410,14 @@ mod tests {
|
||||||
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::parse("http://localhost:4545/dynamic").unwrap();
|
ModuleSpecifier::parse("http://localhost:4545/dynamic").unwrap();
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
let first = file.source;
|
let first = file.source;
|
||||||
|
|
||||||
let (file_fetcher, _) =
|
let (file_fetcher, _) =
|
||||||
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
let second = file.source;
|
let second = file.source;
|
||||||
|
@ -1419,18 +1433,14 @@ mod tests {
|
||||||
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::parse("http://localhost:4545/dynamic_cache").unwrap();
|
ModuleSpecifier::parse("http://localhost:4545/dynamic_cache").unwrap();
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
let first = file.source;
|
let first = file.source;
|
||||||
|
|
||||||
let (file_fetcher, _) =
|
let (file_fetcher, _) =
|
||||||
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
|
||||||
let result = file_fetcher
|
let result = file_fetcher.fetch_bypass_permissions(&specifier).await;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await;
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let file = result.unwrap();
|
let file = result.unwrap();
|
||||||
let second = file.source;
|
let second = file.source;
|
||||||
|
|
|
@ -9,9 +9,9 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::RwLock;
|
use deno_core::parking_lot::RwLock;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
|
|
||||||
use crate::args::CliOptions;
|
use crate::args::CliOptions;
|
||||||
|
use crate::file_fetcher::FetchPermissionsOption;
|
||||||
use crate::module_loader::ModuleLoadPreparer;
|
use crate::module_loader::ModuleLoadPreparer;
|
||||||
use crate::util::fs::collect_specifiers;
|
use crate::util::fs::collect_specifiers;
|
||||||
use crate::util::path::is_script_ext;
|
use crate::util::path::is_script_ext;
|
||||||
|
@ -75,7 +75,7 @@ impl MainModuleGraphContainer {
|
||||||
specifiers,
|
specifiers,
|
||||||
false,
|
false,
|
||||||
self.cli_options.ts_type_lib_window(),
|
self.cli_options.ts_type_lib_window(),
|
||||||
PermissionsContainer::allow_all(),
|
FetchPermissionsOption::AllowAll,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
graph_permit.commit();
|
graph_permit.commit();
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::cache::ModuleInfoCache;
|
||||||
use crate::cache::ParsedSourceCache;
|
use crate::cache::ParsedSourceCache;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::errors::get_error_class_name;
|
use crate::errors::get_error_class_name;
|
||||||
|
use crate::file_fetcher::FetchPermissionsOption;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
|
@ -41,7 +42,6 @@ use deno_graph::ResolutionError;
|
||||||
use deno_graph::SpecifierError;
|
use deno_graph::SpecifierError;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::jsr::JsrDepPackageReq;
|
use deno_semver::jsr::JsrDepPackageReq;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
|
@ -670,12 +670,12 @@ impl ModuleGraphBuilder {
|
||||||
|
|
||||||
/// Creates the default loader used for creating a graph.
|
/// Creates the default loader used for creating a graph.
|
||||||
pub fn create_graph_loader(&self) -> cache::FetchCacher {
|
pub fn create_graph_loader(&self) -> cache::FetchCacher {
|
||||||
self.create_fetch_cacher(PermissionsContainer::allow_all())
|
self.create_fetch_cacher(FetchPermissionsOption::AllowAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_fetch_cacher(
|
pub fn create_fetch_cacher(
|
||||||
&self,
|
&self,
|
||||||
permissions: PermissionsContainer,
|
permissions: FetchPermissionsOption,
|
||||||
) -> cache::FetchCacher {
|
) -> cache::FetchCacher {
|
||||||
cache::FetchCacher::new(
|
cache::FetchCacher::new(
|
||||||
self.file_fetcher.clone(),
|
self.file_fetcher.clone(),
|
||||||
|
|
11
cli/jsr.rs
11
cli/jsr.rs
|
@ -6,7 +6,6 @@ use dashmap::DashMap;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_graph::packages::JsrPackageInfo;
|
use deno_graph::packages::JsrPackageInfo;
|
||||||
use deno_graph::packages::JsrPackageVersionInfo;
|
use deno_graph::packages::JsrPackageVersionInfo;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -68,10 +67,7 @@ impl JsrFetchResolver {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
file_fetcher.fetch_bypass_permissions(&meta_url).await.ok()
|
||||||
.fetch(&meta_url, &PermissionsContainer::allow_all())
|
|
||||||
.await
|
|
||||||
.ok()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.ok()??;
|
.ok()??;
|
||||||
|
@ -96,10 +92,7 @@ impl JsrFetchResolver {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
file_fetcher.fetch_bypass_permissions(&meta_url).await.ok()
|
||||||
.fetch(&meta_url, &PermissionsContainer::allow_all())
|
|
||||||
.await
|
|
||||||
.ok()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.ok()??;
|
.ok()??;
|
||||||
|
|
|
@ -37,7 +37,6 @@ use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_package_json::PackageJsonCache;
|
use deno_package_json::PackageJsonCache;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_runtime::fs_util::specifier_to_file_path;
|
use deno_runtime::fs_util::specifier_to_file_path;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use lsp_types::ClientCapabilities;
|
use lsp_types::ClientCapabilities;
|
||||||
|
@ -1509,17 +1508,16 @@ impl ConfigData {
|
||||||
ConfigWatchedFileType::ImportMap,
|
ConfigWatchedFileType::ImportMap,
|
||||||
);
|
);
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let fetch_result = deno_core::unsync::spawn({
|
let fetch_result =
|
||||||
let file_fetcher = file_fetcher.cloned().unwrap();
|
deno_core::unsync::spawn({
|
||||||
let import_map_url = import_map_url.clone();
|
let file_fetcher = file_fetcher.cloned().unwrap();
|
||||||
async move {
|
let import_map_url = import_map_url.clone();
|
||||||
file_fetcher
|
async move {
|
||||||
.fetch(&import_map_url, &PermissionsContainer::allow_all())
|
file_fetcher.fetch_bypass_permissions(&import_map_url).await
|
||||||
.await
|
}
|
||||||
}
|
})
|
||||||
})
|
.await
|
||||||
.await
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let value_result = fetch_result.and_then(|f| {
|
let value_result = fetch_result.and_then(|f| {
|
||||||
serde_json::from_slice::<Value>(&f.source).map_err(|e| e.into())
|
serde_json::from_slice::<Value>(&f.source).map_err(|e| e.into())
|
||||||
|
@ -1558,7 +1556,7 @@ impl ConfigData {
|
||||||
let file_fetcher = file_fetcher.clone().unwrap();
|
let file_fetcher = file_fetcher.clone().unwrap();
|
||||||
async move {
|
async move {
|
||||||
let file = file_fetcher
|
let file = file_fetcher
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await?
|
.await?
|
||||||
.into_text_decoded()?;
|
.into_text_decoded()?;
|
||||||
Ok(file.source.to_string())
|
Ok(file.source.to_string())
|
||||||
|
|
|
@ -14,7 +14,6 @@ use deno_graph::packages::JsrPackageInfo;
|
||||||
use deno_graph::packages::JsrPackageInfoVersion;
|
use deno_graph::packages::JsrPackageInfoVersion;
|
||||||
use deno_graph::packages::JsrPackageVersionInfo;
|
use deno_graph::packages::JsrPackageVersionInfo;
|
||||||
use deno_graph::ModuleSpecifier;
|
use deno_graph::ModuleSpecifier;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
@ -311,7 +310,7 @@ impl PackageSearchApi for CliJsrSearchApi {
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch(&search_url, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&search_url)
|
||||||
.await?
|
.await?
|
||||||
.into_text_decoded()
|
.into_text_decoded()
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,6 @@ use dashmap::DashMap;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -55,7 +54,7 @@ impl PackageSearchApi for CliNpmSearchApi {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch(&search_url, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&search_url)
|
||||||
.await?
|
.await?
|
||||||
.into_text_decoded()
|
.into_text_decoded()
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,6 +16,7 @@ use crate::args::CacheSetting;
|
||||||
use crate::cache::GlobalHttpCache;
|
use crate::cache::GlobalHttpCache;
|
||||||
use crate::cache::HttpCache;
|
use crate::cache::HttpCache;
|
||||||
use crate::file_fetcher::FetchOptions;
|
use crate::file_fetcher::FetchOptions;
|
||||||
|
use crate::file_fetcher::FetchPermissionsOptionRef;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
use crate::http_util::HttpClientProvider;
|
use crate::http_util::HttpClientProvider;
|
||||||
|
|
||||||
|
@ -30,7 +31,6 @@ use deno_core::url::Position;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::Dependency;
|
use deno_graph::Dependency;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -481,7 +481,7 @@ impl ModuleRegistry {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch_with_options(FetchOptions {
|
.fetch_with_options(FetchOptions {
|
||||||
specifier: &specifier,
|
specifier: &specifier,
|
||||||
permissions: &PermissionsContainer::allow_all(),
|
permissions: FetchPermissionsOptionRef::AllowAll,
|
||||||
maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
|
maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
|
||||||
maybe_cache_setting: None,
|
maybe_cache_setting: None,
|
||||||
})
|
})
|
||||||
|
@ -584,7 +584,7 @@ impl ModuleRegistry {
|
||||||
let file = deno_core::unsync::spawn({
|
let file = deno_core::unsync::spawn({
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch(&endpoint, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&endpoint)
|
||||||
.await
|
.await
|
||||||
.ok()?
|
.ok()?
|
||||||
.into_text_decoded()
|
.into_text_decoded()
|
||||||
|
@ -983,7 +983,7 @@ impl ModuleRegistry {
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await
|
.await
|
||||||
.ok()?
|
.ok()?
|
||||||
.into_text_decoded()
|
.into_text_decoded()
|
||||||
|
@ -1049,7 +1049,7 @@ impl ModuleRegistry {
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!(
|
error!(
|
||||||
|
@ -1095,7 +1095,7 @@ impl ModuleRegistry {
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!(
|
error!(
|
||||||
|
|
|
@ -31,6 +31,7 @@ use deno_core::unsync::spawn;
|
||||||
use deno_core::unsync::spawn_blocking;
|
use deno_core::unsync::spawn_blocking;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -227,8 +228,11 @@ impl TestRun {
|
||||||
// Various test files should not share the same permissions in terms of
|
// Various test files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permission_desc_parser = factory.permission_desc_parser()?.clone();
|
||||||
Permissions::from_options(&cli_options.permissions_options()?)?;
|
let permissions = Permissions::from_options(
|
||||||
|
permission_desc_parser.as_ref(),
|
||||||
|
&cli_options.permissions_options(),
|
||||||
|
)?;
|
||||||
let main_graph_container = factory.main_module_graph_container().await?;
|
let main_graph_container = factory.main_module_graph_container().await?;
|
||||||
test::check_specifiers(
|
test::check_specifiers(
|
||||||
factory.file_fetcher()?,
|
factory.file_fetcher()?,
|
||||||
|
@ -276,7 +280,10 @@ impl TestRun {
|
||||||
let join_handles = queue.into_iter().map(move |specifier| {
|
let join_handles = queue.into_iter().map(move |specifier| {
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
let worker_factory = worker_factory.clone();
|
let worker_factory = worker_factory.clone();
|
||||||
let permissions = permissions.clone();
|
let permissions_container = PermissionsContainer::new(
|
||||||
|
permission_desc_parser.clone(),
|
||||||
|
permissions.clone(),
|
||||||
|
);
|
||||||
let worker_sender = test_event_sender_factory.worker();
|
let worker_sender = test_event_sender_factory.worker();
|
||||||
let fail_fast_tracker = fail_fast_tracker.clone();
|
let fail_fast_tracker = fail_fast_tracker.clone();
|
||||||
let lsp_filter = self.filters.get(&specifier);
|
let lsp_filter = self.filters.get(&specifier);
|
||||||
|
@ -305,7 +312,7 @@ impl TestRun {
|
||||||
// channel.
|
// channel.
|
||||||
create_and_run_current_thread(test::test_specifier(
|
create_and_run_current_thread(test::test_specifier(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
permissions,
|
permissions_container,
|
||||||
specifier,
|
specifier,
|
||||||
worker_sender,
|
worker_sender,
|
||||||
fail_fast_tracker,
|
fail_fast_tracker,
|
||||||
|
|
|
@ -104,7 +104,7 @@ impl ModuleLoadPreparer {
|
||||||
roots: &[ModuleSpecifier],
|
roots: &[ModuleSpecifier],
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
lib: TsTypeLib,
|
lib: TsTypeLib,
|
||||||
permissions: PermissionsContainer,
|
permissions: crate::file_fetcher::FetchPermissionsOption,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
log::debug!("Preparing module load.");
|
log::debug!("Preparing module load.");
|
||||||
let _pb_clear_guard = self.progress_bar.clear_guard();
|
let _pb_clear_guard = self.progress_bar.clear_guard();
|
||||||
|
@ -762,7 +762,7 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
|
||||||
&[specifier],
|
&[specifier],
|
||||||
is_dynamic,
|
is_dynamic,
|
||||||
lib,
|
lib,
|
||||||
root_permissions,
|
root_permissions.into(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
update_permit.commit();
|
update_permit.commit();
|
||||||
|
|
|
@ -280,7 +280,7 @@ impl NodeRequireResolver for ByonmCliNpmResolver {
|
||||||
.components()
|
.components()
|
||||||
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
||||||
{
|
{
|
||||||
permissions.check_read(path)?;
|
_ = permissions.check_read_path(path)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,8 @@ impl RegistryReadPermissionChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions.check_read(path)
|
_ = permissions.check_read_path(path)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ use deno_core::serde_json;
|
||||||
use deno_npm::registry::NpmPackageInfo;
|
use deno_npm::registry::NpmPackageInfo;
|
||||||
use deno_runtime::deno_node::NodeRequireResolver;
|
use deno_runtime::deno_node::NodeRequireResolver;
|
||||||
use deno_runtime::deno_node::NpmProcessStateProvider;
|
use deno_runtime::deno_node::NpmProcessStateProvider;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use node_resolver::NpmResolver;
|
use node_resolver::NpmResolver;
|
||||||
|
@ -152,10 +151,7 @@ impl NpmFetchResolver {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
file_fetcher.fetch_bypass_permissions(&info_url).await.ok()
|
||||||
.fetch(&info_url, &PermissionsContainer::allow_all())
|
|
||||||
.await
|
|
||||||
.ok()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.ok()??;
|
.ok()??;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
|
@ -13,6 +14,7 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_runtime::deno_permissions::create_child_permissions;
|
use deno_runtime::deno_permissions::create_child_permissions;
|
||||||
use deno_runtime::deno_permissions::ChildPermissionsArg;
|
use deno_runtime::deno_permissions::ChildPermissionsArg;
|
||||||
|
use deno_runtime::deno_permissions::PermissionDescriptorParser;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -59,11 +61,18 @@ pub fn op_pledge_test_permissions(
|
||||||
#[serde] args: ChildPermissionsArg,
|
#[serde] args: ChildPermissionsArg,
|
||||||
) -> Result<Uuid, AnyError> {
|
) -> Result<Uuid, AnyError> {
|
||||||
let token = Uuid::new_v4();
|
let token = Uuid::new_v4();
|
||||||
|
let permission_desc_parser = state
|
||||||
|
.borrow::<Arc<dyn PermissionDescriptorParser>>()
|
||||||
|
.clone();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = {
|
let worker_permissions = {
|
||||||
let mut parent_permissions = parent_permissions.0.lock();
|
let mut parent_permissions = parent_permissions.inner.lock();
|
||||||
let perms = create_child_permissions(&mut parent_permissions, args)?;
|
let perms = create_child_permissions(
|
||||||
PermissionsContainer::new(perms)
|
permission_desc_parser.as_ref(),
|
||||||
|
&mut parent_permissions,
|
||||||
|
args,
|
||||||
|
)?;
|
||||||
|
PermissionsContainer::new(permission_desc_parser, perms)
|
||||||
};
|
};
|
||||||
let parent_permissions = parent_permissions.clone();
|
let parent_permissions = parent_permissions.clone();
|
||||||
|
|
||||||
|
@ -74,7 +83,7 @@ pub fn op_pledge_test_permissions(
|
||||||
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
||||||
|
|
||||||
// NOTE: This call overrides current permission set for the worker
|
// NOTE: This call overrides current permission set for the worker
|
||||||
state.put(worker_permissions.0.clone());
|
state.put(worker_permissions.inner.clone());
|
||||||
state.put::<PermissionsContainer>(worker_permissions);
|
state.put::<PermissionsContainer>(worker_permissions);
|
||||||
|
|
||||||
Ok(token)
|
Ok(token)
|
||||||
|
@ -91,7 +100,7 @@ pub fn op_restore_test_permissions(
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissions = permissions_holder.1;
|
let permissions = permissions_holder.1;
|
||||||
state.put(permissions.0.clone());
|
state.put(permissions.inner.clone());
|
||||||
state.put::<PermissionsContainer>(permissions);
|
state.put::<PermissionsContainer>(permissions);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,9 +18,11 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_runtime::deno_permissions::create_child_permissions;
|
use deno_runtime::deno_permissions::create_child_permissions;
|
||||||
use deno_runtime::deno_permissions::ChildPermissionsArg;
|
use deno_runtime::deno_permissions::ChildPermissionsArg;
|
||||||
|
use deno_runtime::deno_permissions::PermissionDescriptorParser;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
deno_core::extension!(deno_test,
|
deno_core::extension!(deno_test,
|
||||||
|
@ -54,11 +56,18 @@ pub fn op_pledge_test_permissions(
|
||||||
#[serde] args: ChildPermissionsArg,
|
#[serde] args: ChildPermissionsArg,
|
||||||
) -> Result<Uuid, AnyError> {
|
) -> Result<Uuid, AnyError> {
|
||||||
let token = Uuid::new_v4();
|
let token = Uuid::new_v4();
|
||||||
|
let permission_desc_parser = state
|
||||||
|
.borrow::<Arc<dyn PermissionDescriptorParser>>()
|
||||||
|
.clone();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = {
|
let worker_permissions = {
|
||||||
let mut parent_permissions = parent_permissions.0.lock();
|
let mut parent_permissions = parent_permissions.inner.lock();
|
||||||
let perms = create_child_permissions(&mut parent_permissions, args)?;
|
let perms = create_child_permissions(
|
||||||
PermissionsContainer::new(perms)
|
permission_desc_parser.as_ref(),
|
||||||
|
&mut parent_permissions,
|
||||||
|
args,
|
||||||
|
)?;
|
||||||
|
PermissionsContainer::new(permission_desc_parser, perms)
|
||||||
};
|
};
|
||||||
let parent_permissions = parent_permissions.clone();
|
let parent_permissions = parent_permissions.clone();
|
||||||
|
|
||||||
|
@ -68,7 +77,7 @@ pub fn op_pledge_test_permissions(
|
||||||
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
||||||
|
|
||||||
// NOTE: This call overrides current permission set for the worker
|
// NOTE: This call overrides current permission set for the worker
|
||||||
state.put(worker_permissions.0.clone());
|
state.put(worker_permissions.inner.clone());
|
||||||
state.put::<PermissionsContainer>(worker_permissions);
|
state.put::<PermissionsContainer>(worker_permissions);
|
||||||
|
|
||||||
Ok(token)
|
Ok(token)
|
||||||
|
@ -85,7 +94,7 @@ pub fn op_restore_test_permissions(
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissions = permissions_holder.1;
|
let permissions = permissions_holder.1;
|
||||||
state.put(permissions.0.clone());
|
state.put(permissions.inner.clone());
|
||||||
state.put::<PermissionsContainer>(permissions);
|
state.put::<PermissionsContainer>(permissions);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -32,6 +32,8 @@ use deno_runtime::deno_permissions::Permissions;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
|
use deno_runtime::deno_web::BlobStore;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_runtime::WorkerLogLevel;
|
use deno_runtime::WorkerLogLevel;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
@ -449,7 +451,6 @@ pub async fn run(
|
||||||
let current_exe_path = std::env::current_exe().unwrap();
|
let current_exe_path = std::env::current_exe().unwrap();
|
||||||
let current_exe_name =
|
let current_exe_name =
|
||||||
current_exe_path.file_name().unwrap().to_string_lossy();
|
current_exe_path.file_name().unwrap().to_string_lossy();
|
||||||
let maybe_cwd = std::env::current_dir().ok();
|
|
||||||
let deno_dir_provider = Arc::new(DenoDirProvider::new(None));
|
let deno_dir_provider = Arc::new(DenoDirProvider::new(None));
|
||||||
let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider {
|
let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider {
|
||||||
ca_stores: metadata.ca_stores,
|
ca_stores: metadata.ca_stores,
|
||||||
|
@ -660,8 +661,7 @@ pub async fn run(
|
||||||
};
|
};
|
||||||
|
|
||||||
let permissions = {
|
let permissions = {
|
||||||
let mut permissions =
|
let mut permissions = metadata.permissions.to_options();
|
||||||
metadata.permissions.to_options(maybe_cwd.as_deref())?;
|
|
||||||
// if running with an npm vfs, grant read access to it
|
// if running with an npm vfs, grant read access to it
|
||||||
if let Some(vfs_root) = maybe_vfs_root {
|
if let Some(vfs_root) = maybe_vfs_root {
|
||||||
match &mut permissions.allow_read {
|
match &mut permissions.allow_read {
|
||||||
|
@ -669,15 +669,20 @@ pub async fn run(
|
||||||
// do nothing, already granted
|
// do nothing, already granted
|
||||||
}
|
}
|
||||||
Some(vec) => {
|
Some(vec) => {
|
||||||
vec.push(vfs_root);
|
vec.push(vfs_root.to_string_lossy().to_string());
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
permissions.allow_read = Some(vec![vfs_root]);
|
permissions.allow_read =
|
||||||
|
Some(vec![vfs_root.to_string_lossy().to_string()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionsContainer::new(Permissions::from_options(&permissions)?)
|
let desc_parser =
|
||||||
|
Arc::new(RuntimePermissionDescriptorParser::new(fs.clone()));
|
||||||
|
let permissions =
|
||||||
|
Permissions::from_options(desc_parser.as_ref(), &permissions)?;
|
||||||
|
PermissionsContainer::new(desc_parser, permissions)
|
||||||
};
|
};
|
||||||
let feature_checker = Arc::new({
|
let feature_checker = Arc::new({
|
||||||
let mut checker = FeatureChecker::default();
|
let mut checker = FeatureChecker::default();
|
||||||
|
@ -689,21 +694,24 @@ pub async fn run(
|
||||||
}
|
}
|
||||||
checker
|
checker
|
||||||
});
|
});
|
||||||
|
let permission_desc_parser =
|
||||||
|
Arc::new(RuntimePermissionDescriptorParser::new(fs.clone()));
|
||||||
let worker_factory = CliMainWorkerFactory::new(
|
let worker_factory = CliMainWorkerFactory::new(
|
||||||
StorageKeyResolver::empty(),
|
Arc::new(BlobStore::default()),
|
||||||
crate::args::DenoSubcommand::Run(Default::default()),
|
// Code cache is not supported for standalone binary yet.
|
||||||
npm_resolver,
|
None,
|
||||||
node_resolver,
|
feature_checker,
|
||||||
Default::default(),
|
|
||||||
Box::new(module_loader_factory),
|
|
||||||
root_cert_store_provider,
|
|
||||||
fs,
|
fs,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
feature_checker,
|
Box::new(module_loader_factory),
|
||||||
// Code cache is not supported for standalone binary yet.
|
node_resolver,
|
||||||
None,
|
npm_resolver,
|
||||||
|
permission_desc_parser,
|
||||||
|
root_cert_store_provider,
|
||||||
|
StorageKeyResolver::empty(),
|
||||||
|
crate::args::DenoSubcommand::Run(Default::default()),
|
||||||
CliMainWorkerOptions {
|
CliMainWorkerOptions {
|
||||||
argv: metadata.argv,
|
argv: metadata.argv,
|
||||||
log_level: WorkerLogLevel::Info,
|
log_level: WorkerLogLevel::Info,
|
||||||
|
|
|
@ -30,6 +30,7 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::PollEventLoopOptions;
|
use deno_core::PollEventLoopOptions;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -144,14 +145,14 @@ fn create_reporter(
|
||||||
/// Run a single specifier as an executable bench module.
|
/// Run a single specifier as an executable bench module.
|
||||||
async fn bench_specifier(
|
async fn bench_specifier(
|
||||||
worker_factory: Arc<CliMainWorkerFactory>,
|
worker_factory: Arc<CliMainWorkerFactory>,
|
||||||
permissions: Permissions,
|
permissions_container: PermissionsContainer,
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
sender: UnboundedSender<BenchEvent>,
|
sender: UnboundedSender<BenchEvent>,
|
||||||
filter: TestFilter,
|
filter: TestFilter,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
match bench_specifier_inner(
|
match bench_specifier_inner(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
permissions,
|
permissions_container,
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
&sender,
|
&sender,
|
||||||
filter,
|
filter,
|
||||||
|
@ -176,7 +177,7 @@ async fn bench_specifier(
|
||||||
/// Run a single specifier as an executable bench module.
|
/// Run a single specifier as an executable bench module.
|
||||||
async fn bench_specifier_inner(
|
async fn bench_specifier_inner(
|
||||||
worker_factory: Arc<CliMainWorkerFactory>,
|
worker_factory: Arc<CliMainWorkerFactory>,
|
||||||
permissions: Permissions,
|
permissions_container: PermissionsContainer,
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
sender: &UnboundedSender<BenchEvent>,
|
sender: &UnboundedSender<BenchEvent>,
|
||||||
filter: TestFilter,
|
filter: TestFilter,
|
||||||
|
@ -185,7 +186,7 @@ async fn bench_specifier_inner(
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
WorkerExecutionMode::Bench,
|
WorkerExecutionMode::Bench,
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
PermissionsContainer::new(permissions),
|
permissions_container,
|
||||||
vec![ops::bench::deno_bench::init_ops(sender.clone())],
|
vec![ops::bench::deno_bench::init_ops(sender.clone())],
|
||||||
Default::default(),
|
Default::default(),
|
||||||
)
|
)
|
||||||
|
@ -264,6 +265,7 @@ async fn bench_specifier_inner(
|
||||||
async fn bench_specifiers(
|
async fn bench_specifiers(
|
||||||
worker_factory: Arc<CliMainWorkerFactory>,
|
worker_factory: Arc<CliMainWorkerFactory>,
|
||||||
permissions: &Permissions,
|
permissions: &Permissions,
|
||||||
|
permissions_desc_parser: &Arc<RuntimePermissionDescriptorParser>,
|
||||||
specifiers: Vec<ModuleSpecifier>,
|
specifiers: Vec<ModuleSpecifier>,
|
||||||
options: BenchSpecifierOptions,
|
options: BenchSpecifierOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
@ -273,13 +275,16 @@ async fn bench_specifiers(
|
||||||
|
|
||||||
let join_handles = specifiers.into_iter().map(move |specifier| {
|
let join_handles = specifiers.into_iter().map(move |specifier| {
|
||||||
let worker_factory = worker_factory.clone();
|
let worker_factory = worker_factory.clone();
|
||||||
let permissions = permissions.clone();
|
let permissions_container = PermissionsContainer::new(
|
||||||
|
permissions_desc_parser.clone(),
|
||||||
|
permissions.clone(),
|
||||||
|
);
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let options = option_for_handles.clone();
|
let options = option_for_handles.clone();
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
let future = bench_specifier(
|
let future = bench_specifier(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
permissions,
|
permissions_container,
|
||||||
specifier,
|
specifier,
|
||||||
sender,
|
sender,
|
||||||
options.filter,
|
options.filter,
|
||||||
|
@ -410,8 +415,11 @@ pub async fn run_benchmarks(
|
||||||
// Various bench files should not share the same permissions in terms of
|
// Various bench files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permission_desc_parser = factory.permission_desc_parser()?.clone();
|
||||||
Permissions::from_options(&cli_options.permissions_options()?)?;
|
let permissions = Permissions::from_options(
|
||||||
|
permission_desc_parser.as_ref(),
|
||||||
|
&cli_options.permissions_options(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let members_with_bench_options =
|
let members_with_bench_options =
|
||||||
cli_options.resolve_bench_options_for_members(&bench_flags)?;
|
cli_options.resolve_bench_options_for_members(&bench_flags)?;
|
||||||
|
@ -446,6 +454,7 @@ pub async fn run_benchmarks(
|
||||||
bench_specifiers(
|
bench_specifiers(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
&permissions,
|
&permissions,
|
||||||
|
&permission_desc_parser,
|
||||||
specifiers,
|
specifiers,
|
||||||
BenchSpecifierOptions {
|
BenchSpecifierOptions {
|
||||||
filter: TestFilter::from_flag(&workspace_bench_options.filter),
|
filter: TestFilter::from_flag(&workspace_bench_options.filter),
|
||||||
|
@ -519,8 +528,11 @@ pub async fn run_benchmarks_with_watch(
|
||||||
// Various bench files should not share the same permissions in terms of
|
// Various bench files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permission_desc_parser = factory.permission_desc_parser()?.clone();
|
||||||
Permissions::from_options(&cli_options.permissions_options()?)?;
|
let permissions = Permissions::from_options(
|
||||||
|
permission_desc_parser.as_ref(),
|
||||||
|
&cli_options.permissions_options(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let graph = module_graph_creator
|
let graph = module_graph_creator
|
||||||
.create_graph(graph_kind, collected_bench_modules.clone())
|
.create_graph(graph_kind, collected_bench_modules.clone())
|
||||||
|
@ -568,6 +580,7 @@ pub async fn run_benchmarks_with_watch(
|
||||||
bench_specifiers(
|
bench_specifiers(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
&permissions,
|
&permissions,
|
||||||
|
&permission_desc_parser,
|
||||||
specifiers,
|
specifiers,
|
||||||
BenchSpecifierOptions {
|
BenchSpecifierOptions {
|
||||||
filter: TestFilter::from_flag(&workspace_bench_options.filter),
|
filter: TestFilter::from_flag(&workspace_bench_options.filter),
|
||||||
|
|
|
@ -25,7 +25,6 @@ use deno_core::serde_json::json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_runtime::deno_io::Stdio;
|
use deno_runtime::deno_io::Stdio;
|
||||||
use deno_runtime::deno_io::StdioPipe;
|
use deno_runtime::deno_io::StdioPipe;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
|
@ -65,7 +64,8 @@ pub async fn kernel(
|
||||||
resolve_url_or_path("./$deno$jupyter.ts", cli_options.initial_cwd())
|
resolve_url_or_path("./$deno$jupyter.ts", cli_options.initial_cwd())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// TODO(bartlomieju): should we run with all permissions?
|
// TODO(bartlomieju): should we run with all permissions?
|
||||||
let permissions = PermissionsContainer::new(Permissions::allow_all());
|
let permissions =
|
||||||
|
PermissionsContainer::allow_all(factory.permission_desc_parser()?.clone());
|
||||||
let npm_resolver = factory.npm_resolver().await?.clone();
|
let npm_resolver = factory.npm_resolver().await?.clone();
|
||||||
let resolver = factory.resolver().await?.clone();
|
let resolver = factory.resolver().await?.clone();
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
|
|
|
@ -106,7 +106,7 @@ pub async fn cache_top_level_deps(
|
||||||
&roots,
|
&roots,
|
||||||
false,
|
false,
|
||||||
deno_config::deno_json::TsTypeLib::DenoWorker,
|
deno_config::deno_json::TsTypeLib::DenoWorker,
|
||||||
deno_runtime::deno_permissions::PermissionsContainer::allow_all(),
|
crate::file_fetcher::FetchPermissionsOption::AllowAll,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::futures::StreamExt;
|
use deno_core::futures::StreamExt;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::unsync::spawn_blocking;
|
use deno_core::unsync::spawn_blocking;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
|
|
||||||
|
@ -151,9 +149,7 @@ async fn read_eval_file(
|
||||||
let specifier =
|
let specifier =
|
||||||
deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?;
|
deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?;
|
||||||
|
|
||||||
let file = file_fetcher
|
let file = file_fetcher.fetch_bypass_permissions(&specifier).await?;
|
||||||
.fetch(&specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(file.into_text_decoded()?.source)
|
Ok(file.into_text_decoded()?.source)
|
||||||
}
|
}
|
||||||
|
@ -166,9 +162,7 @@ pub async fn run(
|
||||||
let factory = CliFactory::from_flags(flags);
|
let factory = CliFactory::from_flags(flags);
|
||||||
let cli_options = factory.cli_options()?;
|
let cli_options = factory.cli_options()?;
|
||||||
let main_module = cli_options.resolve_main_module()?;
|
let main_module = cli_options.resolve_main_module()?;
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let npm_resolver = factory.npm_resolver().await?.clone();
|
let npm_resolver = factory.npm_resolver().await?.clone();
|
||||||
let resolver = factory.resolver().await?.clone();
|
let resolver = factory.resolver().await?.clone();
|
||||||
let file_fetcher = factory.file_fetcher()?;
|
let file_fetcher = factory.file_fetcher()?;
|
||||||
|
|
|
@ -5,8 +5,6 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use deno_config::deno_json::NodeModulesDirMode;
|
use deno_config::deno_json::NodeModulesDirMode;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
|
|
||||||
use crate::args::EvalFlags;
|
use crate::args::EvalFlags;
|
||||||
|
@ -62,9 +60,7 @@ pub async fn run_script(
|
||||||
|
|
||||||
maybe_npm_install(&factory).await?;
|
maybe_npm_install(&factory).await?;
|
||||||
|
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_main_worker(mode, main_module, permissions)
|
.create_main_worker(mode, main_module, permissions)
|
||||||
|
@ -83,9 +79,7 @@ pub async fn run_from_stdin(flags: Arc<Flags>) -> Result<i32, AnyError> {
|
||||||
|
|
||||||
let file_fetcher = factory.file_fetcher()?;
|
let file_fetcher = factory.file_fetcher()?;
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let mut source = Vec::new();
|
let mut source = Vec::new();
|
||||||
std::io::stdin().read_to_end(&mut source)?;
|
std::io::stdin().read_to_end(&mut source)?;
|
||||||
// Save a fake file into file fetcher cache
|
// Save a fake file into file fetcher cache
|
||||||
|
@ -131,9 +125,7 @@ async fn run_with_watch(
|
||||||
|
|
||||||
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
||||||
|
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let mut worker = factory
|
let mut worker = factory
|
||||||
.create_cli_main_worker_factory()
|
.create_cli_main_worker_factory()
|
||||||
.await?
|
.await?
|
||||||
|
@ -181,9 +173,7 @@ pub async fn eval_command(
|
||||||
source: source_code.into_bytes().into(),
|
source: source_code.into_bytes().into(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_main_worker(WorkerExecutionMode::Eval, main_module, permissions)
|
.create_main_worker(WorkerExecutionMode::Eval, main_module, permissions)
|
||||||
|
|
|
@ -5,7 +5,6 @@ use std::sync::Arc;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::TryFutureExt;
|
use deno_core::futures::TryFutureExt;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
|
|
||||||
use super::run::check_permission_before_script;
|
use super::run::check_permission_before_script;
|
||||||
|
@ -45,9 +44,7 @@ pub async fn serve(
|
||||||
|
|
||||||
maybe_npm_install(&factory).await?;
|
maybe_npm_install(&factory).await?;
|
||||||
|
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
|
|
||||||
do_serve(
|
do_serve(
|
||||||
|
@ -175,9 +172,7 @@ async fn serve_with_watch(
|
||||||
|
|
||||||
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
||||||
|
|
||||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
let permissions = factory.create_permissions_container()?;
|
||||||
&cli_options.permissions_options()?,
|
|
||||||
)?);
|
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
|
|
||||||
do_serve(worker_factory, main_module, permissions, worker_count, hmr)
|
do_serve(worker_factory, main_module, permissions, worker_count, hmr)
|
||||||
|
|
|
@ -56,6 +56,7 @@ use deno_runtime::deno_io::StdioPipe;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||||
use deno_runtime::worker::MainWorker;
|
use deno_runtime::worker::MainWorker;
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
|
@ -595,7 +596,7 @@ fn get_test_reporter(options: &TestSpecifiersOptions) -> Box<dyn TestReporter> {
|
||||||
async fn configure_main_worker(
|
async fn configure_main_worker(
|
||||||
worker_factory: Arc<CliMainWorkerFactory>,
|
worker_factory: Arc<CliMainWorkerFactory>,
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
permissions: Permissions,
|
permissions_container: PermissionsContainer,
|
||||||
worker_sender: TestEventWorkerSender,
|
worker_sender: TestEventWorkerSender,
|
||||||
options: &TestSpecifierOptions,
|
options: &TestSpecifierOptions,
|
||||||
) -> Result<(Option<Box<dyn CoverageCollector>>, MainWorker), anyhow::Error> {
|
) -> Result<(Option<Box<dyn CoverageCollector>>, MainWorker), anyhow::Error> {
|
||||||
|
@ -603,7 +604,7 @@ async fn configure_main_worker(
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
WorkerExecutionMode::Test,
|
WorkerExecutionMode::Test,
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
PermissionsContainer::new(permissions),
|
permissions_container,
|
||||||
vec![ops::testing::deno_test::init_ops(worker_sender.sender)],
|
vec![ops::testing::deno_test::init_ops(worker_sender.sender)],
|
||||||
Stdio {
|
Stdio {
|
||||||
stdin: StdioPipe::inherit(),
|
stdin: StdioPipe::inherit(),
|
||||||
|
@ -646,7 +647,7 @@ async fn configure_main_worker(
|
||||||
/// both.
|
/// both.
|
||||||
pub async fn test_specifier(
|
pub async fn test_specifier(
|
||||||
worker_factory: Arc<CliMainWorkerFactory>,
|
worker_factory: Arc<CliMainWorkerFactory>,
|
||||||
permissions: Permissions,
|
permissions_container: PermissionsContainer,
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
worker_sender: TestEventWorkerSender,
|
worker_sender: TestEventWorkerSender,
|
||||||
fail_fast_tracker: FailFastTracker,
|
fail_fast_tracker: FailFastTracker,
|
||||||
|
@ -658,7 +659,7 @@ pub async fn test_specifier(
|
||||||
let (coverage_collector, mut worker) = configure_main_worker(
|
let (coverage_collector, mut worker) = configure_main_worker(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
&specifier,
|
&specifier,
|
||||||
permissions,
|
permissions_container,
|
||||||
worker_sender,
|
worker_sender,
|
||||||
&options,
|
&options,
|
||||||
)
|
)
|
||||||
|
@ -1327,9 +1328,8 @@ async fn fetch_inline_files(
|
||||||
) -> Result<Vec<File>, AnyError> {
|
) -> Result<Vec<File>, AnyError> {
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
for specifier in specifiers {
|
for specifier in specifiers {
|
||||||
let fetch_permissions = PermissionsContainer::allow_all();
|
|
||||||
let file = file_fetcher
|
let file = file_fetcher
|
||||||
.fetch(&specifier, &fetch_permissions)
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await?
|
.await?
|
||||||
.into_text_decoded()?;
|
.into_text_decoded()?;
|
||||||
|
|
||||||
|
@ -1407,6 +1407,7 @@ static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false);
|
||||||
async fn test_specifiers(
|
async fn test_specifiers(
|
||||||
worker_factory: Arc<CliMainWorkerFactory>,
|
worker_factory: Arc<CliMainWorkerFactory>,
|
||||||
permissions: &Permissions,
|
permissions: &Permissions,
|
||||||
|
permission_desc_parser: &Arc<RuntimePermissionDescriptorParser>,
|
||||||
specifiers: Vec<ModuleSpecifier>,
|
specifiers: Vec<ModuleSpecifier>,
|
||||||
options: TestSpecifiersOptions,
|
options: TestSpecifiersOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
@ -1434,14 +1435,17 @@ async fn test_specifiers(
|
||||||
|
|
||||||
let join_handles = specifiers.into_iter().map(move |specifier| {
|
let join_handles = specifiers.into_iter().map(move |specifier| {
|
||||||
let worker_factory = worker_factory.clone();
|
let worker_factory = worker_factory.clone();
|
||||||
let permissions = permissions.clone();
|
let permissions_container = PermissionsContainer::new(
|
||||||
|
permission_desc_parser.clone(),
|
||||||
|
permissions.clone(),
|
||||||
|
);
|
||||||
let worker_sender = test_event_sender_factory.worker();
|
let worker_sender = test_event_sender_factory.worker();
|
||||||
let fail_fast_tracker = fail_fast_tracker.clone();
|
let fail_fast_tracker = fail_fast_tracker.clone();
|
||||||
let specifier_options = options.specifier.clone();
|
let specifier_options = options.specifier.clone();
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
create_and_run_current_thread(test_specifier(
|
create_and_run_current_thread(test_specifier(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
permissions,
|
permissions_container,
|
||||||
specifier,
|
specifier,
|
||||||
worker_sender,
|
worker_sender,
|
||||||
fail_fast_tracker,
|
fail_fast_tracker,
|
||||||
|
@ -1739,9 +1743,7 @@ async fn fetch_specifiers_with_test_mode(
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for (specifier, mode) in &mut specifiers_with_mode {
|
for (specifier, mode) in &mut specifiers_with_mode {
|
||||||
let file = file_fetcher
|
let file = file_fetcher.fetch_bypass_permissions(specifier).await?;
|
||||||
.fetch(specifier, &PermissionsContainer::allow_all())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let (media_type, _) = file.resolve_media_type_and_charset();
|
let (media_type, _) = file.resolve_media_type_and_charset();
|
||||||
if matches!(media_type, MediaType::Unknown | MediaType::Dts) {
|
if matches!(media_type, MediaType::Unknown | MediaType::Dts) {
|
||||||
|
@ -1764,8 +1766,11 @@ pub async fn run_tests(
|
||||||
// Various test files should not share the same permissions in terms of
|
// Various test files should not share the same permissions in terms of
|
||||||
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
// `PermissionsContainer` - otherwise granting/revoking permissions in one
|
||||||
// file would have impact on other files, which is undesirable.
|
// file would have impact on other files, which is undesirable.
|
||||||
let permissions =
|
let permission_desc_parser = factory.permission_desc_parser()?;
|
||||||
Permissions::from_options(&cli_options.permissions_options()?)?;
|
let permissions = Permissions::from_options(
|
||||||
|
permission_desc_parser.as_ref(),
|
||||||
|
&cli_options.permissions_options(),
|
||||||
|
)?;
|
||||||
let log_level = cli_options.log_level();
|
let log_level = cli_options.log_level();
|
||||||
|
|
||||||
let members_with_test_options =
|
let members_with_test_options =
|
||||||
|
@ -1802,6 +1807,7 @@ pub async fn run_tests(
|
||||||
test_specifiers(
|
test_specifiers(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
&permissions,
|
&permissions,
|
||||||
|
permission_desc_parser,
|
||||||
specifiers_with_mode
|
specifiers_with_mode
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(s, m)| match m {
|
.filter_map(|(s, m)| match m {
|
||||||
|
@ -1914,8 +1920,11 @@ pub async fn run_tests_with_watch(
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let permissions =
|
let permission_desc_parser = factory.permission_desc_parser()?;
|
||||||
Permissions::from_options(&cli_options.permissions_options()?)?;
|
let permissions = Permissions::from_options(
|
||||||
|
permission_desc_parser.as_ref(),
|
||||||
|
&cli_options.permissions_options(),
|
||||||
|
)?;
|
||||||
let graph = module_graph_creator
|
let graph = module_graph_creator
|
||||||
.create_graph(graph_kind, test_modules)
|
.create_graph(graph_kind, test_modules)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -1969,6 +1978,7 @@ pub async fn run_tests_with_watch(
|
||||||
test_specifiers(
|
test_specifiers(
|
||||||
worker_factory,
|
worker_factory,
|
||||||
&permissions,
|
&permissions,
|
||||||
|
permission_desc_parser,
|
||||||
specifiers_with_mode
|
specifiers_with_mode
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(s, m)| match m {
|
.filter_map(|(s, m)| match m {
|
||||||
|
|
|
@ -30,6 +30,7 @@ use deno_runtime::deno_web::BlobStore;
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
|
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
use deno_runtime::web_worker::WebWorker;
|
use deno_runtime::web_worker::WebWorker;
|
||||||
use deno_runtime::web_worker::WebWorkerOptions;
|
use deno_runtime::web_worker::WebWorkerOptions;
|
||||||
use deno_runtime::worker::MainWorker;
|
use deno_runtime::worker::MainWorker;
|
||||||
|
@ -121,23 +122,24 @@ pub struct CliMainWorkerOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SharedWorkerState {
|
struct SharedWorkerState {
|
||||||
options: CliMainWorkerOptions,
|
|
||||||
subcommand: DenoSubcommand,
|
|
||||||
storage_key_resolver: StorageKeyResolver,
|
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
|
||||||
node_resolver: Arc<NodeResolver>,
|
|
||||||
blob_store: Arc<BlobStore>,
|
blob_store: Arc<BlobStore>,
|
||||||
broadcast_channel: InMemoryBroadcastChannel,
|
broadcast_channel: InMemoryBroadcastChannel,
|
||||||
shared_array_buffer_store: SharedArrayBufferStore,
|
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
||||||
compiled_wasm_module_store: CompiledWasmModuleStore,
|
compiled_wasm_module_store: CompiledWasmModuleStore,
|
||||||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
feature_checker: Arc<FeatureChecker>,
|
||||||
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
|
maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
|
||||||
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
feature_checker: Arc<FeatureChecker>,
|
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||||
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
|
permission_desc_parser: Arc<RuntimePermissionDescriptorParser>,
|
||||||
|
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||||
|
shared_array_buffer_store: SharedArrayBufferStore,
|
||||||
|
storage_key_resolver: StorageKeyResolver,
|
||||||
|
options: CliMainWorkerOptions,
|
||||||
|
subcommand: DenoSubcommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedWorkerState {
|
impl SharedWorkerState {
|
||||||
|
@ -418,40 +420,42 @@ pub struct CliMainWorkerFactory {
|
||||||
impl CliMainWorkerFactory {
|
impl CliMainWorkerFactory {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
storage_key_resolver: StorageKeyResolver,
|
|
||||||
subcommand: DenoSubcommand,
|
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
|
||||||
node_resolver: Arc<NodeResolver>,
|
|
||||||
blob_store: Arc<BlobStore>,
|
blob_store: Arc<BlobStore>,
|
||||||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
||||||
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
feature_checker: Arc<FeatureChecker>,
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
|
maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
|
||||||
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
feature_checker: Arc<FeatureChecker>,
|
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||||
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
|
permission_parser: Arc<RuntimePermissionDescriptorParser>,
|
||||||
|
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||||
|
storage_key_resolver: StorageKeyResolver,
|
||||||
|
subcommand: DenoSubcommand,
|
||||||
options: CliMainWorkerOptions,
|
options: CliMainWorkerOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
shared: Arc::new(SharedWorkerState {
|
shared: Arc::new(SharedWorkerState {
|
||||||
options,
|
|
||||||
subcommand,
|
|
||||||
storage_key_resolver,
|
|
||||||
npm_resolver,
|
|
||||||
node_resolver,
|
|
||||||
blob_store,
|
blob_store,
|
||||||
broadcast_channel: Default::default(),
|
broadcast_channel: Default::default(),
|
||||||
shared_array_buffer_store: Default::default(),
|
code_cache,
|
||||||
compiled_wasm_module_store: Default::default(),
|
compiled_wasm_module_store: Default::default(),
|
||||||
module_loader_factory,
|
feature_checker,
|
||||||
root_cert_store_provider,
|
|
||||||
fs,
|
fs,
|
||||||
maybe_file_watcher_communicator,
|
maybe_file_watcher_communicator,
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
maybe_lockfile,
|
maybe_lockfile,
|
||||||
feature_checker,
|
module_loader_factory,
|
||||||
code_cache,
|
node_resolver,
|
||||||
|
npm_resolver,
|
||||||
|
permission_desc_parser: permission_parser,
|
||||||
|
root_cert_store_provider,
|
||||||
|
shared_array_buffer_store: Default::default(),
|
||||||
|
storage_key_resolver,
|
||||||
|
options,
|
||||||
|
subcommand,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,9 +529,13 @@ impl CliMainWorkerFactory {
|
||||||
(main_module, false)
|
(main_module, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let ModuleLoaderAndSourceMapGetter { module_loader } = shared
|
let ModuleLoaderAndSourceMapGetter { module_loader } =
|
||||||
.module_loader_factory
|
shared.module_loader_factory.create_for_main(
|
||||||
.create_for_main(PermissionsContainer::allow_all(), permissions.clone());
|
PermissionsContainer::allow_all(
|
||||||
|
self.shared.permission_desc_parser.clone(),
|
||||||
|
),
|
||||||
|
permissions.clone(),
|
||||||
|
);
|
||||||
let maybe_inspector_server = shared.maybe_inspector_server.clone();
|
let maybe_inspector_server = shared.maybe_inspector_server.clone();
|
||||||
|
|
||||||
let create_web_worker_cb =
|
let create_web_worker_cb =
|
||||||
|
@ -619,6 +627,7 @@ impl CliMainWorkerFactory {
|
||||||
),
|
),
|
||||||
stdio,
|
stdio,
|
||||||
feature_checker,
|
feature_checker,
|
||||||
|
permission_desc_parser: shared.permission_desc_parser.clone(),
|
||||||
skip_op_registration: shared.options.skip_op_registration,
|
skip_op_registration: shared.options.skip_op_registration,
|
||||||
v8_code_cache: shared.code_cache.clone(),
|
v8_code_cache: shared.code_cache.clone(),
|
||||||
};
|
};
|
||||||
|
@ -809,6 +818,7 @@ fn create_web_worker_callback(
|
||||||
stdio: stdio.clone(),
|
stdio: stdio.clone(),
|
||||||
cache_storage_dir,
|
cache_storage_dir,
|
||||||
feature_checker,
|
feature_checker,
|
||||||
|
permission_desc_parser: shared.permission_desc_parser.clone(),
|
||||||
strace_ops: shared.options.strace_ops.clone(),
|
strace_ops: shared.options.strace_ops.clone(),
|
||||||
close_on_idle: args.close_on_idle,
|
close_on_idle: args.close_on_idle,
|
||||||
maybe_worker_metadata: args.maybe_worker_metadata,
|
maybe_worker_metadata: args.maybe_worker_metadata,
|
||||||
|
@ -830,13 +840,16 @@ fn create_web_worker_callback(
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use deno_core::resolve_path;
|
use deno_core::resolve_path;
|
||||||
|
use deno_fs::RealFs;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
|
|
||||||
fn create_test_worker() -> MainWorker {
|
fn create_test_worker() -> MainWorker {
|
||||||
let main_module =
|
let main_module =
|
||||||
resolve_path("./hello.js", &std::env::current_dir().unwrap()).unwrap();
|
resolve_path("./hello.js", &std::env::current_dir().unwrap()).unwrap();
|
||||||
let permissions =
|
let permissions = PermissionsContainer::new(
|
||||||
PermissionsContainer::new(Permissions::none_without_prompt());
|
Arc::new(RuntimePermissionDescriptorParser::new(Arc::new(RealFs))),
|
||||||
|
Permissions::none_without_prompt(),
|
||||||
|
);
|
||||||
|
|
||||||
let options = WorkerOptions {
|
let options = WorkerOptions {
|
||||||
startup_snapshot: crate::js::deno_isolate_init(),
|
startup_snapshot: crate::js::deno_isolate_init(),
|
||||||
|
|
|
@ -299,10 +299,15 @@ impl Drop for ResourceToBodyAdapter {
|
||||||
pub trait FetchPermissions {
|
pub trait FetchPermissions {
|
||||||
fn check_net_url(
|
fn check_net_url(
|
||||||
&mut self,
|
&mut self,
|
||||||
_url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), AnyError>;
|
||||||
fn check_read(&mut self, _p: &Path, api_name: &str) -> Result<(), AnyError>;
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_read<'a>(
|
||||||
|
&mut self,
|
||||||
|
p: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchPermissions for deno_permissions::PermissionsContainer {
|
impl FetchPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -316,12 +321,16 @@ impl FetchPermissions for deno_permissions::PermissionsContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read(
|
fn check_read<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_read_path(
|
||||||
|
self,
|
||||||
|
path,
|
||||||
|
Some(api_name),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,7 +368,11 @@ where
|
||||||
type_error("NetworkError when attempting to fetch resource")
|
type_error("NetworkError when attempting to fetch resource")
|
||||||
})?;
|
})?;
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_read(&path, "fetch()")?;
|
let path = permissions.check_read(&path, "fetch()")?;
|
||||||
|
let url = match path {
|
||||||
|
Cow::Owned(path) => Url::from_file_path(path).unwrap(),
|
||||||
|
Cow::Borrowed(_) => url,
|
||||||
|
};
|
||||||
|
|
||||||
if method != Method::GET {
|
if method != Method::GET {
|
||||||
return Err(type_error(format!(
|
return Err(type_error(format!(
|
||||||
|
|
|
@ -287,7 +287,7 @@ where
|
||||||
{
|
{
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let symbol = PtrSymbol::new(pointer, &def)?;
|
let symbol = PtrSymbol::new(pointer, &def)?;
|
||||||
|
@ -384,7 +384,7 @@ where
|
||||||
{
|
{
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let symbol = PtrSymbol::new(pointer, &def)?;
|
let symbol = PtrSymbol::new(pointer, &def)?;
|
||||||
|
|
|
@ -557,7 +557,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
let thread_id: u32 = LOCAL_THREAD_ID.with(|s| {
|
let thread_id: u32 = LOCAL_THREAD_ID.with(|s| {
|
||||||
let value = *s.borrow();
|
let value = *s.borrow();
|
||||||
|
|
|
@ -19,7 +19,6 @@ use serde_value::ValueDeserializer;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct DynamicLibraryResource {
|
pub struct DynamicLibraryResource {
|
||||||
|
@ -121,15 +120,13 @@ pub fn op_ffi_load<'scope, FP>(
|
||||||
where
|
where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = args.path;
|
|
||||||
|
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(Some(&PathBuf::from(&path)))?;
|
let path = permissions.check_partial_with_path(&args.path)?;
|
||||||
|
|
||||||
let lib = Library::open(&path).map_err(|e| {
|
let lib = Library::open(&path).map_err(|e| {
|
||||||
dlopen2::Error::OpeningLibraryError(std::io::Error::new(
|
dlopen2::Error::OpeningLibraryError(std::io::Error::new(
|
||||||
std::io::ErrorKind::Other,
|
std::io::ErrorKind::Other,
|
||||||
format_error(e, path),
|
format_error(e, &path),
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let mut resource = DynamicLibraryResource {
|
let mut resource = DynamicLibraryResource {
|
||||||
|
@ -290,7 +287,10 @@ fn sync_fn_impl<'s>(
|
||||||
|
|
||||||
// `path` is only used on Windows.
|
// `path` is only used on Windows.
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub(crate) fn format_error(e: dlopen2::Error, path: String) -> String {
|
pub(crate) fn format_error(
|
||||||
|
e: dlopen2::Error,
|
||||||
|
path: &std::path::Path,
|
||||||
|
) -> String {
|
||||||
match e {
|
match e {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
// This calls FormatMessageW with library path
|
// This calls FormatMessageW with library path
|
||||||
|
@ -300,7 +300,6 @@ pub(crate) fn format_error(e: dlopen2::Error, path: String) -> String {
|
||||||
//
|
//
|
||||||
// https://github.com/denoland/deno/issues/11632
|
// https://github.com/denoland/deno/issues/11632
|
||||||
dlopen2::Error::OpeningLibraryError(e) => {
|
dlopen2::Error::OpeningLibraryError(e) => {
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::os::windows::ffi::OsStrExt;
|
use std::os::windows::ffi::OsStrExt;
|
||||||
use winapi::shared::minwindef::DWORD;
|
use winapi::shared::minwindef::DWORD;
|
||||||
use winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER;
|
use winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
@ -324,7 +323,8 @@ pub(crate) fn format_error(e: dlopen2::Error, path: String) -> String {
|
||||||
|
|
||||||
let mut buf = vec![0; 500];
|
let mut buf = vec![0; 500];
|
||||||
|
|
||||||
let path = OsStr::new(&path)
|
let path = path
|
||||||
|
.as_os_str()
|
||||||
.encode_wide()
|
.encode_wide()
|
||||||
.chain(Some(0))
|
.chain(Some(0))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -384,7 +384,7 @@ mod tests {
|
||||||
std::io::Error::from_raw_os_error(0x000000C1),
|
std::io::Error::from_raw_os_error(0x000000C1),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format_error(err, "foo.dll".to_string()),
|
format_error(err, &std::path::PathBuf::from("foo.dll")),
|
||||||
"foo.dll is not a valid Win32 application.\r\n".to_string(),
|
"foo.dll is not a valid Win32 application.\r\n".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use deno_core::error::AnyError;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::os::raw::c_short;
|
use std::os::raw::c_short;
|
||||||
use std::path::Path;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
mod call;
|
mod call;
|
||||||
mod callback;
|
mod callback;
|
||||||
|
@ -41,13 +41,28 @@ const _: () = {
|
||||||
pub const UNSTABLE_FEATURE_NAME: &str = "ffi";
|
pub const UNSTABLE_FEATURE_NAME: &str = "ffi";
|
||||||
|
|
||||||
pub trait FfiPermissions {
|
pub trait FfiPermissions {
|
||||||
fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError>;
|
fn check_partial_no_path(&mut self) -> Result<(), AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_partial_with_path(
|
||||||
|
&mut self,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<PathBuf, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FfiPermissions for deno_permissions::PermissionsContainer {
|
impl FfiPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
fn check_partial_no_path(&mut self) -> Result<(), AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_ffi_partial(self, path)
|
deno_permissions::PermissionsContainer::check_ffi_partial_no_path(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_partial_with_path(
|
||||||
|
&mut self,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<PathBuf, AnyError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_ffi_partial_with_path(
|
||||||
|
self, path,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
Ok(ptr_number as *mut c_void)
|
Ok(ptr_number as *mut c_void)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
Ok(a == b)
|
Ok(a == b)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
Ok(buf as *mut c_void)
|
Ok(buf as *mut c_void)
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
let Some(buf) = buf.get_backing_store() else {
|
let Some(buf) = buf.get_backing_store() else {
|
||||||
return Ok(0 as _);
|
return Ok(0 as _);
|
||||||
|
@ -85,7 +85,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid pointer to offset, pointer is null"));
|
return Err(type_error("Invalid pointer to offset, pointer is null"));
|
||||||
|
@ -115,7 +115,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
Ok(ptr as usize)
|
Ok(ptr as usize)
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid ArrayBuffer pointer, pointer is null"));
|
return Err(type_error("Invalid ArrayBuffer pointer, pointer is null"));
|
||||||
|
@ -164,7 +164,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if src.is_null() {
|
if src.is_null() {
|
||||||
Err(type_error("Invalid ArrayBuffer pointer, pointer is null"))
|
Err(type_error("Invalid ArrayBuffer pointer, pointer is null"))
|
||||||
|
@ -195,7 +195,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid CString pointer, pointer is null"));
|
return Err(type_error("Invalid CString pointer, pointer is null"));
|
||||||
|
@ -221,7 +221,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid bool pointer, pointer is null"));
|
return Err(type_error("Invalid bool pointer, pointer is null"));
|
||||||
|
@ -241,7 +241,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid u8 pointer, pointer is null"));
|
return Err(type_error("Invalid u8 pointer, pointer is null"));
|
||||||
|
@ -263,7 +263,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid i8 pointer, pointer is null"));
|
return Err(type_error("Invalid i8 pointer, pointer is null"));
|
||||||
|
@ -285,7 +285,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid u16 pointer, pointer is null"));
|
return Err(type_error("Invalid u16 pointer, pointer is null"));
|
||||||
|
@ -307,7 +307,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid i16 pointer, pointer is null"));
|
return Err(type_error("Invalid i16 pointer, pointer is null"));
|
||||||
|
@ -329,7 +329,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid u32 pointer, pointer is null"));
|
return Err(type_error("Invalid u32 pointer, pointer is null"));
|
||||||
|
@ -349,7 +349,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid i32 pointer, pointer is null"));
|
return Err(type_error("Invalid i32 pointer, pointer is null"));
|
||||||
|
@ -372,7 +372,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid u64 pointer, pointer is null"));
|
return Err(type_error("Invalid u64 pointer, pointer is null"));
|
||||||
|
@ -398,7 +398,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid i64 pointer, pointer is null"));
|
return Err(type_error("Invalid i64 pointer, pointer is null"));
|
||||||
|
@ -421,7 +421,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid f32 pointer, pointer is null"));
|
return Err(type_error("Invalid f32 pointer, pointer is null"));
|
||||||
|
@ -441,7 +441,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid f64 pointer, pointer is null"));
|
return Err(type_error("Invalid f64 pointer, pointer is null"));
|
||||||
|
@ -461,7 +461,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions.check_partial(None)?;
|
permissions.check_partial_no_path()?;
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(type_error("Invalid pointer pointer, pointer is null"));
|
return Err(type_error("Invalid pointer pointer, pointer is null"));
|
||||||
|
|
|
@ -24,6 +24,7 @@ use deno_core::error::AnyError;
|
||||||
use deno_io::fs::FsError;
|
use deno_io::fs::FsError;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub trait FsPermissions {
|
pub trait FsPermissions {
|
||||||
fn check_open<'a>(
|
fn check_open<'a>(
|
||||||
|
@ -34,8 +35,18 @@ pub trait FsPermissions {
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<std::borrow::Cow<'a, Path>, FsError>;
|
) -> Result<std::borrow::Cow<'a, Path>, FsError>;
|
||||||
fn check_read(&mut self, path: &Path, api_name: &str)
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
-> Result<(), AnyError>;
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
path: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_read_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError>;
|
||||||
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
||||||
fn check_read_blind(
|
fn check_read_blind(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -43,16 +54,24 @@ pub trait FsPermissions {
|
||||||
display: &str,
|
display: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write_partial(
|
fn check_write_partial(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
||||||
fn check_write_blind(
|
fn check_write_blind(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -96,25 +115,44 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
|
||||||
// If somehow read or write aren't specified, use read
|
// If somehow read or write aren't specified, use read
|
||||||
let read = read || !write;
|
let read = read || !write;
|
||||||
|
let mut path: Cow<'a, Path> = Cow::Borrowed(path);
|
||||||
if read {
|
if read {
|
||||||
FsPermissions::check_read(self, path, api_name)
|
let resolved_path = FsPermissions::check_read_path(self, &path, api_name)
|
||||||
.map_err(|_| FsError::NotCapable("read"))?;
|
.map_err(|_| FsError::NotCapable("read"))?;
|
||||||
|
if let Cow::Owned(resolved_path) = resolved_path {
|
||||||
|
path = Cow::Owned(resolved_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if write {
|
if write {
|
||||||
FsPermissions::check_write(self, path, api_name)
|
let resolved_path =
|
||||||
.map_err(|_| FsError::NotCapable("write"))?;
|
FsPermissions::check_write_path(self, &path, api_name)
|
||||||
|
.map_err(|_| FsError::NotCapable("write"))?;
|
||||||
|
if let Cow::Owned(resolved_path) = resolved_path {
|
||||||
|
path = Cow::Owned(resolved_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(Cow::Borrowed(path))
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_read_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_read_path(
|
||||||
|
self,
|
||||||
|
path,
|
||||||
|
Some(api_name),
|
||||||
|
)
|
||||||
|
}
|
||||||
fn check_read_blind(
|
fn check_read_blind(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
@ -128,17 +166,27 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_write_path(
|
||||||
|
self, path, api_name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn check_write_partial(
|
fn check_write_partial(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_partial(
|
deno_permissions::PermissionsContainer::check_write_partial(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
|
|
302
ext/fs/ops.rs
302
ext/fs/ops.rs
|
@ -5,6 +5,7 @@ use std::io;
|
||||||
use std::io::SeekFrom;
|
use std::io::SeekFrom;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::path::StripPrefixError;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
|
@ -105,8 +106,9 @@ pub fn op_fs_chdir<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let d = PathBuf::from(&directory);
|
let d = state
|
||||||
state.borrow_mut::<P>().check_read(&d, "Deno.chdir()")?;
|
.borrow_mut::<P>()
|
||||||
|
.check_read(directory, "Deno.chdir()")?;
|
||||||
state
|
state
|
||||||
.borrow::<FileSystemRc>()
|
.borrow::<FileSystemRc>()
|
||||||
.chdir(&d)
|
.chdir(&d)
|
||||||
|
@ -188,11 +190,9 @@ pub fn op_fs_mkdir_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
|
||||||
|
|
||||||
let mode = mode.unwrap_or(0o777) & 0o777;
|
let mode = mode.unwrap_or(0o777) & 0o777;
|
||||||
|
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.mkdirSync()")?;
|
.check_write(&path, "Deno.mkdirSync()")?;
|
||||||
|
|
||||||
|
@ -213,14 +213,12 @@ pub async fn op_fs_mkdir_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
|
||||||
|
|
||||||
let mode = mode.unwrap_or(0o777) & 0o777;
|
let mode = mode.unwrap_or(0o777) & 0o777;
|
||||||
|
|
||||||
let fs = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state.borrow_mut::<P>().check_write(&path, "Deno.mkdir()")?;
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.mkdir()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.mkdir_async(path.clone(), recursive, mode)
|
fs.mkdir_async(path.clone(), recursive, mode)
|
||||||
|
@ -239,8 +237,7 @@ pub fn op_fs_chmod_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.chmodSync()")?;
|
.check_write(&path, "Deno.chmodSync()")?;
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
@ -257,11 +254,10 @@ pub async fn op_fs_chmod_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state.borrow_mut::<P>().check_write(&path, "Deno.chmod()")?;
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.chmod()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
fs.chmod_async(path.clone(), mode)
|
fs.chmod_async(path.clone(), mode)
|
||||||
.await
|
.await
|
||||||
|
@ -279,8 +275,7 @@ pub fn op_fs_chown_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.chownSync()")?;
|
.check_write(&path, "Deno.chownSync()")?;
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
@ -299,11 +294,10 @@ pub async fn op_fs_chown_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state.borrow_mut::<P>().check_write(&path, "Deno.chown()")?;
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.chown()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
fs.chown_async(path.clone(), uid, gid)
|
fs.chown_async(path.clone(), uid, gid)
|
||||||
.await
|
.await
|
||||||
|
@ -320,11 +314,9 @@ pub fn op_fs_remove_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
|
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.removeSync()")?;
|
.check_write(path, "Deno.removeSync()")?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.remove_sync(&path, recursive)
|
fs.remove_sync(&path, recursive)
|
||||||
|
@ -342,21 +334,19 @@ pub async fn op_fs_remove_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
if recursive {
|
let path = if recursive {
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.remove()")?;
|
.check_write(&path, "Deno.remove()")?
|
||||||
} else {
|
} else {
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_partial(&path, "Deno.remove()")?;
|
.check_write_partial(&path, "Deno.remove()")?
|
||||||
}
|
};
|
||||||
|
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.remove_async(path.clone(), recursive)
|
fs.remove_async(path.clone(), recursive)
|
||||||
|
@ -375,12 +365,9 @@ pub fn op_fs_copy_file_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let from = PathBuf::from(from);
|
|
||||||
let to = PathBuf::from(to);
|
|
||||||
|
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&from, "Deno.copyFileSync()")?;
|
let from = permissions.check_read(from, "Deno.copyFileSync()")?;
|
||||||
permissions.check_write(&to, "Deno.copyFileSync()")?;
|
let to = permissions.check_write(to, "Deno.copyFileSync()")?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.copy_file_sync(&from, &to)
|
fs.copy_file_sync(&from, &to)
|
||||||
|
@ -398,15 +385,12 @@ pub async fn op_fs_copy_file_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let from = PathBuf::from(from);
|
let (fs, from, to) = {
|
||||||
let to = PathBuf::from(to);
|
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&from, "Deno.copyFile()")?;
|
let from = permissions.check_read(&from, "Deno.copyFile()")?;
|
||||||
permissions.check_write(&to, "Deno.copyFile()")?;
|
let to = permissions.check_write(&to, "Deno.copyFile()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), from, to)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.copy_file_async(from.clone(), to.clone())
|
fs.copy_file_async(from.clone(), to.clone())
|
||||||
|
@ -425,8 +409,7 @@ pub fn op_fs_stat_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.statSync()")?;
|
.check_read(&path, "Deno.statSync()")?;
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
@ -445,12 +428,11 @@ pub async fn op_fs_stat_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&path, "Deno.stat()")?;
|
let path = permissions.check_read(&path, "Deno.stat()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
let stat = fs
|
let stat = fs
|
||||||
.stat_async(path.clone())
|
.stat_async(path.clone())
|
||||||
|
@ -468,8 +450,7 @@ pub fn op_fs_lstat_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.lstatSync()")?;
|
.check_read(&path, "Deno.lstatSync()")?;
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
@ -488,12 +469,11 @@ pub async fn op_fs_lstat_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&path, "Deno.lstat()")?;
|
let path = permissions.check_read(&path, "Deno.lstat()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
let stat = fs
|
let stat = fs
|
||||||
.lstat_async(path.clone())
|
.lstat_async(path.clone())
|
||||||
|
@ -511,11 +491,9 @@ pub fn op_fs_realpath_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&path, "Deno.realPathSync()")?;
|
let path = permissions.check_read(&path, "Deno.realPathSync()")?;
|
||||||
if path.is_relative() {
|
if path.is_relative() {
|
||||||
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")?;
|
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")?;
|
||||||
}
|
}
|
||||||
|
@ -536,18 +514,16 @@ pub async fn op_fs_realpath_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs;
|
|
||||||
{
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&path, "Deno.realPath()")?;
|
let path = permissions.check_read(&path, "Deno.realPath()")?;
|
||||||
if path.is_relative() {
|
if path.is_relative() {
|
||||||
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")?;
|
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")?;
|
||||||
}
|
}
|
||||||
}
|
(fs, path)
|
||||||
|
};
|
||||||
let resolved_path = fs
|
let resolved_path = fs
|
||||||
.realpath_async(path.clone())
|
.realpath_async(path.clone())
|
||||||
.await
|
.await
|
||||||
|
@ -566,9 +542,7 @@ pub fn op_fs_read_dir_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
|
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readDirSync()")?;
|
.check_read(&path, "Deno.readDirSync()")?;
|
||||||
|
|
||||||
|
@ -587,14 +561,12 @@ pub async fn op_fs_read_dir_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readDir()")?;
|
.check_read(&path, "Deno.readDir()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
let entries = fs
|
let entries = fs
|
||||||
|
@ -614,13 +586,10 @@ pub fn op_fs_rename_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let oldpath = PathBuf::from(oldpath);
|
|
||||||
let newpath = PathBuf::from(newpath);
|
|
||||||
|
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&oldpath, "Deno.renameSync()")?;
|
let _ = permissions.check_read(&oldpath, "Deno.renameSync()")?;
|
||||||
permissions.check_write(&oldpath, "Deno.renameSync()")?;
|
let oldpath = permissions.check_write(&oldpath, "Deno.renameSync()")?;
|
||||||
permissions.check_write(&newpath, "Deno.renameSync()")?;
|
let newpath = permissions.check_write(&newpath, "Deno.renameSync()")?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.rename_sync(&oldpath, &newpath)
|
fs.rename_sync(&oldpath, &newpath)
|
||||||
|
@ -638,16 +607,13 @@ pub async fn op_fs_rename_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let oldpath = PathBuf::from(oldpath);
|
let (fs, oldpath, newpath) = {
|
||||||
let newpath = PathBuf::from(newpath);
|
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&oldpath, "Deno.rename()")?;
|
_ = permissions.check_read(&oldpath, "Deno.rename()")?;
|
||||||
permissions.check_write(&oldpath, "Deno.rename()")?;
|
let oldpath = permissions.check_write(&oldpath, "Deno.rename()")?;
|
||||||
permissions.check_write(&newpath, "Deno.rename()")?;
|
let newpath = permissions.check_write(&newpath, "Deno.rename()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.rename_async(oldpath.clone(), newpath.clone())
|
fs.rename_async(oldpath.clone(), newpath.clone())
|
||||||
|
@ -666,14 +632,11 @@ pub fn op_fs_link_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let oldpath = PathBuf::from(oldpath);
|
|
||||||
let newpath = PathBuf::from(newpath);
|
|
||||||
|
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&oldpath, "Deno.linkSync()")?;
|
_ = permissions.check_read(oldpath, "Deno.linkSync()")?;
|
||||||
permissions.check_write(&oldpath, "Deno.linkSync()")?;
|
let oldpath = permissions.check_write(oldpath, "Deno.linkSync()")?;
|
||||||
permissions.check_read(&newpath, "Deno.linkSync()")?;
|
_ = permissions.check_read(newpath, "Deno.linkSync()")?;
|
||||||
permissions.check_write(&newpath, "Deno.linkSync()")?;
|
let newpath = permissions.check_write(newpath, "Deno.linkSync()")?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.link_sync(&oldpath, &newpath)
|
fs.link_sync(&oldpath, &newpath)
|
||||||
|
@ -691,17 +654,14 @@ pub async fn op_fs_link_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let oldpath = PathBuf::from(&oldpath);
|
let (fs, oldpath, newpath) = {
|
||||||
let newpath = PathBuf::from(&newpath);
|
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_read(&oldpath, "Deno.link()")?;
|
_ = permissions.check_read(&oldpath, "Deno.link()")?;
|
||||||
permissions.check_write(&oldpath, "Deno.link()")?;
|
let oldpath = permissions.check_write(&oldpath, "Deno.link()")?;
|
||||||
permissions.check_read(&newpath, "Deno.link()")?;
|
_ = permissions.check_read(&newpath, "Deno.link()")?;
|
||||||
permissions.check_write(&newpath, "Deno.link()")?;
|
let newpath = permissions.check_write(&newpath, "Deno.link()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.link_async(oldpath.clone(), newpath.clone())
|
fs.link_async(oldpath.clone(), newpath.clone())
|
||||||
|
@ -772,9 +732,7 @@ pub fn op_fs_read_link_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
|
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readLink()")?;
|
.check_read(&path, "Deno.readLink()")?;
|
||||||
|
|
||||||
|
@ -794,14 +752,12 @@ pub async fn op_fs_read_link_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readLink()")?;
|
.check_read(&path, "Deno.readLink()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = fs
|
let target = fs
|
||||||
|
@ -821,11 +777,9 @@ pub fn op_fs_truncate_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
|
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.truncateSync()")?;
|
.check_write(path, "Deno.truncateSync()")?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.truncate_sync(&path, len)
|
fs.truncate_sync(&path, len)
|
||||||
|
@ -843,14 +797,12 @@ pub async fn op_fs_truncate_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.truncate()")?;
|
.check_write(&path, "Deno.truncate()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.truncate_async(path.clone(), len)
|
fs.truncate_async(path.clone(), len)
|
||||||
|
@ -872,9 +824,7 @@ pub fn op_fs_utime_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state.borrow_mut::<P>().check_write(path, "Deno.utime()")?;
|
||||||
|
|
||||||
state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
||||||
|
@ -895,12 +845,10 @@ pub async fn op_fs_utime_async<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.utime_async(
|
fs.utime_async(
|
||||||
|
@ -920,15 +868,18 @@ where
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_fs_make_temp_dir_sync<P>(
|
pub fn op_fs_make_temp_dir_sync<P>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] dir: Option<String>,
|
#[string] dir_arg: Option<String>,
|
||||||
#[string] prefix: Option<String>,
|
#[string] prefix: Option<String>,
|
||||||
#[string] suffix: Option<String>,
|
#[string] suffix: Option<String>,
|
||||||
) -> Result<String, AnyError>
|
) -> Result<String, AnyError>
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let (dir, fs) =
|
let (dir, fs) = make_temp_check_sync::<P>(
|
||||||
make_temp_check_sync::<P>(state, dir, "Deno.makeTempDirSync()")?;
|
state,
|
||||||
|
dir_arg.as_deref(),
|
||||||
|
"Deno.makeTempDirSync()",
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
|
@ -936,7 +887,11 @@ where
|
||||||
for _ in 0..MAX_TRIES {
|
for _ in 0..MAX_TRIES {
|
||||||
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
||||||
match fs.mkdir_sync(&path, false, 0o700) {
|
match fs.mkdir_sync(&path, false, 0o700) {
|
||||||
Ok(_) => return path_into_string(path.into_os_string()),
|
Ok(_) => {
|
||||||
|
// PERMISSIONS: ensure the absolute path is not leaked
|
||||||
|
let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
|
||||||
|
return path_into_string(path.into_os_string());
|
||||||
|
}
|
||||||
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -955,14 +910,18 @@ where
|
||||||
#[string]
|
#[string]
|
||||||
pub async fn op_fs_make_temp_dir_async<P>(
|
pub async fn op_fs_make_temp_dir_async<P>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
#[string] dir: Option<String>,
|
#[string] dir_arg: Option<String>,
|
||||||
#[string] prefix: Option<String>,
|
#[string] prefix: Option<String>,
|
||||||
#[string] suffix: Option<String>,
|
#[string] suffix: Option<String>,
|
||||||
) -> Result<String, AnyError>
|
) -> Result<String, AnyError>
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let (dir, fs) = make_temp_check_async::<P>(state, dir, "Deno.makeTempDir()")?;
|
let (dir, fs) = make_temp_check_async::<P>(
|
||||||
|
state,
|
||||||
|
dir_arg.as_deref(),
|
||||||
|
"Deno.makeTempDir()",
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
|
@ -970,7 +929,11 @@ where
|
||||||
for _ in 0..MAX_TRIES {
|
for _ in 0..MAX_TRIES {
|
||||||
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
||||||
match fs.clone().mkdir_async(path.clone(), false, 0o700).await {
|
match fs.clone().mkdir_async(path.clone(), false, 0o700).await {
|
||||||
Ok(_) => return path_into_string(path.into_os_string()),
|
Ok(_) => {
|
||||||
|
// PERMISSIONS: ensure the absolute path is not leaked
|
||||||
|
let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
|
||||||
|
return path_into_string(path.into_os_string());
|
||||||
|
}
|
||||||
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -989,15 +952,18 @@ where
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_fs_make_temp_file_sync<P>(
|
pub fn op_fs_make_temp_file_sync<P>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] dir: Option<String>,
|
#[string] dir_arg: Option<String>,
|
||||||
#[string] prefix: Option<String>,
|
#[string] prefix: Option<String>,
|
||||||
#[string] suffix: Option<String>,
|
#[string] suffix: Option<String>,
|
||||||
) -> Result<String, AnyError>
|
) -> Result<String, AnyError>
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let (dir, fs) =
|
let (dir, fs) = make_temp_check_sync::<P>(
|
||||||
make_temp_check_sync::<P>(state, dir, "Deno.makeTempFileSync()")?;
|
state,
|
||||||
|
dir_arg.as_deref(),
|
||||||
|
"Deno.makeTempFileSync()",
|
||||||
|
)?;
|
||||||
|
|
||||||
let open_opts = OpenOptions {
|
let open_opts = OpenOptions {
|
||||||
write: true,
|
write: true,
|
||||||
|
@ -1011,7 +977,11 @@ where
|
||||||
for _ in 0..MAX_TRIES {
|
for _ in 0..MAX_TRIES {
|
||||||
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
||||||
match fs.open_sync(&path, open_opts, None) {
|
match fs.open_sync(&path, open_opts, None) {
|
||||||
Ok(_) => return path_into_string(path.into_os_string()),
|
Ok(_) => {
|
||||||
|
// PERMISSIONS: ensure the absolute path is not leaked
|
||||||
|
let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
|
||||||
|
return path_into_string(path.into_os_string());
|
||||||
|
}
|
||||||
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1030,15 +1000,18 @@ where
|
||||||
#[string]
|
#[string]
|
||||||
pub async fn op_fs_make_temp_file_async<P>(
|
pub async fn op_fs_make_temp_file_async<P>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
#[string] dir: Option<String>,
|
#[string] dir_arg: Option<String>,
|
||||||
#[string] prefix: Option<String>,
|
#[string] prefix: Option<String>,
|
||||||
#[string] suffix: Option<String>,
|
#[string] suffix: Option<String>,
|
||||||
) -> Result<String, AnyError>
|
) -> Result<String, AnyError>
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let (dir, fs) =
|
let (dir, fs) = make_temp_check_async::<P>(
|
||||||
make_temp_check_async::<P>(state, dir, "Deno.makeTempFile()")?;
|
state,
|
||||||
|
dir_arg.as_deref(),
|
||||||
|
"Deno.makeTempFile()",
|
||||||
|
)?;
|
||||||
|
|
||||||
let open_opts = OpenOptions {
|
let open_opts = OpenOptions {
|
||||||
write: true,
|
write: true,
|
||||||
|
@ -1053,7 +1026,11 @@ where
|
||||||
for _ in 0..MAX_TRIES {
|
for _ in 0..MAX_TRIES {
|
||||||
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
|
||||||
match fs.clone().open_async(path.clone(), open_opts, None).await {
|
match fs.clone().open_async(path.clone(), open_opts, None).await {
|
||||||
Ok(_) => return path_into_string(path.into_os_string()),
|
Ok(_) => {
|
||||||
|
// PERMISSIONS: ensure the absolute path is not leaked
|
||||||
|
let path = strip_dir_prefix(&dir, dir_arg.as_deref(), path)?;
|
||||||
|
return path_into_string(path.into_os_string());
|
||||||
|
}
|
||||||
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1067,9 +1044,26 @@ where
|
||||||
.context("tmpfile")
|
.context("tmpfile")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn strip_dir_prefix(
|
||||||
|
resolved_dir: &Path,
|
||||||
|
dir_arg: Option<&str>,
|
||||||
|
result_path: PathBuf,
|
||||||
|
) -> Result<PathBuf, StripPrefixError> {
|
||||||
|
if resolved_dir.is_absolute() {
|
||||||
|
match &dir_arg {
|
||||||
|
Some(dir_arg) => {
|
||||||
|
Ok(Path::new(dir_arg).join(result_path.strip_prefix(resolved_dir)?))
|
||||||
|
}
|
||||||
|
None => Ok(result_path),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(result_path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn make_temp_check_sync<P>(
|
fn make_temp_check_sync<P>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
dir: Option<String>,
|
dir: Option<&str>,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(PathBuf, FileSystemRc), AnyError>
|
) -> Result<(PathBuf, FileSystemRc), AnyError>
|
||||||
where
|
where
|
||||||
|
@ -1077,11 +1071,7 @@ where
|
||||||
{
|
{
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let dir = match dir {
|
let dir = match dir {
|
||||||
Some(dir) => {
|
Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
|
||||||
let dir = PathBuf::from(dir);
|
|
||||||
state.borrow_mut::<P>().check_write(&dir, api_name)?;
|
|
||||||
dir
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let dir = fs.tmp_dir().context("tmpdir")?;
|
let dir = fs.tmp_dir().context("tmpdir")?;
|
||||||
state
|
state
|
||||||
|
@ -1095,7 +1085,7 @@ where
|
||||||
|
|
||||||
fn make_temp_check_async<P>(
|
fn make_temp_check_async<P>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
dir: Option<String>,
|
dir: Option<&str>,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(PathBuf, FileSystemRc), AnyError>
|
) -> Result<(PathBuf, FileSystemRc), AnyError>
|
||||||
where
|
where
|
||||||
|
@ -1104,11 +1094,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let dir = match dir {
|
let dir = match dir {
|
||||||
Some(dir) => {
|
Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
|
||||||
let dir = PathBuf::from(dir);
|
|
||||||
state.borrow_mut::<P>().check_write(&dir, api_name)?;
|
|
||||||
dir
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let dir = fs.tmp_dir().context("tmpdir")?;
|
let dir = fs.tmp_dir().context("tmpdir")?;
|
||||||
state
|
state
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
|
@ -36,19 +37,37 @@ pub struct SqliteDbHandler<P: SqliteDbHandlerPermissions + 'static> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SqliteDbHandlerPermissions {
|
pub trait SqliteDbHandlerPermissions {
|
||||||
fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>;
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>;
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
p: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_write<'a>(
|
||||||
|
&mut self,
|
||||||
|
p: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> {
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
p: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, p, api_name)
|
deno_permissions::PermissionsContainer::check_read(self, p, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> {
|
fn check_write<'a>(
|
||||||
deno_permissions::PermissionsContainer::check_write(self, p, api_name)
|
&mut self,
|
||||||
|
p: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_write_path(self, p, api_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,28 +93,35 @@ impl<P: SqliteDbHandlerPermissions> DatabaseHandler for SqliteDbHandler<P> {
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
) -> Result<Self::DB, AnyError> {
|
) -> Result<Self::DB, AnyError> {
|
||||||
// Validate path
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
if let Some(path) = &path {
|
fn validate_path<P: SqliteDbHandlerPermissions + 'static>(
|
||||||
if path != ":memory:" {
|
state: &RefCell<OpState>,
|
||||||
if path.is_empty() {
|
path: Option<String>,
|
||||||
return Err(type_error("Filename cannot be empty"));
|
) -> Result<Option<String>, AnyError> {
|
||||||
}
|
let Some(path) = path else {
|
||||||
if path.starts_with(':') {
|
return Ok(None);
|
||||||
return Err(type_error(
|
};
|
||||||
"Filename cannot start with ':' unless prefixed with './'",
|
if path == ":memory:" {
|
||||||
));
|
return Ok(Some(path));
|
||||||
}
|
}
|
||||||
let path = Path::new(path);
|
if path.is_empty() {
|
||||||
{
|
return Err(type_error("Filename cannot be empty"));
|
||||||
let mut state = state.borrow_mut();
|
}
|
||||||
let permissions = state.borrow_mut::<P>();
|
if path.starts_with(':') {
|
||||||
permissions.check_read(path, "Deno.openKv")?;
|
return Err(type_error(
|
||||||
permissions.check_write(path, "Deno.openKv")?;
|
"Filename cannot start with ':' unless prefixed with './'",
|
||||||
}
|
));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut state = state.borrow_mut();
|
||||||
|
let permissions = state.borrow_mut::<P>();
|
||||||
|
let path = permissions.check_read(&path, "Deno.openKv")?;
|
||||||
|
let path = permissions.check_write(&path, "Deno.openKv")?;
|
||||||
|
Ok(Some(path.to_string_lossy().to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = path.clone();
|
let path = validate_path::<P>(&state, path)?;
|
||||||
let default_storage_dir = self.default_storage_dir.clone();
|
let default_storage_dir = self.default_storage_dir.clone();
|
||||||
type ConnGen =
|
type ConnGen =
|
||||||
Arc<dyn Fn() -> rusqlite::Result<rusqlite::Connection> + Send + Sync>;
|
Arc<dyn Fn() -> rusqlite::Result<rusqlite::Connection> + Send + Sync>;
|
||||||
|
|
|
@ -16,7 +16,6 @@ use deno_core::OpState;
|
||||||
use deno_core::V8CrossThreadTaskSpawner;
|
use deno_core::V8CrossThreadTaskSpawner;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::thread_local;
|
use std::thread_local;
|
||||||
|
@ -482,15 +481,15 @@ deno_core::extension!(deno_napi,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub trait NapiPermissions {
|
pub trait NapiPermissions {
|
||||||
fn check(&mut self, path: Option<&Path>)
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
-> std::result::Result<(), AnyError>;
|
fn check(&mut self, path: &str) -> std::result::Result<PathBuf, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
|
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
|
||||||
// change in the future.
|
// change in the future.
|
||||||
impl NapiPermissions for deno_permissions::PermissionsContainer {
|
impl NapiPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
fn check(&mut self, path: &str) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_ffi(self, path)
|
deno_permissions::PermissionsContainer::check_ffi(self, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,7 +500,7 @@ unsafe impl Send for NapiModuleHandle {}
|
||||||
struct NapiModuleHandle(*const NapiModule);
|
struct NapiModuleHandle(*const NapiModule);
|
||||||
|
|
||||||
static NAPI_LOADED_MODULES: std::sync::LazyLock<
|
static NAPI_LOADED_MODULES: std::sync::LazyLock<
|
||||||
RwLock<HashMap<String, NapiModuleHandle>>,
|
RwLock<HashMap<PathBuf, NapiModuleHandle>>,
|
||||||
> = std::sync::LazyLock::new(|| RwLock::new(HashMap::new()));
|
> = std::sync::LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||||
|
|
||||||
#[op2(reentrant)]
|
#[op2(reentrant)]
|
||||||
|
@ -519,15 +518,16 @@ where
|
||||||
{
|
{
|
||||||
// We must limit the OpState borrow because this function can trigger a
|
// We must limit the OpState borrow because this function can trigger a
|
||||||
// re-borrow through the NAPI module.
|
// re-borrow through the NAPI module.
|
||||||
let (async_work_sender, cleanup_hooks, external_ops_tracker) = {
|
let (async_work_sender, cleanup_hooks, external_ops_tracker, path) = {
|
||||||
let mut op_state = op_state.borrow_mut();
|
let mut op_state = op_state.borrow_mut();
|
||||||
let permissions = op_state.borrow_mut::<NP>();
|
let permissions = op_state.borrow_mut::<NP>();
|
||||||
permissions.check(Some(&PathBuf::from(&path)))?;
|
let path = permissions.check(&path)?;
|
||||||
let napi_state = op_state.borrow::<NapiState>();
|
let napi_state = op_state.borrow::<NapiState>();
|
||||||
(
|
(
|
||||||
op_state.borrow::<V8CrossThreadTaskSpawner>().clone(),
|
op_state.borrow::<V8CrossThreadTaskSpawner>().clone(),
|
||||||
napi_state.env_cleanup_hooks.clone(),
|
napi_state.env_cleanup_hooks.clone(),
|
||||||
op_state.external_ops_tracker.clone(),
|
op_state.external_ops_tracker.clone(),
|
||||||
|
path,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -612,7 +612,7 @@ where
|
||||||
} else {
|
} else {
|
||||||
return Err(type_error(format!(
|
return Err(type_error(format!(
|
||||||
"Unable to find register Node-API module at {}",
|
"Unable to find register Node-API module at {}",
|
||||||
path
|
path.display()
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -22,12 +23,27 @@ pub const UNSTABLE_FEATURE_NAME: &str = "net";
|
||||||
pub trait NetPermissions {
|
pub trait NetPermissions {
|
||||||
fn check_net<T: AsRef<str>>(
|
fn check_net<T: AsRef<str>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_host: &(T, Option<u16>),
|
host: &(T, Option<u16>),
|
||||||
_api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), AnyError>;
|
||||||
fn check_read(&mut self, _p: &Path, _api_name: &str) -> Result<(), AnyError>;
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write(&mut self, _p: &Path, _api_name: &str)
|
fn check_read(
|
||||||
-> Result<(), AnyError>;
|
&mut self,
|
||||||
|
p: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_write(
|
||||||
|
&mut self,
|
||||||
|
p: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
p: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetPermissions for deno_permissions::PermissionsContainer {
|
impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -43,20 +59,31 @@ impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_write_path(
|
||||||
|
self, path, api_name,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for checking unstable features. Used for sync ops.
|
/// Helper for checking unstable features. Used for sync ops.
|
||||||
|
|
|
@ -784,6 +784,7 @@ mod tests {
|
||||||
use std::net::Ipv6Addr;
|
use std::net::Ipv6Addr;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use trust_dns_proto::rr::rdata::a::A;
|
use trust_dns_proto::rr::rdata::a::A;
|
||||||
|
@ -991,18 +992,26 @@ mod tests {
|
||||||
|
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
p: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
Ok(())
|
Ok(PathBuf::from(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
p: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
Ok(())
|
Ok(PathBuf::from(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
p: &'a Path,
|
||||||
|
_api_name: &str,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
Ok(Cow::Borrowed(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ use std::io::ErrorKind;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::path::Path;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
@ -356,15 +355,17 @@ where
|
||||||
.try_borrow::<UnsafelyIgnoreCertificateErrors>()
|
.try_borrow::<UnsafelyIgnoreCertificateErrors>()
|
||||||
.and_then(|it| it.0.clone());
|
.and_then(|it| it.0.clone());
|
||||||
|
|
||||||
{
|
let cert_file = {
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
let permissions = s.borrow_mut::<NP>();
|
let permissions = s.borrow_mut::<NP>();
|
||||||
permissions
|
permissions
|
||||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connectTls()")?;
|
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connectTls()")?;
|
||||||
if let Some(path) = cert_file {
|
if let Some(path) = cert_file {
|
||||||
permissions.check_read(Path::new(path), "Deno.connectTls()")?;
|
Some(permissions.check_read(path, "Deno.connectTls()")?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut ca_certs = args
|
let mut ca_certs = args
|
||||||
.ca_certs
|
.ca_certs
|
||||||
|
|
|
@ -94,22 +94,22 @@ pub async fn op_net_accept_unix(
|
||||||
#[serde]
|
#[serde]
|
||||||
pub async fn op_net_connect_unix<NP>(
|
pub async fn op_net_connect_unix<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
#[string] path: String,
|
#[string] address_path: String,
|
||||||
) -> Result<(ResourceId, Option<String>, Option<String>), AnyError>
|
) -> Result<(ResourceId, Option<String>, Option<String>), AnyError>
|
||||||
where
|
where
|
||||||
NP: NetPermissions + 'static,
|
NP: NetPermissions + 'static,
|
||||||
{
|
{
|
||||||
let address_path = Path::new(&path);
|
let address_path = {
|
||||||
{
|
|
||||||
let mut state_ = state.borrow_mut();
|
let mut state_ = state.borrow_mut();
|
||||||
state_
|
let address_path = state_
|
||||||
.borrow_mut::<NP>()
|
.borrow_mut::<NP>()
|
||||||
.check_read(address_path, "Deno.connect()")?;
|
.check_read(&address_path, "Deno.connect()")?;
|
||||||
state_
|
_ = state_
|
||||||
.borrow_mut::<NP>()
|
.borrow_mut::<NP>()
|
||||||
.check_write(address_path, "Deno.connect()")?;
|
.check_write_path(&address_path, "Deno.connect()")?;
|
||||||
}
|
address_path
|
||||||
let unix_stream = UnixStream::connect(Path::new(&path)).await?;
|
};
|
||||||
|
let unix_stream = UnixStream::connect(&address_path).await?;
|
||||||
let local_addr = unix_stream.local_addr()?;
|
let local_addr = unix_stream.local_addr()?;
|
||||||
let remote_addr = unix_stream.peer_addr()?;
|
let remote_addr = unix_stream.peer_addr()?;
|
||||||
let local_addr_path = local_addr.as_pathname().map(pathstring).transpose()?;
|
let local_addr_path = local_addr.as_pathname().map(pathstring).transpose()?;
|
||||||
|
@ -148,18 +148,17 @@ pub async fn op_net_recv_unixpacket(
|
||||||
pub async fn op_net_send_unixpacket<NP>(
|
pub async fn op_net_send_unixpacket<NP>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
#[smi] rid: ResourceId,
|
#[smi] rid: ResourceId,
|
||||||
#[string] path: String,
|
#[string] address_path: String,
|
||||||
#[buffer] zero_copy: JsBuffer,
|
#[buffer] zero_copy: JsBuffer,
|
||||||
) -> Result<usize, AnyError>
|
) -> Result<usize, AnyError>
|
||||||
where
|
where
|
||||||
NP: NetPermissions + 'static,
|
NP: NetPermissions + 'static,
|
||||||
{
|
{
|
||||||
let address_path = Path::new(&path);
|
let address_path = {
|
||||||
{
|
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
s.borrow_mut::<NP>()
|
s.borrow_mut::<NP>()
|
||||||
.check_write(address_path, "Deno.DatagramConn.send()")?;
|
.check_write(&address_path, "Deno.DatagramConn.send()")?
|
||||||
}
|
};
|
||||||
|
|
||||||
let resource = state
|
let resource = state
|
||||||
.borrow()
|
.borrow()
|
||||||
|
@ -178,17 +177,16 @@ where
|
||||||
#[serde]
|
#[serde]
|
||||||
pub fn op_net_listen_unix<NP>(
|
pub fn op_net_listen_unix<NP>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] path: String,
|
#[string] address_path: String,
|
||||||
#[string] api_name: String,
|
#[string] api_name: String,
|
||||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||||
where
|
where
|
||||||
NP: NetPermissions + 'static,
|
NP: NetPermissions + 'static,
|
||||||
{
|
{
|
||||||
let address_path = Path::new(&path);
|
|
||||||
let permissions = state.borrow_mut::<NP>();
|
let permissions = state.borrow_mut::<NP>();
|
||||||
let api_call_expr = format!("{}()", api_name);
|
let api_call_expr = format!("{}()", api_name);
|
||||||
permissions.check_read(address_path, &api_call_expr)?;
|
let address_path = permissions.check_read(&address_path, &api_call_expr)?;
|
||||||
permissions.check_write(address_path, &api_call_expr)?;
|
_ = permissions.check_write_path(&address_path, &api_call_expr)?;
|
||||||
let listener = UnixListener::bind(address_path)?;
|
let listener = UnixListener::bind(address_path)?;
|
||||||
let local_addr = listener.local_addr()?;
|
let local_addr = listener.local_addr()?;
|
||||||
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;
|
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;
|
||||||
|
@ -199,15 +197,15 @@ where
|
||||||
|
|
||||||
pub fn net_listen_unixpacket<NP>(
|
pub fn net_listen_unixpacket<NP>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
path: String,
|
address_path: String,
|
||||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||||
where
|
where
|
||||||
NP: NetPermissions + 'static,
|
NP: NetPermissions + 'static,
|
||||||
{
|
{
|
||||||
let address_path = Path::new(&path);
|
|
||||||
let permissions = state.borrow_mut::<NP>();
|
let permissions = state.borrow_mut::<NP>();
|
||||||
permissions.check_read(address_path, "Deno.listenDatagram()")?;
|
let address_path =
|
||||||
permissions.check_write(address_path, "Deno.listenDatagram()")?;
|
permissions.check_read(&address_path, "Deno.listenDatagram()")?;
|
||||||
|
_ = permissions.check_write_path(&address_path, "Deno.listenDatagram()")?;
|
||||||
let socket = UnixDatagram::bind(address_path)?;
|
let socket = UnixDatagram::bind(address_path)?;
|
||||||
let local_addr = socket.local_addr()?;
|
let local_addr = socket.local_addr()?;
|
||||||
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;
|
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
#![deny(clippy::print_stderr)]
|
#![deny(clippy::print_stderr)]
|
||||||
#![deny(clippy::print_stdout)]
|
#![deny(clippy::print_stdout)]
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::located_script_name;
|
use deno_core::located_script_name;
|
||||||
|
@ -49,21 +51,29 @@ pub trait NodePermissions {
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read(&mut self, path: &Path) -> Result<(), AnyError> {
|
fn check_read(&mut self, path: &str) -> Result<PathBuf, AnyError> {
|
||||||
self.check_read_with_api_name(path, None)
|
self.check_read_with_api_name(path, None)
|
||||||
}
|
}
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_read_with_api_name(
|
fn check_read_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
fn check_read_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError>;
|
||||||
fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>;
|
fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>;
|
||||||
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write_with_api_name(
|
fn check_write_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodePermissions for deno_permissions::PermissionsContainer {
|
impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -79,20 +89,27 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read_with_api_name(
|
fn check_read_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_with_api_name(
|
deno_permissions::PermissionsContainer::check_read_with_api_name(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_read_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
path: &'a Path,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_read_path(self, path, None)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_write_with_api_name(
|
fn check_write_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_with_api_name(
|
deno_permissions::PermissionsContainer::check_write_with_api_name(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -21,8 +19,7 @@ pub fn op_node_fs_exists_sync<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(&path, Some("node:fs.existsSync()"))?;
|
.check_read_with_api_name(&path, Some("node:fs.existsSync()"))?;
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
@ -37,14 +34,12 @@ pub async fn op_node_fs_exists<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(&path, Some("node:fs.exists()"))?;
|
.check_read_with_api_name(&path, Some("node:fs.exists()"))?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(fs.exists_async(path).await?)
|
Ok(fs.exists_async(path).await?)
|
||||||
|
@ -59,18 +54,15 @@ pub fn op_node_cp_sync<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = Path::new(path);
|
let path = state
|
||||||
let new_path = Path::new(new_path);
|
|
||||||
|
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(path, Some("node:fs.cpSync"))?;
|
.check_read_with_api_name(path, Some("node:fs.cpSync"))?;
|
||||||
state
|
let new_path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(new_path, Some("node:fs.cpSync"))?;
|
.check_write_with_api_name(new_path, Some("node:fs.cpSync"))?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.cp_sync(path, new_path)?;
|
fs.cp_sync(&path, &new_path)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,18 +75,15 @@ pub async fn op_node_cp<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path, new_path) = {
|
||||||
let new_path = PathBuf::from(new_path);
|
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(&path, Some("node:fs.cpSync"))?;
|
.check_read_with_api_name(&path, Some("node:fs.cpSync"))?;
|
||||||
state
|
let new_path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&new_path, Some("node:fs.cpSync"))?;
|
.check_write_with_api_name(&new_path, Some("node:fs.cpSync"))?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path, new_path)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.cp_async(path, new_path).await?;
|
fs.cp_async(path, new_path).await?;
|
||||||
|
@ -123,21 +112,21 @@ pub fn op_node_statfs<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
{
|
let path = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(Path::new(&path), Some("node:fs.statfs"))?;
|
.check_read_with_api_name(&path, Some("node:fs.statfs"))?;
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_sys("statfs", "node:fs.statfs")?;
|
.check_sys("statfs", "node:fs.statfs")?;
|
||||||
}
|
path
|
||||||
|
};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
let path = OsStr::new(&path);
|
let path = path.as_os_str();
|
||||||
let mut cpath = path.as_bytes().to_vec();
|
let mut cpath = path.as_bytes().to_vec();
|
||||||
cpath.push(0);
|
cpath.push(0);
|
||||||
if bigint {
|
if bigint {
|
||||||
|
@ -196,7 +185,7 @@ where
|
||||||
// Using a vfs here doesn't make sense, it won't align with the windows API
|
// Using a vfs here doesn't make sense, it won't align with the windows API
|
||||||
// call below.
|
// call below.
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
let path = Path::new(&path).canonicalize()?;
|
let path = path.canonicalize()?;
|
||||||
let root = path
|
let root = path
|
||||||
.ancestors()
|
.ancestors()
|
||||||
.last()
|
.last()
|
||||||
|
@ -256,14 +245,12 @@ pub fn op_node_lutimes_sync<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = Path::new(path);
|
let path = state
|
||||||
|
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(path, Some("node:fs.lutimes"))?;
|
.check_write_with_api_name(path, Some("node:fs.lutimes"))?;
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.lutime_sync(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?;
|
fs.lutime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,14 +266,12 @@ pub async fn op_node_lutimes<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
|
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&path, Some("node:fs.lutimesSync"))?;
|
.check_write_with_api_name(&path, Some("node:fs.lutimesSync"))?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.lutime_async(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
fs.lutime_async(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
||||||
|
@ -305,8 +290,7 @@ pub fn op_node_lchown_sync<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&path, Some("node:fs.lchownSync"))?;
|
.check_write_with_api_name(&path, Some("node:fs.lchownSync"))?;
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
@ -324,13 +308,12 @@ pub async fn op_node_lchown<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let (fs, path) = {
|
||||||
let fs = {
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&path, Some("node:fs.lchown"))?;
|
.check_write_with_api_name(&path, Some("node:fs.lchown"))?;
|
||||||
state.borrow::<FileSystemRc>().clone()
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
fs.lchown_async(path, uid, gid).await?;
|
fs.lchown_async(path, uid, gid).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,12 +5,15 @@
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::FsModuleLoader;
|
use deno_core::FsModuleLoader;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_fs::RealFs;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
use deno_runtime::worker::MainWorker;
|
use deno_runtime::worker::MainWorker;
|
||||||
use deno_runtime::worker::WorkerOptions;
|
use deno_runtime::worker::WorkerOptions;
|
||||||
|
|
||||||
|
@ -34,7 +37,9 @@ async fn main() -> Result<(), AnyError> {
|
||||||
eprintln!("Running {main_module}...");
|
eprintln!("Running {main_module}...");
|
||||||
let mut worker = MainWorker::bootstrap_from_options(
|
let mut worker = MainWorker::bootstrap_from_options(
|
||||||
main_module.clone(),
|
main_module.clone(),
|
||||||
PermissionsContainer::allow_all(),
|
PermissionsContainer::allow_all(Arc::new(
|
||||||
|
RuntimePermissionDescriptorParser::new(Arc::new(RealFs)),
|
||||||
|
)),
|
||||||
WorkerOptions {
|
WorkerOptions {
|
||||||
module_loader: Rc::new(FsModuleLoader),
|
module_loader: Rc::new(FsModuleLoader),
|
||||||
extensions: vec![hello_runtime::init_ops_and_esm()],
|
extensions: vec![hello_runtime::init_ops_and_esm()],
|
||||||
|
|
|
@ -33,6 +33,7 @@ pub mod fs_util;
|
||||||
pub mod inspector_server;
|
pub mod inspector_server;
|
||||||
pub mod js;
|
pub mod js;
|
||||||
pub mod ops;
|
pub mod ops;
|
||||||
|
pub mod permissions;
|
||||||
pub mod snapshot;
|
pub mod snapshot;
|
||||||
pub mod tokio_util;
|
pub mod tokio_util;
|
||||||
pub mod web_worker;
|
pub mod web_worker;
|
||||||
|
|
|
@ -123,10 +123,9 @@ fn op_fs_events_open(
|
||||||
RecursiveMode::NonRecursive
|
RecursiveMode::NonRecursive
|
||||||
};
|
};
|
||||||
for path in &args.paths {
|
for path in &args.paths {
|
||||||
let path = PathBuf::from(path);
|
let path = state
|
||||||
state
|
|
||||||
.borrow_mut::<PermissionsContainer>()
|
.borrow_mut::<PermissionsContainer>()
|
||||||
.check_read(&path, "Deno.watchFs()")?;
|
.check_read(path, "Deno.watchFs()")?;
|
||||||
watcher.watch(&path, recursive_mode)?;
|
watcher.watch(&path, recursive_mode)?;
|
||||||
}
|
}
|
||||||
let resource = FsEventsResource {
|
let resource = FsEventsResource {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use ::deno_permissions::parse_sys_kind;
|
use ::deno_permissions::parse_sys_kind;
|
||||||
use ::deno_permissions::NetDescriptor;
|
use ::deno_permissions::PermissionDescriptorParser;
|
||||||
use ::deno_permissions::PermissionState;
|
use ::deno_permissions::PermissionState;
|
||||||
use ::deno_permissions::PermissionsContainer;
|
use ::deno_permissions::PermissionsContainer;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
|
@ -10,7 +10,7 @@ use deno_core::op2;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::Path;
|
use std::sync::Arc;
|
||||||
|
|
||||||
deno_core::extension!(
|
deno_core::extension!(
|
||||||
deno_permissions,
|
deno_permissions,
|
||||||
|
@ -19,6 +19,12 @@ deno_core::extension!(
|
||||||
op_revoke_permission,
|
op_revoke_permission,
|
||||||
op_request_permission,
|
op_request_permission,
|
||||||
],
|
],
|
||||||
|
options = {
|
||||||
|
permission_desc_parser: Arc<dyn PermissionDescriptorParser>,
|
||||||
|
},
|
||||||
|
state = |state, options| {
|
||||||
|
state.put(options.permission_desc_parser);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -56,15 +62,37 @@ pub fn op_query_permission(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[serde] args: PermissionArgs,
|
#[serde] args: PermissionArgs,
|
||||||
) -> Result<PermissionStatus, AnyError> {
|
) -> Result<PermissionStatus, AnyError> {
|
||||||
let permissions = state.borrow::<PermissionsContainer>().0.lock();
|
let permissions_container = state.borrow::<PermissionsContainer>();
|
||||||
|
// todo(dsherret): don't have this function use the properties of
|
||||||
|
// permission container
|
||||||
|
let desc_parser = &permissions_container.descriptor_parser;
|
||||||
|
let permissions = permissions_container.inner.lock();
|
||||||
let path = args.path.as_deref();
|
let path = args.path.as_deref();
|
||||||
let perm = match args.name.as_ref() {
|
let perm = match args.name.as_ref() {
|
||||||
"read" => permissions.read.query(path.map(Path::new)),
|
"read" => permissions.read.query(
|
||||||
"write" => permissions.write.query(path.map(Path::new)),
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_read(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
|
"write" => permissions.write.query(
|
||||||
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_write(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
"net" => permissions.net.query(
|
"net" => permissions.net.query(
|
||||||
match args.host.as_deref() {
|
match args.host.as_deref() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(NetDescriptor::parse(h)?),
|
Some(h) => Some(desc_parser.parse_net_descriptor(h)?),
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
|
@ -72,8 +100,24 @@ pub fn op_query_permission(
|
||||||
"sys" => permissions
|
"sys" => permissions
|
||||||
.sys
|
.sys
|
||||||
.query(args.kind.as_deref().map(parse_sys_kind).transpose()?),
|
.query(args.kind.as_deref().map(parse_sys_kind).transpose()?),
|
||||||
"run" => permissions.run.query(args.command.as_deref()),
|
"run" => permissions.run.query(
|
||||||
"ffi" => permissions.ffi.query(args.path.as_deref().map(Path::new)),
|
args
|
||||||
|
.command
|
||||||
|
.as_deref()
|
||||||
|
.map(|request| desc_parser.parse_run_query(request))
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
|
"ffi" => permissions.ffi.query(
|
||||||
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_ffi(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
n => {
|
n => {
|
||||||
return Err(custom_error(
|
return Err(custom_error(
|
||||||
"ReferenceError",
|
"ReferenceError",
|
||||||
|
@ -90,15 +134,37 @@ pub fn op_revoke_permission(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[serde] args: PermissionArgs,
|
#[serde] args: PermissionArgs,
|
||||||
) -> Result<PermissionStatus, AnyError> {
|
) -> Result<PermissionStatus, AnyError> {
|
||||||
let mut permissions = state.borrow_mut::<PermissionsContainer>().0.lock();
|
// todo(dsherret): don't have this function use the properties of
|
||||||
|
// permission container
|
||||||
|
let permissions_container = state.borrow_mut::<PermissionsContainer>();
|
||||||
|
let desc_parser = &permissions_container.descriptor_parser;
|
||||||
|
let mut permissions = permissions_container.inner.lock();
|
||||||
let path = args.path.as_deref();
|
let path = args.path.as_deref();
|
||||||
let perm = match args.name.as_ref() {
|
let perm = match args.name.as_ref() {
|
||||||
"read" => permissions.read.revoke(path.map(Path::new)),
|
"read" => permissions.read.revoke(
|
||||||
"write" => permissions.write.revoke(path.map(Path::new)),
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_read(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
|
"write" => permissions.write.revoke(
|
||||||
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_write(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
"net" => permissions.net.revoke(
|
"net" => permissions.net.revoke(
|
||||||
match args.host.as_deref() {
|
match args.host.as_deref() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(NetDescriptor::parse(h)?),
|
Some(h) => Some(desc_parser.parse_net_descriptor(h)?),
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
|
@ -106,8 +172,24 @@ pub fn op_revoke_permission(
|
||||||
"sys" => permissions
|
"sys" => permissions
|
||||||
.sys
|
.sys
|
||||||
.revoke(args.kind.as_deref().map(parse_sys_kind).transpose()?),
|
.revoke(args.kind.as_deref().map(parse_sys_kind).transpose()?),
|
||||||
"run" => permissions.run.revoke(args.command.as_deref()),
|
"run" => permissions.run.revoke(
|
||||||
"ffi" => permissions.ffi.revoke(args.path.as_deref().map(Path::new)),
|
args
|
||||||
|
.command
|
||||||
|
.as_deref()
|
||||||
|
.map(|request| desc_parser.parse_run_query(request))
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
|
"ffi" => permissions.ffi.revoke(
|
||||||
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_ffi(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
n => {
|
n => {
|
||||||
return Err(custom_error(
|
return Err(custom_error(
|
||||||
"ReferenceError",
|
"ReferenceError",
|
||||||
|
@ -124,15 +206,37 @@ pub fn op_request_permission(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[serde] args: PermissionArgs,
|
#[serde] args: PermissionArgs,
|
||||||
) -> Result<PermissionStatus, AnyError> {
|
) -> Result<PermissionStatus, AnyError> {
|
||||||
let mut permissions = state.borrow_mut::<PermissionsContainer>().0.lock();
|
// todo(dsherret): don't have this function use the properties of
|
||||||
|
// permission container
|
||||||
|
let permissions_container = state.borrow_mut::<PermissionsContainer>();
|
||||||
|
let desc_parser = &permissions_container.descriptor_parser;
|
||||||
|
let mut permissions = permissions_container.inner.lock();
|
||||||
let path = args.path.as_deref();
|
let path = args.path.as_deref();
|
||||||
let perm = match args.name.as_ref() {
|
let perm = match args.name.as_ref() {
|
||||||
"read" => permissions.read.request(path.map(Path::new)),
|
"read" => permissions.read.request(
|
||||||
"write" => permissions.write.request(path.map(Path::new)),
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_read(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
|
"write" => permissions.write.request(
|
||||||
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_write(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
"net" => permissions.net.request(
|
"net" => permissions.net.request(
|
||||||
match args.host.as_deref() {
|
match args.host.as_deref() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(NetDescriptor::parse(h)?),
|
Some(h) => Some(desc_parser.parse_net_descriptor(h)?),
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
|
@ -140,8 +244,24 @@ pub fn op_request_permission(
|
||||||
"sys" => permissions
|
"sys" => permissions
|
||||||
.sys
|
.sys
|
||||||
.request(args.kind.as_deref().map(parse_sys_kind).transpose()?),
|
.request(args.kind.as_deref().map(parse_sys_kind).transpose()?),
|
||||||
"run" => permissions.run.request(args.command.as_deref()),
|
"run" => permissions.run.request(
|
||||||
"ffi" => permissions.ffi.request(args.path.as_deref().map(Path::new)),
|
args
|
||||||
|
.command
|
||||||
|
.as_deref()
|
||||||
|
.map(|request| desc_parser.parse_run_query(request))
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
|
"ffi" => permissions.ffi.request(
|
||||||
|
path
|
||||||
|
.map(|path| {
|
||||||
|
Result::<_, AnyError>::Ok(
|
||||||
|
desc_parser.parse_path_query(path)?.into_ffi(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.as_ref(),
|
||||||
|
),
|
||||||
n => {
|
n => {
|
||||||
return Err(custom_error(
|
return Err(custom_error(
|
||||||
"ReferenceError",
|
"ReferenceError",
|
||||||
|
|
|
@ -17,12 +17,13 @@ use deno_io::ChildStderrResource;
|
||||||
use deno_io::ChildStdinResource;
|
use deno_io::ChildStdinResource;
|
||||||
use deno_io::ChildStdoutResource;
|
use deno_io::ChildStdoutResource;
|
||||||
use deno_permissions::PermissionsContainer;
|
use deno_permissions::PermissionsContainer;
|
||||||
use deno_permissions::RunPathQuery;
|
use deno_permissions::RunQueryDescriptor;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
|
@ -536,9 +537,9 @@ fn compute_run_cmd_and_check_permissions(
|
||||||
.with_context(|| format!("Failed to spawn '{}'", arg_cmd))?;
|
.with_context(|| format!("Failed to spawn '{}'", arg_cmd))?;
|
||||||
check_run_permission(
|
check_run_permission(
|
||||||
state,
|
state,
|
||||||
RunPathQuery {
|
&RunQueryDescriptor::Path {
|
||||||
requested: arg_cmd,
|
requested: arg_cmd.to_string(),
|
||||||
resolved: &cmd,
|
resolved: cmd.clone(),
|
||||||
},
|
},
|
||||||
&run_env,
|
&run_env,
|
||||||
api_name,
|
api_name,
|
||||||
|
@ -547,7 +548,7 @@ fn compute_run_cmd_and_check_permissions(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RunEnv {
|
struct RunEnv {
|
||||||
envs: HashMap<String, String>,
|
envs: HashMap<OsString, OsString>,
|
||||||
cwd: PathBuf,
|
cwd: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,11 +568,32 @@ fn compute_run_env(
|
||||||
.map(|cwd_arg| resolve_path(cwd_arg, &cwd))
|
.map(|cwd_arg| resolve_path(cwd_arg, &cwd))
|
||||||
.unwrap_or(cwd);
|
.unwrap_or(cwd);
|
||||||
let envs = if arg_clear_env {
|
let envs = if arg_clear_env {
|
||||||
arg_envs.iter().cloned().collect()
|
arg_envs
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (OsString::from(k), OsString::from(v)))
|
||||||
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
let mut envs = std::env::vars().collect::<HashMap<_, _>>();
|
let mut envs = std::env::vars_os()
|
||||||
|
.map(|(k, v)| {
|
||||||
|
(
|
||||||
|
if cfg!(windows) {
|
||||||
|
k.to_ascii_uppercase()
|
||||||
|
} else {
|
||||||
|
k
|
||||||
|
},
|
||||||
|
v,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
for (key, value) in arg_envs {
|
for (key, value) in arg_envs {
|
||||||
envs.insert(key.clone(), value.clone());
|
envs.insert(
|
||||||
|
OsString::from(if cfg!(windows) {
|
||||||
|
key.to_ascii_uppercase()
|
||||||
|
} else {
|
||||||
|
key.clone()
|
||||||
|
}),
|
||||||
|
OsString::from(value.clone()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
envs
|
envs
|
||||||
};
|
};
|
||||||
|
@ -585,19 +607,7 @@ fn resolve_cmd(cmd: &str, env: &RunEnv) -> Result<PathBuf, AnyError> {
|
||||||
if is_path {
|
if is_path {
|
||||||
Ok(resolve_path(cmd, &env.cwd))
|
Ok(resolve_path(cmd, &env.cwd))
|
||||||
} else {
|
} else {
|
||||||
let path = env.envs.get("PATH").or_else(|| {
|
let path = env.envs.get(&OsString::from("PATH"));
|
||||||
if cfg!(windows) {
|
|
||||||
env.envs.iter().find_map(|(k, v)| {
|
|
||||||
if k.to_uppercase() == "PATH" {
|
|
||||||
Some(v)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
match which::which_in(cmd, path, &env.cwd) {
|
match which::which_in(cmd, path, &env.cwd) {
|
||||||
Ok(cmd) => Ok(cmd),
|
Ok(cmd) => Ok(cmd),
|
||||||
Err(which::Error::CannotFindBinaryPath) => {
|
Err(which::Error::CannotFindBinaryPath) => {
|
||||||
|
@ -614,7 +624,7 @@ fn resolve_path(path: &str, cwd: &Path) -> PathBuf {
|
||||||
|
|
||||||
fn check_run_permission(
|
fn check_run_permission(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
cmd: RunPathQuery,
|
cmd: &RunQueryDescriptor,
|
||||||
run_env: &RunEnv,
|
run_env: &RunEnv,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
@ -647,11 +657,22 @@ fn get_requires_allow_all_env_vars(env: &RunEnv) -> Vec<&str> {
|
||||||
key.starts_with("LD_") || key.starts_with("DYLD_")
|
key.starts_with("LD_") || key.starts_with("DYLD_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_empty(value: &OsString) -> bool {
|
||||||
|
value.is_empty()
|
||||||
|
|| value.to_str().map(|v| v.trim().is_empty()).unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
let mut found_envs = env
|
let mut found_envs = env
|
||||||
.envs
|
.envs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(k, v)| requires_allow_all(k) && !v.trim().is_empty())
|
.filter_map(|(k, v)| {
|
||||||
.map(|(k, _)| k.as_str())
|
let key = k.to_str()?;
|
||||||
|
if requires_allow_all(key) && !is_empty(v) {
|
||||||
|
Some(key)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
found_envs.sort();
|
found_envs.sort();
|
||||||
found_envs
|
found_envs
|
||||||
|
|
|
@ -19,6 +19,7 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_permissions::create_child_permissions;
|
use deno_permissions::create_child_permissions;
|
||||||
use deno_permissions::ChildPermissionsArg;
|
use deno_permissions::ChildPermissionsArg;
|
||||||
|
use deno_permissions::PermissionDescriptorParser;
|
||||||
use deno_permissions::PermissionsContainer;
|
use deno_permissions::PermissionsContainer;
|
||||||
use deno_web::deserialize_js_transferables;
|
use deno_web::deserialize_js_transferables;
|
||||||
use deno_web::JsMessageData;
|
use deno_web::JsMessageData;
|
||||||
|
@ -153,13 +154,19 @@ fn op_create_worker(
|
||||||
"Worker.deno.permissions",
|
"Worker.deno.permissions",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
let permission_desc_parser = state
|
||||||
|
.borrow::<Arc<dyn PermissionDescriptorParser>>()
|
||||||
|
.clone();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = if let Some(child_permissions_arg) = args.permissions
|
let worker_permissions = if let Some(child_permissions_arg) = args.permissions
|
||||||
{
|
{
|
||||||
let mut parent_permissions = parent_permissions.0.lock();
|
let mut parent_permissions = parent_permissions.inner.lock();
|
||||||
let perms =
|
let perms = create_child_permissions(
|
||||||
create_child_permissions(&mut parent_permissions, child_permissions_arg)?;
|
permission_desc_parser.as_ref(),
|
||||||
PermissionsContainer::new(perms)
|
&mut parent_permissions,
|
||||||
|
child_permissions_arg,
|
||||||
|
)?;
|
||||||
|
PermissionsContainer::new(permission_desc_parser, perms)
|
||||||
} else {
|
} else {
|
||||||
parent_permissions.clone()
|
parent_permissions.clone()
|
||||||
};
|
};
|
||||||
|
|
164
runtime/permissions.rs
Normal file
164
runtime/permissions.rs
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use deno_core::anyhow::bail;
|
||||||
|
use deno_core::anyhow::Context;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::normalize_path;
|
||||||
|
use deno_permissions::AllowRunDescriptor;
|
||||||
|
use deno_permissions::AllowRunDescriptorParseResult;
|
||||||
|
use deno_permissions::DenyRunDescriptor;
|
||||||
|
use deno_permissions::EnvDescriptor;
|
||||||
|
use deno_permissions::FfiDescriptor;
|
||||||
|
use deno_permissions::NetDescriptor;
|
||||||
|
use deno_permissions::PathQueryDescriptor;
|
||||||
|
use deno_permissions::ReadDescriptor;
|
||||||
|
use deno_permissions::RunQueryDescriptor;
|
||||||
|
use deno_permissions::SysDescriptor;
|
||||||
|
use deno_permissions::WriteDescriptor;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RuntimePermissionDescriptorParser {
|
||||||
|
fs: deno_fs::FileSystemRc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RuntimePermissionDescriptorParser {
|
||||||
|
pub fn new(fs: deno_fs::FileSystemRc) -> Self {
|
||||||
|
Self { fs }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_from_cwd(&self, path: &str) -> Result<PathBuf, AnyError> {
|
||||||
|
if path.is_empty() {
|
||||||
|
bail!("Empty path is not allowed");
|
||||||
|
}
|
||||||
|
let path = Path::new(path);
|
||||||
|
if path.is_absolute() {
|
||||||
|
Ok(normalize_path(path))
|
||||||
|
} else {
|
||||||
|
let cwd = self.resolve_cwd()?;
|
||||||
|
Ok(normalize_path(cwd.join(path)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_cwd(&self) -> Result<PathBuf, AnyError> {
|
||||||
|
self
|
||||||
|
.fs
|
||||||
|
.cwd()
|
||||||
|
.map_err(|e| e.into_io_error())
|
||||||
|
.context("failed resolving cwd")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_permissions::PermissionDescriptorParser
|
||||||
|
for RuntimePermissionDescriptorParser
|
||||||
|
{
|
||||||
|
fn parse_read_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<ReadDescriptor, AnyError> {
|
||||||
|
Ok(ReadDescriptor(self.resolve_from_cwd(text)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_write_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<WriteDescriptor, AnyError> {
|
||||||
|
Ok(WriteDescriptor(self.resolve_from_cwd(text)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_net_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<NetDescriptor, AnyError> {
|
||||||
|
NetDescriptor::parse(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_env_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<EnvDescriptor, AnyError> {
|
||||||
|
if text.is_empty() {
|
||||||
|
Err(AnyError::msg("Empty env not allowed"))
|
||||||
|
} else {
|
||||||
|
Ok(EnvDescriptor::new(text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_sys_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<deno_permissions::SysDescriptor, AnyError> {
|
||||||
|
if text.is_empty() {
|
||||||
|
Err(AnyError::msg("Empty sys not allowed"))
|
||||||
|
} else {
|
||||||
|
Ok(SysDescriptor(text.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_allow_run_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<AllowRunDescriptorParseResult, AnyError> {
|
||||||
|
Ok(AllowRunDescriptor::parse(text, &self.resolve_cwd()?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_deny_run_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<DenyRunDescriptor, AnyError> {
|
||||||
|
Ok(DenyRunDescriptor::parse(text, &self.resolve_cwd()?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ffi_descriptor(
|
||||||
|
&self,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<deno_permissions::FfiDescriptor, AnyError> {
|
||||||
|
Ok(FfiDescriptor(self.resolve_from_cwd(text)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
// queries
|
||||||
|
|
||||||
|
fn parse_path_query(
|
||||||
|
&self,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<PathQueryDescriptor, AnyError> {
|
||||||
|
Ok(PathQueryDescriptor {
|
||||||
|
resolved: self.resolve_from_cwd(path)?,
|
||||||
|
requested: path.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_run_query(
|
||||||
|
&self,
|
||||||
|
requested: &str,
|
||||||
|
) -> Result<RunQueryDescriptor, AnyError> {
|
||||||
|
if requested.is_empty() {
|
||||||
|
bail!("Empty run query is not allowed");
|
||||||
|
}
|
||||||
|
RunQueryDescriptor::parse(requested)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_fs::RealFs;
|
||||||
|
use deno_permissions::PermissionDescriptorParser;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handle_empty_value() {
|
||||||
|
let parser = RuntimePermissionDescriptorParser::new(Arc::new(RealFs));
|
||||||
|
assert!(parser.parse_read_descriptor("").is_err());
|
||||||
|
assert!(parser.parse_write_descriptor("").is_err());
|
||||||
|
assert!(parser.parse_env_descriptor("").is_err());
|
||||||
|
assert!(parser.parse_net_descriptor("").is_err());
|
||||||
|
assert!(parser.parse_ffi_descriptor("").is_err());
|
||||||
|
assert!(parser.parse_path_query("").is_err());
|
||||||
|
assert!(parser.parse_run_query("").is_err());
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use crate::ops;
|
use crate::ops;
|
||||||
use crate::ops::bootstrap::SnapshotOptions;
|
use crate::ops::bootstrap::SnapshotOptions;
|
||||||
|
use crate::permissions::RuntimePermissionDescriptorParser;
|
||||||
use crate::shared::maybe_transpile_source;
|
use crate::shared::maybe_transpile_source;
|
||||||
use crate::shared::runtime;
|
use crate::shared::runtime;
|
||||||
use deno_cache::SqliteBackedCache;
|
use deno_cache::SqliteBackedCache;
|
||||||
|
@ -11,6 +12,7 @@ use deno_core::v8;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
use deno_http::DefaultHttpPropertyExtractor;
|
use deno_http::DefaultHttpPropertyExtractor;
|
||||||
use deno_io::fs::FsError;
|
use deno_io::fs::FsError;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -45,29 +47,32 @@ impl deno_fetch::FetchPermissions for Permissions {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_read(
|
fn check_read<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
_p: &'a Path,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl deno_ffi::FfiPermissions for Permissions {
|
impl deno_ffi::FfiPermissions for Permissions {
|
||||||
fn check_partial(
|
fn check_partial_no_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
_path: Option<&Path>,
|
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<(), deno_core::error::AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_partial_with_path(
|
||||||
|
&mut self,
|
||||||
|
_path: &str,
|
||||||
|
) -> Result<PathBuf, AnyError> {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl deno_napi::NapiPermissions for Permissions {
|
impl deno_napi::NapiPermissions for Permissions {
|
||||||
fn check(
|
fn check(&mut self, _path: &str) -> std::result::Result<PathBuf, AnyError> {
|
||||||
&mut self,
|
|
||||||
_path: Option<&Path>,
|
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,18 +85,24 @@ impl deno_node::NodePermissions for Permissions {
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<(), deno_core::error::AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
fn check_read_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
_path: &'a Path,
|
||||||
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
fn check_read_with_api_name(
|
fn check_read_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
_p: &str,
|
||||||
_api_name: Option<&str>,
|
_api_name: Option<&str>,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
fn check_write_with_api_name(
|
fn check_write_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
_p: &str,
|
||||||
_api_name: Option<&str>,
|
_api_name: Option<&str>,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
fn check_sys(
|
fn check_sys(
|
||||||
|
@ -114,17 +125,25 @@ impl deno_net::NetPermissions for Permissions {
|
||||||
|
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
_p: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
_p: &Path,
|
_p: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
_p: &'a Path,
|
||||||
|
_api_name: &str,
|
||||||
|
) -> Result<std::borrow::Cow<'a, Path>, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,9 +162,9 @@ impl deno_fs::FsPermissions for Permissions {
|
||||||
|
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
_path: &Path,
|
_path: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,17 +183,17 @@ impl deno_fs::FsPermissions for Permissions {
|
||||||
|
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
_path: &Path,
|
_path: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_write_partial(
|
fn check_write_partial(
|
||||||
&mut self,
|
&mut self,
|
||||||
_path: &Path,
|
_path: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,22 +209,38 @@ impl deno_fs::FsPermissions for Permissions {
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_read_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
_path: &'a Path,
|
||||||
|
_api_name: &str,
|
||||||
|
) -> Result<std::borrow::Cow<'a, Path>, AnyError> {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write_path<'a>(
|
||||||
|
&mut self,
|
||||||
|
_path: &'a Path,
|
||||||
|
_api_name: &str,
|
||||||
|
) -> Result<std::borrow::Cow<'a, Path>, AnyError> {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl deno_kv::sqlite::SqliteDbHandlerPermissions for Permissions {
|
impl deno_kv::sqlite::SqliteDbHandlerPermissions for Permissions {
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
_path: &Path,
|
_path: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_write(
|
fn check_write<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_path: &Path,
|
_path: &'a Path,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<Cow<'a, Path>, AnyError> {
|
||||||
unreachable!("snapshotting!")
|
unreachable!("snapshotting!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +290,7 @@ pub fn create_runtime_snapshot(
|
||||||
deno_http::deno_http::init_ops_and_esm::<DefaultHttpPropertyExtractor>(),
|
deno_http::deno_http::init_ops_and_esm::<DefaultHttpPropertyExtractor>(),
|
||||||
deno_io::deno_io::init_ops_and_esm(Default::default()),
|
deno_io::deno_io::init_ops_and_esm(Default::default()),
|
||||||
deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
|
deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
|
||||||
deno_node::deno_node::init_ops_and_esm::<Permissions>(None, fs),
|
deno_node::deno_node::init_ops_and_esm::<Permissions>(None, fs.clone()),
|
||||||
runtime::init_ops_and_esm(),
|
runtime::init_ops_and_esm(),
|
||||||
ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()),
|
ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()),
|
||||||
ops::worker_host::deno_worker_host::init_ops(
|
ops::worker_host::deno_worker_host::init_ops(
|
||||||
|
@ -264,7 +299,9 @@ pub fn create_runtime_snapshot(
|
||||||
),
|
),
|
||||||
ops::fs_events::deno_fs_events::init_ops(),
|
ops::fs_events::deno_fs_events::init_ops(),
|
||||||
ops::os::deno_os::init_ops(Default::default()),
|
ops::os::deno_os::init_ops(Default::default()),
|
||||||
ops::permissions::deno_permissions::init_ops(),
|
ops::permissions::deno_permissions::init_ops(Arc::new(
|
||||||
|
RuntimePermissionDescriptorParser::new(fs),
|
||||||
|
)),
|
||||||
ops::process::deno_process::init_ops(),
|
ops::process::deno_process::init_ops(),
|
||||||
ops::signal::deno_signal::init_ops(),
|
ops::signal::deno_signal::init_ops(),
|
||||||
ops::tty::deno_tty::init_ops(),
|
ops::tty::deno_tty::init_ops(),
|
||||||
|
|
|
@ -44,6 +44,7 @@ use deno_http::DefaultHttpPropertyExtractor;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::dynamic::MultiBackendDbHandler;
|
use deno_kv::dynamic::MultiBackendDbHandler;
|
||||||
use deno_node::NodeExtInitServices;
|
use deno_node::NodeExtInitServices;
|
||||||
|
use deno_permissions::PermissionDescriptorParser;
|
||||||
use deno_permissions::PermissionsContainer;
|
use deno_permissions::PermissionsContainer;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
@ -356,6 +357,7 @@ pub struct WebWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WebWorkerOptions {
|
pub struct WebWorkerOptions {
|
||||||
|
// todo(dsherret): extract out the service structs from this options bag
|
||||||
pub bootstrap: BootstrapOptions,
|
pub bootstrap: BootstrapOptions,
|
||||||
pub extensions: Vec<Extension>,
|
pub extensions: Vec<Extension>,
|
||||||
pub startup_snapshot: Option<&'static [u8]>,
|
pub startup_snapshot: Option<&'static [u8]>,
|
||||||
|
@ -377,6 +379,7 @@ pub struct WebWorkerOptions {
|
||||||
pub cache_storage_dir: Option<std::path::PathBuf>,
|
pub cache_storage_dir: Option<std::path::PathBuf>,
|
||||||
pub stdio: Stdio,
|
pub stdio: Stdio,
|
||||||
pub feature_checker: Arc<FeatureChecker>,
|
pub feature_checker: Arc<FeatureChecker>,
|
||||||
|
pub permission_desc_parser: Arc<dyn PermissionDescriptorParser>,
|
||||||
pub strace_ops: Option<Vec<String>>,
|
pub strace_ops: Option<Vec<String>>,
|
||||||
pub close_on_idle: bool,
|
pub close_on_idle: bool,
|
||||||
pub maybe_worker_metadata: Option<WorkerMetadata>,
|
pub maybe_worker_metadata: Option<WorkerMetadata>,
|
||||||
|
@ -501,7 +504,9 @@ impl WebWorker {
|
||||||
),
|
),
|
||||||
ops::fs_events::deno_fs_events::init_ops_and_esm(),
|
ops::fs_events::deno_fs_events::init_ops_and_esm(),
|
||||||
ops::os::deno_os_worker::init_ops_and_esm(),
|
ops::os::deno_os_worker::init_ops_and_esm(),
|
||||||
ops::permissions::deno_permissions::init_ops_and_esm(),
|
ops::permissions::deno_permissions::init_ops_and_esm(
|
||||||
|
options.permission_desc_parser.clone(),
|
||||||
|
),
|
||||||
ops::process::deno_process::init_ops_and_esm(),
|
ops::process::deno_process::init_ops_and_esm(),
|
||||||
ops::signal::deno_signal::init_ops_and_esm(),
|
ops::signal::deno_signal::init_ops_and_esm(),
|
||||||
ops::tty::deno_tty::init_ops_and_esm(),
|
ops::tty::deno_tty::init_ops_and_esm(),
|
||||||
|
|
|
@ -49,6 +49,7 @@ use crate::code_cache::CodeCache;
|
||||||
use crate::code_cache::CodeCacheType;
|
use crate::code_cache::CodeCacheType;
|
||||||
use crate::inspector_server::InspectorServer;
|
use crate::inspector_server::InspectorServer;
|
||||||
use crate::ops;
|
use crate::ops;
|
||||||
|
use crate::permissions::RuntimePermissionDescriptorParser;
|
||||||
use crate::shared::maybe_transpile_source;
|
use crate::shared::maybe_transpile_source;
|
||||||
use crate::shared::runtime;
|
use crate::shared::runtime;
|
||||||
use crate::BootstrapOptions;
|
use crate::BootstrapOptions;
|
||||||
|
@ -157,6 +158,8 @@ pub struct WorkerOptions {
|
||||||
/// executed tries to load modules.
|
/// executed tries to load modules.
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
pub node_services: Option<NodeExtInitServices>,
|
pub node_services: Option<NodeExtInitServices>,
|
||||||
|
pub permission_desc_parser:
|
||||||
|
Arc<dyn deno_permissions::PermissionDescriptorParser>,
|
||||||
// Callbacks invoked when creating new instance of WebWorker
|
// Callbacks invoked when creating new instance of WebWorker
|
||||||
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
||||||
pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>,
|
pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>,
|
||||||
|
@ -201,13 +204,16 @@ pub struct WorkerOptions {
|
||||||
pub v8_code_cache: Option<Arc<dyn CodeCache>>,
|
pub v8_code_cache: Option<Arc<dyn CodeCache>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo(dsherret): this is error prone to use. We should separate
|
||||||
|
// out the WorkerOptions from the services.
|
||||||
impl Default for WorkerOptions {
|
impl Default for WorkerOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
let real_fs = Arc::new(deno_fs::RealFs);
|
||||||
Self {
|
Self {
|
||||||
create_web_worker_cb: Arc::new(|_| {
|
create_web_worker_cb: Arc::new(|_| {
|
||||||
unimplemented!("web workers are not supported")
|
unimplemented!("web workers are not supported")
|
||||||
}),
|
}),
|
||||||
fs: Arc::new(deno_fs::RealFs),
|
fs: real_fs.clone(),
|
||||||
module_loader: Rc::new(FsModuleLoader),
|
module_loader: Rc::new(FsModuleLoader),
|
||||||
skip_op_registration: false,
|
skip_op_registration: false,
|
||||||
seed: None,
|
seed: None,
|
||||||
|
@ -232,6 +238,9 @@ impl Default for WorkerOptions {
|
||||||
bootstrap: Default::default(),
|
bootstrap: Default::default(),
|
||||||
stdio: Default::default(),
|
stdio: Default::default(),
|
||||||
feature_checker: Default::default(),
|
feature_checker: Default::default(),
|
||||||
|
permission_desc_parser: Arc::new(RuntimePermissionDescriptorParser::new(
|
||||||
|
real_fs,
|
||||||
|
)),
|
||||||
v8_code_cache: Default::default(),
|
v8_code_cache: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,7 +434,9 @@ impl MainWorker {
|
||||||
),
|
),
|
||||||
ops::fs_events::deno_fs_events::init_ops_and_esm(),
|
ops::fs_events::deno_fs_events::init_ops_and_esm(),
|
||||||
ops::os::deno_os::init_ops_and_esm(exit_code.clone()),
|
ops::os::deno_os::init_ops_and_esm(exit_code.clone()),
|
||||||
ops::permissions::deno_permissions::init_ops_and_esm(),
|
ops::permissions::deno_permissions::init_ops_and_esm(
|
||||||
|
options.permission_desc_parser,
|
||||||
|
),
|
||||||
ops::process::deno_process::init_ops_and_esm(),
|
ops::process::deno_process::init_ops_and_esm(),
|
||||||
ops::signal::deno_signal::init_ops_and_esm(),
|
ops::signal::deno_signal::init_ops_and_esm(),
|
||||||
ops::tty::deno_tty::init_ops_and_esm(),
|
ops::tty::deno_tty::init_ops_and_esm(),
|
||||||
|
|
|
@ -255,12 +255,6 @@ itest!(_052_no_remote_flag {
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(_056_make_temp_file_write_perm {
|
|
||||||
args:
|
|
||||||
"run --quiet --allow-read --allow-write=./subdir/ run/056_make_temp_file_write_perm.ts",
|
|
||||||
output: "run/056_make_temp_file_write_perm.out",
|
|
||||||
});
|
|
||||||
|
|
||||||
itest!(_058_tasks_microtasks_close {
|
itest!(_058_tasks_microtasks_close {
|
||||||
args: "run --quiet run/058_tasks_microtasks_close.ts",
|
args: "run --quiet run/058_tasks_microtasks_close.ts",
|
||||||
output: "run/058_tasks_microtasks_close.ts.out",
|
output: "run/058_tasks_microtasks_close.ts.out",
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"envs": {
|
||||||
|
"DYLD_FALLBACK_LIBRARY_PATH": "",
|
||||||
|
"LD_LIBRARY_PATH": ""
|
||||||
|
},
|
||||||
|
"args": "run --allow-run --deny-run=deno --allow-read main.ts",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
NotCapable: Requires run access to "deno", run again with the --allow-run flag
|
||||||
|
at [WILDCARD] {
|
||||||
|
name: "NotCapable"
|
||||||
|
}
|
||||||
|
NotCapable: Requires run access to "[WILDLINE]", run again with the --allow-run flag
|
||||||
|
at [WILDCARD] {
|
||||||
|
name: "NotCapable"
|
||||||
|
}
|
15
tests/specs/permission/deny_run_binary_absolute_path/main.ts
Normal file
15
tests/specs/permission/deny_run_binary_absolute_path/main.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
try {
|
||||||
|
new Deno.Command("deno", {
|
||||||
|
args: ["--version"],
|
||||||
|
}).outputSync();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new Deno.Command(Deno.execPath(), {
|
||||||
|
args: ["--version"],
|
||||||
|
}).outputSync();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
good [WILDCARD]subdir[WILDCARD]
|
||||||
|
good [WILDCARD]subdir[WILDCARD]
|
||||||
|
good [WILDCARD]subdir[WILDCARD]
|
||||||
|
good [WILDCARD]subdir[WILDCARD]
|
|
@ -0,0 +1,52 @@
|
||||||
|
Deno.mkdirSync("subdir");
|
||||||
|
|
||||||
|
// async file
|
||||||
|
{
|
||||||
|
const path = await Deno.makeTempFile({ dir: `subdir` });
|
||||||
|
try {
|
||||||
|
if (!path.match(/^subdir[/\\][^/\\]+/)) {
|
||||||
|
throw Error("bad " + path);
|
||||||
|
}
|
||||||
|
console.log("good", path);
|
||||||
|
} finally {
|
||||||
|
await Deno.remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sync file
|
||||||
|
{
|
||||||
|
const path = Deno.makeTempFileSync({ dir: `subdir` });
|
||||||
|
try {
|
||||||
|
if (!path.match(/^subdir[/\\][^/\\]+/)) {
|
||||||
|
throw Error("bad " + path);
|
||||||
|
}
|
||||||
|
console.log("good", path);
|
||||||
|
} finally {
|
||||||
|
await Deno.remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// async dir
|
||||||
|
{
|
||||||
|
const path = await Deno.makeTempDir({ dir: `subdir` });
|
||||||
|
try {
|
||||||
|
if (!path.match(/^subdir[/\\][^/\\]+/)) {
|
||||||
|
throw Error("bad " + path);
|
||||||
|
}
|
||||||
|
console.log("good", path);
|
||||||
|
} finally {
|
||||||
|
await Deno.remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync dir
|
||||||
|
{
|
||||||
|
const path = Deno.makeTempDirSync({ dir: `subdir` });
|
||||||
|
try {
|
||||||
|
if (!path.match(/^subdir[/\\][^/\\]+/)) {
|
||||||
|
throw Error("bad " + path);
|
||||||
|
}
|
||||||
|
console.log("good", path);
|
||||||
|
} finally {
|
||||||
|
await Deno.remove(path);
|
||||||
|
}
|
||||||
|
}
|
15
tests/specs/permission/make_temp_write_perm/__test__.jsonc
Normal file
15
tests/specs/permission/make_temp_write_perm/__test__.jsonc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"tests": {
|
||||||
|
"reduced_perms": {
|
||||||
|
// this should not expose the full directory
|
||||||
|
"args": "run --quiet --allow-read --allow-write=./subdir/ 056_make_temp_file_write_perm.ts",
|
||||||
|
"output": "056_make_temp_file_write_perm.out"
|
||||||
|
},
|
||||||
|
"all_perms": {
|
||||||
|
// this will work the same as above
|
||||||
|
"args": "run --quiet -A 056_make_temp_file_write_perm.ts",
|
||||||
|
"output": "056_make_temp_file_write_perm.out"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
{
|
{
|
||||||
"args": "run --quiet -A main.ts",
|
"tempDir": true,
|
||||||
"output": "main.out",
|
|
||||||
"envs": {
|
"envs": {
|
||||||
"DYLD_FALLBACK_LIBRARY_PATH": "",
|
"DYLD_FALLBACK_LIBRARY_PATH": "",
|
||||||
"LD_LIBRARY_PATH": ""
|
"LD_LIBRARY_PATH": ""
|
||||||
}
|
},
|
||||||
|
"args": "run --quiet -A main.ts",
|
||||||
|
"output": "main.out"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ PermissionStatus { state: "granted", onchange: null }
|
||||||
PermissionStatus { state: "prompt", onchange: null }
|
PermissionStatus { state: "prompt", onchange: null }
|
||||||
PermissionStatus { state: "granted", onchange: null }
|
PermissionStatus { state: "granted", onchange: null }
|
||||||
---
|
---
|
||||||
Info Failed to resolve 'deno' for allow-run: cannot find binary path
|
Info Failed to resolve 'binary' for allow-run: cannot find binary path
|
||||||
PermissionStatus { state: "prompt", onchange: null }
|
PermissionStatus { state: "prompt", onchange: null }
|
||||||
PermissionStatus { state: "prompt", onchange: null }
|
PermissionStatus { state: "prompt", onchange: null }
|
||||||
PermissionStatus { state: "prompt", onchange: null }
|
PermissionStatus { state: "prompt", onchange: null }
|
||||||
|
|
|
@ -1,36 +1,41 @@
|
||||||
// Testing the following (but with `deno` instead of `echo`):
|
// Testing the following:
|
||||||
// | `deno run --allow-run=echo` | `which path == "/usr/bin/echo"` at startup | `which path != "/usr/bin/echo"` at startup |
|
// | `deno run --allow-run=binary` | `which path == "/usr/bin/binary"` at startup | `which path != "/usr/bin/binary"` at startup |
|
||||||
// |-------------------------------------|--------------------------------------------|--------------------------------------------|
|
// |---------------------------------------|----------------------------------------------|--------------------------------------------|
|
||||||
// | **`Deno.Command("echo")`** | ✅ | ✅ |
|
// | **`Deno.Command("binary")`** | :white_check_mark: | :white_check_mark: |
|
||||||
// | **`Deno.Command("/usr/bin/echo")`** | ✅ | ❌ |
|
// | **`Deno.Command("/usr/bin/binary")`** | :white_check_mark: | :x: |
|
||||||
|
// | `deno run --allow-run=/usr/bin/binary | `which path == "/usr/bin/binary"` at runtime | `which path != "/usr/bin/binary"` at runtime |
|
||||||
|
// |---------------------------------------|----------------------------------------------|--------------------------------------------|
|
||||||
|
// | **`Deno.Command("binary")`** | :white_check_mark: | :x: |
|
||||||
|
// | **`Deno.Command("/usr/bin/binary")`** | :white_check_mark: | :white_check_mark: |
|
||||||
|
|
||||||
// | `deno run --allow-run=/usr/bin/echo | `which path == "/usr/bin/echo"` at runtime | `which path != "/usr/bin/echo"` at runtime |
|
const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary";
|
||||||
// |-------------------------------------|--------------------------------------------|--------------------------------------------|
|
const pathSep = Deno.build.os === "windows" ? "\\" : "/";
|
||||||
// | **`Deno.Command("echo")`** | ✅ | ❌ |
|
const cwd = Deno.cwd();
|
||||||
// | **`Deno.Command("/usr/bin/echo")`** | ✅ | ✅ |
|
const execPathParent = `${Deno.cwd()}${pathSep}sub`;
|
||||||
|
const execPath = `${execPathParent}${pathSep}${binaryName}`;
|
||||||
|
|
||||||
const execPath = Deno.execPath();
|
Deno.mkdirSync(execPathParent);
|
||||||
const execPathParent = execPath.replace(/[/\\][^/\\]+$/, "");
|
Deno.copyFileSync(Deno.execPath(), execPath);
|
||||||
|
|
||||||
const testUrl = `data:application/typescript;base64,${
|
const testUrl = `data:application/typescript;base64,${
|
||||||
btoa(`
|
btoa(`
|
||||||
console.error(await Deno.permissions.query({ name: "run", command: "deno" }));
|
console.error(await Deno.permissions.query({ name: "run", command: "binary" }));
|
||||||
console.error(await Deno.permissions.query({ name: "run", command: "${
|
console.error(await Deno.permissions.query({ name: "run", command: "${
|
||||||
execPath.replaceAll("\\", "\\\\")
|
execPath.replaceAll("\\", "\\\\")
|
||||||
}" }));
|
}" }));
|
||||||
Deno.env.set("PATH", "");
|
Deno.env.set("PATH", "");
|
||||||
console.error(await Deno.permissions.query({ name: "run", command: "deno" }));
|
console.error(await Deno.permissions.query({ name: "run", command: "binary" }));
|
||||||
console.error(await Deno.permissions.query({ name: "run", command: "${
|
console.error(await Deno.permissions.query({ name: "run", command: "${
|
||||||
execPath.replaceAll("\\", "\\\\")
|
execPath.replaceAll("\\", "\\\\")
|
||||||
}" }));
|
}" }));
|
||||||
`)
|
`)
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const process1 = await new Deno.Command(Deno.execPath(), {
|
await new Deno.Command(Deno.execPath(), {
|
||||||
args: [
|
args: [
|
||||||
"run",
|
"run",
|
||||||
"--allow-env",
|
"--allow-env",
|
||||||
"--allow-run=deno",
|
"--allow-run=binary",
|
||||||
testUrl,
|
testUrl,
|
||||||
],
|
],
|
||||||
stdout: "inherit",
|
stdout: "inherit",
|
||||||
|
@ -44,7 +49,7 @@ await new Deno.Command(Deno.execPath(), {
|
||||||
args: [
|
args: [
|
||||||
"run",
|
"run",
|
||||||
"--allow-env",
|
"--allow-env",
|
||||||
"--allow-run=deno",
|
"--allow-run=binary",
|
||||||
testUrl,
|
testUrl,
|
||||||
],
|
],
|
||||||
stderr: "inherit",
|
stderr: "inherit",
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
},
|
},
|
||||||
"tests": {
|
"tests": {
|
||||||
"env_arg": {
|
"env_arg": {
|
||||||
"args": "run --allow-run=echo env_arg.ts",
|
"args": "run --allow-run=curl env_arg.ts",
|
||||||
"output": "env_arg.out"
|
"output": "env_arg.out"
|
||||||
},
|
},
|
||||||
"set_with_allow_env": {
|
"set_with_allow_env": {
|
||||||
"args": "run --allow-run=echo --allow-env set_with_allow_env.ts",
|
"args": "run --allow-run=curl --allow-env set_with_allow_env.ts",
|
||||||
"output": "set_with_allow_env.out"
|
"output": "set_with_allow_env.out"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Deno.env.set("LD_PRELOAD", "./libpreload.so");
|
Deno.env.set("LD_PRELOAD", "./libpreload.so");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new Deno.Command("echo").spawn();
|
new Deno.Command("curl").spawn();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ try {
|
||||||
Deno.env.set("DYLD_FALLBACK_LIBRARY_PATH", "./libpreload.so");
|
Deno.env.set("DYLD_FALLBACK_LIBRARY_PATH", "./libpreload.so");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Deno.run({ cmd: ["echo"] }).spawnSync();
|
Deno.run({ cmd: ["curl"] }).spawnSync();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
good [WILDCARD]subdir[WILDCARD]
|
|
|
@ -1,9 +0,0 @@
|
||||||
const path = await Deno.makeTempFile({ dir: `subdir` });
|
|
||||||
try {
|
|
||||||
if (!path.match(/^subdir[/\\][^/\\]+/)) {
|
|
||||||
throw Error("bad " + path);
|
|
||||||
}
|
|
||||||
console.log("good", path);
|
|
||||||
} finally {
|
|
||||||
await Deno.remove(path);
|
|
||||||
}
|
|
|
@ -1,4 +1,16 @@
|
||||||
// deno-fmt-ignore-file
|
// deno-fmt-ignore-file
|
||||||
|
import { toFileUrl } from "@std/path/to-file-url";
|
||||||
|
|
||||||
|
function tryGetCwd() {
|
||||||
|
// will throw in one test but not the other
|
||||||
|
try {
|
||||||
|
return Deno.cwd()
|
||||||
|
} catch {
|
||||||
|
return import.meta.dirname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fooExePath = tryGetCwd() + "/foo" + (Deno.build.os === "windows" ? ".exe" : "");
|
||||||
postMessage({
|
postMessage({
|
||||||
envGlobal: (await Deno.permissions.query({ name: "env" })).state,
|
envGlobal: (await Deno.permissions.query({ name: "env" })).state,
|
||||||
envFoo: (await Deno.permissions.query({ name: "env", variable: "foo" })).state,
|
envFoo: (await Deno.permissions.query({ name: "env", variable: "foo" })).state,
|
||||||
|
@ -15,11 +27,13 @@ postMessage({
|
||||||
readGlobal: (await Deno.permissions.query({ name: "read" })).state,
|
readGlobal: (await Deno.permissions.query({ name: "read" })).state,
|
||||||
readFoo: (await Deno.permissions.query({ name: "read", path: new URL("foo", import.meta.url) })).state,
|
readFoo: (await Deno.permissions.query({ name: "read", path: new URL("foo", import.meta.url) })).state,
|
||||||
readBar: (await Deno.permissions.query({ name: "read", path: "bar" })).state,
|
readBar: (await Deno.permissions.query({ name: "read", path: "bar" })).state,
|
||||||
readAbsent: (await Deno.permissions.query({ name: "read", path: "absent" })).state,
|
readAbsent: (await Deno.permissions.query({ name: "read", path: "../absent" })).state,
|
||||||
runGlobal: (await Deno.permissions.query({ name: "run" })).state,
|
runGlobal: (await Deno.permissions.query({ name: "run" })).state,
|
||||||
runFoo: (await Deno.permissions.query({ name: "run", command: new URL("foo", import.meta.url) })).state,
|
runFoo: (await Deno.permissions.query({ name: "run", command: toFileUrl(fooExePath) })).state,
|
||||||
|
runFooPath: (await Deno.permissions.query({ name: "run", command: fooExePath })).state,
|
||||||
runBar: (await Deno.permissions.query({ name: "run", command: "bar" })).state,
|
runBar: (await Deno.permissions.query({ name: "run", command: "bar" })).state,
|
||||||
runBaz: (await Deno.permissions.query({ name: "run", command: "./baz" })).state,
|
runBaz: (await Deno.permissions.query({ name: "run", command: "./baz" })).state,
|
||||||
|
runUnresolved: (await Deno.permissions.query({ name: "run", command: "unresolved-exec" })).state,
|
||||||
runAbsent: (await Deno.permissions.query({ name: "run", command: "absent" })).state,
|
runAbsent: (await Deno.permissions.query({ name: "run", command: "absent" })).state,
|
||||||
writeGlobal: (await Deno.permissions.query({ name: "write" })).state,
|
writeGlobal: (await Deno.permissions.query({ name: "write" })).state,
|
||||||
writeFoo: (await Deno.permissions.query({ name: "write", path: new URL("foo", import.meta.url) })).state,
|
writeFoo: (await Deno.permissions.query({ name: "write", path: new URL("foo", import.meta.url) })).state,
|
||||||
|
|
|
@ -79,7 +79,9 @@ Deno.test(
|
||||||
) => {
|
) => {
|
||||||
const src = `
|
const src = `
|
||||||
console.log(
|
console.log(
|
||||||
${JSON.stringify(Object.keys(expectedEnv))}.map(k => Deno.env.get(k))
|
${
|
||||||
|
JSON.stringify(Object.keys(expectedEnv))
|
||||||
|
}.map(k => Deno.env.get(k) ?? null)
|
||||||
)`;
|
)`;
|
||||||
const { success, stdout } = await new Deno.Command(Deno.execPath(), {
|
const { success, stdout } = await new Deno.Command(Deno.execPath(), {
|
||||||
args: ["eval", src],
|
args: ["eval", src],
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
// Requires to be run with `--allow-net` flag
|
// Requires to be run with `--allow-net` flag
|
||||||
|
|
||||||
import { assert, assertEquals, assertMatch, assertThrows } from "@std/assert";
|
import { assert, assertEquals, assertMatch, assertThrows } from "@std/assert";
|
||||||
|
import { toFileUrl } from "@std/path/to-file-url";
|
||||||
|
|
||||||
function resolveWorker(worker: string): string {
|
function resolveWorker(worker: string): string {
|
||||||
return import.meta.resolve(`../testdata/workers/${worker}`);
|
return import.meta.resolve(`../testdata/workers/${worker}`);
|
||||||
|
@ -442,7 +443,31 @@ Deno.test("Worker limit children permissions", async function () {
|
||||||
worker.terminate();
|
worker.terminate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function setupReadCheckGranularWorkerTest() {
|
||||||
|
const tempDir = Deno.realPathSync(Deno.makeTempDirSync());
|
||||||
|
const initialPath = Deno.env.get("PATH")!;
|
||||||
|
const initialCwd = Deno.cwd();
|
||||||
|
Deno.chdir(tempDir);
|
||||||
|
const envSep = Deno.build.os === "windows" ? ";" : ":";
|
||||||
|
Deno.env.set("PATH", initialPath + envSep + tempDir);
|
||||||
|
|
||||||
|
// create executables that will be resolved when doing `which`
|
||||||
|
const ext = Deno.build.os === "windows" ? ".exe" : "";
|
||||||
|
Deno.copyFileSync(Deno.execPath(), tempDir + "/bar" + ext);
|
||||||
|
|
||||||
|
return {
|
||||||
|
tempDir,
|
||||||
|
runFooFilePath: tempDir + "/foo" + ext,
|
||||||
|
[Symbol.dispose]() {
|
||||||
|
Deno.removeSync(tempDir, { recursive: true });
|
||||||
|
Deno.env.set("PATH", initialPath);
|
||||||
|
Deno.chdir(initialCwd);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Deno.test("Worker limit children permissions granularly", async function () {
|
Deno.test("Worker limit children permissions granularly", async function () {
|
||||||
|
const ctx = setupReadCheckGranularWorkerTest();
|
||||||
const workerUrl = resolveWorker("read_check_granular_worker.js");
|
const workerUrl = resolveWorker("read_check_granular_worker.js");
|
||||||
const worker = new Worker(
|
const worker = new Worker(
|
||||||
workerUrl,
|
workerUrl,
|
||||||
|
@ -453,8 +478,13 @@ Deno.test("Worker limit children permissions granularly", async function () {
|
||||||
env: ["foo"],
|
env: ["foo"],
|
||||||
net: ["foo", "bar:8000"],
|
net: ["foo", "bar:8000"],
|
||||||
ffi: [new URL("foo", workerUrl), "bar"],
|
ffi: [new URL("foo", workerUrl), "bar"],
|
||||||
read: [new URL("foo", workerUrl), "bar"],
|
read: [new URL("foo", workerUrl), "bar", ctx.tempDir],
|
||||||
run: [new URL("foo", workerUrl), "bar", "./baz"],
|
run: [
|
||||||
|
toFileUrl(ctx.runFooFilePath),
|
||||||
|
"bar",
|
||||||
|
"./baz",
|
||||||
|
"unresolved-exec",
|
||||||
|
],
|
||||||
write: [new URL("foo", workerUrl), "bar"],
|
write: [new URL("foo", workerUrl), "bar"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -482,8 +512,10 @@ Deno.test("Worker limit children permissions granularly", async function () {
|
||||||
readAbsent: "prompt",
|
readAbsent: "prompt",
|
||||||
runGlobal: "prompt",
|
runGlobal: "prompt",
|
||||||
runFoo: "granted",
|
runFoo: "granted",
|
||||||
|
runFooPath: "granted",
|
||||||
runBar: "granted",
|
runBar: "granted",
|
||||||
runBaz: "granted",
|
runBaz: "granted",
|
||||||
|
runUnresolved: "prompt", // unresolved binaries remain as "prompt"
|
||||||
runAbsent: "prompt",
|
runAbsent: "prompt",
|
||||||
writeGlobal: "prompt",
|
writeGlobal: "prompt",
|
||||||
writeFoo: "granted",
|
writeFoo: "granted",
|
||||||
|
@ -494,6 +526,7 @@ Deno.test("Worker limit children permissions granularly", async function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test("Nested worker limit children permissions", async function () {
|
Deno.test("Nested worker limit children permissions", async function () {
|
||||||
|
const _cleanup = setupReadCheckGranularWorkerTest();
|
||||||
/** This worker has permissions but doesn't grant them to its children */
|
/** This worker has permissions but doesn't grant them to its children */
|
||||||
const worker = new Worker(
|
const worker = new Worker(
|
||||||
resolveWorker("parent_read_check_worker.js"),
|
resolveWorker("parent_read_check_worker.js"),
|
||||||
|
@ -521,8 +554,10 @@ Deno.test("Nested worker limit children permissions", async function () {
|
||||||
readAbsent: "prompt",
|
readAbsent: "prompt",
|
||||||
runGlobal: "prompt",
|
runGlobal: "prompt",
|
||||||
runFoo: "prompt",
|
runFoo: "prompt",
|
||||||
|
runFooPath: "prompt",
|
||||||
runBar: "prompt",
|
runBar: "prompt",
|
||||||
runBaz: "prompt",
|
runBaz: "prompt",
|
||||||
|
runUnresolved: "prompt",
|
||||||
runAbsent: "prompt",
|
runAbsent: "prompt",
|
||||||
writeGlobal: "prompt",
|
writeGlobal: "prompt",
|
||||||
writeFoo: "prompt",
|
writeFoo: "prompt",
|
||||||
|
|
|
@ -218,7 +218,7 @@ async function ensureNoNewITests() {
|
||||||
"pm_tests.rs": 0,
|
"pm_tests.rs": 0,
|
||||||
"publish_tests.rs": 0,
|
"publish_tests.rs": 0,
|
||||||
"repl_tests.rs": 0,
|
"repl_tests.rs": 0,
|
||||||
"run_tests.rs": 334,
|
"run_tests.rs": 333,
|
||||||
"shared_library_tests.rs": 0,
|
"shared_library_tests.rs": 0,
|
||||||
"task_tests.rs": 4,
|
"task_tests.rs": 4,
|
||||||
"test_tests.rs": 0,
|
"test_tests.rs": 0,
|
||||||
|
|
Loading…
Reference in a new issue