From 4f49f703c10afcde7155baac2b494fa6670c0115 Mon Sep 17 00:00:00 2001 From: Yazan AbdAl-Rahman Date: Tue, 20 Aug 2024 04:20:06 +0300 Subject: [PATCH] fix(cli): update permission prompt message for compiled binaries (#24081) Co-authored-by: David Sherret --- Cargo.lock | 4 +-- cli/mainrt.rs | 1 + ext/fs/ops.rs | 9 ++++++- runtime/permissions/lib.rs | 25 ++++++++++++++++--- runtime/permissions/prompter.rs | 8 +++++- .../compile/permissions_denied/__test__.jsonc | 24 ++++++++++++++++++ .../specs/compile/permissions_denied/main.out | 2 ++ .../specs/compile/permissions_denied/main.ts | 1 + .../npm/deno_run_cowsay_no_permissions.out | 2 +- 9 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 tests/specs/compile/permissions_denied/__test__.jsonc create mode 100644 tests/specs/compile/permissions_denied/main.out create mode 100644 tests/specs/compile/permissions_denied/main.ts diff --git a/Cargo.lock b/Cargo.lock index d7feda5e60..d2202a7e7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2060,9 +2060,9 @@ dependencies = [ [[package]] name = "deno_unsync" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ee1607db298c8f12124b345a52d5f2f504a7504c9d535f1d8f07127b237010" +checksum = "2f36b4ef61a04ce201b925a5dffa90f88437d37fee4836c758470dd15ba7f05e" dependencies = [ "parking_lot 0.12.3", "tokio", diff --git a/cli/mainrt.rs b/cli/mainrt.rs index fd03224bed..02d58fcee1 100644 --- a/cli/mainrt.rs +++ b/cli/mainrt.rs @@ -83,6 +83,7 @@ fn load_env_vars(env_vars: &IndexMap) { } fn main() { + deno_runtime::deno_permissions::mark_standalone(); let args: Vec<_> = env::args_os().collect(); let standalone = standalone::extract_standalone(Cow::Owned(args)); let future = async move { diff --git a/ext/fs/ops.rs b/ext/fs/ops.rs index 57b0e0b9e0..e8a074be50 100644 --- a/ext/fs/ops.rs +++ b/ext/fs/ops.rs @@ -67,7 +67,14 @@ fn map_permission_error( } else { (path.as_str(), "") }; - custom_error("PermissionDenied", format!("Requires {err} access to {path}{truncated}, run again with the --allow-{err} flag")) + let msg = if deno_permissions::is_standalone() { + format!( + "Requires {err} access to {path}{truncated}, specify the required permissions during compilation using `deno compile --allow-{err}`") + } else { + format!( + "Requires {err} access to {path}{truncated}, run again with the --allow-{err} flag") + }; + custom_error("PermissionDenied", msg) } err => Err::<(), _>(err) .context_path(operation, path) diff --git a/runtime/permissions/lib.rs b/runtime/permissions/lib.rs index b0fa9eb101..55a94d909a 100644 --- a/runtime/permissions/lib.rs +++ b/runtime/permissions/lib.rs @@ -12,6 +12,7 @@ use deno_core::serde::Deserialize; use deno_core::serde::Deserializer; use deno_core::serde::Serialize; use deno_core::serde_json; +use deno_core::unsync::sync::AtomicFlag; use deno_core::url; use deno_core::url::Url; use deno_core::ModuleSpecifier; @@ -132,14 +133,20 @@ impl PermissionState { } fn error(name: &str, info: impl FnOnce() -> Option) -> AnyError { - custom_error( - "PermissionDenied", + 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("PermissionDenied", msg) } /// Check the permission state. bool is whether a prompt was issued. @@ -2313,6 +2320,16 @@ pub fn create_child_permissions( Ok(worker_perms) } +static IS_STANDALONE: AtomicFlag = AtomicFlag::lowered(); + +pub fn mark_standalone() { + IS_STANDALONE.raise(); +} + +pub fn is_standalone() -> bool { + IS_STANDALONE.is_raised() +} + #[cfg(test)] mod tests { use super::*; diff --git a/runtime/permissions/prompter.rs b/runtime/permissions/prompter.rs index 050902d59a..e48e0af10d 100644 --- a/runtime/permissions/prompter.rs +++ b/runtime/permissions/prompter.rs @@ -11,6 +11,8 @@ use std::io::StderrLock; use std::io::StdinLock; use std::io::Write as IoWrite; +use crate::is_standalone; + /// Helper function to make control characters visible so users can see the underlying filename. fn escape_control_characters(s: &str) -> std::borrow::Cow { if !s.contains(|c: char| c.is_ascii_control() || c.is_control()) { @@ -339,7 +341,11 @@ impl PermissionPrompter for TtyPrompter { )) ); writeln!(&mut output, "┠─ {}", colors::italic(&msg)).unwrap(); - let msg = format!("Run again with --allow-{name} to bypass this prompt."); + let msg = if is_standalone() { + format!("Specify the required permissions during compile time using `deno compile --allow-{name}`.") + } else { + format!("Run again with --allow-{name} to bypass this prompt.") + }; writeln!(&mut output, "┠─ {}", colors::italic(&msg)).unwrap(); write!(&mut output, "┗ {}", colors::bold("Allow?")).unwrap(); write!(&mut output, " {opts} > ").unwrap(); diff --git a/tests/specs/compile/permissions_denied/__test__.jsonc b/tests/specs/compile/permissions_denied/__test__.jsonc new file mode 100644 index 0000000000..8f85901628 --- /dev/null +++ b/tests/specs/compile/permissions_denied/__test__.jsonc @@ -0,0 +1,24 @@ +{ + "tempDir": true, + "steps": [{ + "if": "unix", + "args": "compile --output main main.ts", + "output": "[WILDCARD]" + }, { + "if": "unix", + "commandName": "./main", + "args": [], + "exitCode": 1, + "output": "main.out" + }, { + "if": "windows", + "args": "compile --output main.exe main.ts", + "output": "[WILDCARD]" + }, { + "if": "windows", + "commandName": "./main.exe", + "args": [], + "exitCode": 1, + "output": "main.out" + }] +} diff --git a/tests/specs/compile/permissions_denied/main.out b/tests/specs/compile/permissions_denied/main.out new file mode 100644 index 0000000000..e9ea45c812 --- /dev/null +++ b/tests/specs/compile/permissions_denied/main.out @@ -0,0 +1,2 @@ +error: Uncaught (in promise) PermissionDenied: Requires run access to "deno", specify the required permissions during compilation using `deno compile --allow-run` +[WILDCARD] \ No newline at end of file diff --git a/tests/specs/compile/permissions_denied/main.ts b/tests/specs/compile/permissions_denied/main.ts new file mode 100644 index 0000000000..eeac858ffc --- /dev/null +++ b/tests/specs/compile/permissions_denied/main.ts @@ -0,0 +1 @@ +new Deno.Command("deno").outputSync(); diff --git a/tests/testdata/npm/deno_run_cowsay_no_permissions.out b/tests/testdata/npm/deno_run_cowsay_no_permissions.out index 206ef1484f..837394d495 100644 --- a/tests/testdata/npm/deno_run_cowsay_no_permissions.out +++ b/tests/testdata/npm/deno_run_cowsay_no_permissions.out @@ -1,2 +1,2 @@ -error: Uncaught PermissionDenied: Requires read access to , run again with the --allow-read flag +error: Uncaught PermissionDenied: Requires read access to , specify the required permissions during compilation using `deno compile --allow-read` [WILDCARD]