mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor: improve node permission checks (#26028)
Does less work when requesting permissions with `-A`
This commit is contained in:
parent
f288730c38
commit
2de4faa483
11 changed files with 207 additions and 121 deletions
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
@ -32,18 +33,19 @@ pub type CliByonmNpmResolver = ByonmNpmResolver<CliDenoResolverFs>;
|
|||
struct CliByonmWrapper(Arc<CliByonmNpmResolver>);
|
||||
|
||||
impl NodeRequireResolver for CliByonmWrapper {
|
||||
fn ensure_read_permission(
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError> {
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
if !path
|
||||
.components()
|
||||
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
||||
{
|
||||
_ = permissions.check_read_path(path)?;
|
||||
permissions.check_read_path(path)
|
||||
} else {
|
||||
Ok(Cow::Borrowed(path))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
@ -593,11 +594,11 @@ impl NpmResolver for ManagedCliNpmResolver {
|
|||
}
|
||||
|
||||
impl NodeRequireResolver for ManagedCliNpmResolver {
|
||||
fn ensure_read_permission(
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError> {
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
self.fs_resolver.ensure_read_permission(permissions, path)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
pub mod bin_entries;
|
||||
pub mod lifecycle_scripts;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::io::ErrorKind;
|
||||
use std::path::Path;
|
||||
|
@ -62,11 +63,12 @@ pub trait NpmPackageFsResolver: Send + Sync {
|
|||
|
||||
async fn cache_packages(&self) -> Result<(), AnyError>;
|
||||
|
||||
fn ensure_read_permission(
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError>;
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -85,11 +87,15 @@ impl RegistryReadPermissionChecker {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ensure_registry_read_permission(
|
||||
pub fn ensure_registry_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError> {
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
if permissions.query_read_all() {
|
||||
return Ok(Cow::Borrowed(path)); // skip permissions checks below
|
||||
}
|
||||
|
||||
// allow reading if it's in the node_modules
|
||||
let is_path_in_node_modules = path.starts_with(&self.registry_path)
|
||||
&& path
|
||||
|
@ -118,20 +124,20 @@ impl RegistryReadPermissionChecker {
|
|||
},
|
||||
}
|
||||
};
|
||||
let Some(registry_path_canon) = canonicalize(&self.registry_path)? else {
|
||||
return Ok(()); // not exists, allow reading
|
||||
};
|
||||
let Some(path_canon) = canonicalize(path)? else {
|
||||
return Ok(()); // not exists, allow reading
|
||||
};
|
||||
|
||||
if let Some(registry_path_canon) = canonicalize(&self.registry_path)? {
|
||||
if let Some(path_canon) = canonicalize(path)? {
|
||||
if path_canon.starts_with(registry_path_canon) {
|
||||
return Ok(());
|
||||
return Ok(Cow::Owned(path_canon));
|
||||
}
|
||||
} else if path.starts_with(registry_path_canon)
|
||||
|| path.starts_with(&self.registry_path)
|
||||
{
|
||||
return Ok(Cow::Borrowed(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = permissions.check_read_path(path)?;
|
||||
Ok(())
|
||||
permissions.check_read_path(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,11 +183,11 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_read_permission(
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError> {
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
self
|
||||
.registry_read_permission_checker
|
||||
.ensure_registry_read_permission(permissions, path)
|
||||
|
|
|
@ -257,11 +257,11 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
|||
.await
|
||||
}
|
||||
|
||||
fn ensure_read_permission(
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError> {
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
self
|
||||
.registry_read_permission_checker
|
||||
.ensure_registry_read_permission(permissions, path)
|
||||
|
|
|
@ -66,6 +66,7 @@ pub trait NodePermissions {
|
|||
&mut self,
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError>;
|
||||
fn query_read_all(&mut self) -> bool;
|
||||
fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_write_with_api_name(
|
||||
|
@ -103,6 +104,10 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
|
|||
deno_permissions::PermissionsContainer::check_read_path(self, path, None)
|
||||
}
|
||||
|
||||
fn query_read_all(&mut self) -> bool {
|
||||
deno_permissions::PermissionsContainer::query_read_all(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn check_write_with_api_name(
|
||||
&mut self,
|
||||
|
@ -124,11 +129,12 @@ pub type NodeRequireResolverRc =
|
|||
deno_fs::sync::MaybeArc<dyn NodeRequireResolver>;
|
||||
|
||||
pub trait NodeRequireResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
||||
fn ensure_read_permission(
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &Path,
|
||||
) -> Result<(), AnyError>;
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError>;
|
||||
}
|
||||
|
||||
pub static NODE_ENV_VAR_ALLOWLIST: Lazy<HashSet<String>> = Lazy::new(|| {
|
||||
|
|
|
@ -15,6 +15,7 @@ use deno_path_util::normalize_path;
|
|||
use node_resolver::NodeModuleKind;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
use node_resolver::REQUIRE_CONDITIONS;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
@ -25,10 +26,11 @@ use crate::NodeRequireResolverRc;
|
|||
use crate::NodeResolverRc;
|
||||
use crate::NpmResolverRc;
|
||||
|
||||
fn ensure_read_permission<P>(
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn ensure_read_permission<'a, P>(
|
||||
state: &mut OpState,
|
||||
file_path: &Path,
|
||||
) -> Result<(), AnyError>
|
||||
file_path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError>
|
||||
where
|
||||
P: NodePermissions + 'static,
|
||||
{
|
||||
|
@ -107,7 +109,7 @@ where
|
|||
deno_path_util::normalize_path(current_dir.join(from))
|
||||
};
|
||||
|
||||
ensure_read_permission::<P>(state, &from)?;
|
||||
let from = ensure_read_permission::<P>(state, &from)?;
|
||||
|
||||
if cfg!(windows) {
|
||||
// return root node_modules when path is 'D:\\'.
|
||||
|
@ -129,7 +131,7 @@ where
|
|||
}
|
||||
|
||||
let mut paths = Vec::with_capacity(from.components().count());
|
||||
let mut current_path = from.as_path();
|
||||
let mut current_path = from.as_ref();
|
||||
let mut maybe_parent = Some(current_path);
|
||||
while let Some(parent) = maybe_parent {
|
||||
if !parent.ends_with("node_modules") {
|
||||
|
@ -267,7 +269,7 @@ where
|
|||
P: NodePermissions + 'static,
|
||||
{
|
||||
let path = PathBuf::from(path);
|
||||
ensure_read_permission::<P>(state, &path)?;
|
||||
let path = ensure_read_permission::<P>(state, &path)?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
if let Ok(metadata) = fs.stat_sync(&path) {
|
||||
if metadata.is_file {
|
||||
|
@ -290,7 +292,7 @@ where
|
|||
P: NodePermissions + 'static,
|
||||
{
|
||||
let path = PathBuf::from(request);
|
||||
ensure_read_permission::<P>(state, &path)?;
|
||||
let path = ensure_read_permission::<P>(state, &path)?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
let canonicalized_path =
|
||||
deno_core::strip_unc_prefix(fs.realpath_sync(&path)?);
|
||||
|
@ -362,7 +364,7 @@ where
|
|||
if parent_id == "<repl>" || parent_id == "internal/preload" {
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
if let Ok(cwd) = fs.cwd() {
|
||||
ensure_read_permission::<P>(state, &cwd)?;
|
||||
let cwd = ensure_read_permission::<P>(state, &cwd)?;
|
||||
return Ok(Some(cwd.to_string_lossy().into_owned()));
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +445,7 @@ where
|
|||
P: NodePermissions + 'static,
|
||||
{
|
||||
let file_path = PathBuf::from(file_path);
|
||||
ensure_read_permission::<P>(state, &file_path)?;
|
||||
let file_path = ensure_read_permission::<P>(state, &file_path)?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
Ok(fs.read_text_file_lossy_sync(&file_path, None)?)
|
||||
}
|
||||
|
@ -528,7 +530,7 @@ where
|
|||
P: NodePermissions + 'static,
|
||||
{
|
||||
let filename = PathBuf::from(filename);
|
||||
ensure_read_permission::<P>(state, filename.parent().unwrap())?;
|
||||
// permissions: allow reading the closest package.json files
|
||||
let node_resolver = state.borrow::<NodeResolverRc>().clone();
|
||||
node_resolver
|
||||
.get_closest_package_json_from_path(&filename)
|
||||
|
@ -567,7 +569,7 @@ where
|
|||
P: NodePermissions + 'static,
|
||||
{
|
||||
let referrer_path = PathBuf::from(&referrer_filename);
|
||||
ensure_read_permission::<P>(state, &referrer_path)?;
|
||||
let referrer_path = ensure_read_permission::<P>(state, &referrer_path)?;
|
||||
let node_resolver = state.borrow::<NodeResolverRc>();
|
||||
let Some(pkg) =
|
||||
node_resolver.get_closest_package_json_from_path(&referrer_path)?
|
||||
|
|
|
@ -7,6 +7,7 @@ use deno_core::url::Url;
|
|||
use deno_core::OpState;
|
||||
use deno_fs::FileSystemRc;
|
||||
use node_resolver::NodeResolution;
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -14,10 +15,11 @@ use crate::NodePermissions;
|
|||
use crate::NodeRequireResolverRc;
|
||||
use crate::NodeResolverRc;
|
||||
|
||||
fn ensure_read_permission<P>(
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn ensure_read_permission<'a, P>(
|
||||
state: &mut OpState,
|
||||
file_path: &Path,
|
||||
) -> Result<(), AnyError>
|
||||
file_path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError>
|
||||
where
|
||||
P: NodePermissions + 'static,
|
||||
{
|
||||
|
@ -47,7 +49,7 @@ where
|
|||
"Relative path entries must start with '.' or '..'",
|
||||
));
|
||||
}
|
||||
ensure_read_permission::<P>(state, &path)?;
|
||||
let path = ensure_read_permission::<P>(state, &path)?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
let canonicalized_path =
|
||||
deno_core::strip_unc_prefix(fs.realpath_sync(&path)?);
|
||||
|
@ -57,7 +59,7 @@ where
|
|||
let url_path = url
|
||||
.to_file_path()
|
||||
.map_err(|e| generic_error(format!("URL to Path-String: {:#?}", e)))?;
|
||||
ensure_read_permission::<P>(state, &url_path)?;
|
||||
let url_path = ensure_read_permission::<P>(state, &url_path)?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
if !fs.exists_sync(&url_path) {
|
||||
return Err(generic_error(format!("File not found [{:?}]", url_path)));
|
||||
|
|
|
@ -2285,6 +2285,11 @@ impl PermissionsContainer {
|
|||
self.inner.lock().read.check_all(Some(api_name))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn query_read_all(&self) -> bool {
|
||||
self.inner.lock().read.query(None) == PermissionState::Granted
|
||||
}
|
||||
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
#[inline(always)]
|
||||
pub fn check_write(
|
||||
|
@ -2614,8 +2619,13 @@ impl PermissionsContainer {
|
|||
&self,
|
||||
path: Option<&str>,
|
||||
) -> Result<PermissionState, AnyError> {
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.read;
|
||||
if permission.is_allow_all() {
|
||||
return Ok(PermissionState::Granted);
|
||||
}
|
||||
Ok(
|
||||
self.inner.lock().read.query(
|
||||
permission.query(
|
||||
path
|
||||
.map(|path| {
|
||||
Result::<_, AnyError>::Ok(
|
||||
|
@ -2633,8 +2643,13 @@ impl PermissionsContainer {
|
|||
&self,
|
||||
path: Option<&str>,
|
||||
) -> Result<PermissionState, AnyError> {
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.write;
|
||||
if permission.is_allow_all() {
|
||||
return Ok(PermissionState::Granted);
|
||||
}
|
||||
Ok(
|
||||
self.inner.lock().write.query(
|
||||
permission.query(
|
||||
path
|
||||
.map(|path| {
|
||||
Result::<_, AnyError>::Ok(
|
||||
|
@ -2652,8 +2667,13 @@ impl PermissionsContainer {
|
|||
&self,
|
||||
host: Option<&str>,
|
||||
) -> Result<PermissionState, AnyError> {
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.net;
|
||||
if permission.is_allow_all() {
|
||||
return Ok(PermissionState::Granted);
|
||||
}
|
||||
Ok(
|
||||
self.inner.lock().net.query(
|
||||
permission.query(
|
||||
match host {
|
||||
None => None,
|
||||
Some(h) => Some(self.descriptor_parser.parse_net_descriptor(h)?),
|
||||
|
@ -2665,7 +2685,12 @@ impl PermissionsContainer {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn query_env(&self, var: Option<&str>) -> PermissionState {
|
||||
self.inner.lock().env.query(var)
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.env;
|
||||
if permission.is_allow_all() {
|
||||
return PermissionState::Granted;
|
||||
}
|
||||
permission.query(var)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -2673,8 +2698,13 @@ impl PermissionsContainer {
|
|||
&self,
|
||||
kind: Option<&str>,
|
||||
) -> Result<PermissionState, AnyError> {
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.sys;
|
||||
if permission.is_allow_all() {
|
||||
return Ok(PermissionState::Granted);
|
||||
}
|
||||
Ok(
|
||||
self.inner.lock().sys.query(
|
||||
permission.query(
|
||||
kind
|
||||
.map(|kind| self.descriptor_parser.parse_sys_descriptor(kind))
|
||||
.transpose()?
|
||||
|
@ -2688,8 +2718,13 @@ impl PermissionsContainer {
|
|||
&self,
|
||||
cmd: Option<&str>,
|
||||
) -> Result<PermissionState, AnyError> {
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.run;
|
||||
if permission.is_allow_all() {
|
||||
return Ok(PermissionState::Granted);
|
||||
}
|
||||
Ok(
|
||||
self.inner.lock().run.query(
|
||||
permission.query(
|
||||
cmd
|
||||
.map(|request| self.descriptor_parser.parse_run_query(request))
|
||||
.transpose()?
|
||||
|
@ -2703,8 +2738,13 @@ impl PermissionsContainer {
|
|||
&self,
|
||||
path: Option<&str>,
|
||||
) -> Result<PermissionState, AnyError> {
|
||||
let inner = self.inner.lock();
|
||||
let permission = &inner.ffi;
|
||||
if permission.is_allow_all() {
|
||||
return Ok(PermissionState::Granted);
|
||||
}
|
||||
Ok(
|
||||
self.inner.lock().ffi.query(
|
||||
permission.query(
|
||||
path
|
||||
.map(|path| {
|
||||
Result::<_, AnyError>::Ok(
|
||||
|
|
|
@ -97,6 +97,9 @@ impl deno_node::NodePermissions for Permissions {
|
|||
) -> Result<PathBuf, deno_core::error::AnyError> {
|
||||
unreachable!("snapshotting!")
|
||||
}
|
||||
fn query_read_all(&mut self) -> bool {
|
||||
unreachable!("snapshotting!")
|
||||
}
|
||||
fn check_write_with_api_name(
|
||||
&mut self,
|
||||
_p: &str,
|
||||
|
|
|
@ -20,19 +20,27 @@ Deno.test(function permissionInvalidNameSync() {
|
|||
}, TypeError);
|
||||
});
|
||||
|
||||
Deno.test(async function permissionNetInvalidHost() {
|
||||
Deno.test(
|
||||
{ permissions: { net: [] } },
|
||||
async function permissionNetInvalidHost() {
|
||||
await assertRejects(async () => {
|
||||
await Deno.permissions.query({ name: "net", host: ":" });
|
||||
}, URIError);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(function permissionNetInvalidHostSync() {
|
||||
Deno.test(
|
||||
{ permissions: { net: [] } },
|
||||
function permissionNetInvalidHostSync() {
|
||||
assertThrows(() => {
|
||||
Deno.permissions.querySync({ name: "net", host: ":" });
|
||||
}, URIError);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(async function permissionSysValidKind() {
|
||||
Deno.test(
|
||||
{ permissions: { sys: [] } },
|
||||
async function permissionSysValidKind() {
|
||||
await Deno.permissions.query({ name: "sys", kind: "loadavg" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "osRelease" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "osUptime" });
|
||||
|
@ -42,9 +50,12 @@ Deno.test(async function permissionSysValidKind() {
|
|||
await Deno.permissions.query({ name: "sys", kind: "uid" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "gid" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "cpus" });
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(function permissionSysValidKindSync() {
|
||||
Deno.test(
|
||||
{ permissions: { sys: [] } },
|
||||
function permissionSysValidKindSync() {
|
||||
Deno.permissions.querySync({ name: "sys", kind: "loadavg" });
|
||||
Deno.permissions.querySync({ name: "sys", kind: "osRelease" });
|
||||
Deno.permissions.querySync({ name: "sys", kind: "networkInterfaces" });
|
||||
|
@ -53,21 +64,28 @@ Deno.test(function permissionSysValidKindSync() {
|
|||
Deno.permissions.querySync({ name: "sys", kind: "uid" });
|
||||
Deno.permissions.querySync({ name: "sys", kind: "gid" });
|
||||
Deno.permissions.querySync({ name: "sys", kind: "cpus" });
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(async function permissionSysInvalidKind() {
|
||||
Deno.test(
|
||||
{ permissions: { sys: [] } },
|
||||
async function permissionSysInvalidKind() {
|
||||
await assertRejects(async () => {
|
||||
// deno-lint-ignore no-explicit-any
|
||||
await Deno.permissions.query({ name: "sys", kind: "abc" as any });
|
||||
}, TypeError);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(function permissionSysInvalidKindSync() {
|
||||
Deno.test(
|
||||
{ permissions: { sys: [] } },
|
||||
function permissionSysInvalidKindSync() {
|
||||
assertThrows(() => {
|
||||
// deno-lint-ignore no-explicit-any
|
||||
Deno.permissions.querySync({ name: "sys", kind: "abc" as any });
|
||||
}, TypeError);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(async function permissionQueryReturnsEventTarget() {
|
||||
const status = await Deno.permissions.query({ name: "read", path: "." });
|
||||
|
@ -134,16 +152,21 @@ Deno.test(function permissionStatusIllegalConstructor() {
|
|||
});
|
||||
|
||||
// Regression test for https://github.com/denoland/deno/issues/17020
|
||||
Deno.test(async function permissionURL() {
|
||||
Deno.test(
|
||||
{ permissions: { read: [], write: [], ffi: [], run: [] } },
|
||||
async function permissionURL() {
|
||||
const path = new URL(".", import.meta.url);
|
||||
|
||||
await Deno.permissions.query({ name: "read", path });
|
||||
await Deno.permissions.query({ name: "write", path });
|
||||
await Deno.permissions.query({ name: "ffi", path });
|
||||
await Deno.permissions.query({ name: "run", command: path });
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(function permissionURLSync() {
|
||||
Deno.test(
|
||||
{ permissions: { read: [], write: [], ffi: [], run: [] } },
|
||||
function permissionURLSync() {
|
||||
Deno.permissions.querySync({
|
||||
name: "read",
|
||||
path: new URL(".", import.meta.url),
|
||||
|
@ -156,7 +179,8 @@ Deno.test(function permissionURLSync() {
|
|||
name: "run",
|
||||
command: new URL(".", import.meta.url),
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(async function permissionDescriptorValidation() {
|
||||
for (const value of [undefined, null, {}]) {
|
||||
|
|
Loading…
Reference in a new issue