mirror of https://github.com/tauri-apps/tauri
refactor(core): allow configuring both local and remote URLs on capability (#8950)
This commit is contained in:
parent
e538ba586c
commit
a76fb118ce
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
"tauri-utils": patch:breaking
|
||||
"tauri-cli": patch:breaking
|
||||
"@tauri-apps/cli": patch:breaking
|
||||
---
|
||||
|
||||
Changed the capability format to allow configuring both `remote: { urls: Vec<String> }` and `local: bool (default: true)` instead of choosing one on the `context` field.
|
|
@ -1085,15 +1085,22 @@
|
|||
"default": "",
|
||||
"type": "string"
|
||||
},
|
||||
"context": {
|
||||
"description": "Execution context of the capability.\n\nAt runtime, Tauri filters the IPC command together with the context to determine whether it is allowed or not and its scope.",
|
||||
"default": "local",
|
||||
"allOf": [
|
||||
"remote": {
|
||||
"description": "Configure remote URLs that can use the capability permissions.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CapabilityContext"
|
||||
"$ref": "#/definitions/CapabilityRemote"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"local": {
|
||||
"description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"windows": {
|
||||
"description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.",
|
||||
"type": "array",
|
||||
|
@ -1131,42 +1138,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"CapabilityContext": {
|
||||
"description": "Context of the capability.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Capability refers to local URL usage.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"local"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Capability refers to remote usage.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"remote"
|
||||
],
|
||||
"properties": {
|
||||
"remote": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"urls"
|
||||
],
|
||||
"properties": {
|
||||
"urls": {
|
||||
"description": "Remote domains this capability refers to. Can use glob patterns.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"CapabilityRemote": {
|
||||
"description": "Configuration for remote URLs that are associated with the capability.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"urls"
|
||||
],
|
||||
"properties": {
|
||||
"urls": {
|
||||
"description": "Remote domains this capability refers to. Can use glob patterns.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"PermissionEntry": {
|
||||
"description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.",
|
||||
|
|
|
@ -56,11 +56,11 @@ pub struct Capability {
|
|||
/// Description of the capability.
|
||||
#[serde(default)]
|
||||
pub description: String,
|
||||
/// Execution context of the capability.
|
||||
///
|
||||
/// At runtime, Tauri filters the IPC command together with the context to determine whether it is allowed or not and its scope.
|
||||
#[serde(default)]
|
||||
pub context: CapabilityContext,
|
||||
/// Configure remote URLs that can use the capability permissions.
|
||||
pub remote: Option<CapabilityRemote>,
|
||||
/// Whether this capability is enabled for local app URLs or not. Defaults to `true`.
|
||||
#[serde(default = "default_capability_local")]
|
||||
pub local: bool,
|
||||
/// List of windows that uses this capability. Can be a glob pattern.
|
||||
///
|
||||
/// On multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.
|
||||
|
@ -78,6 +78,10 @@ pub struct Capability {
|
|||
pub platforms: Vec<Target>,
|
||||
}
|
||||
|
||||
fn default_capability_local() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_platforms() -> Vec<Target> {
|
||||
vec![
|
||||
Target::Linux,
|
||||
|
@ -88,19 +92,13 @@ fn default_platforms() -> Vec<Target> {
|
|||
]
|
||||
}
|
||||
|
||||
/// Context of the capability.
|
||||
/// Configuration for remote URLs that are associated with the capability.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum CapabilityContext {
|
||||
/// Capability refers to local URL usage.
|
||||
#[default]
|
||||
Local,
|
||||
/// Capability refers to remote usage.
|
||||
Remote {
|
||||
/// Remote domains this capability refers to. Can use glob patterns.
|
||||
urls: Vec<String>,
|
||||
},
|
||||
pub struct CapabilityRemote {
|
||||
/// Remote domains this capability refers to. Can use glob patterns.
|
||||
pub urls: Vec<String>,
|
||||
}
|
||||
|
||||
/// Capability formats accepted in a capability file.
|
||||
|
@ -154,19 +152,14 @@ mod build {
|
|||
use super::*;
|
||||
use crate::{literal_struct, tokens::*};
|
||||
|
||||
impl ToTokens for CapabilityContext {
|
||||
impl ToTokens for CapabilityRemote {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::utils::acl::capability::CapabilityContext };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::Remote { urls } => {
|
||||
let urls = vec_lit(urls, str_lit);
|
||||
quote! { #prefix::Remote { urls: #urls } }
|
||||
}
|
||||
Self::Local => {
|
||||
quote! { #prefix::Local }
|
||||
}
|
||||
});
|
||||
let urls = vec_lit(&self.urls, str_lit);
|
||||
literal_struct!(
|
||||
tokens,
|
||||
::tauri::utils::acl::capability::CapabilityRemote,
|
||||
urls
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +185,8 @@ mod build {
|
|||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let identifier = str_lit(&self.identifier);
|
||||
let description = str_lit(&self.description);
|
||||
let context = &self.context;
|
||||
let remote = &self.remote;
|
||||
let local = self.local;
|
||||
let windows = vec_lit(&self.windows, str_lit);
|
||||
let permissions = vec_lit(&self.permissions, identity);
|
||||
let platforms = vec_lit(&self.platforms, identity);
|
||||
|
@ -202,7 +196,8 @@ mod build {
|
|||
::tauri::utils::acl::capability::Capability,
|
||||
identifier,
|
||||
description,
|
||||
context,
|
||||
remote,
|
||||
local,
|
||||
windows,
|
||||
permissions,
|
||||
platforms
|
||||
|
|
|
@ -15,7 +15,7 @@ use glob::Pattern;
|
|||
use crate::platform::Target;
|
||||
|
||||
use super::{
|
||||
capability::{Capability, CapabilityContext, PermissionEntry},
|
||||
capability::{Capability, PermissionEntry},
|
||||
plugin::Manifest,
|
||||
Commands, Error, ExecutionContext, Permission, PermissionSet, Scopes, Value,
|
||||
};
|
||||
|
@ -346,18 +346,18 @@ fn resolve_command(
|
|||
scope_id: Option<ScopeKey>,
|
||||
#[cfg(debug_assertions)] referenced_by_permission_identifier: String,
|
||||
) {
|
||||
let contexts = match &capability.context {
|
||||
CapabilityContext::Local => {
|
||||
vec![ExecutionContext::Local]
|
||||
}
|
||||
CapabilityContext::Remote { urls } => urls
|
||||
.iter()
|
||||
.map(|url| ExecutionContext::Remote {
|
||||
let mut contexts = Vec::new();
|
||||
if capability.local {
|
||||
contexts.push(ExecutionContext::Local);
|
||||
}
|
||||
if let Some(remote) = &capability.remote {
|
||||
contexts.extend(remote.urls.iter().map(|url| {
|
||||
ExecutionContext::Remote {
|
||||
url: Pattern::new(url)
|
||||
.unwrap_or_else(|e| panic!("invalid glob pattern for remote URL {url}: {e}")),
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for context in contexts {
|
||||
let resolved = commands
|
||||
|
|
|
@ -2,5 +2,6 @@ identifier = "run-app"
|
|||
description = "app capability"
|
||||
windows = ["main"]
|
||||
permissions = ["fs:read", "fs:allow-app"]
|
||||
[context.remote]
|
||||
local = false
|
||||
[remote]
|
||||
urls = ["https://tauri.app"]
|
||||
|
|
|
@ -1085,15 +1085,22 @@
|
|||
"default": "",
|
||||
"type": "string"
|
||||
},
|
||||
"context": {
|
||||
"description": "Execution context of the capability.\n\nAt runtime, Tauri filters the IPC command together with the context to determine whether it is allowed or not and its scope.",
|
||||
"default": "local",
|
||||
"allOf": [
|
||||
"remote": {
|
||||
"description": "Configure remote URLs that can use the capability permissions.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CapabilityContext"
|
||||
"$ref": "#/definitions/CapabilityRemote"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"local": {
|
||||
"description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"windows": {
|
||||
"description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.",
|
||||
"type": "array",
|
||||
|
@ -1131,42 +1138,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"CapabilityContext": {
|
||||
"description": "Context of the capability.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Capability refers to local URL usage.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"local"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Capability refers to remote usage.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"remote"
|
||||
],
|
||||
"properties": {
|
||||
"remote": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"urls"
|
||||
],
|
||||
"properties": {
|
||||
"urls": {
|
||||
"description": "Remote domains this capability refers to. Can use glob patterns.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"CapabilityRemote": {
|
||||
"description": "Configuration for remote URLs that are associated with the capability.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"urls"
|
||||
],
|
||||
"properties": {
|
||||
"urls": {
|
||||
"description": "Remote domains this capability refers to. Can use glob patterns.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"PermissionEntry": {
|
||||
"description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.",
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::Result;
|
|||
use serde_json::{Map, Value};
|
||||
use tauri_utils::{
|
||||
acl::{
|
||||
capability::{Capability, CapabilityContext, PermissionEntry},
|
||||
capability::{Capability, PermissionEntry},
|
||||
Scopes, Value as AclValue,
|
||||
},
|
||||
platform::Target,
|
||||
|
@ -59,7 +59,8 @@ pub fn migrate(tauri_dir: &Path) -> Result<()> {
|
|||
serde_json::to_string_pretty(&Capability {
|
||||
identifier: "migrated".to_string(),
|
||||
description: "permissions that were migrated from v1".into(),
|
||||
context: CapabilityContext::Local,
|
||||
local: true,
|
||||
remote: None,
|
||||
windows: vec!["main".into()],
|
||||
webviews: vec![],
|
||||
permissions,
|
||||
|
|
Loading…
Reference in New Issue