1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-21 14:54:47 -05:00

refactor(permissions): remove FromStr implementations, add ::parse methods (#25473)

The `.parse()` calls in permission code are only making it more
confusing, verbosity
is encouraged and welcome in this code even at the cost of not being
concise.

Left a couple TODOs to not use `AnyError`.
This commit is contained in:
Bartek Iwańczuk 2024-09-06 10:28:53 +01:00 committed by GitHub
parent 73ab32c551
commit 5dedb49ac4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 50 deletions

View file

@ -50,7 +50,7 @@ pub fn parse(paths: Vec<String>) -> clap::error::Result<Vec<String>> {
out.push(format!("{}:{}", host, port.0));
}
} else {
host_and_port.parse::<NetDescriptor>().map_err(|e| {
NetDescriptor::parse(&host_and_port).map_err(|e| {
clap::Error::raw(clap::error::ErrorKind::InvalidValue, format!("{e:?}"))
})?;
out.push(host_and_port)

View file

@ -1,6 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use ::deno_permissions::parse_sys_kind;
use ::deno_permissions::NetDescriptor;
use ::deno_permissions::PermissionState;
use ::deno_permissions::PermissionsContainer;
use deno_core::error::custom_error;
@ -63,7 +64,7 @@ pub fn op_query_permission(
"net" => permissions.net.query(
match args.host.as_deref() {
None => None,
Some(h) => Some(h.parse()?),
Some(h) => Some(NetDescriptor::parse(h)?),
}
.as_ref(),
),
@ -97,7 +98,7 @@ pub fn op_revoke_permission(
"net" => permissions.net.revoke(
match args.host.as_deref() {
None => None,
Some(h) => Some(h.parse()?),
Some(h) => Some(NetDescriptor::parse(h)?),
}
.as_ref(),
),
@ -131,7 +132,7 @@ pub fn op_request_permission(
"net" => permissions.net.request(
match args.host.as_deref() {
None => None,
Some(h) => Some(h.parse()?),
Some(h) => Some(NetDescriptor::parse(h)?),
}
.as_ref(),
),

View file

@ -0,0 +1,3 @@
disallowed-methods = [
{ path = "std::str::FromStr", reason = "Don't want to have stuff like `'0.0.0.0'.parse().unwrap()`. Instead implement ConcreteType::parse methods." },
]

View file

@ -29,7 +29,6 @@ use std::net::IpAddr;
use std::net::Ipv6Addr;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;
use std::string::ToString;
use std::sync::Arc;
@ -683,10 +682,9 @@ pub enum Host {
Ip(IpAddr),
}
impl FromStr for Host {
type Err = AnyError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
impl Host {
// TODO(bartlomieju): rewrite to not use `AnyError` but a specific error implementations
fn parse(s: &str) -> Result<Self, AnyError> {
if s.starts_with('[') && s.ends_with(']') {
let ip = s[1..s.len() - 1]
.parse::<Ipv6Addr>()
@ -708,14 +706,23 @@ impl FromStr for Host {
} else {
Cow::Owned(s.to_ascii_lowercase())
};
let fqdn = FQDN::from_str(&lower)
.with_context(|| format!("invalid host: '{s}'"))?;
let fqdn = {
use std::str::FromStr;
FQDN::from_str(&lower)
.with_context(|| format!("invalid host: '{s}'"))?
};
if fqdn.is_root() {
return Err(uri_error(format!("invalid empty host: '{s}'")));
}
Ok(Host::Fqdn(fqdn))
}
}
#[cfg(test)]
#[track_caller]
fn must_parse(s: &str) -> Self {
Self::parse(s).unwrap()
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
@ -750,10 +757,9 @@ impl Descriptor for NetDescriptor {
}
}
impl FromStr for NetDescriptor {
type Err = AnyError;
fn from_str(hostname: &str) -> Result<Self, Self::Err> {
// TODO(bartlomieju): rewrite to not use `AnyError` but a specific error implementations
impl NetDescriptor {
pub fn parse(hostname: &str) -> Result<Self, AnyError> {
// If this is a IPv6 address enclosed in square brackets, parse it as such.
if hostname.starts_with('[') {
if let Some((ip, after)) = hostname.split_once(']') {
@ -784,7 +790,7 @@ impl FromStr for NetDescriptor {
Some((host, port)) => (host, port),
None => (hostname, ""),
};
let host = host.parse::<Host>()?;
let host = Host::parse(host)?;
let port = if port.is_empty() {
None
@ -1222,7 +1228,7 @@ impl UnaryPermission<NetDescriptor> {
let host = url
.host_str()
.ok_or_else(|| type_error(format!("Missing host in url: '{}'", url)))?;
let host = host.parse::<Host>()?;
let host = Host::parse(host)?;
let port = url.port_or_known_default();
let descriptor = NetDescriptor(host, port);
self.check_desc(Some(&descriptor), false, api_name, || {
@ -1865,7 +1871,7 @@ impl PermissionsContainer {
host: &(T, Option<u16>),
api_name: &str,
) -> Result<(), AnyError> {
let hostname = host.0.as_ref().parse::<Host>()?;
let hostname = Host::parse(host.0.as_ref())?;
let descriptor = NetDescriptor(hostname, host.1);
self.0.lock().net.check(&descriptor, Some(api_name))
}
@ -1914,7 +1920,7 @@ fn parse_net_list(
) -> Result<HashSet<NetDescriptor>, AnyError> {
if let Some(v) = list {
v.iter()
.map(|x| NetDescriptor::from_str(x))
.map(|x| NetDescriptor::parse(x))
.collect::<Result<HashSet<NetDescriptor>, AnyError>>()
} else {
Ok(HashSet::new())
@ -2480,7 +2486,7 @@ mod tests {
];
for (host, port, is_ok) in domain_tests {
let host = host.parse().unwrap();
let host = Host::parse(host).unwrap();
let descriptor = NetDescriptor(host, Some(port));
assert_eq!(
is_ok,
@ -2522,7 +2528,7 @@ mod tests {
];
for (host_str, port) in domain_tests {
let host = host_str.parse().unwrap();
let host = Host::parse(host_str).unwrap();
let descriptor = NetDescriptor(host, Some(port));
assert!(
perms.net.check(&descriptor, None).is_ok(),
@ -2563,7 +2569,7 @@ mod tests {
];
for (host_str, port) in domain_tests {
let host = host_str.parse().unwrap();
let host = Host::parse(host_str).unwrap();
let descriptor = NetDescriptor(host, Some(port));
assert!(
perms.net.check(&descriptor, None).is_err(),
@ -2835,14 +2841,14 @@ mod tests {
assert_eq!(perms4.ffi.query(Some(Path::new("/foo/bar"))), PermissionState::Denied);
assert_eq!(perms4.ffi.query(Some(Path::new("/bar"))), PermissionState::Granted);
assert_eq!(perms1.net.query(None), PermissionState::Granted);
assert_eq!(perms1.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Granted);
assert_eq!(perms1.net.query(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), None))), PermissionState::Granted);
assert_eq!(perms2.net.query(None), PermissionState::Prompt);
assert_eq!(perms2.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
assert_eq!(perms2.net.query(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)))), PermissionState::Granted);
assert_eq!(perms3.net.query(None), PermissionState::Prompt);
assert_eq!(perms3.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Denied);
assert_eq!(perms3.net.query(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)))), PermissionState::Denied);
assert_eq!(perms4.net.query(None), PermissionState::GrantedPartial);
assert_eq!(perms4.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Denied);
assert_eq!(perms4.net.query(Some(&NetDescriptor("192.168.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
assert_eq!(perms4.net.query(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)))), PermissionState::Denied);
assert_eq!(perms4.net.query(Some(&NetDescriptor(Host::must_parse("192.168.0.1"), Some(8000)))), PermissionState::Granted);
assert_eq!(perms1.env.query(None), PermissionState::Granted);
assert_eq!(perms1.env.query(Some("HOME")), PermissionState::Granted);
assert_eq!(perms2.env.query(None), PermissionState::Prompt);
@ -2896,9 +2902,9 @@ mod tests {
prompt_value.set(true);
assert_eq!(perms.ffi.request(None), PermissionState::Denied);
prompt_value.set(true);
assert_eq!(perms.net.request(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Granted);
assert_eq!(perms.net.request(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), None))), PermissionState::Granted);
prompt_value.set(false);
assert_eq!(perms.net.request(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
assert_eq!(perms.net.request(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)))), PermissionState::Granted);
prompt_value.set(true);
assert_eq!(perms.env.request(Some("HOME")), PermissionState::Granted);
assert_eq!(perms.env.query(None), PermissionState::Prompt);
@ -2967,9 +2973,9 @@ mod tests {
assert_eq!(perms.ffi.revoke(Some(Path::new("/foo/bar"))), PermissionState::Prompt);
assert_eq!(perms.ffi.query(Some(Path::new("/foo"))), PermissionState::Prompt);
assert_eq!(perms.ffi.query(Some(Path::new("/foo/baz"))), PermissionState::Granted);
assert_eq!(perms.net.revoke(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(9000)))), PermissionState::Prompt);
assert_eq!(perms.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Prompt);
assert_eq!(perms.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
assert_eq!(perms.net.revoke(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), Some(9000)))), PermissionState::Prompt);
assert_eq!(perms.net.query(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), None))), PermissionState::Prompt);
assert_eq!(perms.net.query(Some(&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)))), PermissionState::Granted);
assert_eq!(perms.env.revoke(Some("HOME")), PermissionState::Prompt);
assert_eq!(perms.env.revoke(Some("hostname")), PermissionState::Prompt);
assert_eq!(perms.run.revoke(Some("deno")), PermissionState::Prompt);
@ -3004,7 +3010,7 @@ mod tests {
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)),
None
)
.is_ok());
@ -3012,31 +3018,31 @@ mod tests {
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)),
None
)
.is_ok());
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8001)),
None
)
.is_err());
assert!(perms
.net
.check(&NetDescriptor("127.0.0.1".parse().unwrap(), None), None)
.check(&NetDescriptor(Host::must_parse("127.0.0.1"), None), None)
.is_err());
assert!(perms
.net
.check(
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("deno.land"), Some(8000)),
None
)
.is_err());
assert!(perms
.net
.check(&NetDescriptor("deno.land".parse().unwrap(), None), None)
.check(&NetDescriptor(Host::must_parse("deno.land"), None), None)
.is_err());
#[allow(clippy::disallowed_methods)]
@ -3121,7 +3127,7 @@ mod tests {
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)),
None
)
.is_err());
@ -3129,21 +3135,21 @@ mod tests {
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8000)),
None
)
.is_err());
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8001)),
None
)
.is_ok());
assert!(perms
.net
.check(
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("deno.land"), Some(8000)),
None
)
.is_ok());
@ -3151,14 +3157,14 @@ mod tests {
assert!(perms
.net
.check(
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
&NetDescriptor(Host::must_parse("127.0.0.1"), Some(8001)),
None
)
.is_ok());
assert!(perms
.net
.check(
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
&NetDescriptor(Host::must_parse("deno.land"), Some(8000)),
None
)
.is_ok());
@ -3286,24 +3292,24 @@ mod tests {
perms
.net
.check(
&NetDescriptor("allowed.domain.".parse().unwrap(), None),
&NetDescriptor(Host::must_parse("allowed.domain."), None),
None,
)
.unwrap();
perms
.net
.check(&NetDescriptor("1.1.1.1".parse().unwrap(), None), None)
.check(&NetDescriptor(Host::must_parse("1.1.1.1"), None), None)
.unwrap();
assert!(perms
.net
.check(
&NetDescriptor("denied.domain.".parse().unwrap(), None),
&NetDescriptor(Host::must_parse("denied.domain."), None),
None
)
.is_err());
assert!(perms
.net
.check(&NetDescriptor("2.2.2.2".parse().unwrap(), None), None)
.check(&NetDescriptor(Host::must_parse("2.2.2.2"), None), None)
.is_err());
}
@ -3599,7 +3605,7 @@ mod tests {
];
for (host_str, expected) in hosts {
assert_eq!(host_str.parse::<Host>().ok(), *expected, "{host_str}");
assert_eq!(Host::parse(host_str).ok(), *expected, "{host_str}");
}
}
@ -3665,7 +3671,7 @@ mod tests {
];
for (input, expected) in cases {
assert_eq!(input.parse::<NetDescriptor>().ok(), *expected, "'{input}'");
assert_eq!(NetDescriptor::parse(input).ok(), *expected, "'{input}'");
}
}
}