mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
refactor: add deno_permissions
crate (#22236)
Issue https://github.com/denoland/deno/issues/22222 ![image](https://github.com/denoland/deno/assets/34997667/2af8474b-b919-4519-98ce-9d29bc7829f2) This PR moves `runtime/permissions` code to a upstream crate called `deno_permissions`. The `deno_permissions::PermissionsContainer` is put into the OpState and can be used instead of the current trait-based permissions system. For this PR, I've migrated `deno_fetch` to the new crate but kept the rest of the trait-based system as a wrapper of `deno_permissions` crate. Doing the migration all at once is error prone and hard to review. Comparing incremental compile times for `ext/fetch` on Mac M1: | profile | `cargo build --bin deno` | `cargo plonk build --bin deno` | | --------- | ------------- | ------------------- | | `debug` | 20 s | 0.8s | | `release` | 4 mins 12 s | 1.4s |
This commit is contained in:
parent
4a88695563
commit
de28e6fc09
16 changed files with 381 additions and 210 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -1728,6 +1728,22 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deno_permissions"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"console_static_text",
|
||||||
|
"deno_core",
|
||||||
|
"deno_terminal",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"termcolor",
|
||||||
|
"which 4.4.2",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_runtime"
|
name = "deno_runtime"
|
||||||
version = "0.149.0"
|
version = "0.149.0"
|
||||||
|
@ -1750,6 +1766,7 @@ dependencies = [
|
||||||
"deno_napi",
|
"deno_napi",
|
||||||
"deno_net",
|
"deno_net",
|
||||||
"deno_node",
|
"deno_node",
|
||||||
|
"deno_permissions",
|
||||||
"deno_terminal",
|
"deno_terminal",
|
||||||
"deno_tls",
|
"deno_tls",
|
||||||
"deno_url",
|
"deno_url",
|
||||||
|
|
|
@ -28,6 +28,7 @@ members = [
|
||||||
"ext/websocket",
|
"ext/websocket",
|
||||||
"ext/webstorage",
|
"ext/webstorage",
|
||||||
"runtime",
|
"runtime",
|
||||||
|
"runtime/permissions",
|
||||||
"tests",
|
"tests",
|
||||||
"tests/ffi",
|
"tests/ffi",
|
||||||
"tests/napi",
|
"tests/napi",
|
||||||
|
@ -48,6 +49,7 @@ deno_core = { version = "0.269.0", features = ["lazy_eval_snapshot"] }
|
||||||
deno_bench_util = { version = "0.135.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.135.0", path = "./bench_util" }
|
||||||
deno_lockfile = "0.19.0"
|
deno_lockfile = "0.19.0"
|
||||||
deno_media_type = { version = "0.1.1", features = ["module_specifier"] }
|
deno_media_type = { version = "0.1.1", features = ["module_specifier"] }
|
||||||
|
deno_permissions = { version = "0.1.0", path = "./runtime/permissions" }
|
||||||
deno_runtime = { version = "0.149.0", path = "./runtime" }
|
deno_runtime = { version = "0.149.0", path = "./runtime" }
|
||||||
deno_terminal = "0.1.1"
|
deno_terminal = "0.1.1"
|
||||||
napi_sym = { version = "0.71.0", path = "./cli/napi/sym" }
|
napi_sym = { version = "0.71.0", path = "./cli/napi/sym" }
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub fn op_pledge_test_permissions(
|
||||||
let token = Uuid::new_v4();
|
let token = Uuid::new_v4();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = {
|
let worker_permissions = {
|
||||||
let mut parent_permissions = parent_permissions.0.lock();
|
let mut parent_permissions = parent_permissions.0 .0.lock();
|
||||||
let perms = create_child_permissions(&mut parent_permissions, args)?;
|
let perms = create_child_permissions(&mut parent_permissions, args)?;
|
||||||
PermissionsContainer::new(perms)
|
PermissionsContainer::new(perms)
|
||||||
};
|
};
|
||||||
|
@ -69,6 +69,7 @@ pub fn op_pledge_test_permissions(
|
||||||
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
||||||
|
|
||||||
// NOTE: This call overrides current permission set for the worker
|
// NOTE: This call overrides current permission set for the worker
|
||||||
|
state.put(worker_permissions.0.clone());
|
||||||
state.put::<PermissionsContainer>(worker_permissions);
|
state.put::<PermissionsContainer>(worker_permissions);
|
||||||
|
|
||||||
Ok(token)
|
Ok(token)
|
||||||
|
@ -85,6 +86,7 @@ pub fn op_restore_test_permissions(
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissions = permissions_holder.1;
|
let permissions = permissions_holder.1;
|
||||||
|
state.put(permissions.0.clone());
|
||||||
state.put::<PermissionsContainer>(permissions);
|
state.put::<PermissionsContainer>(permissions);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub fn op_pledge_test_permissions(
|
||||||
let token = Uuid::new_v4();
|
let token = Uuid::new_v4();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = {
|
let worker_permissions = {
|
||||||
let mut parent_permissions = parent_permissions.0.lock();
|
let mut parent_permissions = parent_permissions.0 .0.lock();
|
||||||
let perms = create_child_permissions(&mut parent_permissions, args)?;
|
let perms = create_child_permissions(&mut parent_permissions, args)?;
|
||||||
PermissionsContainer::new(perms)
|
PermissionsContainer::new(perms)
|
||||||
};
|
};
|
||||||
|
@ -69,6 +69,7 @@ pub fn op_pledge_test_permissions(
|
||||||
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
||||||
|
|
||||||
// NOTE: This call overrides current permission set for the worker
|
// NOTE: This call overrides current permission set for the worker
|
||||||
|
state.put(worker_permissions.0.clone());
|
||||||
state.put::<PermissionsContainer>(worker_permissions);
|
state.put::<PermissionsContainer>(worker_permissions);
|
||||||
|
|
||||||
Ok(token)
|
Ok(token)
|
||||||
|
@ -85,6 +86,7 @@ pub fn op_restore_test_permissions(
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissions = permissions_holder.1;
|
let permissions = permissions_holder.1;
|
||||||
|
state.put(permissions.0.clone());
|
||||||
state.put::<PermissionsContainer>(permissions);
|
state.put::<PermissionsContainer>(permissions);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -168,15 +168,6 @@ impl FetchHandler for DefaultFileFetchHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FetchPermissions {
|
|
||||||
fn check_net_url(
|
|
||||||
&mut self,
|
|
||||||
_url: &Url,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError>;
|
|
||||||
fn check_read(&mut self, _p: &Path, api_name: &str) -> Result<(), AnyError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_declaration() -> PathBuf {
|
pub fn get_declaration() -> PathBuf {
|
||||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_fetch.d.ts")
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_fetch.d.ts")
|
||||||
}
|
}
|
||||||
|
@ -268,6 +259,15 @@ impl Drop for ResourceToBodyAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FetchPermissions {
|
||||||
|
fn check_net_url(
|
||||||
|
&mut self,
|
||||||
|
_url: &Url,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError>;
|
||||||
|
fn check_read(&mut self, _p: &Path, api_name: &str) -> Result<(), AnyError>;
|
||||||
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[serde]
|
#[serde]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
|
|
@ -90,6 +90,7 @@ deno_kv.workspace = true
|
||||||
deno_napi.workspace = true
|
deno_napi.workspace = true
|
||||||
deno_net.workspace = true
|
deno_net.workspace = true
|
||||||
deno_node.workspace = true
|
deno_node.workspace = true
|
||||||
|
deno_permissions.workspace = true
|
||||||
deno_terminal.workspace = true
|
deno_terminal.workspace = true
|
||||||
deno_tls.workspace = true
|
deno_tls.workspace = true
|
||||||
deno_url.workspace = true
|
deno_url.workspace = true
|
||||||
|
|
|
@ -16,6 +16,8 @@ pub use deno_kv;
|
||||||
pub use deno_napi;
|
pub use deno_napi;
|
||||||
pub use deno_net;
|
pub use deno_net;
|
||||||
pub use deno_node;
|
pub use deno_node;
|
||||||
|
pub use deno_permissions;
|
||||||
|
pub use deno_terminal::colors;
|
||||||
pub use deno_tls;
|
pub use deno_tls;
|
||||||
pub use deno_url;
|
pub use deno_url;
|
||||||
pub use deno_web;
|
pub use deno_web;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::permissions::parse_sys_kind;
|
use ::deno_permissions::parse_sys_kind;
|
||||||
use crate::permissions::PermissionState;
|
use ::deno_permissions::PermissionState;
|
||||||
use crate::permissions::PermissionsContainer;
|
use ::deno_permissions::PermissionsContainer;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::uri_error;
|
use deno_core::error::uri_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
|
|
@ -153,7 +153,7 @@ fn op_create_worker(
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = if let Some(child_permissions_arg) = args.permissions
|
let worker_permissions = if let Some(child_permissions_arg) = args.permissions
|
||||||
{
|
{
|
||||||
let mut parent_permissions = parent_permissions.0.lock();
|
let mut parent_permissions = parent_permissions.0 .0.lock();
|
||||||
let perms =
|
let perms =
|
||||||
create_child_permissions(&mut parent_permissions, child_permissions_arg)?;
|
create_child_permissions(&mut parent_permissions, child_permissions_arg)?;
|
||||||
PermissionsContainer::new(perms)
|
PermissionsContainer::new(perms)
|
||||||
|
|
238
runtime/permissions.rs
Normal file
238
runtime/permissions.rs
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::url::Url;
|
||||||
|
pub use deno_permissions::create_child_permissions;
|
||||||
|
pub use deno_permissions::parse_sys_kind;
|
||||||
|
pub use deno_permissions::set_prompt_callbacks;
|
||||||
|
pub use deno_permissions::ChildPermissionsArg;
|
||||||
|
pub use deno_permissions::Permissions;
|
||||||
|
pub use deno_permissions::PermissionsOptions;
|
||||||
|
|
||||||
|
// NOTE: Temporary permissions container to satisfy traits. We are migrating to the deno_permissions
|
||||||
|
// crate.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
|
||||||
|
pub struct PermissionsContainer(pub deno_permissions::PermissionsContainer);
|
||||||
|
|
||||||
|
impl PermissionsContainer {
|
||||||
|
pub fn new(permissions: deno_permissions::Permissions) -> Self {
|
||||||
|
Self(deno_permissions::PermissionsContainer::new(permissions))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow_all() -> Self {
|
||||||
|
Self(deno_permissions::PermissionsContainer::allow_all())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for PermissionsContainer {
|
||||||
|
type Target = deno_permissions::PermissionsContainer;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for PermissionsContainer {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_node::NodePermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_net_url(
|
||||||
|
&mut self,
|
||||||
|
url: &Url,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_net_url(url, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_read_with_api_name(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: Option<&str>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read_with_api_name(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_write_with_api_name(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: Option<&str>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write_with_api_name(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> {
|
||||||
|
self.0.check_sys(kind, api_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_fetch::FetchPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_net_url(
|
||||||
|
&mut self,
|
||||||
|
url: &Url,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_net_url(url, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read(path, api_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_net::NetPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_net<T: AsRef<str>>(
|
||||||
|
&mut self,
|
||||||
|
host: &(T, Option<u16>),
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_net(host, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_write(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write(path, api_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_web::TimersPermission for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn allow_hrtime(&mut self) -> bool {
|
||||||
|
self.0.allow_hrtime()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_websocket::WebSocketPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_net_url(
|
||||||
|
&mut self,
|
||||||
|
url: &Url,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_net_url(url, api_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_fs::FsPermissions for PermissionsContainer {
|
||||||
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_read_blind(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
display: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read_blind(path, display, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write_partial(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write_partial(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write_blind(
|
||||||
|
&mut self,
|
||||||
|
p: &Path,
|
||||||
|
display: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write_blind(p, display, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read_all(api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write_all(api_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
|
||||||
|
// change in the future.
|
||||||
|
impl deno_napi::NapiPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
||||||
|
self.0.check_ffi(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_ffi::FfiPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
||||||
|
self.0.check_ffi_partial(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_kv::sqlite::SqliteDbHandlerPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> {
|
||||||
|
self.0.check_read(p, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> {
|
||||||
|
self.0.check_write(p, api_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_kv::remote::RemoteDbHandlerPermissions for PermissionsContainer {
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_env(&mut self, var: &str) -> Result<(), AnyError> {
|
||||||
|
self.0.check_env(var)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn check_net_url(
|
||||||
|
&mut self,
|
||||||
|
url: &Url,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.check_net_url(url, api_name)
|
||||||
|
}
|
||||||
|
}
|
28
runtime/permissions/Cargo.toml
Normal file
28
runtime/permissions/Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "deno_permissions"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
description = "Provides the deno permissions implementation."
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "deno_permissions"
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
console_static_text.workspace = true
|
||||||
|
deno_core.workspace = true
|
||||||
|
deno_terminal.workspace = true
|
||||||
|
libc.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
once_cell.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
termcolor.workspace = true
|
||||||
|
which = "4.2.5"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
winapi = { workspace = true, features = ["commapi", "knownfolders", "mswsock", "objbase", "psapi", "shlobj", "tlhelp32", "winbase", "winerror", "winuser", "winsock2"] }
|
0
runtime/permissions/README.md
Normal file
0
runtime/permissions/README.md
Normal file
|
@ -1,10 +1,11 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::fs_util::resolve_from_cwd;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::uri_error;
|
use deno_core::error::uri_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::normalize_path;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::serde::de;
|
use deno_core::serde::de;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
|
@ -15,7 +16,6 @@ use deno_core::url;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
use log;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -28,7 +28,7 @@ use std::string::ToString;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use which::which;
|
use which::which;
|
||||||
|
|
||||||
mod prompter;
|
pub mod prompter;
|
||||||
use prompter::permission_prompt;
|
use prompter::permission_prompt;
|
||||||
use prompter::PromptResponse;
|
use prompter::PromptResponse;
|
||||||
use prompter::PERMISSION_EMOJI;
|
use prompter::PERMISSION_EMOJI;
|
||||||
|
@ -36,6 +36,18 @@ use prompter::PERMISSION_EMOJI;
|
||||||
pub use prompter::set_prompt_callbacks;
|
pub use prompter::set_prompt_callbacks;
|
||||||
pub use prompter::PromptCallback;
|
pub use prompter::PromptCallback;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> {
|
||||||
|
if path.is_absolute() {
|
||||||
|
Ok(normalize_path(path))
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::disallowed_methods)]
|
||||||
|
let cwd = std::env::current_dir()
|
||||||
|
.context("Failed to get current working directory")?;
|
||||||
|
Ok(normalize_path(cwd.join(path)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static DEBUG_LOG_ENABLED: Lazy<bool> =
|
static DEBUG_LOG_ENABLED: Lazy<bool> =
|
||||||
Lazy::new(|| log::log_enabled!(log::Level::Debug));
|
Lazy::new(|| log::log_enabled!(log::Level::Debug));
|
||||||
|
|
||||||
|
@ -1271,6 +1283,11 @@ impl PermissionsContainer {
|
||||||
Self(Arc::new(Mutex::new(perms)))
|
Self(Arc::new(Mutex::new(perms)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn allow_hrtime(&mut self) -> bool {
|
||||||
|
self.0.lock().hrtime.check().is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn allow_all() -> Self {
|
pub fn allow_all() -> Self {
|
||||||
Self::new(Permissions::allow_all())
|
Self::new(Permissions::allow_all())
|
||||||
}
|
}
|
||||||
|
@ -1292,6 +1309,15 @@ impl PermissionsContainer {
|
||||||
self.0.lock().read.check(path, Some(api_name))
|
self.0.lock().read.check(path, Some(api_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn check_read_with_api_name(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: Option<&str>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.lock().read.check(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn check_read_blind(
|
pub fn check_read_blind(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1316,6 +1342,15 @@ impl PermissionsContainer {
|
||||||
self.0.lock().write.check(path, Some(api_name))
|
self.0.lock().write.check(path, Some(api_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn check_write_with_api_name(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: Option<&str>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.lock().write.check(path, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
pub fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
||||||
self.0.lock().write.check_all(Some(api_name))
|
self.0.lock().write.check_all(Some(api_name))
|
||||||
|
@ -1331,6 +1366,15 @@ impl PermissionsContainer {
|
||||||
self.0.lock().write.check_blind(path, display, api_name)
|
self.0.lock().write.check_blind(path, display, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn check_write_partial(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.0.lock().write.check_partial(path, Some(api_name))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn check_run(
|
pub fn check_run(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1346,11 +1390,7 @@ impl PermissionsContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn check_sys(
|
pub fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> {
|
||||||
&mut self,
|
|
||||||
kind: &str,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().sys.check(kind, Some(api_name))
|
self.0.lock().sys.check(kind, Some(api_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1363,11 +1403,9 @@ impl PermissionsContainer {
|
||||||
pub fn check_env_all(&mut self) -> Result<(), AnyError> {
|
pub fn check_env_all(&mut self) -> Result<(), AnyError> {
|
||||||
self.0.lock().env.check_all()
|
self.0.lock().env.check_all()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_node::NodePermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_net_url(
|
pub fn check_net_url(
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
|
@ -1376,31 +1414,7 @@ impl deno_node::NodePermissions for PermissionsContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read_with_api_name(
|
pub fn check_net<T: AsRef<str>>(
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: Option<&str>,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check(path, api_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_write_with_api_name(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: Option<&str>,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().write.check(path, api_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().sys.check(kind, Some(api_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_net::NetPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_net<T: AsRef<str>>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
host: &(T, Option<u16>),
|
host: &(T, Option<u16>),
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
|
@ -1409,155 +1423,16 @@ impl deno_net::NetPermissions for PermissionsContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read(
|
pub fn check_ffi(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check(path, Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_write(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().write.check(path, Some(api_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_fetch::FetchPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_net_url(
|
|
||||||
&mut self,
|
|
||||||
url: &url::Url,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().net.check_url(url, Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_read(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check(path, Some(api_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_web::TimersPermission for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn allow_hrtime(&mut self) -> bool {
|
|
||||||
self.0.lock().hrtime.check().is_ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_websocket::WebSocketPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_net_url(
|
|
||||||
&mut self,
|
|
||||||
url: &url::Url,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().net.check_url(url, Some(api_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_fs::FsPermissions for PermissionsContainer {
|
|
||||||
fn check_read(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check(path, Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_read_blind(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
display: &str,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check_blind(path, display, api_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_write(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().write.check(path, Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_write_partial(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().write.check_partial(path, Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_write_blind(
|
|
||||||
&mut self,
|
|
||||||
p: &Path,
|
|
||||||
display: &str,
|
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().write.check_blind(p, display, api_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check_all(Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().write.check_all(Some(api_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
|
|
||||||
// change in the future.
|
|
||||||
impl deno_napi::NapiPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().ffi.check(path.unwrap(), None)
|
self.0.lock().ffi.check(path.unwrap(), None)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_ffi::FfiPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().ffi.check_partial(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_kv::sqlite::SqliteDbHandlerPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().read.check(p, Some(api_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> {
|
pub fn check_ffi_partial(
|
||||||
self.0.lock().write.check(p, Some(api_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_kv::remote::RemoteDbHandlerPermissions for PermissionsContainer {
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_env(&mut self, var: &str) -> Result<(), AnyError> {
|
|
||||||
self.0.lock().env.check(var)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_net_url(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &url::Url,
|
path: Option<&Path>,
|
||||||
api_name: &str,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.0.lock().net.check_url(url, Some(api_name))
|
self.0.lock().ffi.check_partial(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,22 @@ use std::sync::Arc;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Permissions;
|
struct Permissions;
|
||||||
|
|
||||||
|
impl deno_websocket::WebSocketPermissions for Permissions {
|
||||||
|
fn check_net_url(
|
||||||
|
&mut self,
|
||||||
|
_url: &deno_core::url::Url,
|
||||||
|
_api_name: &str,
|
||||||
|
) -> Result<(), deno_core::error::AnyError> {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_web::TimersPermission for Permissions {
|
||||||
|
fn allow_hrtime(&mut self) -> bool {
|
||||||
|
unreachable!("snapshotting!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl deno_fetch::FetchPermissions for Permissions {
|
impl deno_fetch::FetchPermissions for Permissions {
|
||||||
fn check_net_url(
|
fn check_net_url(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -37,22 +53,6 @@ impl deno_fetch::FetchPermissions for Permissions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl deno_websocket::WebSocketPermissions for Permissions {
|
|
||||||
fn check_net_url(
|
|
||||||
&mut self,
|
|
||||||
_url: &deno_core::url::Url,
|
|
||||||
_api_name: &str,
|
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
|
||||||
unreachable!("snapshotting!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_web::TimersPermission for Permissions {
|
|
||||||
fn allow_hrtime(&mut self) -> bool {
|
|
||||||
unreachable!("snapshotting!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl deno_ffi::FfiPermissions for Permissions {
|
impl deno_ffi::FfiPermissions for Permissions {
|
||||||
fn check_partial(
|
fn check_partial(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -390,6 +390,7 @@ impl WebWorker {
|
||||||
enable_testing_features: bool,
|
enable_testing_features: bool,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
|
state.put(options.permissions.0.clone());
|
||||||
state.put::<PermissionsContainer>(options.permissions);
|
state.put::<PermissionsContainer>(options.permissions);
|
||||||
state.put(ops::TestingFeaturesEnabled(options.enable_testing_features));
|
state.put(ops::TestingFeaturesEnabled(options.enable_testing_features));
|
||||||
},
|
},
|
||||||
|
|
|
@ -315,6 +315,9 @@ impl MainWorker {
|
||||||
enable_testing_features: bool,
|
enable_testing_features: bool,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
|
// Save the permissions container and the wrapper.
|
||||||
|
state.put(options.permissions.0.clone());
|
||||||
|
// This is temporary until we migrate all exts/ to the deno_permissions crate.
|
||||||
state.put::<PermissionsContainer>(options.permissions);
|
state.put::<PermissionsContainer>(options.permissions);
|
||||||
state.put(ops::TestingFeaturesEnabled(options.enable_testing_features));
|
state.put(ops::TestingFeaturesEnabled(options.enable_testing_features));
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue