mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
feat(permissions): allow env permission to take values (#9825)
This commit is contained in:
parent
ec1fce58d9
commit
8b59d9f7bc
6 changed files with 350 additions and 59 deletions
1
cli/dts/lib.deno.ns.d.ts
vendored
1
cli/dts/lib.deno.ns.d.ts
vendored
|
@ -2164,6 +2164,7 @@ declare namespace Deno {
|
||||||
|
|
||||||
export interface EnvPermissionDescriptor {
|
export interface EnvPermissionDescriptor {
|
||||||
name: "env";
|
name: "env";
|
||||||
|
variable?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PluginPermissionDescriptor {
|
export interface PluginPermissionDescriptor {
|
||||||
|
|
115
cli/flags.rs
115
cli/flags.rs
|
@ -128,7 +128,7 @@ pub struct Flags {
|
||||||
pub argv: Vec<String>,
|
pub argv: Vec<String>,
|
||||||
pub subcommand: DenoSubcommand,
|
pub subcommand: DenoSubcommand,
|
||||||
|
|
||||||
pub allow_env: bool,
|
pub allow_env: Option<Vec<String>>,
|
||||||
pub allow_hrtime: bool,
|
pub allow_hrtime: bool,
|
||||||
pub allow_net: Option<Vec<String>>,
|
pub allow_net: Option<Vec<String>>,
|
||||||
pub allow_plugin: bool,
|
pub allow_plugin: bool,
|
||||||
|
@ -207,8 +207,15 @@ impl Flags {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.allow_env {
|
match &self.allow_env {
|
||||||
args.push("--allow-env".to_string());
|
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 {
|
match &self.allow_run {
|
||||||
|
@ -527,7 +534,7 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
flags.repl = true;
|
flags.repl = true;
|
||||||
flags.subcommand = DenoSubcommand::Repl;
|
flags.subcommand = DenoSubcommand::Repl;
|
||||||
flags.allow_net = Some(vec![]);
|
flags.allow_net = Some(vec![]);
|
||||||
flags.allow_env = true;
|
flags.allow_env = Some(vec![]);
|
||||||
flags.allow_run = Some(vec![]);
|
flags.allow_run = Some(vec![]);
|
||||||
flags.allow_read = Some(vec![]);
|
flags.allow_read = Some(vec![]);
|
||||||
flags.allow_write = 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) {
|
fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, false, true);
|
runtime_args_parse(flags, matches, false, true);
|
||||||
flags.allow_net = Some(vec![]);
|
flags.allow_net = Some(vec![]);
|
||||||
flags.allow_env = true;
|
flags.allow_env = Some(vec![]);
|
||||||
flags.allow_run = Some(vec![]);
|
flags.allow_run = Some(vec![]);
|
||||||
flags.allow_read = Some(vec![]);
|
flags.allow_read = Some(vec![]);
|
||||||
flags.allow_write = 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(
|
||||||
Arg::with_name("allow-env")
|
Arg::with_name("allow-env")
|
||||||
.long("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(
|
||||||
Arg::with_name("allow-run")
|
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);
|
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") {
|
if let Some(run_wl) = matches.values_of("allow-run") {
|
||||||
let run_allowlist: Vec<String> = run_wl.map(ToString::to_string).collect();
|
let run_allowlist: Vec<String> = run_wl.map(ToString::to_string).collect();
|
||||||
flags.allow_run = Some(run_allowlist);
|
flags.allow_run = Some(run_allowlist);
|
||||||
debug!("run allowlist: {:#?}", &flags.allow_run);
|
debug!("run allowlist: {:#?}", &flags.allow_run);
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches.is_present("allow-env") {
|
|
||||||
flags.allow_env = true;
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-plugin") {
|
if matches.is_present("allow-plugin") {
|
||||||
flags.allow_plugin = true;
|
flags.allow_plugin = true;
|
||||||
}
|
}
|
||||||
|
@ -1843,7 +1873,7 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
if matches.is_present("allow-all") {
|
if matches.is_present("allow-all") {
|
||||||
flags.allow_read = Some(vec![]);
|
flags.allow_read = Some(vec![]);
|
||||||
flags.allow_env = true;
|
flags.allow_env = Some(vec![]);
|
||||||
flags.allow_net = Some(vec![]);
|
flags.allow_net = Some(vec![]);
|
||||||
flags.allow_run = Some(vec![]);
|
flags.allow_run = Some(vec![]);
|
||||||
flags.allow_write = Some(vec![]);
|
flags.allow_write = Some(vec![]);
|
||||||
|
@ -2054,7 +2084,7 @@ mod tests {
|
||||||
script: "gist.ts".to_string(),
|
script: "gist.ts".to_string(),
|
||||||
},
|
},
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2426,7 +2456,7 @@ mod tests {
|
||||||
ext: "js".to_string(),
|
ext: "js".to_string(),
|
||||||
},
|
},
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2449,7 +2479,7 @@ mod tests {
|
||||||
ext: "js".to_string(),
|
ext: "js".to_string(),
|
||||||
},
|
},
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2473,7 +2503,7 @@ mod tests {
|
||||||
ext: "ts".to_string(),
|
ext: "ts".to_string(),
|
||||||
},
|
},
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2510,7 +2540,7 @@ mod tests {
|
||||||
seed: Some(1),
|
seed: Some(1),
|
||||||
inspect: Some("127.0.0.1:9229".parse().unwrap()),
|
inspect: Some("127.0.0.1:9229".parse().unwrap()),
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2540,7 +2570,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
argv: svec!["arg1", "arg2"],
|
argv: svec!["arg1", "arg2"],
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2560,7 +2590,7 @@ mod tests {
|
||||||
repl: true,
|
repl: true,
|
||||||
subcommand: DenoSubcommand::Repl,
|
subcommand: DenoSubcommand::Repl,
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2594,7 +2624,7 @@ mod tests {
|
||||||
seed: Some(1),
|
seed: Some(1),
|
||||||
inspect: Some("127.0.0.1:9229".parse().unwrap()),
|
inspect: Some("127.0.0.1:9229".parse().unwrap()),
|
||||||
allow_net: Some(vec![]),
|
allow_net: Some(vec![]),
|
||||||
allow_env: true,
|
allow_env: Some(vec![]),
|
||||||
allow_run: Some(vec![]),
|
allow_run: Some(vec![]),
|
||||||
allow_read: Some(vec![]),
|
allow_read: Some(vec![]),
|
||||||
allow_write: Some(vec![]),
|
allow_write: Some(vec![]),
|
||||||
|
@ -2671,6 +2701,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]
|
#[test]
|
||||||
fn bundle() {
|
fn bundle() {
|
||||||
let r = flags_from_vec(svec!["deno", "bundle", "source.ts"]);
|
let r = flags_from_vec(svec!["deno", "bundle", "source.ts"]);
|
||||||
|
|
|
@ -54,7 +54,7 @@ fn op_set_env(
|
||||||
args: SetEnv,
|
args: SetEnv,
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
state.borrow_mut::<Permissions>().env.check()?;
|
state.borrow_mut::<Permissions>().env.check(&args.key)?;
|
||||||
let invalid_key =
|
let invalid_key =
|
||||||
args.key.is_empty() || args.key.contains(&['=', '\0'] as &[char]);
|
args.key.is_empty() || args.key.contains(&['=', '\0'] as &[char]);
|
||||||
let invalid_value = args.value.contains('\0');
|
let invalid_value = args.value.contains('\0');
|
||||||
|
@ -70,7 +70,7 @@ fn op_env(
|
||||||
_args: (),
|
_args: (),
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<HashMap<String, String>, AnyError> {
|
) -> Result<HashMap<String, String>, AnyError> {
|
||||||
state.borrow_mut::<Permissions>().env.check()?;
|
state.borrow_mut::<Permissions>().env.check_all()?;
|
||||||
Ok(env::vars().collect())
|
Ok(env::vars().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ fn op_get_env(
|
||||||
key: String,
|
key: String,
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> 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]) {
|
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
|
||||||
return Err(type_error("Key contains invalid characters."));
|
return Err(type_error("Key contains invalid characters."));
|
||||||
}
|
}
|
||||||
|
@ -89,12 +89,13 @@ fn op_get_env(
|
||||||
};
|
};
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_delete_env(
|
fn op_delete_env(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
key: String,
|
key: String,
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
state.borrow_mut::<Permissions>().env.check()?;
|
state.borrow_mut::<Permissions>().env.check(&key)?;
|
||||||
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
|
if key.is_empty() || key.contains(&['=', '\0'] as &[char]) {
|
||||||
return Err(type_error("Key contains invalid characters."));
|
return Err(type_error("Key contains invalid characters."));
|
||||||
}
|
}
|
||||||
|
@ -116,7 +117,7 @@ fn op_loadavg(
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<(f64, f64, f64), AnyError> {
|
) -> Result<(f64, f64, f64), AnyError> {
|
||||||
super::check_unstable(state, "Deno.loadavg");
|
super::check_unstable(state, "Deno.loadavg");
|
||||||
state.borrow_mut::<Permissions>().env.check()?;
|
state.borrow_mut::<Permissions>().env.check_all()?;
|
||||||
match sys_info::loadavg() {
|
match sys_info::loadavg() {
|
||||||
Ok(loadavg) => Ok((loadavg.one, loadavg.five, loadavg.fifteen)),
|
Ok(loadavg) => Ok((loadavg.one, loadavg.five, loadavg.fifteen)),
|
||||||
Err(_) => Ok((0.0, 0.0, 0.0)),
|
Err(_) => Ok((0.0, 0.0, 0.0)),
|
||||||
|
@ -129,7 +130,7 @@ fn op_hostname(
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
super::check_unstable(state, "Deno.hostname");
|
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());
|
let hostname = sys_info::hostname().unwrap_or_else(|_| "".to_string());
|
||||||
Ok(hostname)
|
Ok(hostname)
|
||||||
}
|
}
|
||||||
|
@ -140,7 +141,7 @@ fn op_os_release(
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
super::check_unstable(state, "Deno.osRelease");
|
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());
|
let release = sys_info::os_release().unwrap_or_else(|_| "".to_string());
|
||||||
Ok(release)
|
Ok(release)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +165,7 @@ fn op_system_memory_info(
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<Option<MemInfo>, AnyError> {
|
) -> Result<Option<MemInfo>, AnyError> {
|
||||||
super::check_unstable(state, "Deno.systemMemoryInfo");
|
super::check_unstable(state, "Deno.systemMemoryInfo");
|
||||||
state.borrow_mut::<Permissions>().env.check()?;
|
state.borrow_mut::<Permissions>().env.check_all()?;
|
||||||
match sys_info::mem_info() {
|
match sys_info::mem_info() {
|
||||||
Ok(info) => Ok(Some(MemInfo {
|
Ok(info) => Ok(Some(MemInfo {
|
||||||
total: info.total,
|
total: info.total,
|
||||||
|
@ -191,7 +192,7 @@ fn op_system_cpu_info(
|
||||||
_zero_copy: Option<ZeroCopyBuf>,
|
_zero_copy: Option<ZeroCopyBuf>,
|
||||||
) -> Result<CpuInfo, AnyError> {
|
) -> Result<CpuInfo, AnyError> {
|
||||||
super::check_unstable(state, "Deno.systemCpuInfo");
|
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 cores = sys_info::cpu_num().ok();
|
||||||
let speed = sys_info::cpu_speed().ok();
|
let speed = sys_info::cpu_speed().ok();
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub struct PermissionArgs {
|
||||||
name: String,
|
name: String,
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
host: Option<String>,
|
host: Option<String>,
|
||||||
|
variable: Option<String>,
|
||||||
command: Option<String>,
|
command: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ pub fn op_query_permission(
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
"env" => permissions.env.query(),
|
"env" => permissions.env.query(args.variable.as_deref()),
|
||||||
"run" => permissions.run.query(args.command.as_deref()),
|
"run" => permissions.run.query(args.command.as_deref()),
|
||||||
"plugin" => permissions.plugin.query(),
|
"plugin" => permissions.plugin.query(),
|
||||||
"hrtime" => permissions.hrtime.query(),
|
"hrtime" => permissions.hrtime.query(),
|
||||||
|
@ -72,7 +73,7 @@ pub fn op_revoke_permission(
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
"env" => permissions.env.revoke(),
|
"env" => permissions.env.revoke(args.variable.as_deref()),
|
||||||
"run" => permissions.run.revoke(args.command.as_deref()),
|
"run" => permissions.run.revoke(args.command.as_deref()),
|
||||||
"plugin" => permissions.plugin.revoke(),
|
"plugin" => permissions.plugin.revoke(),
|
||||||
"hrtime" => permissions.hrtime.revoke(),
|
"hrtime" => permissions.hrtime.revoke(),
|
||||||
|
@ -103,7 +104,7 @@ pub fn op_request_permission(
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
"env" => permissions.env.request(),
|
"env" => permissions.env.request(args.variable.as_deref()),
|
||||||
"run" => permissions.run.request(args.command.as_deref()),
|
"run" => permissions.run.request(args.command.as_deref()),
|
||||||
"plugin" => permissions.plugin.request(),
|
"plugin" => permissions.plugin.request(),
|
||||||
"hrtime" => permissions.hrtime.request(),
|
"hrtime" => permissions.hrtime.request(),
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::permissions::resolve_read_allowlist;
|
use crate::permissions::resolve_read_allowlist;
|
||||||
use crate::permissions::resolve_write_allowlist;
|
use crate::permissions::resolve_write_allowlist;
|
||||||
|
use crate::permissions::EnvDescriptor;
|
||||||
use crate::permissions::NetDescriptor;
|
use crate::permissions::NetDescriptor;
|
||||||
use crate::permissions::PermissionState;
|
use crate::permissions::PermissionState;
|
||||||
use crate::permissions::Permissions;
|
use crate::permissions::Permissions;
|
||||||
|
@ -186,6 +188,26 @@ fn merge_write_permission(
|
||||||
Ok(main)
|
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(
|
fn merge_run_permission(
|
||||||
mut main: UnaryPermission<RunDescriptor>,
|
mut main: UnaryPermission<RunDescriptor>,
|
||||||
worker: Option<UnaryPermission<RunDescriptor>>,
|
worker: Option<UnaryPermission<RunDescriptor>>,
|
||||||
|
@ -211,7 +233,7 @@ fn create_worker_permissions(
|
||||||
worker_perms: PermissionsArg,
|
worker_perms: PermissionsArg,
|
||||||
) -> Result<Permissions, AnyError> {
|
) -> Result<Permissions, AnyError> {
|
||||||
Ok(Permissions {
|
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)?,
|
hrtime: merge_boolean_permission(main_perms.hrtime, worker_perms.hrtime)?,
|
||||||
net: merge_net_permission(main_perms.net, worker_perms.net)?,
|
net: merge_net_permission(main_perms.net, worker_perms.net)?,
|
||||||
plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?,
|
plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?,
|
||||||
|
@ -223,8 +245,8 @@ fn create_worker_permissions(
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct PermissionsArg {
|
struct PermissionsArg {
|
||||||
#[serde(default, deserialize_with = "as_permission_state")]
|
#[serde(default, deserialize_with = "as_unary_env_permission")]
|
||||||
env: Option<PermissionState>,
|
env: Option<UnaryPermission<EnvDescriptor>>,
|
||||||
#[serde(default, deserialize_with = "as_permission_state")]
|
#[serde(default, deserialize_with = "as_permission_state")]
|
||||||
hrtime: Option<PermissionState>,
|
hrtime: Option<PermissionState>,
|
||||||
#[serde(default, deserialize_with = "as_unary_net_permission")]
|
#[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>(
|
fn as_unary_run_permission<'de, D>(
|
||||||
deserializer: D,
|
deserializer: D,
|
||||||
) -> Result<Option<UnaryPermission<RunDescriptor>>, D::Error>
|
) -> Result<Option<UnaryPermission<RunDescriptor>>, D::Error>
|
||||||
|
|
|
@ -195,6 +195,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)]
|
#[derive(Clone, Eq, PartialEq, Hash, Debug, Default, Deserialize)]
|
||||||
pub struct RunDescriptor(pub String);
|
pub struct RunDescriptor(pub String);
|
||||||
|
|
||||||
|
@ -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> {
|
impl UnaryPermission<RunDescriptor> {
|
||||||
pub fn query(&self, cmd: Option<&str>) -> PermissionState {
|
pub fn query(&self, cmd: Option<&str>) -> PermissionState {
|
||||||
if self.global_state == PermissionState::Denied
|
if self.global_state == PermissionState::Denied
|
||||||
|
@ -677,7 +788,7 @@ pub struct Permissions {
|
||||||
pub read: UnaryPermission<ReadDescriptor>,
|
pub read: UnaryPermission<ReadDescriptor>,
|
||||||
pub write: UnaryPermission<WriteDescriptor>,
|
pub write: UnaryPermission<WriteDescriptor>,
|
||||||
pub net: UnaryPermission<NetDescriptor>,
|
pub net: UnaryPermission<NetDescriptor>,
|
||||||
pub env: UnitPermission,
|
pub env: UnaryPermission<EnvDescriptor>,
|
||||||
pub run: UnaryPermission<RunDescriptor>,
|
pub run: UnaryPermission<RunDescriptor>,
|
||||||
pub plugin: UnitPermission,
|
pub plugin: UnitPermission,
|
||||||
pub hrtime: UnitPermission,
|
pub hrtime: UnitPermission,
|
||||||
|
@ -685,7 +796,7 @@ pub struct Permissions {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||||
pub struct PermissionsOptions {
|
pub struct PermissionsOptions {
|
||||||
pub allow_env: bool,
|
pub allow_env: Option<Vec<String>>,
|
||||||
pub allow_hrtime: bool,
|
pub allow_hrtime: bool,
|
||||||
pub allow_net: Option<Vec<String>>,
|
pub allow_net: Option<Vec<String>>,
|
||||||
pub allow_plugin: bool,
|
pub allow_plugin: bool,
|
||||||
|
@ -745,13 +856,31 @@ impl Permissions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_env(state: bool, prompt: bool) -> UnitPermission {
|
pub fn new_env(
|
||||||
boolean_permission_from_flag_bool(
|
state: &Option<Vec<String>>,
|
||||||
state,
|
prompt: bool,
|
||||||
"env",
|
) -> UnaryPermission<EnvDescriptor> {
|
||||||
"environment variables",
|
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,
|
prompt,
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_run(
|
pub fn new_run(
|
||||||
|
@ -772,11 +901,11 @@ impl Permissions {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_plugin(state: bool, prompt: bool) -> UnitPermission {
|
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 {
|
pub fn new_hrtime(state: bool, prompt: bool) -> UnitPermission {
|
||||||
boolean_permission_from_flag_bool(
|
unit_permission_from_flag_bool(
|
||||||
state,
|
state,
|
||||||
"hrtime",
|
"hrtime",
|
||||||
"high precision time",
|
"high precision time",
|
||||||
|
@ -789,7 +918,7 @@ impl Permissions {
|
||||||
read: Permissions::new_read(&opts.allow_read, opts.prompt),
|
read: Permissions::new_read(&opts.allow_read, opts.prompt),
|
||||||
write: Permissions::new_write(&opts.allow_write, opts.prompt),
|
write: Permissions::new_write(&opts.allow_write, opts.prompt),
|
||||||
net: Permissions::new_net(&opts.allow_net, 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),
|
run: Permissions::new_run(&opts.allow_run, opts.prompt),
|
||||||
plugin: Permissions::new_plugin(opts.allow_plugin, opts.prompt),
|
plugin: Permissions::new_plugin(opts.allow_plugin, opts.prompt),
|
||||||
hrtime: Permissions::new_hrtime(opts.allow_hrtime, opts.prompt),
|
hrtime: Permissions::new_hrtime(opts.allow_hrtime, opts.prompt),
|
||||||
|
@ -801,7 +930,7 @@ impl Permissions {
|
||||||
read: Permissions::new_read(&Some(vec![]), false),
|
read: Permissions::new_read(&Some(vec![]), false),
|
||||||
write: Permissions::new_write(&Some(vec![]), false),
|
write: Permissions::new_write(&Some(vec![]), false),
|
||||||
net: Permissions::new_net(&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),
|
run: Permissions::new_run(&Some(vec![]), false),
|
||||||
plugin: Permissions::new_plugin(true, false),
|
plugin: Permissions::new_plugin(true, false),
|
||||||
hrtime: Permissions::new_hrtime(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,
|
flag: bool,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
description: &'static str,
|
description: &'static str,
|
||||||
|
@ -1289,9 +1418,9 @@ mod tests {
|
||||||
global_state: PermissionState::Prompt,
|
global_state: PermissionState::Prompt,
|
||||||
..Permissions::new_net(&Some(svec!["127.0.0.1:8000"]), false)
|
..Permissions::new_net(&Some(svec!["127.0.0.1:8000"]), false)
|
||||||
},
|
},
|
||||||
env: UnitPermission {
|
env: UnaryPermission {
|
||||||
state: PermissionState::Prompt,
|
global_state: PermissionState::Prompt,
|
||||||
..Default::default()
|
..Permissions::new_env(&Some(svec!["HOME"]), false)
|
||||||
},
|
},
|
||||||
run: UnaryPermission {
|
run: UnaryPermission {
|
||||||
global_state: PermissionState::Prompt,
|
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!(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::<&str>(None), PermissionState::Prompt);
|
||||||
assert_eq!(perms2.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
assert_eq!(perms2.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
||||||
assert_eq!(perms1.env.query(), PermissionState::Granted);
|
assert_eq!(perms1.env.query(None), PermissionState::Granted);
|
||||||
assert_eq!(perms2.env.query(), PermissionState::Prompt);
|
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(None), PermissionState::Granted);
|
||||||
assert_eq!(perms1.run.query(Some(&"deno".to_string())), PermissionState::Granted);
|
assert_eq!(perms1.run.query(Some(&"deno".to_string())), PermissionState::Granted);
|
||||||
assert_eq!(perms2.run.query(None), PermissionState::Prompt);
|
assert_eq!(perms2.run.query(None), PermissionState::Prompt);
|
||||||
|
@ -1356,9 +1487,10 @@ mod tests {
|
||||||
set_prompt_result(false);
|
set_prompt_result(false);
|
||||||
assert_eq!(perms.net.request(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
assert_eq!(perms.net.request(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
||||||
set_prompt_result(true);
|
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);
|
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);
|
set_prompt_result(true);
|
||||||
assert_eq!(perms.run.request(Some(&"deno".to_string())), PermissionState::Granted);
|
assert_eq!(perms.run.request(Some(&"deno".to_string())), PermissionState::Granted);
|
||||||
assert_eq!(perms.run.query(None), PermissionState::Prompt);
|
assert_eq!(perms.run.query(None), PermissionState::Prompt);
|
||||||
|
@ -1390,9 +1522,9 @@ mod tests {
|
||||||
global_state: PermissionState::Prompt,
|
global_state: PermissionState::Prompt,
|
||||||
..Permissions::new_net(&Some(svec!["127.0.0.1"]), false)
|
..Permissions::new_net(&Some(svec!["127.0.0.1"]), false)
|
||||||
},
|
},
|
||||||
env: UnitPermission {
|
env: UnaryPermission {
|
||||||
state: PermissionState::Granted,
|
global_state: PermissionState::Prompt,
|
||||||
..Default::default()
|
..Permissions::new_env(&Some(svec!["HOME"]), false)
|
||||||
},
|
},
|
||||||
run: UnaryPermission {
|
run: UnaryPermission {
|
||||||
global_state: PermissionState::Prompt,
|
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.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", Some(8000)))), PermissionState::Granted);
|
||||||
assert_eq!(perms.net.revoke(Some(&("127.0.0.1", None))), PermissionState::Prompt);
|
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.run.revoke(Some(&"deno".to_string())), PermissionState::Prompt);
|
||||||
assert_eq!(perms.plugin.revoke(), PermissionState::Prompt);
|
assert_eq!(perms.plugin.revoke(), PermissionState::Prompt);
|
||||||
assert_eq!(perms.hrtime.revoke(), PermissionState::Denied);
|
assert_eq!(perms.hrtime.revoke(), PermissionState::Denied);
|
||||||
|
@ -1430,7 +1562,7 @@ mod tests {
|
||||||
read: Permissions::new_read(&None, true),
|
read: Permissions::new_read(&None, true),
|
||||||
write: Permissions::new_write(&None, true),
|
write: Permissions::new_write(&None, true),
|
||||||
net: Permissions::new_net(&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),
|
run: Permissions::new_run(&None, true),
|
||||||
plugin: Permissions::new_plugin(false, true),
|
plugin: Permissions::new_plugin(false, true),
|
||||||
hrtime: Permissions::new_hrtime(false, true),
|
hrtime: Permissions::new_hrtime(false, true),
|
||||||
|
@ -1465,6 +1597,12 @@ mod tests {
|
||||||
assert!(perms.run.check("cat").is_ok());
|
assert!(perms.run.check("cat").is_ok());
|
||||||
assert!(perms.run.check("ls").is_err());
|
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);
|
set_prompt_result(true);
|
||||||
assert!(perms.hrtime.check().is_ok());
|
assert!(perms.hrtime.check().is_ok());
|
||||||
set_prompt_result(false);
|
set_prompt_result(false);
|
||||||
|
@ -1477,7 +1615,7 @@ mod tests {
|
||||||
read: Permissions::new_read(&None, true),
|
read: Permissions::new_read(&None, true),
|
||||||
write: Permissions::new_write(&None, true),
|
write: Permissions::new_write(&None, true),
|
||||||
net: Permissions::new_net(&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),
|
run: Permissions::new_run(&None, true),
|
||||||
plugin: Permissions::new_plugin(false, true),
|
plugin: Permissions::new_plugin(false, true),
|
||||||
hrtime: Permissions::new_hrtime(false, true),
|
hrtime: Permissions::new_hrtime(false, true),
|
||||||
|
@ -1519,9 +1657,38 @@ mod tests {
|
||||||
set_prompt_result(false);
|
set_prompt_result(false);
|
||||||
assert!(perms.run.check("ls").is_ok());
|
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);
|
set_prompt_result(false);
|
||||||
assert!(perms.hrtime.check().is_err());
|
assert!(perms.hrtime.check().is_err());
|
||||||
set_prompt_result(true);
|
set_prompt_result(true);
|
||||||
assert!(perms.hrtime.check().is_err());
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue