// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::path::Path; use std::path::PathBuf; use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::normalize_path; use deno_permissions::AllowRunDescriptor; use deno_permissions::AllowRunDescriptorParseResult; use deno_permissions::DenyRunDescriptor; use deno_permissions::EnvDescriptor; use deno_permissions::FfiDescriptor; use deno_permissions::NetDescriptor; use deno_permissions::PathQueryDescriptor; use deno_permissions::ReadDescriptor; use deno_permissions::RunQueryDescriptor; use deno_permissions::SysDescriptor; use deno_permissions::WriteDescriptor; #[derive(Debug)] pub struct RuntimePermissionDescriptorParser { fs: deno_fs::FileSystemRc, } impl RuntimePermissionDescriptorParser { pub fn new(fs: deno_fs::FileSystemRc) -> Self { Self { fs } } fn resolve_from_cwd(&self, path: &str) -> Result { if path.is_empty() { bail!("Empty path is not allowed"); } let path = Path::new(path); if path.is_absolute() { Ok(normalize_path(path)) } else { let cwd = self.resolve_cwd()?; Ok(normalize_path(cwd.join(path))) } } fn resolve_cwd(&self) -> Result { self .fs .cwd() .map_err(|e| e.into_io_error()) .context("failed resolving cwd") } } impl deno_permissions::PermissionDescriptorParser for RuntimePermissionDescriptorParser { fn parse_read_descriptor( &self, text: &str, ) -> Result { Ok(ReadDescriptor(self.resolve_from_cwd(text)?)) } fn parse_write_descriptor( &self, text: &str, ) -> Result { Ok(WriteDescriptor(self.resolve_from_cwd(text)?)) } fn parse_net_descriptor( &self, text: &str, ) -> Result { NetDescriptor::parse(text) } fn parse_env_descriptor( &self, text: &str, ) -> Result { if text.is_empty() { Err(AnyError::msg("Empty env not allowed")) } else { Ok(EnvDescriptor::new(text)) } } fn parse_sys_descriptor( &self, text: &str, ) -> Result { if text.is_empty() { Err(AnyError::msg("Empty sys not allowed")) } else { Ok(SysDescriptor(text.to_string())) } } fn parse_allow_run_descriptor( &self, text: &str, ) -> Result { Ok(AllowRunDescriptor::parse(text, &self.resolve_cwd()?)?) } fn parse_deny_run_descriptor( &self, text: &str, ) -> Result { Ok(DenyRunDescriptor::parse(text, &self.resolve_cwd()?)) } fn parse_ffi_descriptor( &self, text: &str, ) -> Result { Ok(FfiDescriptor(self.resolve_from_cwd(text)?)) } // queries fn parse_path_query( &self, path: &str, ) -> Result { Ok(PathQueryDescriptor { resolved: self.resolve_from_cwd(path)?, requested: path.to_string(), }) } fn parse_run_query( &self, requested: &str, ) -> Result { if requested.is_empty() { bail!("Empty run query is not allowed"); } RunQueryDescriptor::parse(requested) } } #[cfg(test)] mod test { use std::sync::Arc; use deno_fs::RealFs; use deno_permissions::PermissionDescriptorParser; use super::*; #[test] fn test_handle_empty_value() { let parser = RuntimePermissionDescriptorParser::new(Arc::new(RealFs)); assert!(parser.parse_read_descriptor("").is_err()); assert!(parser.parse_write_descriptor("").is_err()); assert!(parser.parse_env_descriptor("").is_err()); assert!(parser.parse_net_descriptor("").is_err()); assert!(parser.parse_ffi_descriptor("").is_err()); assert!(parser.parse_path_query("").is_err()); assert!(parser.parse_run_query("").is_err()); } }