mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-10-26 18:12:23 +03:00
fix(acl): inconsistencies on urlpattern usage for remote domain URL (#9133)
* fix(acl): inconsistencies on urlpattern usage for remote domain URL * remove println! * typo * fix tests
This commit is contained in:
parent
490a6b424e
commit
e673854c83
5
.changes/fix-remote-domain-url.md
Normal file
5
.changes/fix-remote-domain-url.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch:bug
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes capability remote domain not allowing subpaths, query parameters and hash when those values are empty.
|
@ -1141,7 +1141,7 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"urls": {
|
"urls": {
|
||||||
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).",
|
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n# Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -90,6 +90,11 @@ fn default_capability_local() -> bool {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CapabilityRemote {
|
pub struct CapabilityRemote {
|
||||||
/// Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).
|
/// Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// - "https://*.mydomain.dev": allows subdomains of mydomain.dev
|
||||||
|
/// - "https://mydomain.dev/api/*": allows any subpath of mydomain.dev/api
|
||||||
pub urls: Vec<String>,
|
pub urls: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,21 @@ impl FromStr for RemoteUrlPattern {
|
|||||||
type Err = urlpattern::quirks::Error;
|
type Err = urlpattern::quirks::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
let init = urlpattern::UrlPatternInit::parse_constructor_string::<regex::Regex>(s, None)?;
|
let mut init = urlpattern::UrlPatternInit::parse_constructor_string::<regex::Regex>(s, None)?;
|
||||||
|
if init.search.as_ref().map(|p| p.is_empty()).unwrap_or(true) {
|
||||||
|
init.search.replace("*".to_string());
|
||||||
|
}
|
||||||
|
if init.hash.as_ref().map(|p| p.is_empty()).unwrap_or(true) {
|
||||||
|
init.hash.replace("*".to_string());
|
||||||
|
}
|
||||||
|
if init
|
||||||
|
.pathname
|
||||||
|
.as_ref()
|
||||||
|
.map(|p| p.is_empty() || p == "/")
|
||||||
|
.unwrap_or(true)
|
||||||
|
{
|
||||||
|
init.pathname.replace("*".to_string());
|
||||||
|
}
|
||||||
let pattern = urlpattern::UrlPattern::parse(init)?;
|
let pattern = urlpattern::UrlPattern::parse(init)?;
|
||||||
Ok(Self(Arc::new(pattern), s.to_string()))
|
Ok(Self(Arc::new(pattern), s.to_string()))
|
||||||
}
|
}
|
||||||
@ -251,6 +265,46 @@ pub enum ExecutionContext {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::acl::RemoteUrlPattern;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn url_pattern_domain_wildcard() {
|
||||||
|
let pattern: RemoteUrlPattern = "http://*".parse().unwrap();
|
||||||
|
|
||||||
|
assert!(pattern.test(&"http://tauri.app/path".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"http://tauri.app/path?q=1".parse().unwrap()));
|
||||||
|
|
||||||
|
assert!(pattern.test(&"http://localhost/path".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"http://localhost/path?q=1".parse().unwrap()));
|
||||||
|
|
||||||
|
let pattern: RemoteUrlPattern = "http://*.tauri.app".parse().unwrap();
|
||||||
|
|
||||||
|
assert!(!pattern.test(&"http://tauri.app/path".parse().unwrap()));
|
||||||
|
assert!(!pattern.test(&"http://tauri.app/path?q=1".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"http://api.tauri.app/path".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"http://api.tauri.app/path?q=1".parse().unwrap()));
|
||||||
|
assert!(!pattern.test(&"http://localhost/path".parse().unwrap()));
|
||||||
|
assert!(!pattern.test(&"http://localhost/path?q=1".parse().unwrap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn url_pattern_path_wildcard() {
|
||||||
|
let pattern: RemoteUrlPattern = "http://localhost/*".parse().unwrap();
|
||||||
|
assert!(pattern.test(&"http://localhost/path".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"http://localhost/path?q=1".parse().unwrap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn url_pattern_scheme_wildcard() {
|
||||||
|
let pattern: RemoteUrlPattern = "*://localhost".parse().unwrap();
|
||||||
|
assert!(pattern.test(&"http://localhost/path".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"https://localhost/path?q=1".parse().unwrap()));
|
||||||
|
assert!(pattern.test(&"custom://localhost/path".parse().unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "build")]
|
#[cfg(feature = "build")]
|
||||||
mod build_ {
|
mod build_ {
|
||||||
use std::convert::identity;
|
use std::convert::identity;
|
||||||
|
@ -90,50 +90,59 @@ Resolved {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
pathname: Component {
|
pathname: Component {
|
||||||
pattern_string: "/",
|
pattern_string: "*",
|
||||||
regexp: Ok(
|
regexp: Ok(
|
||||||
Regex(
|
Regex(
|
||||||
"^/$",
|
"^(.*)$",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
group_name_list: [],
|
group_name_list: [
|
||||||
|
"0",
|
||||||
|
],
|
||||||
matcher: Matcher {
|
matcher: Matcher {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
inner: Literal {
|
inner: SingleCapture {
|
||||||
literal: "/",
|
filter: None,
|
||||||
|
allow_empty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
search: Component {
|
search: Component {
|
||||||
pattern_string: "",
|
pattern_string: "*",
|
||||||
regexp: Ok(
|
regexp: Ok(
|
||||||
Regex(
|
Regex(
|
||||||
"^$",
|
"^(.*)$",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
group_name_list: [],
|
group_name_list: [
|
||||||
|
"0",
|
||||||
|
],
|
||||||
matcher: Matcher {
|
matcher: Matcher {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
inner: Literal {
|
inner: SingleCapture {
|
||||||
literal: "",
|
filter: None,
|
||||||
|
allow_empty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hash: Component {
|
hash: Component {
|
||||||
pattern_string: "",
|
pattern_string: "*",
|
||||||
regexp: Ok(
|
regexp: Ok(
|
||||||
Regex(
|
Regex(
|
||||||
"^$",
|
"^(.*)$",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
group_name_list: [],
|
group_name_list: [
|
||||||
|
"0",
|
||||||
|
],
|
||||||
matcher: Matcher {
|
matcher: Matcher {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
inner: Literal {
|
inner: SingleCapture {
|
||||||
literal: "",
|
filter: None,
|
||||||
|
allow_empty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -251,50 +260,59 @@ Resolved {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
pathname: Component {
|
pathname: Component {
|
||||||
pattern_string: "/",
|
pattern_string: "*",
|
||||||
regexp: Ok(
|
regexp: Ok(
|
||||||
Regex(
|
Regex(
|
||||||
"^/$",
|
"^(.*)$",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
group_name_list: [],
|
group_name_list: [
|
||||||
|
"0",
|
||||||
|
],
|
||||||
matcher: Matcher {
|
matcher: Matcher {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
inner: Literal {
|
inner: SingleCapture {
|
||||||
literal: "/",
|
filter: None,
|
||||||
|
allow_empty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
search: Component {
|
search: Component {
|
||||||
pattern_string: "",
|
pattern_string: "*",
|
||||||
regexp: Ok(
|
regexp: Ok(
|
||||||
Regex(
|
Regex(
|
||||||
"^$",
|
"^(.*)$",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
group_name_list: [],
|
group_name_list: [
|
||||||
|
"0",
|
||||||
|
],
|
||||||
matcher: Matcher {
|
matcher: Matcher {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
inner: Literal {
|
inner: SingleCapture {
|
||||||
literal: "",
|
filter: None,
|
||||||
|
allow_empty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hash: Component {
|
hash: Component {
|
||||||
pattern_string: "",
|
pattern_string: "*",
|
||||||
regexp: Ok(
|
regexp: Ok(
|
||||||
Regex(
|
Regex(
|
||||||
"^$",
|
"^(.*)$",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
group_name_list: [],
|
group_name_list: [
|
||||||
|
"0",
|
||||||
|
],
|
||||||
matcher: Matcher {
|
matcher: Matcher {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
suffix: "",
|
suffix: "",
|
||||||
inner: Literal {
|
inner: SingleCapture {
|
||||||
literal: "",
|
filter: None,
|
||||||
|
allow_empty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
"$schema": "../gen/schemas/desktop-schema.json",
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
"identifier": "run-app",
|
"identifier": "run-app",
|
||||||
"description": "permissions to run the app",
|
"description": "permissions to run the app",
|
||||||
"windows": ["main", "main-*"],
|
"windows": [
|
||||||
|
"main",
|
||||||
|
"main-*"
|
||||||
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"identifier": "allow-log-operation",
|
"identifier": "allow-log-operation",
|
||||||
|
@ -1141,7 +1141,7 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"urls": {
|
"urls": {
|
||||||
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).",
|
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n# Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
Loading…
Reference in New Issue
Block a user