diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2024-11-04 09:17:21 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-04 09:17:21 -0800 |
commit | fe9f0ee5934871175758857899fe64e56c397fd5 (patch) | |
tree | ee770a45366d1b054e7429cea2eff56b04532830 /runtime | |
parent | fb1d33a7111e45e9b414cfe922a5db5ee4daf3ea (diff) |
refactor(runtime/permissions): use concrete error types (#26464)
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/errors.rs | 147 | ||||
-rw-r--r-- | runtime/ops/fs_events.rs | 5 | ||||
-rw-r--r-- | runtime/ops/os/mod.rs | 23 | ||||
-rw-r--r-- | runtime/ops/permissions.rs | 43 | ||||
-rw-r--r-- | runtime/ops/process.rs | 24 | ||||
-rw-r--r-- | runtime/ops/worker_host.rs | 2 | ||||
-rw-r--r-- | runtime/permissions.rs | 44 | ||||
-rw-r--r-- | runtime/permissions/Cargo.toml | 1 | ||||
-rw-r--r-- | runtime/permissions/lib.rs | 776 | ||||
-rw-r--r-- | runtime/permissions/prompter.rs | 69 | ||||
-rw-r--r-- | runtime/snapshot.rs | 64 |
11 files changed, 759 insertions, 439 deletions
diff --git a/runtime/errors.rs b/runtime/errors.rs index ada26ec35..5051150f2 100644 --- a/runtime/errors.rs +++ b/runtime/errors.rs @@ -12,6 +12,8 @@ use crate::ops::fs_events::FsEventsError; use crate::ops::http::HttpStartError; use crate::ops::os::OsError; +use crate::ops::permissions::PermissionError; +use crate::ops::process::CheckRunPermissionError; use crate::ops::process::ProcessError; use crate::ops::signal::SignalError; use crate::ops::tty::TtyError; @@ -48,6 +50,12 @@ use deno_kv::KvError; use deno_kv::KvMutationError; use deno_napi::NApiError; use deno_net::ops::NetError; +use deno_permissions::ChildPermissionError; +use deno_permissions::NetDescriptorFromUrlParseError; +use deno_permissions::PathResolveError; +use deno_permissions::PermissionCheckError; +use deno_permissions::RunDescriptorParseError; +use deno_permissions::SysDescriptorParseError; use deno_tls::TlsError; use deno_web::BlobError; use deno_web::CompressionError; @@ -63,6 +71,54 @@ use std::error::Error; use std::io; use std::sync::Arc; +fn get_run_descriptor_parse_error(e: &RunDescriptorParseError) -> &'static str { + match e { + RunDescriptorParseError::Which(_) => "Error", + RunDescriptorParseError::PathResolve(e) => get_path_resolve_error(e), + RunDescriptorParseError::EmptyRunQuery => "Error", + } +} + +fn get_sys_descriptor_parse_error(e: &SysDescriptorParseError) -> &'static str { + match e { + SysDescriptorParseError::InvalidKind(_) => "TypeError", + SysDescriptorParseError::Empty => "Error", + } +} + +fn get_path_resolve_error(e: &PathResolveError) -> &'static str { + match e { + PathResolveError::CwdResolve(e) => get_io_error_class(e), + PathResolveError::EmptyPath => "Error", + } +} + +fn get_permission_error_class(e: &PermissionError) -> &'static str { + match e { + PermissionError::InvalidPermissionName(_) => "ReferenceError", + PermissionError::PathResolve(e) => get_path_resolve_error(e), + PermissionError::NetDescriptorParse(_) => "URIError", + PermissionError::SysDescriptorParse(e) => get_sys_descriptor_parse_error(e), + PermissionError::RunDescriptorParse(e) => get_run_descriptor_parse_error(e), + } +} + +fn get_permission_check_error_class(e: &PermissionCheckError) -> &'static str { + match e { + PermissionCheckError::PermissionDenied(_) => "NotCapable", + PermissionCheckError::InvalidFilePath(_) => "URIError", + PermissionCheckError::NetDescriptorForUrlParse(e) => match e { + NetDescriptorFromUrlParseError::MissingHost(_) => "TypeError", + NetDescriptorFromUrlParseError::Host(_) => "URIError", + }, + PermissionCheckError::SysDescriptorParse(e) => { + get_sys_descriptor_parse_error(e) + } + PermissionCheckError::PathResolve(e) => get_path_resolve_error(e), + PermissionCheckError::HostParse(_) => "URIError", + } +} + fn get_dlopen_error_class(error: &dlopen2::Error) -> &'static str { use dlopen2::Error::*; match error { @@ -445,7 +501,7 @@ fn get_napi_error_class(e: &NApiError) -> &'static str { NApiError::InvalidPath | NApiError::LibLoading(_) | NApiError::ModuleNotFound(_) => "TypeError", - NApiError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + NApiError::Permission(e) => get_permission_check_error_class(e), } } @@ -523,7 +579,7 @@ fn get_ffi_repr_error_class(e: &ReprError) -> &'static str { ReprError::InvalidF32 => "TypeError", ReprError::InvalidF64 => "TypeError", ReprError::InvalidPointer => "TypeError", - ReprError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + ReprError::Permission(e) => get_permission_check_error_class(e), } } @@ -531,7 +587,7 @@ fn get_ffi_dlfcn_error_class(e: &DlfcnError) -> &'static str { match e { DlfcnError::RegisterSymbol { .. } => "Error", DlfcnError::Dlopen(_) => "Error", - DlfcnError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + DlfcnError::Permission(e) => get_permission_check_error_class(e), DlfcnError::Other(e) => get_error_class_name(e).unwrap_or("Error"), } } @@ -549,7 +605,7 @@ fn get_ffi_callback_error_class(e: &CallbackError) -> &'static str { match e { CallbackError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), CallbackError::Other(e) => get_error_class_name(e).unwrap_or("Error"), - CallbackError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + CallbackError::Permission(e) => get_permission_check_error_class(e), } } @@ -558,8 +614,9 @@ fn get_ffi_call_error_class(e: &CallError) -> &'static str { CallError::IR(_) => "TypeError", CallError::NonblockingCallFailure(_) => "Error", CallError::InvalidSymbol(_) => "TypeError", - CallError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + CallError::Permission(e) => get_permission_check_error_class(e), CallError::Callback(e) => get_ffi_callback_error_class(e), + CallError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), } } @@ -633,9 +690,8 @@ fn get_broadcast_channel_error(error: &BroadcastChannelError) -> &'static str { fn get_fetch_error(error: &FetchError) -> &'static str { match error { - FetchError::Resource(e) | FetchError::Permission(e) => { - get_error_class_name(e).unwrap_or("Error") - } + FetchError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + FetchError::Permission(e) => get_permission_check_error_class(e), FetchError::NetworkError => "TypeError", FetchError::FsNotGet(_) => "TypeError", FetchError::InvalidUrl(_) => "TypeError", @@ -669,9 +725,8 @@ fn get_http_client_create_error(error: &HttpClientCreateError) -> &'static str { fn get_websocket_error(error: &WebsocketError) -> &'static str { match error { - WebsocketError::Permission(e) | WebsocketError::Resource(e) => { - get_error_class_name(e).unwrap_or("Error") - } + WebsocketError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + WebsocketError::Permission(e) => get_permission_check_error_class(e), WebsocketError::Url(e) => get_url_parse_error_class(e), WebsocketError::Io(e) => get_io_error_class(e), WebsocketError::WebSocket(_) => "TypeError", @@ -708,9 +763,10 @@ fn get_fs_ops_error(error: &FsOpsError) -> &'static str { match error { FsOpsError::Io(e) => get_io_error_class(e), FsOpsError::OperationError(e) => get_fs_error(&e.err), - FsOpsError::Permission(e) - | FsOpsError::Resource(e) - | FsOpsError::Other(e) => get_error_class_name(e).unwrap_or("Error"), + FsOpsError::Permission(e) => get_permission_check_error_class(e), + FsOpsError::Resource(e) | FsOpsError::Other(e) => { + get_error_class_name(e).unwrap_or("Error") + } FsOpsError::InvalidUtf8(_) => "InvalidData", FsOpsError::StripPrefix(_) => "Error", FsOpsError::Canceled(e) => { @@ -777,9 +833,10 @@ fn get_net_error(error: &NetError) -> &'static str { NetError::SocketBusy => "Busy", NetError::Io(e) => get_io_error_class(e), NetError::AcceptTaskOngoing => "Busy", - NetError::RootCertStore(e) - | NetError::Permission(e) - | NetError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + NetError::RootCertStore(e) | NetError::Resource(e) => { + get_error_class_name(e).unwrap_or("Error") + } + NetError::Permission(e) => get_permission_check_error_class(e), NetError::NoResolvedAddress => "Error", NetError::AddrParse(_) => "Error", NetError::Map(e) => get_net_map_error(e), @@ -810,12 +867,25 @@ fn get_net_map_error(error: &deno_net::io::MapError) -> &'static str { } } +fn get_child_permission_error(e: &ChildPermissionError) -> &'static str { + match e { + ChildPermissionError::Escalation => "NotCapable", + ChildPermissionError::PathResolve(e) => get_path_resolve_error(e), + ChildPermissionError::NetDescriptorParse(_) => "URIError", + ChildPermissionError::EnvDescriptorParse(_) => "Error", + ChildPermissionError::SysDescriptorParse(e) => { + get_sys_descriptor_parse_error(e) + } + ChildPermissionError::RunDescriptorParse(e) => { + get_run_descriptor_parse_error(e) + } + } +} + fn get_create_worker_error(error: &CreateWorkerError) -> &'static str { match error { CreateWorkerError::ClassicWorkers => "DOMExceptionNotSupportedError", - CreateWorkerError::Permission(e) => { - get_error_class_name(e).unwrap_or("Error") - } + CreateWorkerError::Permission(e) => get_child_permission_error(e), CreateWorkerError::ModuleResolution(e) => { get_module_resolution_error_class(e) } @@ -862,9 +932,8 @@ fn get_signal_error(error: &SignalError) -> &'static str { fn get_fs_events_error(error: &FsEventsError) -> &'static str { match error { - FsEventsError::Resource(e) | FsEventsError::Permission(e) => { - get_error_class_name(e).unwrap_or("Error") - } + FsEventsError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), + FsEventsError::Permission(e) => get_permission_check_error_class(e), FsEventsError::Notify(e) => get_notify_error_class(e), FsEventsError::Canceled(e) => { let io_err: io::Error = e.to_owned().into(); @@ -892,9 +961,8 @@ fn get_process_error(error: &ProcessError) -> &'static str { ProcessError::FailedResolvingCwd(e) | ProcessError::Io(e) => { get_io_error_class(e) } - ProcessError::Permission(e) | ProcessError::Resource(e) => { - get_error_class_name(e).unwrap_or("Error") - } + ProcessError::Permission(e) => get_permission_check_error_class(e), + ProcessError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), ProcessError::BorrowMut(_) => "Error", ProcessError::Which(_) => "Error", ProcessError::ChildProcessAlreadyTerminated => "TypeError", @@ -903,6 +971,14 @@ fn get_process_error(error: &ProcessError) -> &'static str { ProcessError::InvalidPid => "TypeError", #[cfg(unix)] ProcessError::Nix(e) => get_nix_error_class(e), + ProcessError::RunPermission(e) => match e { + CheckRunPermissionError::Permission(e) => { + get_permission_check_error_class(e) + } + CheckRunPermissionError::Other(e) => { + get_error_class_name(e).unwrap_or("Error") + } + }, } } @@ -971,6 +1047,7 @@ fn get_fs_error(e: &FsError) -> &'static str { mod node { use super::get_error_class_name; use super::get_io_error_class; + use super::get_permission_check_error_class; use super::get_serde_json_error_class; use super::get_url_parse_error_class; pub use deno_node::ops::blocklist::BlocklistError; @@ -998,7 +1075,7 @@ mod node { pub fn get_fs_error(error: &FsError) -> &'static str { match error { - FsError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + FsError::Permission(e) => get_permission_check_error_class(e), FsError::Io(e) => get_io_error_class(e), #[cfg(windows)] FsError::PathHasNoRoot => "Error", @@ -1084,7 +1161,7 @@ mod node { #[cfg(windows)] PriorityError::InvalidPriority => "TypeError", }, - OsError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + OsError::Permission(e) => get_permission_check_error_class(e), OsError::FailedToGetCpuInfo => "TypeError", OsError::FailedToGetUserInfo(e) => get_io_error_class(e), } @@ -1116,7 +1193,7 @@ mod node { fn get_os_error(error: &OsError) -> &'static str { match error { - OsError::Permission(e) => get_error_class_name(e).unwrap_or("Error"), + OsError::Permission(e) => get_permission_check_error_class(e), OsError::InvalidUtf8(_) => "InvalidData", OsError::EnvEmptyKey => "TypeError", OsError::EnvInvalidKey(_) => "TypeError", @@ -1144,6 +1221,18 @@ fn get_sync_fetch_error(error: &SyncFetchError) -> &'static str { pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { deno_core::error::get_custom_error_class(e) + .or_else(|| { + e.downcast_ref::<ChildPermissionError>() + .map(get_child_permission_error) + }) + .or_else(|| { + e.downcast_ref::<PermissionCheckError>() + .map(get_permission_check_error_class) + }) + .or_else(|| { + e.downcast_ref::<PermissionError>() + .map(get_permission_error_class) + }) .or_else(|| e.downcast_ref::<FsError>().map(get_fs_error)) .or_else(|| { e.downcast_ref::<node::BlocklistError>() diff --git a/runtime/ops/fs_events.rs b/runtime/ops/fs_events.rs index 648553376..c8e0228bc 100644 --- a/runtime/ops/fs_events.rs +++ b/runtime/ops/fs_events.rs @@ -114,7 +114,7 @@ pub enum FsEventsError { #[error(transparent)] Resource(deno_core::error::AnyError), #[error(transparent)] - Permission(deno_core::error::AnyError), + Permission(#[from] deno_permissions::PermissionCheckError), #[error(transparent)] Notify(#[from] NotifyError), #[error(transparent)] @@ -181,8 +181,7 @@ fn op_fs_events_open( for path in &paths { let path = state .borrow_mut::<PermissionsContainer>() - .check_read(path, "Deno.watchFs()") - .map_err(FsEventsError::Permission)?; + .check_read(path, "Deno.watchFs()")?; let watcher = state.borrow_mut::<WatcherState>(); watcher.watcher.watch(&path, recursive_mode)?; diff --git a/runtime/ops/os/mod.rs b/runtime/ops/os/mod.rs index 24b0389e1..9bee9d823 100644 --- a/runtime/ops/os/mod.rs +++ b/runtime/ops/os/mod.rs @@ -73,7 +73,7 @@ deno_core::extension!( #[derive(Debug, thiserror::Error)] pub enum OsError { #[error(transparent)] - Permission(deno_core::error::AnyError), + Permission(#[from] deno_permissions::PermissionCheckError), #[error("File name or path {0:?} is not valid UTF-8")] InvalidUtf8(std::ffi::OsString), #[error("Key is an empty string.")] @@ -94,8 +94,7 @@ fn op_exec_path(state: &mut OpState) -> Result<String, OsError> { let current_exe = env::current_exe().unwrap(); state .borrow_mut::<PermissionsContainer>() - .check_read_blind(¤t_exe, "exec_path", "Deno.execPath()") - .map_err(OsError::Permission)?; + .check_read_blind(¤t_exe, "exec_path", "Deno.execPath()")?; // normalize path so it doesn't include '.' or '..' components let path = normalize_path(current_exe); @@ -111,10 +110,7 @@ fn op_set_env( #[string] key: &str, #[string] value: &str, ) -> Result<(), OsError> { - state - .borrow_mut::<PermissionsContainer>() - .check_env(key) - .map_err(OsError::Permission)?; + state.borrow_mut::<PermissionsContainer>().check_env(key)?; if key.is_empty() { return Err(OsError::EnvEmptyKey); } @@ -146,10 +142,7 @@ fn op_get_env( let skip_permission_check = NODE_ENV_VAR_ALLOWLIST.contains(&key); if !skip_permission_check { - state - .borrow_mut::<PermissionsContainer>() - .check_env(&key) - .map_err(OsError::Permission)?; + state.borrow_mut::<PermissionsContainer>().check_env(&key)?; } if key.is_empty() { @@ -172,10 +165,7 @@ fn op_delete_env( state: &mut OpState, #[string] key: String, ) -> Result<(), OsError> { - state - .borrow_mut::<PermissionsContainer>() - .check_env(&key) - .map_err(OsError::Permission)?; + state.borrow_mut::<PermissionsContainer>().check_env(&key)?; if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { return Err(OsError::EnvInvalidKey(key.to_string())); } @@ -240,8 +230,7 @@ fn op_network_interfaces( ) -> Result<Vec<NetworkInterface>, OsError> { state .borrow_mut::<PermissionsContainer>() - .check_sys("networkInterfaces", "Deno.networkInterfaces()") - .map_err(OsError::Permission)?; + .check_sys("networkInterfaces", "Deno.networkInterfaces()")?; Ok(netif::up()?.map(NetworkInterface::from).collect()) } diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs index 1dbc85259..9ad963f3b 100644 --- a/runtime/ops/permissions.rs +++ b/runtime/ops/permissions.rs @@ -2,8 +2,6 @@ use ::deno_permissions::PermissionState; use ::deno_permissions::PermissionsContainer; -use deno_core::error::custom_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use serde::Deserialize; @@ -47,12 +45,26 @@ impl From<PermissionState> for PermissionStatus { } } +#[derive(Debug, thiserror::Error)] +pub enum PermissionError { + #[error("No such permission name: {0}")] + InvalidPermissionName(String), + #[error("{0}")] + PathResolve(#[from] ::deno_permissions::PathResolveError), + #[error("{0}")] + NetDescriptorParse(#[from] ::deno_permissions::NetDescriptorParseError), + #[error("{0}")] + SysDescriptorParse(#[from] ::deno_permissions::SysDescriptorParseError), + #[error("{0}")] + RunDescriptorParse(#[from] ::deno_permissions::RunDescriptorParseError), +} + #[op2] #[serde] pub fn op_query_permission( state: &mut OpState, #[serde] args: PermissionArgs, -) -> Result<PermissionStatus, AnyError> { +) -> Result<PermissionStatus, PermissionError> { let permissions = state.borrow::<PermissionsContainer>(); let perm = match args.name.as_ref() { "read" => permissions.query_read(args.path.as_deref())?, @@ -62,12 +74,7 @@ pub fn op_query_permission( "sys" => permissions.query_sys(args.kind.as_deref())?, "run" => permissions.query_run(args.command.as_deref())?, "ffi" => permissions.query_ffi(args.path.as_deref())?, - n => { - return Err(custom_error( - "ReferenceError", - format!("No such permission name: {n}"), - )) - } + _ => return Err(PermissionError::InvalidPermissionName(args.name)), }; Ok(PermissionStatus::from(perm)) } @@ -77,7 +84,7 @@ pub fn op_query_permission( pub fn op_revoke_permission( state: &mut OpState, #[serde] args: PermissionArgs, -) -> Result<PermissionStatus, AnyError> { +) -> Result<PermissionStatus, PermissionError> { let permissions = state.borrow::<PermissionsContainer>(); let perm = match args.name.as_ref() { "read" => permissions.revoke_read(args.path.as_deref())?, @@ -87,12 +94,7 @@ pub fn op_revoke_permission( "sys" => permissions.revoke_sys(args.kind.as_deref())?, "run" => permissions.revoke_run(args.command.as_deref())?, "ffi" => permissions.revoke_ffi(args.path.as_deref())?, - n => { - return Err(custom_error( - "ReferenceError", - format!("No such permission name: {n}"), - )) - } + _ => return Err(PermissionError::InvalidPermissionName(args.name)), }; Ok(PermissionStatus::from(perm)) } @@ -102,7 +104,7 @@ pub fn op_revoke_permission( pub fn op_request_permission( state: &mut OpState, #[serde] args: PermissionArgs, -) -> Result<PermissionStatus, AnyError> { +) -> Result<PermissionStatus, PermissionError> { let permissions = state.borrow::<PermissionsContainer>(); let perm = match args.name.as_ref() { "read" => permissions.request_read(args.path.as_deref())?, @@ -112,12 +114,7 @@ pub fn op_request_permission( "sys" => permissions.request_sys(args.kind.as_deref())?, "run" => permissions.request_run(args.command.as_deref())?, "ffi" => permissions.request_ffi(args.path.as_deref())?, - n => { - return Err(custom_error( - "ReferenceError", - format!("No such permission name: {n}"), - )) - } + _ => return Err(PermissionError::InvalidPermissionName(args.name)), }; Ok(PermissionStatus::from(perm)) } diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index 28913f7c1..de3141f1f 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -206,7 +206,9 @@ pub enum ProcessError { #[error("failed resolving cwd: {0}")] FailedResolvingCwd(#[source] std::io::Error), #[error(transparent)] - Permission(deno_core::error::AnyError), + Permission(#[from] deno_permissions::PermissionCheckError), + #[error(transparent)] + RunPermission(#[from] CheckRunPermissionError), #[error(transparent)] Resource(deno_core::error::AnyError), #[error(transparent)] @@ -653,8 +655,7 @@ fn compute_run_cmd_and_check_permissions( }, &run_env, api_name, - ) - .map_err(ProcessError::Permission)?; + )?; Ok((cmd, run_env)) } @@ -734,12 +735,20 @@ fn resolve_path(path: &str, cwd: &Path) -> PathBuf { deno_path_util::normalize_path(cwd.join(path)) } +#[derive(Debug, thiserror::Error)] +pub enum CheckRunPermissionError { + #[error(transparent)] + Permission(#[from] deno_permissions::PermissionCheckError), + #[error("{0}")] + Other(deno_core::error::AnyError), +} + fn check_run_permission( state: &mut OpState, cmd: &RunQueryDescriptor, run_env: &RunEnv, api_name: &str, -) -> Result<(), deno_core::error::AnyError> { +) -> Result<(), CheckRunPermissionError> { let permissions = state.borrow_mut::<PermissionsContainer>(); if !permissions.query_run_all(api_name) { // error the same on all platforms @@ -747,14 +756,14 @@ fn check_run_permission( if !env_var_names.is_empty() { // we don't allow users to launch subprocesses with any LD_ or DYLD_* // env vars set because this allows executing code (ex. LD_PRELOAD) - return Err(deno_core::error::custom_error( + return Err(CheckRunPermissionError::Other(deno_core::error::custom_error( "NotCapable", format!( "Requires --allow-all permissions to spawn subprocess with {} environment variable{}.", env_var_names.join(", "), if env_var_names.len() != 1 { "s" } else { "" } ) - )); + ))); } permissions.check_run(cmd, api_name)?; } @@ -1126,8 +1135,7 @@ mod deprecated { ) -> Result<(), ProcessError> { state .borrow_mut::<PermissionsContainer>() - .check_run_all(&api_name) - .map_err(ProcessError::Permission)?; + .check_run_all(&api_name)?; kill(pid, &signal) } } diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index 82cc94924..521284a6a 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -123,7 +123,7 @@ pub enum CreateWorkerError { #[error("Classic workers are not supported.")] ClassicWorkers, #[error(transparent)] - Permission(deno_core::error::AnyError), + Permission(deno_permissions::ChildPermissionError), #[error(transparent)] ModuleResolution(#[from] deno_core::ModuleResolutionError), #[error(transparent)] diff --git a/runtime/permissions.rs b/runtime/permissions.rs index fa62227e0..e8460e03f 100644 --- a/runtime/permissions.rs +++ b/runtime/permissions.rs @@ -3,9 +3,6 @@ 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_path_util::normalize_path; use deno_permissions::AllowRunDescriptor; use deno_permissions::AllowRunDescriptorParseResult; @@ -15,9 +12,12 @@ use deno_permissions::FfiDescriptor; use deno_permissions::ImportDescriptor; use deno_permissions::NetDescriptor; use deno_permissions::PathQueryDescriptor; +use deno_permissions::PathResolveError; use deno_permissions::ReadDescriptor; +use deno_permissions::RunDescriptorParseError; use deno_permissions::RunQueryDescriptor; use deno_permissions::SysDescriptor; +use deno_permissions::SysDescriptorParseError; use deno_permissions::WriteDescriptor; #[derive(Debug)] @@ -30,9 +30,9 @@ impl RuntimePermissionDescriptorParser { Self { fs } } - fn resolve_from_cwd(&self, path: &str) -> Result<PathBuf, AnyError> { + fn resolve_from_cwd(&self, path: &str) -> Result<PathBuf, PathResolveError> { if path.is_empty() { - bail!("Empty path is not allowed"); + return Err(PathResolveError::EmptyPath); } let path = Path::new(path); if path.is_absolute() { @@ -43,12 +43,11 @@ impl RuntimePermissionDescriptorParser { } } - fn resolve_cwd(&self) -> Result<PathBuf, AnyError> { + fn resolve_cwd(&self) -> Result<PathBuf, PathResolveError> { self .fs .cwd() - .map_err(|e| e.into_io_error()) - .context("failed resolving cwd") + .map_err(|e| PathResolveError::CwdResolve(e.into_io_error())) } } @@ -58,37 +57,37 @@ impl deno_permissions::PermissionDescriptorParser fn parse_read_descriptor( &self, text: &str, - ) -> Result<ReadDescriptor, AnyError> { + ) -> Result<ReadDescriptor, PathResolveError> { Ok(ReadDescriptor(self.resolve_from_cwd(text)?)) } fn parse_write_descriptor( &self, text: &str, - ) -> Result<WriteDescriptor, AnyError> { + ) -> Result<WriteDescriptor, PathResolveError> { Ok(WriteDescriptor(self.resolve_from_cwd(text)?)) } fn parse_net_descriptor( &self, text: &str, - ) -> Result<NetDescriptor, AnyError> { + ) -> Result<NetDescriptor, deno_permissions::NetDescriptorParseError> { NetDescriptor::parse(text) } fn parse_import_descriptor( &self, text: &str, - ) -> Result<ImportDescriptor, AnyError> { + ) -> Result<ImportDescriptor, deno_permissions::NetDescriptorParseError> { ImportDescriptor::parse(text) } fn parse_env_descriptor( &self, text: &str, - ) -> Result<EnvDescriptor, AnyError> { + ) -> Result<EnvDescriptor, deno_permissions::EnvDescriptorParseError> { if text.is_empty() { - Err(AnyError::msg("Empty env not allowed")) + Err(deno_permissions::EnvDescriptorParseError) } else { Ok(EnvDescriptor::new(text)) } @@ -97,9 +96,9 @@ impl deno_permissions::PermissionDescriptorParser fn parse_sys_descriptor( &self, text: &str, - ) -> Result<deno_permissions::SysDescriptor, AnyError> { + ) -> Result<SysDescriptor, SysDescriptorParseError> { if text.is_empty() { - Err(AnyError::msg("Empty sys not allowed")) + Err(SysDescriptorParseError::Empty) } else { Ok(SysDescriptor::parse(text.to_string())?) } @@ -108,21 +107,21 @@ impl deno_permissions::PermissionDescriptorParser fn parse_allow_run_descriptor( &self, text: &str, - ) -> Result<AllowRunDescriptorParseResult, AnyError> { + ) -> Result<AllowRunDescriptorParseResult, RunDescriptorParseError> { Ok(AllowRunDescriptor::parse(text, &self.resolve_cwd()?)?) } fn parse_deny_run_descriptor( &self, text: &str, - ) -> Result<DenyRunDescriptor, AnyError> { + ) -> Result<DenyRunDescriptor, PathResolveError> { Ok(DenyRunDescriptor::parse(text, &self.resolve_cwd()?)) } fn parse_ffi_descriptor( &self, text: &str, - ) -> Result<deno_permissions::FfiDescriptor, AnyError> { + ) -> Result<FfiDescriptor, PathResolveError> { Ok(FfiDescriptor(self.resolve_from_cwd(text)?)) } @@ -131,7 +130,7 @@ impl deno_permissions::PermissionDescriptorParser fn parse_path_query( &self, path: &str, - ) -> Result<PathQueryDescriptor, AnyError> { + ) -> Result<PathQueryDescriptor, PathResolveError> { Ok(PathQueryDescriptor { resolved: self.resolve_from_cwd(path)?, requested: path.to_string(), @@ -141,11 +140,12 @@ impl deno_permissions::PermissionDescriptorParser fn parse_run_query( &self, requested: &str, - ) -> Result<RunQueryDescriptor, AnyError> { + ) -> Result<RunQueryDescriptor, RunDescriptorParseError> { if requested.is_empty() { - bail!("Empty run query is not allowed"); + return Err(RunDescriptorParseError::EmptyRunQuery); } RunQueryDescriptor::parse(requested) + .map_err(RunDescriptorParseError::PathResolve) } } diff --git a/runtime/permissions/Cargo.toml b/runtime/permissions/Cargo.toml index bfa37b489..f0b2e71b5 100644 --- a/runtime/permissions/Cargo.toml +++ b/runtime/permissions/Cargo.toml @@ -23,6 +23,7 @@ log.workspace = true once_cell.workspace = true percent-encoding = { version = "2.3.1", features = [] } serde.workspace = true +thiserror.workspace = true which.workspace = true [target.'cfg(windows)'.dependencies] diff --git a/runtime/permissions/lib.rs b/runtime/permissions/lib.rs index 84503f025..6480f4bf5 100644 --- a/runtime/permissions/lib.rs +++ b/runtime/permissions/lib.rs @@ -1,11 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::anyhow::bail; -use deno_core::anyhow::Context; -use deno_core::error::custom_error; -use deno_core::error::type_error; -use deno_core::error::uri_error; -use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::serde::de; use deno_core::serde::Deserialize; @@ -43,6 +37,21 @@ pub use prompter::PermissionPrompter; pub use prompter::PromptCallback; pub use prompter::PromptResponse; +#[derive(Debug, thiserror::Error)] +#[error("Requires {access}, {}", format_permission_error(.name))] +pub struct PermissionDeniedError { + access: String, + name: &'static str, +} + +fn format_permission_error(name: &'static str) -> String { + if is_standalone() { + format!("specify the required permissions during compilation using `deno compile --allow-{name}`") + } else { + format!("run again with the --allow-{name} flag") + } +} + /// Fast exit from permission check routines if this permission /// is in the "fully-granted" state. macro_rules! skip_check_if_is_permission_fully_granted { @@ -104,7 +113,10 @@ impl From<bool> for AllowPartial { impl PermissionState { #[inline(always)] - fn log_perm_access(name: &str, info: impl FnOnce() -> Option<String>) { + fn log_perm_access( + name: &'static str, + info: impl FnOnce() -> Option<String>, + ) { // Eliminates log overhead (when logging is disabled), // log_enabled!(Debug) check in a hot path still has overhead // TODO(AaronO): generalize or upstream this optimization @@ -120,53 +132,47 @@ impl PermissionState { } } - fn fmt_access(name: &str, info: impl FnOnce() -> Option<String>) -> String { + fn fmt_access( + name: &'static str, + info: impl FnOnce() -> Option<String>, + ) -> String { format!( "{} access{}", name, - info() - .map(|info| { format!(" to {info}") }) - .unwrap_or_default(), + info().map(|info| format!(" to {info}")).unwrap_or_default(), ) } - fn error(name: &str, info: impl FnOnce() -> Option<String>) -> AnyError { - let msg = if is_standalone() { - format!( - "Requires {}, specify the required permissions during compilation using `deno compile --allow-{}`", - Self::fmt_access(name, info), - name - ) - } else { - format!( - "Requires {}, run again with the --allow-{} flag", - Self::fmt_access(name, info), - name - ) - }; - custom_error("NotCapable", msg) + fn error( + name: &'static str, + info: impl FnOnce() -> Option<String>, + ) -> PermissionDeniedError { + PermissionDeniedError { + access: Self::fmt_access(name, info), + name, + } } /// Check the permission state. bool is whether a prompt was issued. #[inline] fn check( self, - name: &str, + name: &'static str, api_name: Option<&str>, info: Option<&str>, prompt: bool, - ) -> (Result<(), AnyError>, bool, bool) { + ) -> (Result<(), PermissionDeniedError>, bool, bool) { self.check2(name, api_name, || info.map(|s| s.to_string()), prompt) } #[inline] fn check2( self, - name: &str, + name: &'static str, api_name: Option<&str>, info: impl Fn() -> Option<String>, prompt: bool, - ) -> (Result<(), AnyError>, bool, bool) { + ) -> (Result<(), PermissionDeniedError>, bool, bool) { match self { PermissionState::Granted => { Self::log_perm_access(name, info); @@ -246,7 +252,7 @@ impl UnitPermission { self.state } - pub fn check(&mut self) -> Result<(), AnyError> { + pub fn check(&mut self) -> Result<(), PermissionDeniedError> { let (result, prompted, _is_allow_all) = self.state.check(self.name, None, None, self.prompt); if prompted { @@ -262,7 +268,7 @@ impl UnitPermission { fn create_child_permissions( &mut self, flag: ChildUnitPermissionArg, - ) -> Result<Self, AnyError> { + ) -> Result<Self, ChildPermissionError> { let mut perm = self.clone(); match flag { ChildUnitPermissionArg::Inherit => { @@ -270,7 +276,7 @@ impl UnitPermission { } ChildUnitPermissionArg::Granted => { if self.check().is_err() { - return Err(escalation_error()); + return Err(ChildPermissionError::Escalation); } perm.state = PermissionState::Granted; } @@ -327,7 +333,7 @@ pub trait QueryDescriptor: Debug { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError>; + ) -> Result<(), PermissionDeniedError>; fn matches_allow(&self, other: &Self::AllowDesc) -> bool; fn matches_deny(&self, other: &Self::DenyDesc) -> bool; @@ -402,7 +408,7 @@ impl<TQuery: QueryDescriptor> UnaryPermission<TQuery> { pub fn check_all_api( &mut self, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, api_name) } @@ -412,7 +418,7 @@ impl<TQuery: QueryDescriptor> UnaryPermission<TQuery> { desc: Option<&TQuery>, assert_non_partial: bool, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { let (result, prompted, is_allow_all) = self .query_desc(desc, AllowPartial::from(!assert_non_partial)) .check2( @@ -599,11 +605,14 @@ impl<TQuery: QueryDescriptor> UnaryPermission<TQuery> { } } - fn create_child_permissions( + fn create_child_permissions<E>( &mut self, flag: ChildUnaryPermissionArg, - parse: impl Fn(&str) -> Result<Option<TQuery::AllowDesc>, AnyError>, - ) -> Result<UnaryPermission<TQuery>, AnyError> { + parse: impl Fn(&str) -> Result<Option<TQuery::AllowDesc>, E>, + ) -> Result<UnaryPermission<TQuery>, ChildPermissionError> + where + ChildPermissionError: From<E>, + { let mut perms = Self::default(); match flag { @@ -612,7 +621,7 @@ impl<TQuery: QueryDescriptor> UnaryPermission<TQuery> { } ChildUnaryPermissionArg::Granted => { if self.check_all_api(None).is_err() { - return Err(escalation_error()); + return Err(ChildPermissionError::Escalation); } perms.granted_global = true; } @@ -621,13 +630,13 @@ impl<TQuery: QueryDescriptor> UnaryPermission<TQuery> { perms.granted_list = granted_list .iter() .filter_map(|i| parse(i).transpose()) - .collect::<Result<_, _>>()?; + .collect::<Result<_, E>>()?; if !perms.granted_list.iter().all(|desc| { TQuery::from_allow(desc) .check_in_permission(self, None) .is_ok() }) { - return Err(escalation_error()); + return Err(ChildPermissionError::Escalation); } } } @@ -698,7 +707,7 @@ impl QueryDescriptor for ReadQueryDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), true, api_name) } @@ -761,7 +770,7 @@ impl QueryDescriptor for WriteQueryDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), true, api_name) } @@ -796,22 +805,37 @@ pub enum Host { Ip(IpAddr), } +#[derive(Debug, thiserror::Error)] +pub enum HostParseError { + #[error("invalid IPv6 address: '{0}'")] + InvalidIpv6(String), + #[error("invalid host: '{0}'")] + InvalidHost(String), + #[error("invalid empty host: '{0}'")] + InvalidEmptyHost(String), + #[error("invalid host '{host}': {error}")] + Fqdn { + #[source] + error: fqdn::Error, + host: String, + }, +} + impl Host { - // TODO(bartlomieju): rewrite to not use `AnyError` but a specific error implementations - fn parse(s: &str) -> Result<Self, AnyError> { + fn parse(s: &str) -> Result<Self, HostParseError> { if s.starts_with('[') && s.ends_with(']') { let ip = s[1..s.len() - 1] .parse::<Ipv6Addr>() - .map_err(|_| uri_error(format!("invalid IPv6 address: '{s}'")))?; + .map_err(|_| HostParseError::InvalidIpv6(s.to_string()))?; return Ok(Host::Ip(IpAddr::V6(ip))); } let (without_trailing_dot, has_trailing_dot) = s.strip_suffix('.').map_or((s, false), |s| (s, true)); if let Ok(ip) = without_trailing_dot.parse::<IpAddr>() { if has_trailing_dot { - return Err(uri_error(format!( - "invalid host: '{without_trailing_dot}'" - ))); + return Err(HostParseError::InvalidHost( + without_trailing_dot.to_string(), + )); } Ok(Host::Ip(ip)) } else { @@ -822,11 +846,13 @@ impl Host { }; let fqdn = { use std::str::FromStr; - FQDN::from_str(&lower) - .with_context(|| format!("invalid host: '{s}'"))? + FQDN::from_str(&lower).map_err(|e| HostParseError::Fqdn { + error: e, + host: s.to_string(), + })? }; if fqdn.is_root() { - return Err(uri_error(format!("invalid empty host: '{s}'"))); + return Err(HostParseError::InvalidEmptyHost(s.to_string())); } Ok(Host::Fqdn(fqdn)) } @@ -870,7 +896,7 @@ impl QueryDescriptor for NetDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), false, api_name) } @@ -896,39 +922,72 @@ impl QueryDescriptor for NetDescriptor { } } -// TODO(bartlomieju): rewrite to not use `AnyError` but a specific error implementations +#[derive(Debug, thiserror::Error)] +pub enum NetDescriptorParseError { + #[error("invalid value '{0}': URLs are not supported, only domains and ips")] + Url(String), + #[error("invalid IPv6 address in '{hostname}': '{ip}'")] + InvalidIpv6 { hostname: String, ip: String }, + #[error("invalid port in '{hostname}': '{port}'")] + InvalidPort { hostname: String, port: String }, + #[error("invalid host: '{0}'")] + InvalidHost(String), + #[error("invalid empty port in '{0}'")] + EmptyPort(String), + #[error("ipv6 addresses must be enclosed in square brackets: '{0}'")] + Ipv6MissingSquareBrackets(String), + #[error("{0}")] + Host(#[from] HostParseError), +} + +#[derive(Debug, thiserror::Error)] +pub enum NetDescriptorFromUrlParseError { + #[error("Missing host in url: '{0}'")] + MissingHost(Url), + #[error("{0}")] + Host(#[from] HostParseError), +} + impl NetDescriptor { - pub fn parse(hostname: &str) -> Result<Self, AnyError> { + pub fn parse(hostname: &str) -> Result<Self, NetDescriptorParseError> { if hostname.starts_with("http://") || hostname.starts_with("https://") { - return Err(uri_error(format!("invalid value '{hostname}': URLs are not supported, only domains and ips"))); + return Err(NetDescriptorParseError::Url(hostname.to_string())); } // If this is a IPv6 address enclosed in square brackets, parse it as such. if hostname.starts_with('[') { if let Some((ip, after)) = hostname.split_once(']') { let ip = ip[1..].parse::<Ipv6Addr>().map_err(|_| { - uri_error(format!("invalid IPv6 address in '{hostname}': '{ip}'")) + NetDescriptorParseError::InvalidIpv6 { + hostname: hostname.to_string(), + ip: ip.to_string(), + } })?; let port = if let Some(port) = after.strip_prefix(':') { let port = port.parse::<u16>().map_err(|_| { - uri_error(format!("invalid port in '{hostname}': '{port}'")) + NetDescriptorParseError::InvalidPort { + hostname: hostname.to_string(), + port: port.to_string(), + } })?; Some(port) } else if after.is_empty() { None } else { - return Err(uri_error(format!("invalid host: '{hostname}'"))); + return Err(NetDescriptorParseError::InvalidHost( + hostname.to_string(), + )); }; return Ok(NetDescriptor(Host::Ip(IpAddr::V6(ip)), port)); } else { - return Err(uri_error(format!("invalid host: '{hostname}'"))); + return Err(NetDescriptorParseError::InvalidHost(hostname.to_string())); } } // Otherwise it is an IPv4 address or a FQDN with an optional port. let (host, port) = match hostname.split_once(':') { Some((_, "")) => { - return Err(uri_error(format!("invalid empty port in '{hostname}'"))); + return Err(NetDescriptorParseError::EmptyPort(hostname.to_string())); } Some((host, port)) => (host, port), None => (hostname, ""), @@ -943,11 +1002,14 @@ impl NetDescriptor { // should give them a hint. There are always at least two colons in an // IPv6 address, so this heuristic finds likely a bare IPv6 address. if port.contains(':') { - uri_error(format!( - "ipv6 addresses must be enclosed in square brackets: '{hostname}'" - )) + NetDescriptorParseError::Ipv6MissingSquareBrackets( + hostname.to_string(), + ) } else { - uri_error(format!("invalid port in '{hostname}': '{port}'")) + NetDescriptorParseError::InvalidPort { + hostname: hostname.to_string(), + port: port.to_string(), + } } })?; Some(port) @@ -956,10 +1018,10 @@ impl NetDescriptor { Ok(NetDescriptor(host, port)) } - pub fn from_url(url: &Url) -> Result<Self, AnyError> { - let host = url - .host_str() - .ok_or_else(|| type_error(format!("Missing host in url: '{}'", url)))?; + pub fn from_url(url: &Url) -> Result<Self, NetDescriptorFromUrlParseError> { + let host = url.host_str().ok_or_else(|| { + NetDescriptorFromUrlParseError::MissingHost(url.clone()) + })?; let host = Host::parse(host)?; let port = url.port_or_known_default(); Ok(NetDescriptor(host, port)) @@ -1011,7 +1073,7 @@ impl QueryDescriptor for ImportDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), false, api_name) } @@ -1038,15 +1100,19 @@ impl QueryDescriptor for ImportDescriptor { } impl ImportDescriptor { - pub fn parse(specifier: &str) -> Result<Self, AnyError> { + pub fn parse(specifier: &str) -> Result<Self, NetDescriptorParseError> { Ok(ImportDescriptor(NetDescriptor::parse(specifier)?)) } - pub fn from_url(url: &Url) -> Result<Self, AnyError> { + pub fn from_url(url: &Url) -> Result<Self, NetDescriptorFromUrlParseError> { Ok(ImportDescriptor(NetDescriptor::from_url(url)?)) } } +#[derive(Debug, thiserror::Error)] +#[error("Empty env not allowed")] +pub struct EnvDescriptorParseError; + #[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct EnvDescriptor(EnvVarName); @@ -1084,7 +1150,7 @@ impl QueryDescriptor for EnvDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), false, api_name) } @@ -1131,14 +1197,25 @@ pub enum RunQueryDescriptor { Name(String), } +#[derive(Debug, thiserror::Error)] +pub enum PathResolveError { + #[error("failed resolving cwd: {0}")] + CwdResolve(#[source] std::io::Error), + #[error("Empty path is not allowed")] + EmptyPath, +} + impl RunQueryDescriptor { - pub fn parse(requested: &str) -> Result<RunQueryDescriptor, AnyError> { + pub fn parse( + requested: &str, + ) -> Result<RunQueryDescriptor, PathResolveError> { if is_path(requested) { let path = PathBuf::from(requested); let resolved = if path.is_absolute() { normalize_path(path) } else { - let cwd = std::env::current_dir().context("failed resolving cwd")?; + let cwd = + std::env::current_dir().map_err(PathResolveError::CwdResolve)?; normalize_path(cwd.join(path)) }; Ok(RunQueryDescriptor::Path { @@ -1210,7 +1287,7 @@ impl QueryDescriptor for RunQueryDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), false, api_name) } @@ -1280,6 +1357,16 @@ pub enum AllowRunDescriptorParseResult { Descriptor(AllowRunDescriptor), } +#[derive(Debug, thiserror::Error)] +pub enum RunDescriptorParseError { + #[error("{0}")] + Which(#[from] which::Error), + #[error("{0}")] + PathResolve(#[from] PathResolveError), + #[error("Empty run query is not allowed")] + EmptyRunQuery, +} + #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub struct AllowRunDescriptor(pub PathBuf); @@ -1360,11 +1447,19 @@ fn denies_run_name(name: &str, cmd_path: &Path) -> bool { suffix.is_empty() || suffix.starts_with('.') } +#[derive(Debug, thiserror::Error)] +pub enum SysDescriptorParseError { + #[error("unknown system info kind \"{0}\"")] + InvalidKind(String), // TypeError + #[error("Empty sys not allowed")] + Empty, // Error +} + #[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct SysDescriptor(String); impl SysDescriptor { - pub fn parse(kind: String) -> Result<Self, AnyError> { + pub fn parse(kind: String) -> Result<Self, SysDescriptorParseError> { match kind.as_str() { "hostname" | "osRelease" | "osUptime" | "loadavg" | "networkInterfaces" | "systemMemoryInfo" | "uid" | "gid" | "cpus" @@ -1374,7 +1469,7 @@ impl SysDescriptor { // the underlying permission check changed to `userInfo` to better match the API, // alias this to avoid breaking existing projects with `--allow-sys=username` "username" => Ok(Self("userInfo".into())), - _ => Err(type_error(format!("unknown system info kind \"{kind}\""))), + _ => Err(SysDescriptorParseError::InvalidKind(kind)), } } @@ -1411,7 +1506,7 @@ impl QueryDescriptor for SysDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), false, api_name) } @@ -1472,7 +1567,7 @@ impl QueryDescriptor for FfiQueryDescriptor { &self, perm: &mut UnaryPermission<Self>, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(perm); perm.check_desc(Some(self), true, api_name) } @@ -1524,7 +1619,7 @@ impl UnaryPermission<ReadQueryDescriptor> { &mut self, desc: &ReadQueryDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(desc), true, api_name) } @@ -1534,12 +1629,15 @@ impl UnaryPermission<ReadQueryDescriptor> { &mut self, desc: &ReadQueryDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(desc), false, api_name) } - pub fn check_all(&mut self, api_name: Option<&str>) -> Result<(), AnyError> { + pub fn check_all( + &mut self, + api_name: Option<&str>, + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, api_name) } @@ -1568,7 +1666,7 @@ impl UnaryPermission<WriteQueryDescriptor> { &mut self, path: &WriteQueryDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(path), true, api_name) } @@ -1578,12 +1676,15 @@ impl UnaryPermission<WriteQueryDescriptor> { &mut self, path: &WriteQueryDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(path), false, api_name) } - pub fn check_all(&mut self, api_name: Option<&str>) -> Result<(), AnyError> { + pub fn check_all( + &mut self, + api_name: Option<&str>, + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, api_name) } @@ -1606,12 +1707,12 @@ impl UnaryPermission<NetDescriptor> { &mut self, host: &NetDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(host), false, api_name) } - pub fn check_all(&mut self) -> Result<(), AnyError> { + pub fn check_all(&mut self) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, None) } @@ -1637,12 +1738,12 @@ impl UnaryPermission<ImportDescriptor> { &mut self, host: &ImportDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(host), false, api_name) } - pub fn check_all(&mut self) -> Result<(), AnyError> { + pub fn check_all(&mut self) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, None) } @@ -1668,12 +1769,12 @@ impl UnaryPermission<EnvDescriptor> { &mut self, env: &str, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(&EnvDescriptor::new(env)), false, api_name) } - pub fn check_all(&mut self) -> Result<(), AnyError> { + pub fn check_all(&mut self) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, None) } @@ -1696,12 +1797,12 @@ impl UnaryPermission<SysDescriptor> { &mut self, kind: &SysDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(kind), false, api_name) } - pub fn check_all(&mut self) -> Result<(), AnyError> { + pub fn check_all(&mut self) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, None) } @@ -1730,11 +1831,14 @@ impl UnaryPermission<RunQueryDescriptor> { &mut self, cmd: &RunQueryDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { self.check_desc(Some(cmd), false, api_name) } - pub fn check_all(&mut self, api_name: Option<&str>) -> Result<(), AnyError> { + pub fn check_all( + &mut self, + api_name: Option<&str>, + ) -> Result<(), PermissionDeniedError> { self.check_desc(None, false, api_name) } @@ -1777,7 +1881,7 @@ impl UnaryPermission<FfiQueryDescriptor> { &mut self, path: &FfiQueryDescriptor, api_name: Option<&str>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(Some(path), true, api_name) } @@ -1785,12 +1889,12 @@ impl UnaryPermission<FfiQueryDescriptor> { pub fn check_partial( &mut self, path: Option<&FfiQueryDescriptor>, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(path, false, None) } - pub fn check_all(&mut self) -> Result<(), AnyError> { + pub fn check_all(&mut self) -> Result<(), PermissionDeniedError> { skip_check_if_is_permission_fully_granted!(self); self.check_desc(None, false, Some("all")) } @@ -1830,23 +1934,39 @@ pub struct PermissionsOptions { pub prompt: bool, } +#[derive(Debug, thiserror::Error)] +pub enum PermissionsFromOptionsError { + #[error("{0}")] + PathResolve(#[from] PathResolveError), + #[error("{0}")] + SysDescriptorParse(#[from] SysDescriptorParseError), + #[error("{0}")] + NetDescriptorParse(#[from] NetDescriptorParseError), + #[error("{0}")] + EnvDescriptorParse(#[from] EnvDescriptorParseError), + #[error("{0}")] + RunDescriptorParse(#[from] RunDescriptorParseError), + #[error("Empty command name not allowed in --allow-run=...")] + RunEmptyCommandName, +} + impl Permissions { pub fn new_unary<TQuery>( allow_list: Option<HashSet<TQuery::AllowDesc>>, deny_list: Option<HashSet<TQuery::DenyDesc>>, prompt: bool, - ) -> Result<UnaryPermission<TQuery>, AnyError> + ) -> UnaryPermission<TQuery> where TQuery: QueryDescriptor, { - Ok(UnaryPermission::<TQuery> { + UnaryPermission::<TQuery> { granted_global: global_from_option(allow_list.as_ref()), granted_list: allow_list.unwrap_or_default(), flag_denied_global: global_from_option(deny_list.as_ref()), flag_denied_list: deny_list.unwrap_or_default(), prompt, ..Default::default() - }) + } } pub const fn new_all(allow_state: bool) -> UnitPermission { @@ -1862,15 +1982,15 @@ impl Permissions { pub fn from_options( parser: &dyn PermissionDescriptorParser, opts: &PermissionsOptions, - ) -> Result<Self, AnyError> { + ) -> Result<Self, PermissionsFromOptionsError> { fn resolve_allow_run( parser: &dyn PermissionDescriptorParser, allow_run: &[String], - ) -> Result<HashSet<AllowRunDescriptor>, AnyError> { + ) -> Result<HashSet<AllowRunDescriptor>, PermissionsFromOptionsError> { let mut new_allow_run = HashSet::with_capacity(allow_run.len()); for unresolved in allow_run { if unresolved.is_empty() { - bail!("Empty command name not allowed in --allow-run=...") + return Err(PermissionsFromOptionsError::RunEmptyCommandName); } match parser.parse_allow_run_descriptor(unresolved)? { AllowRunDescriptorParseResult::Descriptor(descriptor) => { @@ -1889,10 +2009,13 @@ impl Permissions { Ok(new_allow_run) } - fn parse_maybe_vec<T: Eq + PartialEq + Hash>( + fn parse_maybe_vec<T: Eq + PartialEq + Hash, E>( items: Option<&[String]>, - parse: impl Fn(&str) -> Result<T, AnyError>, - ) -> Result<Option<HashSet<T>>, AnyError> { + parse: impl Fn(&str) -> Result<T, E>, + ) -> Result<Option<HashSet<T>>, PermissionsFromOptionsError> + where + PermissionsFromOptionsError: From<E>, + { match items { Some(items) => Ok(Some( items @@ -1944,14 +2067,14 @@ impl Permissions { parser.parse_read_descriptor(item) })?, opts.prompt, - )?, + ), write: Permissions::new_unary( parse_maybe_vec(opts.allow_write.as_deref(), |item| { parser.parse_write_descriptor(item) })?, deny_write, opts.prompt, - )?, + ), net: Permissions::new_unary( parse_maybe_vec(opts.allow_net.as_deref(), |item| { parser.parse_net_descriptor(item) @@ -1960,7 +2083,7 @@ impl Permissions { parser.parse_net_descriptor(item) })?, opts.prompt, - )?, + ), env: Permissions::new_unary( parse_maybe_vec(opts.allow_env.as_deref(), |item| { parser.parse_env_descriptor(item) @@ -1969,7 +2092,7 @@ impl Permissions { parser.parse_env_descriptor(text) })?, opts.prompt, - )?, + ), sys: Permissions::new_unary( parse_maybe_vec(opts.allow_sys.as_deref(), |text| { parser.parse_sys_descriptor(text) @@ -1978,14 +2101,14 @@ impl Permissions { parser.parse_sys_descriptor(text) })?, opts.prompt, - )?, + ), run: Permissions::new_unary( allow_run, parse_maybe_vec(opts.deny_run.as_deref(), |text| { parser.parse_deny_run_descriptor(text) })?, opts.prompt, - )?, + ), ffi: Permissions::new_unary( parse_maybe_vec(opts.allow_ffi.as_deref(), |text| { parser.parse_ffi_descriptor(text) @@ -1994,14 +2117,14 @@ impl Permissions { parser.parse_ffi_descriptor(text) })?, opts.prompt, - )?, + ), import: Permissions::new_unary( parse_maybe_vec(opts.allow_import.as_deref(), |item| { parser.parse_import_descriptor(item) })?, None, opts.prompt, - )?, + ), all: Permissions::new_all(opts.allow_all), }) } @@ -2033,14 +2156,14 @@ impl Permissions { fn none(prompt: bool) -> Self { Self { - read: Permissions::new_unary(None, None, prompt).unwrap(), - write: Permissions::new_unary(None, None, prompt).unwrap(), - net: Permissions::new_unary(None, None, prompt).unwrap(), - env: Permissions::new_unary(None, None, prompt).unwrap(), - sys: Permissions::new_unary(None, None, prompt).unwrap(), - run: Permissions::new_unary(None, None, prompt).unwrap(), - ffi: Permissions::new_unary(None, None, prompt).unwrap(), - import: Permissions::new_unary(None, None, prompt).unwrap(), + read: Permissions::new_unary(None, None, prompt), + write: Permissions::new_unary(None, None, prompt), + net: Permissions::new_unary(None, None, prompt), + env: Permissions::new_unary(None, None, prompt), + sys: Permissions::new_unary(None, None, prompt), + run: Permissions::new_unary(None, None, prompt), + ffi: Permissions::new_unary(None, None, prompt), + import: Permissions::new_unary(None, None, prompt), all: Permissions::new_all(false), } } @@ -2052,6 +2175,38 @@ pub enum CheckSpecifierKind { Dynamic, } +#[derive(Debug, thiserror::Error)] +pub enum ChildPermissionError { + #[error("Can't escalate parent thread permissions")] + Escalation, + #[error("{0}")] + PathResolve(#[from] PathResolveError), + #[error("{0}")] + NetDescriptorParse(#[from] NetDescriptorParseError), + #[error("{0}")] + EnvDescriptorParse(#[from] EnvDescriptorParseError), + #[error("{0}")] + SysDescriptorParse(#[from] SysDescriptorParseError), + #[error("{0}")] + RunDescriptorParse(#[from] RunDescriptorParseError), +} + +#[derive(Debug, thiserror::Error)] +pub enum PermissionCheckError { + #[error(transparent)] + PermissionDenied(#[from] PermissionDeniedError), + #[error("Invalid file path.\n Specifier: {0}")] + InvalidFilePath(Url), + #[error(transparent)] + NetDescriptorForUrlParse(#[from] NetDescriptorFromUrlParseError), + #[error(transparent)] + SysDescriptorParse(#[from] SysDescriptorParseError), + #[error(transparent)] + PathResolve(#[from] PathResolveError), + #[error(transparent)] + HostParse(#[from] HostParseError), +} + /// Wrapper struct for `Permissions` that can be shared across threads. /// /// We need a way to have internal mutability for permissions as they might get @@ -2084,7 +2239,7 @@ impl PermissionsContainer { pub fn create_child_permissions( &self, child_permissions_arg: ChildPermissionsArg, - ) -> Result<PermissionsContainer, AnyError> { + ) -> Result<PermissionsContainer, ChildPermissionError> { fn is_granted_unary(arg: &ChildUnaryPermissionArg) -> bool { match arg { ChildUnaryPermissionArg::Inherit | ChildUnaryPermissionArg::Granted => { @@ -2122,48 +2277,71 @@ impl PermissionsContainer { // WARNING: When adding a permission here, ensure it is handled // in the worker_perms.all block above - worker_perms.read = inner - .read - .create_child_permissions(child_permissions_arg.read, |text| { - Ok(Some(self.descriptor_parser.parse_read_descriptor(text)?)) - })?; - worker_perms.write = inner - .write - .create_child_permissions(child_permissions_arg.write, |text| { - Ok(Some(self.descriptor_parser.parse_write_descriptor(text)?)) - })?; - worker_perms.import = inner - .import - .create_child_permissions(child_permissions_arg.import, |text| { - Ok(Some(self.descriptor_parser.parse_import_descriptor(text)?)) - })?; - worker_perms.net = inner - .net - .create_child_permissions(child_permissions_arg.net, |text| { - Ok(Some(self.descriptor_parser.parse_net_descriptor(text)?)) - })?; - worker_perms.env = inner - .env - .create_child_permissions(child_permissions_arg.env, |text| { - Ok(Some(self.descriptor_parser.parse_env_descriptor(text)?)) - })?; - worker_perms.sys = inner - .sys - .create_child_permissions(child_permissions_arg.sys, |text| { - Ok(Some(self.descriptor_parser.parse_sys_descriptor(text)?)) - })?; + worker_perms.read = inner.read.create_child_permissions( + child_permissions_arg.read, + |text| { + Ok::<_, PathResolveError>(Some( + self.descriptor_parser.parse_read_descriptor(text)?, + )) + }, + )?; + worker_perms.write = inner.write.create_child_permissions( + child_permissions_arg.write, + |text| { + Ok::<_, PathResolveError>(Some( + self.descriptor_parser.parse_write_descriptor(text)?, + )) + }, + )?; + worker_perms.import = inner.import.create_child_permissions( + child_permissions_arg.import, + |text| { + Ok::<_, NetDescriptorParseError>(Some( + self.descriptor_parser.parse_import_descriptor(text)?, + )) + }, + )?; + worker_perms.net = inner.net.create_child_permissions( + child_permissions_arg.net, + |text| { + Ok::<_, NetDescriptorParseError>(Some( + self.descriptor_parser.parse_net_descriptor(text)?, + )) + }, + )?; + worker_perms.env = inner.env.create_child_permissions( + child_permissions_arg.env, + |text| { + Ok::<_, EnvDescriptorParseError>(Some( + self.descriptor_parser.parse_env_descriptor(text)?, + )) + }, + )?; + worker_perms.sys = inner.sys.create_child_permissions( + child_permissions_arg.sys, + |text| { + Ok::<_, SysDescriptorParseError>(Some( + self.descriptor_parser.parse_sys_descriptor(text)?, + )) + }, + )?; worker_perms.run = inner.run.create_child_permissions( child_permissions_arg.run, |text| match self.descriptor_parser.parse_allow_run_descriptor(text)? { - AllowRunDescriptorParseResult::Unresolved(_) => Ok(None), + AllowRunDescriptorParseResult::Unresolved(_) => { + Ok::<_, RunDescriptorParseError>(None) + } AllowRunDescriptorParseResult::Descriptor(desc) => Ok(Some(desc)), }, )?; - worker_perms.ffi = inner - .ffi - .create_child_permissions(child_permissions_arg.ffi, |text| { - Ok(Some(self.descriptor_parser.parse_ffi_descriptor(text)?)) - })?; + worker_perms.ffi = inner.ffi.create_child_permissions( + child_permissions_arg.ffi, + |text| { + Ok::<_, PathResolveError>(Some( + self.descriptor_parser.parse_ffi_descriptor(text)?, + )) + }, + )?; Ok(PermissionsContainer::new( self.descriptor_parser.clone(), @@ -2176,7 +2354,7 @@ impl PermissionsContainer { &self, specifier: &ModuleSpecifier, kind: CheckSpecifierKind, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { let mut inner = self.inner.lock(); match specifier.scheme() { "file" => { @@ -2185,17 +2363,20 @@ impl PermissionsContainer { } match url_to_file_path(specifier) { - Ok(path) => inner.read.check( - &PathQueryDescriptor { - requested: path.to_string_lossy().into_owned(), - resolved: path, - } - .into_read(), - Some("import()"), - ), - Err(_) => Err(uri_error(format!( - "Invalid file path.\n Specifier: {specifier}" - ))), + Ok(path) => inner + .read + .check( + &PathQueryDescriptor { + requested: path.to_string_lossy().into_owned(), + resolved: path, + } + .into_read(), + Some("import()"), + ) + .map_err(PermissionCheckError::PermissionDenied), + Err(_) => { + Err(PermissionCheckError::InvalidFilePath(specifier.clone())) + } } } "data" => Ok(()), @@ -2220,7 +2401,7 @@ impl PermissionsContainer { &self, path: &str, api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { self.check_read_with_api_name(path, Some(api_name)) } @@ -2230,7 +2411,7 @@ impl PermissionsContainer { &self, path: &str, api_name: Option<&str>, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.read; if inner.is_allow_all() { @@ -2248,7 +2429,7 @@ impl PermissionsContainer { &self, path: &'a Path, api_name: Option<&str>, - ) -> Result<Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.read; if inner.is_allow_all() { @@ -2272,7 +2453,7 @@ impl PermissionsContainer { path: &Path, display: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.read; skip_check_if_is_permission_fully_granted!(inner); @@ -2283,12 +2464,17 @@ impl PermissionsContainer { } .into_read(), Some(api_name), - ) + )?; + Ok(()) } #[inline(always)] - pub fn check_read_all(&self, api_name: &str) -> Result<(), AnyError> { - self.inner.lock().read.check_all(Some(api_name)) + pub fn check_read_all( + &self, + api_name: &str, + ) -> Result<(), PermissionCheckError> { + self.inner.lock().read.check_all(Some(api_name))?; + Ok(()) } #[inline(always)] @@ -2302,7 +2488,7 @@ impl PermissionsContainer { &self, path: &str, api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { self.check_write_with_api_name(path, Some(api_name)) } @@ -2312,7 +2498,7 @@ impl PermissionsContainer { &self, path: &str, api_name: Option<&str>, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.write; if inner.is_allow_all() { @@ -2330,7 +2516,7 @@ impl PermissionsContainer { &self, path: &'a Path, api_name: &str, - ) -> Result<Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.write; if inner.is_allow_all() { @@ -2347,8 +2533,12 @@ impl PermissionsContainer { } #[inline(always)] - pub fn check_write_all(&self, api_name: &str) -> Result<(), AnyError> { - self.inner.lock().write.check_all(Some(api_name)) + pub fn check_write_all( + &self, + api_name: &str, + ) -> Result<(), PermissionCheckError> { + self.inner.lock().write.check_all(Some(api_name))?; + Ok(()) } /// As `check_write()`, but permission error messages will anonymize the path @@ -2359,7 +2549,7 @@ impl PermissionsContainer { path: &Path, display: &str, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.write; skip_check_if_is_permission_fully_granted!(inner); @@ -2370,7 +2560,8 @@ impl PermissionsContainer { } .into_write(), Some(api_name), - ) + )?; + Ok(()) } #[inline(always)] @@ -2378,7 +2569,7 @@ impl PermissionsContainer { &mut self, path: &str, api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.write; if inner.is_allow_all() { @@ -2395,13 +2586,18 @@ impl PermissionsContainer { &mut self, cmd: &RunQueryDescriptor, api_name: &str, - ) -> Result<(), AnyError> { - self.inner.lock().run.check(cmd, Some(api_name)) + ) -> Result<(), PermissionCheckError> { + self.inner.lock().run.check(cmd, Some(api_name))?; + Ok(()) } #[inline(always)] - pub fn check_run_all(&mut self, api_name: &str) -> Result<(), AnyError> { - self.inner.lock().run.check_all(Some(api_name)) + pub fn check_run_all( + &mut self, + api_name: &str, + ) -> Result<(), PermissionCheckError> { + self.inner.lock().run.check_all(Some(api_name))?; + Ok(()) } #[inline(always)] @@ -2410,38 +2606,50 @@ impl PermissionsContainer { } #[inline(always)] - pub fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> { + pub fn check_sys( + &self, + kind: &str, + api_name: &str, + ) -> Result<(), PermissionCheckError> { self.inner.lock().sys.check( &self.descriptor_parser.parse_sys_descriptor(kind)?, Some(api_name), - ) + )?; + Ok(()) } #[inline(always)] - pub fn check_env(&mut self, var: &str) -> Result<(), AnyError> { - self.inner.lock().env.check(var, None) + pub fn check_env(&mut self, var: &str) -> Result<(), PermissionCheckError> { + self.inner.lock().env.check(var, None)?; + Ok(()) } #[inline(always)] - pub fn check_env_all(&mut self) -> Result<(), AnyError> { - self.inner.lock().env.check_all() + pub fn check_env_all(&mut self) -> Result<(), PermissionCheckError> { + self.inner.lock().env.check_all()?; + Ok(()) } #[inline(always)] - pub fn check_sys_all(&mut self) -> Result<(), AnyError> { - self.inner.lock().sys.check_all() + pub fn check_sys_all(&mut self) -> Result<(), PermissionCheckError> { + self.inner.lock().sys.check_all()?; + Ok(()) } #[inline(always)] - pub fn check_ffi_all(&mut self) -> Result<(), AnyError> { - self.inner.lock().ffi.check_all() + pub fn check_ffi_all(&mut self) -> Result<(), PermissionCheckError> { + self.inner.lock().ffi.check_all()?; + Ok(()) } /// This checks to see if the allow-all flag was passed, not whether all /// permissions are enabled! #[inline(always)] - pub fn check_was_allow_all_flag_passed(&mut self) -> Result<(), AnyError> { - self.inner.lock().all.check() + pub fn check_was_allow_all_flag_passed( + &mut self, + ) -> Result<(), PermissionCheckError> { + self.inner.lock().all.check()?; + Ok(()) } /// Checks special file access, returning the failed permission type if @@ -2553,13 +2761,14 @@ impl PermissionsContainer { &mut self, url: &Url, api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { let mut inner = self.inner.lock(); if inner.net.is_allow_all() { return Ok(()); } let desc = self.descriptor_parser.parse_net_descriptor_from_url(url)?; - inner.net.check(&desc, Some(api_name)) + inner.net.check(&desc, Some(api_name))?; + Ok(()) } #[inline(always)] @@ -2567,17 +2776,21 @@ impl PermissionsContainer { &mut self, host: &(T, Option<u16>), api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.net; skip_check_if_is_permission_fully_granted!(inner); let hostname = Host::parse(host.0.as_ref())?; let descriptor = NetDescriptor(hostname, host.1); - inner.check(&descriptor, Some(api_name)) + inner.check(&descriptor, Some(api_name))?; + Ok(()) } #[inline(always)] - pub fn check_ffi(&mut self, path: &str) -> Result<PathBuf, AnyError> { + pub fn check_ffi( + &mut self, + path: &str, + ) -> Result<PathBuf, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.ffi; if inner.is_allow_all() { @@ -2591,14 +2804,15 @@ impl PermissionsContainer { #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] #[inline(always)] - pub fn check_ffi_partial_no_path(&mut self) -> Result<(), AnyError> { + pub fn check_ffi_partial_no_path( + &mut self, + ) -> Result<(), PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.ffi; - if inner.is_allow_all() { - Ok(()) - } else { - inner.check_partial(None) + if !inner.is_allow_all() { + inner.check_partial(None)?; } + Ok(()) } #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] @@ -2606,7 +2820,7 @@ impl PermissionsContainer { pub fn check_ffi_partial_with_path( &mut self, path: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { let mut inner = self.inner.lock(); let inner = &mut inner.ffi; if inner.is_allow_all() { @@ -2624,7 +2838,7 @@ impl PermissionsContainer { pub fn query_read( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { let inner = self.inner.lock(); let permission = &inner.read; if permission.is_allow_all() { @@ -2634,7 +2848,7 @@ impl PermissionsContainer { permission.query( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_read(), ) }) @@ -2648,7 +2862,7 @@ impl PermissionsContainer { pub fn query_write( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { let inner = self.inner.lock(); let permission = &inner.write; if permission.is_allow_all() { @@ -2658,7 +2872,7 @@ impl PermissionsContainer { permission.query( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_write(), ) }) @@ -2672,7 +2886,7 @@ impl PermissionsContainer { pub fn query_net( &self, host: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, NetDescriptorParseError> { let inner = self.inner.lock(); let permission = &inner.net; if permission.is_allow_all() { @@ -2703,7 +2917,7 @@ impl PermissionsContainer { pub fn query_sys( &self, kind: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, SysDescriptorParseError> { let inner = self.inner.lock(); let permission = &inner.sys; if permission.is_allow_all() { @@ -2723,7 +2937,7 @@ impl PermissionsContainer { pub fn query_run( &self, cmd: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, RunDescriptorParseError> { let inner = self.inner.lock(); let permission = &inner.run; if permission.is_allow_all() { @@ -2743,7 +2957,7 @@ impl PermissionsContainer { pub fn query_ffi( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { let inner = self.inner.lock(); let permission = &inner.ffi; if permission.is_allow_all() { @@ -2753,7 +2967,7 @@ impl PermissionsContainer { permission.query( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_ffi(), ) }) @@ -2769,12 +2983,12 @@ impl PermissionsContainer { pub fn revoke_read( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { Ok( self.inner.lock().read.revoke( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_read(), ) }) @@ -2788,12 +3002,12 @@ impl PermissionsContainer { pub fn revoke_write( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { Ok( self.inner.lock().write.revoke( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_write(), ) }) @@ -2807,7 +3021,7 @@ impl PermissionsContainer { pub fn revoke_net( &self, host: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, NetDescriptorParseError> { Ok( self.inner.lock().net.revoke( match host { @@ -2828,7 +3042,7 @@ impl PermissionsContainer { pub fn revoke_sys( &self, kind: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, SysDescriptorParseError> { Ok( self.inner.lock().sys.revoke( kind @@ -2843,7 +3057,7 @@ impl PermissionsContainer { pub fn revoke_run( &self, cmd: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, RunDescriptorParseError> { Ok( self.inner.lock().run.revoke( cmd @@ -2858,12 +3072,12 @@ impl PermissionsContainer { pub fn revoke_ffi( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { Ok( self.inner.lock().ffi.revoke( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_ffi(), ) }) @@ -2879,12 +3093,12 @@ impl PermissionsContainer { pub fn request_read( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { Ok( self.inner.lock().read.request( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_read(), ) }) @@ -2898,12 +3112,12 @@ impl PermissionsContainer { pub fn request_write( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { Ok( self.inner.lock().write.request( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_write(), ) }) @@ -2917,7 +3131,7 @@ impl PermissionsContainer { pub fn request_net( &self, host: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, NetDescriptorParseError> { Ok( self.inner.lock().net.request( match host { @@ -2938,7 +3152,7 @@ impl PermissionsContainer { pub fn request_sys( &self, kind: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, SysDescriptorParseError> { Ok( self.inner.lock().sys.request( kind @@ -2953,7 +3167,7 @@ impl PermissionsContainer { pub fn request_run( &self, cmd: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, RunDescriptorParseError> { Ok( self.inner.lock().run.request( cmd @@ -2968,12 +3182,12 @@ impl PermissionsContainer { pub fn request_ffi( &self, path: Option<&str>, - ) -> Result<PermissionState, AnyError> { + ) -> Result<PermissionState, PathResolveError> { Ok( self.inner.lock().ffi.request( path .map(|path| { - Result::<_, AnyError>::Ok( + Ok::<_, PathResolveError>( self.descriptor_parser.parse_path_query(path)?.into_ffi(), ) }) @@ -3009,10 +3223,6 @@ fn global_from_option<T>(flag: Option<&HashSet<T>>) -> bool { matches!(flag, Some(v) if v.is_empty()) } -fn escalation_error() -> AnyError { - custom_error("NotCapable", "Can't escalate parent thread permissions") -} - #[derive(Debug, Eq, PartialEq)] pub enum ChildUnitPermissionArg { Inherit, @@ -3273,65 +3483,73 @@ pub trait PermissionDescriptorParser: Debug + Send + Sync { fn parse_read_descriptor( &self, text: &str, - ) -> Result<ReadDescriptor, AnyError>; + ) -> Result<ReadDescriptor, PathResolveError>; fn parse_write_descriptor( &self, text: &str, - ) -> Result<WriteDescriptor, AnyError>; + ) -> Result<WriteDescriptor, PathResolveError>; - fn parse_net_descriptor(&self, text: &str) - -> Result<NetDescriptor, AnyError>; + fn parse_net_descriptor( + &self, + text: &str, + ) -> Result<NetDescriptor, NetDescriptorParseError>; fn parse_net_descriptor_from_url( &self, url: &Url, - ) -> Result<NetDescriptor, AnyError> { + ) -> Result<NetDescriptor, NetDescriptorFromUrlParseError> { NetDescriptor::from_url(url) } fn parse_import_descriptor( &self, text: &str, - ) -> Result<ImportDescriptor, AnyError>; + ) -> Result<ImportDescriptor, NetDescriptorParseError>; fn parse_import_descriptor_from_url( &self, url: &Url, - ) -> Result<ImportDescriptor, AnyError> { + ) -> Result<ImportDescriptor, NetDescriptorFromUrlParseError> { ImportDescriptor::from_url(url) } - fn parse_env_descriptor(&self, text: &str) - -> Result<EnvDescriptor, AnyError>; + fn parse_env_descriptor( + &self, + text: &str, + ) -> Result<EnvDescriptor, EnvDescriptorParseError>; - fn parse_sys_descriptor(&self, text: &str) - -> Result<SysDescriptor, AnyError>; + fn parse_sys_descriptor( + &self, + text: &str, + ) -> Result<SysDescriptor, SysDescriptorParseError>; fn parse_allow_run_descriptor( &self, text: &str, - ) -> Result<AllowRunDescriptorParseResult, AnyError>; + ) -> Result<AllowRunDescriptorParseResult, RunDescriptorParseError>; fn parse_deny_run_descriptor( &self, text: &str, - ) -> Result<DenyRunDescriptor, AnyError>; + ) -> Result<DenyRunDescriptor, PathResolveError>; - fn parse_ffi_descriptor(&self, text: &str) - -> Result<FfiDescriptor, AnyError>; + fn parse_ffi_descriptor( + &self, + text: &str, + ) -> Result<FfiDescriptor, PathResolveError>; // queries fn parse_path_query( &self, path: &str, - ) -> Result<PathQueryDescriptor, AnyError>; + ) -> Result<PathQueryDescriptor, PathResolveError>; fn parse_run_query( &self, requested: &str, - ) -> Result<RunQueryDescriptor, AnyError>; + ) -> Result<RunQueryDescriptor, RunDescriptorParseError>; } static IS_STANDALONE: AtomicFlag = AtomicFlag::lowered(); @@ -3374,49 +3592,49 @@ mod tests { fn parse_read_descriptor( &self, text: &str, - ) -> Result<ReadDescriptor, AnyError> { + ) -> Result<ReadDescriptor, PathResolveError> { Ok(ReadDescriptor(self.join_path_with_root(text))) } fn parse_write_descriptor( &self, text: &str, - ) -> Result<WriteDescriptor, AnyError> { + ) -> Result<WriteDescriptor, PathResolveError> { Ok(WriteDescriptor(self.join_path_with_root(text))) } fn parse_net_descriptor( &self, text: &str, - ) -> Result<NetDescriptor, AnyError> { + ) -> Result<NetDescriptor, NetDescriptorParseError> { NetDescriptor::parse(text) } fn parse_import_descriptor( &self, text: &str, - ) -> Result<ImportDescriptor, AnyError> { + ) -> Result<ImportDescriptor, NetDescriptorParseError> { ImportDescriptor::parse(text) } fn parse_env_descriptor( &self, text: &str, - ) -> Result<EnvDescriptor, AnyError> { + ) -> Result<EnvDescriptor, EnvDescriptorParseError> { Ok(EnvDescriptor::new(text)) } fn parse_sys_descriptor( &self, text: &str, - ) -> Result<SysDescriptor, AnyError> { + ) -> Result<SysDescriptor, SysDescriptorParseError> { SysDescriptor::parse(text.to_string()) } fn parse_allow_run_descriptor( &self, text: &str, - ) -> Result<AllowRunDescriptorParseResult, AnyError> { + ) -> Result<AllowRunDescriptorParseResult, RunDescriptorParseError> { Ok(AllowRunDescriptorParseResult::Descriptor( AllowRunDescriptor(self.join_path_with_root(text)), )) @@ -3425,7 +3643,7 @@ mod tests { fn parse_deny_run_descriptor( &self, text: &str, - ) -> Result<DenyRunDescriptor, AnyError> { + ) -> Result<DenyRunDescriptor, PathResolveError> { if text.contains("/") { Ok(DenyRunDescriptor::Path(self.join_path_with_root(text))) } else { @@ -3436,14 +3654,14 @@ mod tests { fn parse_ffi_descriptor( &self, text: &str, - ) -> Result<FfiDescriptor, AnyError> { + ) -> Result<FfiDescriptor, PathResolveError> { Ok(FfiDescriptor(self.join_path_with_root(text))) } fn parse_path_query( &self, path: &str, - ) -> Result<PathQueryDescriptor, AnyError> { + ) -> Result<PathQueryDescriptor, PathResolveError> { Ok(PathQueryDescriptor { resolved: self.join_path_with_root(path), requested: path.to_string(), @@ -3453,8 +3671,8 @@ mod tests { fn parse_run_query( &self, requested: &str, - ) -> Result<RunQueryDescriptor, AnyError> { - RunQueryDescriptor::parse(requested) + ) -> Result<RunQueryDescriptor, RunDescriptorParseError> { + RunQueryDescriptor::parse(requested).map_err(Into::into) } } @@ -4335,7 +4553,6 @@ mod tests { None, false, ) - .unwrap() }; prompt_value.set(true); @@ -4562,13 +4779,12 @@ mod tests { .lock() .clone(), Permissions { - env: Permissions::new_unary(Some(HashSet::new()), None, false).unwrap(), + env: Permissions::new_unary(Some(HashSet::new()), None, false), net: Permissions::new_unary( Some(HashSet::from([NetDescriptor::parse("foo").unwrap()])), None, false - ) - .unwrap(), + ), ..Permissions::none_without_prompt() } ); diff --git a/runtime/permissions/prompter.rs b/runtime/permissions/prompter.rs index b582b4f53..168a845a2 100644 --- a/runtime/permissions/prompter.rs +++ b/runtime/permissions/prompter.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_terminal::colors; use once_cell::sync::Lazy; @@ -101,8 +100,7 @@ pub struct TtyPrompter; fn clear_stdin( _stdin_lock: &mut StdinLock, _stderr_lock: &mut StderrLock, -) -> Result<(), AnyError> { - use deno_core::anyhow::bail; +) -> Result<(), std::io::Error> { use std::mem::MaybeUninit; const STDIN_FD: i32 = 0; @@ -117,7 +115,10 @@ fn clear_stdin( loop { let r = libc::tcflush(STDIN_FD, libc::TCIFLUSH); if r != 0 { - bail!("clear_stdin failed (tcflush)"); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "clear_stdin failed (tcflush)", + )); } // Initialize timeout for select to be 100ms @@ -137,7 +138,10 @@ fn clear_stdin( // Check if select returned an error if r < 0 { - bail!("clear_stdin failed (select)"); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "clear_stdin failed (select)", + )); } // Check if select returned due to timeout (stdin is quiescent) @@ -156,8 +160,7 @@ fn clear_stdin( fn clear_stdin( stdin_lock: &mut StdinLock, stderr_lock: &mut StderrLock, -) -> Result<(), AnyError> { - use deno_core::anyhow::bail; +) -> Result<(), std::io::Error> { use winapi::shared::minwindef::TRUE; use winapi::shared::minwindef::UINT; use winapi::shared::minwindef::WORD; @@ -194,18 +197,23 @@ fn clear_stdin( return Ok(()); - unsafe fn flush_input_buffer(stdin: HANDLE) -> Result<(), AnyError> { + unsafe fn flush_input_buffer(stdin: HANDLE) -> Result<(), std::io::Error> { let success = FlushConsoleInputBuffer(stdin); if success != TRUE { - bail!( - "Could not flush the console input buffer: {}", - std::io::Error::last_os_error() - ) + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + format!( + "Could not flush the console input buffer: {}", + std::io::Error::last_os_error() + ), + )); } Ok(()) } - unsafe fn emulate_enter_key_press(stdin: HANDLE) -> Result<(), AnyError> { + unsafe fn emulate_enter_key_press( + stdin: HANDLE, + ) -> Result<(), std::io::Error> { // https://github.com/libuv/libuv/blob/a39009a5a9252a566ca0704d02df8dabc4ce328f/src/win/tty.c#L1121-L1131 let mut input_record: INPUT_RECORD = std::mem::zeroed(); input_record.EventType = KEY_EVENT; @@ -220,34 +228,43 @@ fn clear_stdin( let success = WriteConsoleInputW(stdin, &input_record, 1, &mut record_written); if success != TRUE { - bail!( - "Could not emulate enter key press: {}", - std::io::Error::last_os_error() - ); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + format!( + "Could not emulate enter key press: {}", + std::io::Error::last_os_error() + ), + )); } Ok(()) } - unsafe fn is_input_buffer_empty(stdin: HANDLE) -> Result<bool, AnyError> { + unsafe fn is_input_buffer_empty( + stdin: HANDLE, + ) -> Result<bool, std::io::Error> { let mut buffer = Vec::with_capacity(1); let mut events_read = 0; let success = PeekConsoleInputW(stdin, buffer.as_mut_ptr(), 1, &mut events_read); if success != TRUE { - bail!( - "Could not peek the console input buffer: {}", - std::io::Error::last_os_error() - ) + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + format!( + "Could not peek the console input buffer: {}", + std::io::Error::last_os_error() + ), + )); } Ok(events_read == 0) } - fn move_cursor_up(stderr_lock: &mut StderrLock) -> Result<(), AnyError> { - write!(stderr_lock, "\x1B[1A")?; - Ok(()) + fn move_cursor_up( + stderr_lock: &mut StderrLock, + ) -> Result<(), std::io::Error> { + write!(stderr_lock, "\x1B[1A") } - fn read_stdin_line(stdin_lock: &mut StdinLock) -> Result<(), AnyError> { + fn read_stdin_line(stdin_lock: &mut StdinLock) -> Result<(), std::io::Error> { let mut input = String::new(); stdin_lock.read_line(&mut input)?; Ok(()) diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index 041132f97..0d81af6e7 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -5,12 +5,12 @@ use crate::ops::bootstrap::SnapshotOptions; use crate::shared::maybe_transpile_source; use crate::shared::runtime; use deno_cache::SqliteBackedCache; -use deno_core::error::AnyError; use deno_core::snapshot::*; use deno_core::v8; use deno_core::Extension; use deno_http::DefaultHttpPropertyExtractor; use deno_io::fs::FsError; +use deno_permissions::PermissionCheckError; use std::borrow::Cow; use std::io::Write; use std::path::Path; @@ -26,7 +26,7 @@ impl deno_websocket::WebSocketPermissions for Permissions { &mut self, _url: &deno_core::url::Url, _api_name: &str, - ) -> Result<(), deno_core::error::AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } } @@ -42,7 +42,7 @@ impl deno_fetch::FetchPermissions for Permissions { &mut self, _url: &deno_core::url::Url, _api_name: &str, - ) -> Result<(), deno_core::error::AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } @@ -50,28 +50,26 @@ impl deno_fetch::FetchPermissions for Permissions { &mut self, _p: &'a Path, _api_name: &str, - ) -> Result<Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { unreachable!("snapshotting!") } } impl deno_ffi::FfiPermissions for Permissions { - fn check_partial_no_path( - &mut self, - ) -> Result<(), deno_core::error::AnyError> { + fn check_partial_no_path(&mut self) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } fn check_partial_with_path( &mut self, _path: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } } impl deno_napi::NapiPermissions for Permissions { - fn check(&mut self, _path: &str) -> std::result::Result<PathBuf, AnyError> { + fn check(&mut self, _path: &str) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } } @@ -81,20 +79,20 @@ impl deno_node::NodePermissions for Permissions { &mut self, _url: &deno_core::url::Url, _api_name: &str, - ) -> Result<(), deno_core::error::AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } fn check_read_path<'a>( &mut self, _path: &'a Path, - ) -> Result<Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { unreachable!("snapshotting!") } fn check_read_with_api_name( &mut self, _p: &str, _api_name: Option<&str>, - ) -> Result<PathBuf, deno_core::error::AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } fn query_read_all(&mut self) -> bool { @@ -104,14 +102,14 @@ impl deno_node::NodePermissions for Permissions { &mut self, _p: &str, _api_name: Option<&str>, - ) -> Result<PathBuf, deno_core::error::AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } fn check_sys( &mut self, _kind: &str, _api_name: &str, - ) -> Result<(), deno_core::error::AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } } @@ -121,7 +119,7 @@ impl deno_net::NetPermissions for Permissions { &mut self, _host: &(T, Option<u16>), _api_name: &str, - ) -> Result<(), deno_core::error::AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } @@ -129,7 +127,7 @@ impl deno_net::NetPermissions for Permissions { &mut self, _p: &str, _api_name: &str, - ) -> Result<PathBuf, deno_core::error::AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } @@ -137,7 +135,7 @@ impl deno_net::NetPermissions for Permissions { &mut self, _p: &str, _api_name: &str, - ) -> Result<PathBuf, deno_core::error::AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } @@ -145,7 +143,7 @@ impl deno_net::NetPermissions for Permissions { &mut self, _p: &'a Path, _api_name: &str, - ) -> Result<std::borrow::Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { unreachable!("snapshotting!") } } @@ -158,7 +156,7 @@ impl deno_fs::FsPermissions for Permissions { _write: bool, _path: &'a Path, _api_name: &str, - ) -> Result<std::borrow::Cow<'a, Path>, FsError> { + ) -> Result<Cow<'a, Path>, FsError> { unreachable!("snapshotting!") } @@ -166,11 +164,14 @@ impl deno_fs::FsPermissions for Permissions { &mut self, _path: &str, _api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } - fn check_read_all(&mut self, _api_name: &str) -> Result<(), AnyError> { + fn check_read_all( + &mut self, + _api_name: &str, + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } @@ -179,7 +180,7 @@ impl deno_fs::FsPermissions for Permissions { _path: &Path, _display: &str, _api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } @@ -187,7 +188,7 @@ impl deno_fs::FsPermissions for Permissions { &mut self, _path: &str, _api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } @@ -195,11 +196,14 @@ impl deno_fs::FsPermissions for Permissions { &mut self, _path: &str, _api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } - fn check_write_all(&mut self, _api_name: &str) -> Result<(), AnyError> { + fn check_write_all( + &mut self, + _api_name: &str, + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } @@ -208,7 +212,7 @@ impl deno_fs::FsPermissions for Permissions { _path: &Path, _display: &str, _api_name: &str, - ) -> Result<(), AnyError> { + ) -> Result<(), PermissionCheckError> { unreachable!("snapshotting!") } @@ -216,7 +220,7 @@ impl deno_fs::FsPermissions for Permissions { &mut self, _path: &'a Path, _api_name: &str, - ) -> Result<std::borrow::Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { unreachable!("snapshotting!") } @@ -224,7 +228,7 @@ impl deno_fs::FsPermissions for Permissions { &mut self, _path: &'a Path, _api_name: &str, - ) -> Result<std::borrow::Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { unreachable!("snapshotting!") } } @@ -234,7 +238,7 @@ impl deno_kv::sqlite::SqliteDbHandlerPermissions for Permissions { &mut self, _path: &str, _api_name: &str, - ) -> Result<PathBuf, AnyError> { + ) -> Result<PathBuf, PermissionCheckError> { unreachable!("snapshotting!") } @@ -242,7 +246,7 @@ impl deno_kv::sqlite::SqliteDbHandlerPermissions for Permissions { &mut self, _path: &'a Path, _api_name: &str, - ) -> Result<Cow<'a, Path>, AnyError> { + ) -> Result<Cow<'a, Path>, PermissionCheckError> { unreachable!("snapshotting!") } } |