summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrowlKats <13135287+crowlKats@users.noreply.github.com>2021-04-13 13:25:21 +0200
committerGitHub <noreply@github.com>2021-04-13 13:25:21 +0200
commit8b59d9f7bc2ce4aa33b6b8ac41495c62d3791f3c (patch)
tree2dbbd97062244f65145e917ee6025e5ac595675a
parentec1fce58d93de61462ddf0c9e9c58e6e844d2230 (diff)
feat(permissions): allow env permission to take values (#9825)
-rw-r--r--cli/dts/lib.deno.ns.d.ts1
-rw-r--r--cli/flags.rs115
-rw-r--r--runtime/ops/os.rs19
-rw-r--r--runtime/ops/permissions.rs7
-rw-r--r--runtime/ops/worker_host.rs48
-rw-r--r--runtime/permissions.rs219
6 files changed, 350 insertions, 59 deletions
diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts
index 9108f6dd6..738d0ba54 100644
--- a/cli/dts/lib.deno.ns.d.ts
+++ b/cli/dts/lib.deno.ns.d.ts
@@ -2164,6 +2164,7 @@ declare namespace Deno {
export interface EnvPermissionDescriptor {
name: "env";
+ variable?: string;
}
export interface PluginPermissionDescriptor {
diff --git a/cli/flags.rs b/cli/flags.rs
index 5feb46371..900214701 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -128,7 +128,7 @@ pub struct Flags {
pub argv: Vec<String>,
pub subcommand: DenoSubcommand,
- pub allow_env: bool,
+ pub allow_env: Option<Vec<String>>,
pub allow_hrtime: bool,
pub allow_net: Option<Vec<String>>,
pub allow_plugin: bool,
@@ -207,8 +207,15 @@ impl Flags {
_ => {}
}
- if self.allow_env {
- args.push("--allow-env".to_string());
+ match &self.allow_env {
+ Some(env_allowlist) if env_allowlist.is_empty() => {
+ args.push("--allow-env".to_string());
+ }
+ Some(env_allowlist) => {
+ let s = format!("--allow-env={}", env_allowlist.join(","));
+ args.push(s);
+ }
+ _ => {}
}
match &self.allow_run {
@@ -527,7 +534,7 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
flags.repl = true;
flags.subcommand = DenoSubcommand::Repl;
flags.allow_net = Some(vec![]);
- flags.allow_env = true;
+ flags.allow_env = Some(vec![]);
flags.allow_run = Some(vec![]);
flags.allow_read = Some(vec![]);
flags.allow_write = Some(vec![]);
@@ -538,7 +545,7 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
runtime_args_parse(flags, matches, false, true);
flags.allow_net = Some(vec![]);
- flags.allow_env = true;
+ flags.allow_env = Some(vec![]);
flags.allow_run = Some(vec![]);
flags.allow_read = Some(vec![]);
flags.allow_write = Some(vec![]);
@@ -1402,7 +1409,19 @@ fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
.arg(
Arg::with_name("allow-env")
.long("allow-env")
- .help("Allow environment access"),
+ .min_values(0)
+ .takes_value(true)
+ .use_delimiter(true)
+ .require_equals(true)
+ .help("Allow environment access")
+ .validator(|keys| {
+ for key in keys.split(',') {
+ if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
+ return Err(format!("invalid key \"{}\"", key));
+ }
+ }
+ Ok(())
+ }),
)
.arg(
Arg::with_name("allow-run")
@@ -1826,15 +1845,26 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
debug!("net allowlist: {:#?}", &flags.allow_net);
}
+ if let Some(env_wl) = matches.values_of("allow-env") {
+ let env_allowlist: Vec<String> = env_wl
+ .map(|env: &str| {
+ if cfg!(windows) {
+ env.to_uppercase()
+ } else {
+ env.to_string()
+ }
+ })
+ .collect();
+ flags.allow_env = Some(env_allowlist);
+ debug!("env allowlist: {:#?}", &flags.allow_env);
+ }
+
if let Some(run_wl) = matches.values_of("allow-run") {
let run_allowlist: Vec<String> = run_wl.map(ToString::to_string).collect();
flags.allow_run = Some(run_allowlist);
debug!("run allowlist: {:#?}", &flags.allow_run);
}
- if matches.is_present("allow-env") {
- flags.allow_env = true;
- }
if matches.is_present("allow-plugin") {
flags.allow_plugin = true;
}
@@ -1843,7 +1873,7 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
}
if matches.is_present("allow-all") {
flags.allow_read = Some(vec![]);
- flags.allow_env = true;
+ flags.allow_env = Some(vec![]);
flags.allow_net = Some(vec![]);
flags.allow_run = Some(vec![]);
flags.allow_write = Some(vec![]);
@@ -2054,7 +2084,7 @@ mod tests {
script: "gist.ts".to_string(),
},
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2426,7 +2456,7 @@ mod tests {
ext: "js".to_string(),
},
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2449,7 +2479,7 @@ mod tests {
ext: "js".to_string(),
},
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2473,7 +2503,7 @@ mod tests {
ext: "ts".to_string(),
},
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2510,7 +2540,7 @@ mod tests {
seed: Some(1),
inspect: Some("127.0.0.1:9229".parse().unwrap()),
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2540,7 +2570,7 @@ mod tests {
},
argv: svec!["arg1", "arg2"],
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2560,7 +2590,7 @@ mod tests {
repl: true,
subcommand: DenoSubcommand::Repl,
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2594,7 +2624,7 @@ mod tests {
seed: Some(1),
inspect: Some("127.0.0.1:9229".parse().unwrap()),
allow_net: Some(vec![]),
- allow_env: true,
+ allow_env: Some(vec![]),
allow_run: Some(vec![]),
allow_read: Some(vec![]),
allow_write: Some(vec![]),
@@ -2672,6 +2702,55 @@ mod tests {
}
#[test]
+ fn allow_env_allowlist() {
+ let r =
+ flags_from_vec(svec!["deno", "run", "--allow-env=HOME", "script.ts"]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Run {
+ script: "script.ts".to_string(),
+ },
+ allow_env: Some(svec!["HOME"]),
+ ..Flags::default()
+ }
+ );
+ }
+
+ #[test]
+ fn allow_env_allowlist_multiple() {
+ let r = flags_from_vec(svec![
+ "deno",
+ "run",
+ "--allow-env=HOME,PATH",
+ "script.ts"
+ ]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Run {
+ script: "script.ts".to_string(),
+ },
+ allow_env: Some(svec!["HOME", "PATH"]),
+ ..Flags::default()
+ }
+ );
+ }
+
+ #[test]
+ fn allow_env_allowlist_validator() {
+ let r =
+ flags_from_vec(svec!["deno", "run", "--allow-env=HOME", "script.ts"]);
+ assert!(r.is_ok());
+ let r =
+ flags_from_vec(svec!["deno", "run", "--allow-env=H=ME", "script.ts"]);
+ assert!(r.is_err());
+ let r =
+ flags_from_vec(svec!["deno", "run", "--allow-env=H\0ME", "script.ts"]);
+ assert!(r.is_err());
+ }
+
+ #[test]
fn bundle() {
let r = flags_from_vec(svec!["deno", "bundle", "source.ts"]);
assert_eq!(
diff --git a/runtime/ops/os.rs b/runtime/ops/os.rs
index b9511fcdc..c2c9fb550 100644
--- a/runtime/ops/os.rs
+++ b/runtime/ops/os.rs
@@ -54,7 +54,7 @@ fn op_set_env(
args: SetEnv,
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<(), AnyError> {
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check(&args.key)?;
let invalid_key =
args.key.is_empty() || args.key.contains(&['=', '\0'] as &[char]);
let invalid_value = args.value.contains('\0');
@@ -70,7 +70,7 @@ fn op_env(
_args: (),
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<HashMap<String, String>, AnyError> {
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check_all()?;
Ok(env::vars().collect())
}
@@ -79,7 +79,7 @@ fn op_get_env(
key: String,
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<Option<String>, AnyError> {
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check(&key)?;
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
return Err(type_error("Key contains invalid characters."));
}
@@ -89,12 +89,13 @@ fn op_get_env(
};
Ok(r)
}
+
fn op_delete_env(
state: &mut OpState,
key: String,
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<(), AnyError> {
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check(&key)?;
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
return Err(type_error("Key contains invalid characters."));
}
@@ -116,7 +117,7 @@ fn op_loadavg(
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<(f64, f64, f64), AnyError> {
super::check_unstable(state, "Deno.loadavg");
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check_all()?;
match sys_info::loadavg() {
Ok(loadavg) => Ok((loadavg.one, loadavg.five, loadavg.fifteen)),
Err(_) => Ok((0.0, 0.0, 0.0)),
@@ -129,7 +130,7 @@ fn op_hostname(
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<String, AnyError> {
super::check_unstable(state, "Deno.hostname");
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check_all()?;
let hostname = sys_info::hostname().unwrap_or_else(|_| "".to_string());
Ok(hostname)
}
@@ -140,7 +141,7 @@ fn op_os_release(
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<String, AnyError> {
super::check_unstable(state, "Deno.osRelease");
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check_all()?;
let release = sys_info::os_release().unwrap_or_else(|_| "".to_string());
Ok(release)
}
@@ -164,7 +165,7 @@ fn op_system_memory_info(
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<Option<MemInfo>, AnyError> {
super::check_unstable(state, "Deno.systemMemoryInfo");
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check_all()?;
match sys_info::mem_info() {
Ok(info) => Ok(Some(MemInfo {
total: info.total,
@@ -191,7 +192,7 @@ fn op_system_cpu_info(
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<CpuInfo, AnyError> {
super::check_unstable(state, "Deno.systemCpuInfo");
- state.borrow_mut::<Permissions>().env.check()?;
+ state.borrow_mut::<Permissions>().env.check_all()?;
let cores = sys_info::cpu_num().ok();
let speed = sys_info::cpu_speed().ok();
diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs
index ce89def54..832af485b 100644
--- a/runtime/ops/permissions.rs
+++ b/runtime/ops/permissions.rs
@@ -21,6 +21,7 @@ pub struct PermissionArgs {
name: String,
path: Option<String>,
host: Option<String>,
+ variable: Option<String>,
command: Option<String>,
}
@@ -41,7 +42,7 @@ pub fn op_query_permission(
}
.as_ref(),
),
- "env" => permissions.env.query(),
+ "env" => permissions.env.query(args.variable.as_deref()),
"run" => permissions.run.query(args.command.as_deref()),
"plugin" => permissions.plugin.query(),
"hrtime" => permissions.hrtime.query(),
@@ -72,7 +73,7 @@ pub fn op_revoke_permission(
}
.as_ref(),
),
- "env" => permissions.env.revoke(),
+ "env" => permissions.env.revoke(args.variable.as_deref()),
"run" => permissions.run.revoke(args.command.as_deref()),
"plugin" => permissions.plugin.revoke(),
"hrtime" => permissions.hrtime.revoke(),
@@ -103,7 +104,7 @@ pub fn op_request_permission(
}
.as_ref(),
),
- "env" => permissions.env.request(),
+ "env" => permissions.env.request(args.variable.as_deref()),
"run" => permissions.run.request(args.command.as_deref()),
"plugin" => permissions.plugin.request(),
"hrtime" => permissions.hrtime.request(),
diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs
index 92de420e3..905ae1334 100644
--- a/runtime/ops/worker_host.rs
+++ b/runtime/ops/worker_host.rs
@@ -1,6 +1,8 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
use crate::permissions::resolve_read_allowlist;
use crate::permissions::resolve_write_allowlist;
+use crate::permissions::EnvDescriptor;
use crate::permissions::NetDescriptor;
use crate::permissions::PermissionState;
use crate::permissions::Permissions;
@@ -186,6 +188,26 @@ fn merge_write_permission(
Ok(main)
}
+fn merge_env_permission(
+ mut main: UnaryPermission<EnvDescriptor>,
+ worker: Option<UnaryPermission<EnvDescriptor>>,
+) -> Result<UnaryPermission<EnvDescriptor>, AnyError> {
+ if let Some(worker) = worker {
+ if (worker.global_state < main.global_state)
+ || !worker.granted_list.iter().all(|x| main.check(&x.0).is_ok())
+ {
+ return Err(custom_error(
+ "PermissionDenied",
+ "Can't escalate parent thread permissions",
+ ));
+ } else {
+ main.global_state = worker.global_state;
+ main.granted_list = worker.granted_list;
+ }
+ }
+ Ok(main)
+}
+
fn merge_run_permission(
mut main: UnaryPermission<RunDescriptor>,
worker: Option<UnaryPermission<RunDescriptor>>,
@@ -211,7 +233,7 @@ fn create_worker_permissions(
worker_perms: PermissionsArg,
) -> Result<Permissions, AnyError> {
Ok(Permissions {
- env: merge_boolean_permission(main_perms.env, worker_perms.env)?,
+ env: merge_env_permission(main_perms.env, worker_perms.env)?,
hrtime: merge_boolean_permission(main_perms.hrtime, worker_perms.hrtime)?,
net: merge_net_permission(main_perms.net, worker_perms.net)?,
plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?,
@@ -223,8 +245,8 @@ fn create_worker_permissions(
#[derive(Debug, Deserialize)]
struct PermissionsArg {
- #[serde(default, deserialize_with = "as_permission_state")]
- env: Option<PermissionState>,
+ #[serde(default, deserialize_with = "as_unary_env_permission")]
+ env: Option<UnaryPermission<EnvDescriptor>>,
#[serde(default, deserialize_with = "as_permission_state")]
hrtime: Option<PermissionState>,
#[serde(default, deserialize_with = "as_unary_net_permission")]
@@ -366,6 +388,26 @@ where
}))
}
+fn as_unary_env_permission<'de, D>(
+ deserializer: D,
+) -> Result<Option<UnaryPermission<EnvDescriptor>>, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ let value: UnaryPermissionBase =
+ deserializer.deserialize_any(ParseBooleanOrStringVec)?;
+
+ Ok(Some(UnaryPermission::<EnvDescriptor> {
+ global_state: value.global_state,
+ granted_list: value
+ .paths
+ .into_iter()
+ .map(|env| EnvDescriptor(env.to_uppercase()))
+ .collect(),
+ ..Default::default()
+ }))
+}
+
fn as_unary_run_permission<'de, D>(
deserializer: D,
) -> Result<Option<UnaryPermission<RunDescriptor>>, D::Error>
diff --git a/runtime/permissions.rs b/runtime/permissions.rs
index a266de40b..e43e0eaa0 100644
--- a/runtime/permissions.rs
+++ b/runtime/permissions.rs
@@ -196,6 +196,9 @@ impl fmt::Display for NetDescriptor {
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, Default, Deserialize)]
+pub struct EnvDescriptor(pub String);
+
+#[derive(Clone, Eq, PartialEq, Hash, Debug, Default, Deserialize)]
pub struct RunDescriptor(pub String);
impl UnaryPermission<ReadDescriptor> {
@@ -574,6 +577,114 @@ impl UnaryPermission<NetDescriptor> {
}
}
+impl UnaryPermission<EnvDescriptor> {
+ pub fn query(&self, env: Option<&str>) -> PermissionState {
+ #[cfg(windows)]
+ let env = env.map(|env| env.to_uppercase());
+ #[cfg(windows)]
+ let env = env.as_deref();
+ if self.global_state == PermissionState::Denied
+ && match env {
+ None => true,
+ Some(env) => self.denied_list.iter().any(|env_| env_.0 == env),
+ }
+ {
+ PermissionState::Denied
+ } else if self.global_state == PermissionState::Granted
+ || match env {
+ None => false,
+ Some(env) => self.granted_list.iter().any(|env_| env_.0 == env),
+ }
+ {
+ PermissionState::Granted
+ } else {
+ PermissionState::Prompt
+ }
+ }
+
+ pub fn request(&mut self, env: Option<&str>) -> PermissionState {
+ if let Some(env) = env {
+ #[cfg(windows)]
+ let env = env.to_uppercase();
+ let state = self.query(Some(&env));
+ if state == PermissionState::Prompt {
+ if permission_prompt(&format!("env access to \"{}\"", env)) {
+ self.granted_list.retain(|env_| env_.0 != env);
+ self.granted_list.insert(EnvDescriptor(env.to_string()));
+ PermissionState::Granted
+ } else {
+ self.denied_list.retain(|env_| env_.0 != env);
+ self.denied_list.insert(EnvDescriptor(env.to_string()));
+ self.global_state = PermissionState::Denied;
+ PermissionState::Denied
+ }
+ } else {
+ state
+ }
+ } else {
+ let state = self.query(None);
+ if state == PermissionState::Prompt {
+ if permission_prompt("env access") {
+ self.granted_list.clear();
+ self.global_state = PermissionState::Granted;
+ PermissionState::Granted
+ } else {
+ self.global_state = PermissionState::Denied;
+ PermissionState::Denied
+ }
+ } else {
+ state
+ }
+ }
+ }
+
+ pub fn revoke(&mut self, env: Option<&str>) -> PermissionState {
+ if let Some(env) = env {
+ #[cfg(windows)]
+ let env = env.to_uppercase();
+ self.granted_list.retain(|env_| env_.0 != env);
+ } else {
+ self.granted_list.clear();
+ if self.global_state == PermissionState::Granted {
+ self.global_state = PermissionState::Prompt;
+ }
+ }
+ self.query(env)
+ }
+
+ pub fn check(&mut self, env: &str) -> Result<(), AnyError> {
+ #[cfg(windows)]
+ let env = &env.to_uppercase();
+ let (result, prompted) = self.query(Some(env)).check(
+ self.name,
+ Some(&format!("\"{}\"", env)),
+ self.prompt,
+ );
+ if prompted {
+ if result.is_ok() {
+ self.granted_list.insert(EnvDescriptor(env.to_string()));
+ } else {
+ self.denied_list.insert(EnvDescriptor(env.to_string()));
+ self.global_state = PermissionState::Denied;
+ }
+ }
+ result
+ }
+
+ pub fn check_all(&mut self) -> Result<(), AnyError> {
+ let (result, prompted) =
+ self.query(None).check(self.name, Some("all"), self.prompt);
+ if prompted {
+ if result.is_ok() {
+ self.global_state = PermissionState::Granted;
+ } else {
+ self.global_state = PermissionState::Denied;
+ }
+ }
+ result
+ }
+}
+
impl UnaryPermission<RunDescriptor> {
pub fn query(&self, cmd: Option<&str>) -> PermissionState {
if self.global_state == PermissionState::Denied
@@ -677,7 +788,7 @@ pub struct Permissions {
pub read: UnaryPermission<ReadDescriptor>,
pub write: UnaryPermission<WriteDescriptor>,
pub net: UnaryPermission<NetDescriptor>,
- pub env: UnitPermission,
+ pub env: UnaryPermission<EnvDescriptor>,
pub run: UnaryPermission<RunDescriptor>,
pub plugin: UnitPermission,
pub hrtime: UnitPermission,
@@ -685,7 +796,7 @@ pub struct Permissions {
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
pub struct PermissionsOptions {
- pub allow_env: bool,
+ pub allow_env: Option<Vec<String>>,
pub allow_hrtime: bool,
pub allow_net: Option<Vec<String>>,
pub allow_plugin: bool,
@@ -745,13 +856,31 @@ impl Permissions {
}
}
- pub fn new_env(state: bool, prompt: bool) -> UnitPermission {
- boolean_permission_from_flag_bool(
- state,
- "env",
- "environment variables",
+ pub fn new_env(
+ state: &Option<Vec<String>>,
+ prompt: bool,
+ ) -> UnaryPermission<EnvDescriptor> {
+ UnaryPermission::<EnvDescriptor> {
+ name: "env",
+ description: "environment variables",
+ global_state: global_state_from_option(state),
+ granted_list: state
+ .as_ref()
+ .map(|v| {
+ v.iter()
+ .map(|x| {
+ EnvDescriptor(if cfg!(windows) {
+ x.to_uppercase()
+ } else {
+ x.clone()
+ })
+ })
+ .collect()
+ })
+ .unwrap_or_else(HashSet::new),
+ denied_list: Default::default(),
prompt,
- )
+ }
}
pub fn new_run(
@@ -772,11 +901,11 @@ impl Permissions {
}
pub fn new_plugin(state: bool, prompt: bool) -> UnitPermission {
- boolean_permission_from_flag_bool(state, "plugin", "open a plugin", prompt)
+ unit_permission_from_flag_bool(state, "plugin", "open a plugin", prompt)
}
pub fn new_hrtime(state: bool, prompt: bool) -> UnitPermission {
- boolean_permission_from_flag_bool(
+ unit_permission_from_flag_bool(
state,
"hrtime",
"high precision time",
@@ -789,7 +918,7 @@ impl Permissions {
read: Permissions::new_read(&opts.allow_read, opts.prompt),
write: Permissions::new_write(&opts.allow_write, opts.prompt),
net: Permissions::new_net(&opts.allow_net, opts.prompt),
- env: Permissions::new_env(opts.allow_env, opts.prompt),
+ env: Permissions::new_env(&opts.allow_env, opts.prompt),
run: Permissions::new_run(&opts.allow_run, opts.prompt),
plugin: Permissions::new_plugin(opts.allow_plugin, opts.prompt),
hrtime: Permissions::new_hrtime(opts.allow_hrtime, opts.prompt),
@@ -801,7 +930,7 @@ impl Permissions {
read: Permissions::new_read(&Some(vec![]), false),
write: Permissions::new_write(&Some(vec![]), false),
net: Permissions::new_net(&Some(vec![]), false),
- env: Permissions::new_env(true, false),
+ env: Permissions::new_env(&Some(vec![]), false),
run: Permissions::new_run(&Some(vec![]), false),
plugin: Permissions::new_plugin(true, false),
hrtime: Permissions::new_hrtime(true, false),
@@ -845,7 +974,7 @@ impl deno_websocket::WebSocketPermissions for Permissions {
}
}
-fn boolean_permission_from_flag_bool(
+fn unit_permission_from_flag_bool(
flag: bool,
name: &'static str,
description: &'static str,
@@ -1289,9 +1418,9 @@ mod tests {
global_state: PermissionState::Prompt,
..Permissions::new_net(&Some(svec!["127.0.0.1:8000"]), false)
},
- env: UnitPermission {
- state: PermissionState::Prompt,
- ..Default::default()
+ env: UnaryPermission {
+ global_state: PermissionState::Prompt,
+ ..Permissions::new_env(&Some(svec!["HOME"]), false)
},
run: UnaryPermission {
global_state: PermissionState::Prompt,
@@ -1322,8 +1451,10 @@ mod tests {
assert_eq!(perms1.net.query(Some(&("127.0.0.1", None))), PermissionState::Granted);
assert_eq!(perms2.net.query::<&str>(None), PermissionState::Prompt);
assert_eq!(perms2.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
- assert_eq!(perms1.env.query(), PermissionState::Granted);
- assert_eq!(perms2.env.query(), PermissionState::Prompt);
+ assert_eq!(perms1.env.query(None), PermissionState::Granted);
+ assert_eq!(perms1.env.query(Some(&"HOME".to_string())), PermissionState::Granted);
+ assert_eq!(perms2.env.query(None), PermissionState::Prompt);
+ assert_eq!(perms2.env.query(Some(&"HOME".to_string())), PermissionState::Granted);
assert_eq!(perms1.run.query(None), PermissionState::Granted);
assert_eq!(perms1.run.query(Some(&"deno".to_string())), PermissionState::Granted);
assert_eq!(perms2.run.query(None), PermissionState::Prompt);
@@ -1356,9 +1487,10 @@ mod tests {
set_prompt_result(false);
assert_eq!(perms.net.request(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
set_prompt_result(true);
- assert_eq!(perms.env.request(), PermissionState::Granted);
+ assert_eq!(perms.env.request(Some(&"HOME".to_string())), PermissionState::Granted);
+ assert_eq!(perms.env.query(None), PermissionState::Prompt);
set_prompt_result(false);
- assert_eq!(perms.env.request(), PermissionState::Granted);
+ assert_eq!(perms.env.request(Some(&"HOME".to_string())), PermissionState::Granted);
set_prompt_result(true);
assert_eq!(perms.run.request(Some(&"deno".to_string())), PermissionState::Granted);
assert_eq!(perms.run.query(None), PermissionState::Prompt);
@@ -1390,9 +1522,9 @@ mod tests {
global_state: PermissionState::Prompt,
..Permissions::new_net(&Some(svec!["127.0.0.1"]), false)
},
- env: UnitPermission {
- state: PermissionState::Granted,
- ..Default::default()
+ env: UnaryPermission {
+ global_state: PermissionState::Prompt,
+ ..Permissions::new_env(&Some(svec!["HOME"]), false)
},
run: UnaryPermission {
global_state: PermissionState::Prompt,
@@ -1417,7 +1549,7 @@ mod tests {
assert_eq!(perms.write.query(Some(&Path::new("/foo/bar"))), PermissionState::Prompt);
assert_eq!(perms.net.revoke(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
assert_eq!(perms.net.revoke(Some(&("127.0.0.1", None))), PermissionState::Prompt);
- assert_eq!(perms.env.revoke(), PermissionState::Prompt);
+ assert_eq!(perms.env.revoke(Some(&"HOME".to_string())), PermissionState::Prompt);
assert_eq!(perms.run.revoke(Some(&"deno".to_string())), PermissionState::Prompt);
assert_eq!(perms.plugin.revoke(), PermissionState::Prompt);
assert_eq!(perms.hrtime.revoke(), PermissionState::Denied);
@@ -1430,7 +1562,7 @@ mod tests {
read: Permissions::new_read(&None, true),
write: Permissions::new_write(&None, true),
net: Permissions::new_net(&None, true),
- env: Permissions::new_env(false, true),
+ env: Permissions::new_env(&None, true),
run: Permissions::new_run(&None, true),
plugin: Permissions::new_plugin(false, true),
hrtime: Permissions::new_hrtime(false, true),
@@ -1466,6 +1598,12 @@ mod tests {
assert!(perms.run.check("ls").is_err());
set_prompt_result(true);
+ assert!(perms.env.check("HOME").is_ok());
+ set_prompt_result(false);
+ assert!(perms.env.check("HOME").is_ok());
+ assert!(perms.env.check("PATH").is_err());
+
+ set_prompt_result(true);
assert!(perms.hrtime.check().is_ok());
set_prompt_result(false);
assert!(perms.hrtime.check().is_ok());
@@ -1477,7 +1615,7 @@ mod tests {
read: Permissions::new_read(&None, true),
write: Permissions::new_write(&None, true),
net: Permissions::new_net(&None, true),
- env: Permissions::new_env(false, true),
+ env: Permissions::new_env(&None, true),
run: Permissions::new_run(&None, true),
plugin: Permissions::new_plugin(false, true),
hrtime: Permissions::new_hrtime(false, true),
@@ -1520,8 +1658,37 @@ mod tests {
assert!(perms.run.check("ls").is_ok());
set_prompt_result(false);
+ assert!(perms.env.check("HOME").is_err());
+ set_prompt_result(true);
+ assert!(perms.env.check("HOME").is_err());
+ assert!(perms.env.check("PATH").is_ok());
+ set_prompt_result(false);
+ assert!(perms.env.check("PATH").is_ok());
+
+ set_prompt_result(false);
assert!(perms.hrtime.check().is_err());
set_prompt_result(true);
assert!(perms.hrtime.check().is_err());
}
+
+ #[test]
+ #[cfg(windows)]
+ fn test_env_windows() {
+ let mut perms = Permissions::allow_all();
+ perms.env = UnaryPermission {
+ global_state: PermissionState::Prompt,
+ ..Permissions::new_env(&Some(svec!["HOME"]), false)
+ };
+
+ set_prompt_result(true);
+ assert!(perms.env.check("HOME").is_ok());
+ set_prompt_result(false);
+ assert!(perms.env.check("HOME").is_ok());
+ assert!(perms.env.check("hOmE").is_ok());
+
+ assert_eq!(
+ perms.env.revoke(Some(&"HomE".to_string())),
+ PermissionState::Prompt
+ );
+ }
}