Skip to content

Commit 4ef17d0

Browse files
authored
refactor(acl): use URLPattern instead of glob for remote URLs (#9116)
1 parent 9dc9ca6 commit 4ef17d0

13 files changed

Lines changed: 455 additions & 134 deletions

File tree

.changes/acl-urlpattern.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri": patch:breaking
3+
"tauri-utils": patch:breaking
4+
---
5+
6+
The ACL configuration for remote URLs now uses the URLPattern standard instead of glob patterns.

Cargo.lock

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/tauri-config-schema/schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@
11461146
],
11471147
"properties": {
11481148
"urls": {
1149-
"description": "Remote domains this capability refers to. Can use glob patterns.",
1149+
"description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).",
11501150
"type": "array",
11511151
"items": {
11521152
"type": "string"

core/tauri-utils/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ json5 = { version = "0.4", optional = true }
3333
toml = { version = "0.8", features = [ "parse" ] }
3434
json-patch = "1.2"
3535
glob = "0.3"
36+
urlpattern = "0.2"
37+
regex = "1"
3638
walkdir = { version = "2", optional = true }
3739
memchr = "2"
3840
semver = "1"

core/tauri-utils/src/acl/capability.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn default_platforms() -> Vec<Target> {
9898
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
9999
#[serde(rename_all = "camelCase")]
100100
pub struct CapabilityRemote {
101-
/// Remote domains this capability refers to. Can use glob patterns.
101+
/// Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).
102102
pub urls: Vec<String>,
103103
}
104104

core/tauri-utils/src/acl/mod.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
//! Access Control List types.
66
7-
use glob::Pattern;
87
use serde::{Deserialize, Serialize};
9-
use std::num::NonZeroU64;
8+
use std::{num::NonZeroU64, str::FromStr, sync::Arc};
109
use thiserror::Error;
10+
use url::Url;
1111

1212
use crate::platform::Target;
1313

@@ -204,16 +204,60 @@ pub struct PermissionSet {
204204
pub permissions: Vec<String>,
205205
}
206206

207+
/// UrlPattern for [`ExecutionContext::Remote`].
208+
#[derive(Debug, Clone)]
209+
pub struct RemoteUrlPattern(Arc<urlpattern::UrlPattern>, String);
210+
211+
impl FromStr for RemoteUrlPattern {
212+
type Err = urlpattern::quirks::Error;
213+
214+
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
215+
let init = urlpattern::UrlPatternInit::parse_constructor_string::<regex::Regex>(s, None)?;
216+
let pattern = urlpattern::UrlPattern::parse(init)?;
217+
Ok(Self(Arc::new(pattern), s.to_string()))
218+
}
219+
}
220+
221+
impl RemoteUrlPattern {
222+
#[doc(hidden)]
223+
pub fn as_str(&self) -> &str {
224+
&self.1
225+
}
226+
227+
/// Test if a given URL matches the pattern.
228+
pub fn test(&self, url: &Url) -> bool {
229+
self
230+
.0
231+
.test(urlpattern::UrlPatternMatchInput::Url(url.clone()))
232+
.unwrap_or_default()
233+
}
234+
}
235+
236+
impl PartialEq for RemoteUrlPattern {
237+
fn eq(&self, other: &Self) -> bool {
238+
self.0.protocol() == other.0.protocol()
239+
&& self.0.username() == other.0.username()
240+
&& self.0.password() == other.0.password()
241+
&& self.0.hostname() == other.0.hostname()
242+
&& self.0.port() == other.0.port()
243+
&& self.0.pathname() == other.0.pathname()
244+
&& self.0.search() == other.0.search()
245+
&& self.0.hash() == other.0.hash()
246+
}
247+
}
248+
249+
impl Eq for RemoteUrlPattern {}
250+
207251
/// Execution context of an IPC call.
208-
#[derive(Debug, Default, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
252+
#[derive(Debug, Default, Clone, Eq, PartialEq)]
209253
pub enum ExecutionContext {
210254
/// A local URL is used (the Tauri app URL).
211255
#[default]
212256
Local,
213257
/// Remote URL is tring to use the IPC.
214258
Remote {
215-
/// The URL trying to access the IPC (glob pattern).
216-
url: Pattern,
259+
/// The URL trying to access the IPC (URL pattern).
260+
url: RemoteUrlPattern,
217261
},
218262
}
219263

core/tauri-utils/src/acl/resolved.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
77
use std::{collections::BTreeMap, fmt};
88

9-
use glob::Pattern;
10-
119
use crate::platform::Target;
1210

1311
use super::{
@@ -292,8 +290,9 @@ fn resolve_command(
292290
if let Some(remote) = &capability.remote {
293291
contexts.extend(remote.urls.iter().map(|url| {
294292
ExecutionContext::Remote {
295-
url: Pattern::new(url)
296-
.unwrap_or_else(|e| panic!("invalid glob pattern for remote URL {url}: {e}")),
293+
url: url
294+
.parse()
295+
.unwrap_or_else(|e| panic!("invalid URL pattern for remote URL {url}: {e}")),
297296
}
298297
}));
299298
}

core/tauri/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ reqwest = { version = "0.11", default-features = false, features = [ "json", "st
6464
bytes = { version = "1", features = [ "serde" ] }
6565
raw-window-handle = "0.6"
6666
glob = "0.3"
67+
urlpattern = "0.2"
6768
mime = "0.3"
6869
data-url = { version = "0.3", optional = true }
6970
serialize-to-javascript = "=0.1.1"

core/tauri/src/ipc/authority.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use tauri_utils::acl::{
2020
ExecutionContext, Scopes,
2121
};
2222

23+
use url::Url;
24+
2325
use crate::{ipc::InvokeError, sealed::ManagerBase, Runtime};
2426
use crate::{AppHandle, Manager};
2527

@@ -40,7 +42,7 @@ pub enum Origin {
4042
/// Remote origin.
4143
Remote {
4244
/// Remote URL.
43-
url: String,
45+
url: Url,
4446
},
4547
}
4648

@@ -58,7 +60,7 @@ impl Origin {
5860
match (self, context) {
5961
(Self::Local, ExecutionContext::Local) => true,
6062
(Self::Remote { url }, ExecutionContext::Remote { url: url_pattern }) => {
61-
url_pattern.matches(url)
63+
url_pattern.test(url)
6264
}
6365
_ => false,
6466
}
@@ -816,7 +818,7 @@ mod tests {
816818
let resolved_cmd = vec![ResolvedCommand {
817819
windows: vec![Pattern::new(window).unwrap()],
818820
context: ExecutionContext::Remote {
819-
url: Pattern::new(url).unwrap(),
821+
url: url.parse().unwrap(),
820822
},
821823
..Default::default()
822824
}];
@@ -837,7 +839,9 @@ mod tests {
837839
command,
838840
window,
839841
webview,
840-
&Origin::Remote { url: url.into() }
842+
&Origin::Remote {
843+
url: url.parse().unwrap()
844+
}
841845
),
842846
Some(resolved_cmd)
843847
);
@@ -853,7 +857,7 @@ mod tests {
853857
let resolved_cmd = vec![ResolvedCommand {
854858
windows: vec![Pattern::new(window).unwrap()],
855859
context: ExecutionContext::Remote {
856-
url: Pattern::new(url).unwrap(),
860+
url: url.parse().unwrap(),
857861
},
858862
..Default::default()
859863
}];
@@ -875,7 +879,7 @@ mod tests {
875879
window,
876880
webview,
877881
&Origin::Remote {
878-
url: url.replace('*', "studio")
882+
url: url.replace('*', "studio").parse().unwrap()
879883
}
880884
),
881885
Some(resolved_cmd)
@@ -908,7 +912,7 @@ mod tests {
908912
window,
909913
webview,
910914
&Origin::Remote {
911-
url: "https://tauri.app".into()
915+
url: "https://tauri.app".parse().unwrap()
912916
}
913917
)
914918
.is_none());

core/tauri/src/webview/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ fn main() {
11371137
Origin::Local
11381138
} else {
11391139
Origin::Remote {
1140-
url: current_url.to_string(),
1140+
url: current_url.clone(),
11411141
}
11421142
};
11431143
let (resolved_acl, has_app_acl_manifest) = {

0 commit comments

Comments
 (0)