refactor(core): allow configuring both local and remote URLs on capability (#8950)

This commit is contained in:
Lucas Fernandes Nogueira 2024-02-22 15:15:16 -03:00 committed by GitHub
parent e538ba586c
commit a76fb118ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 99 additions and 123 deletions

View File

@ -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.

View File

@ -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.",

View File

@ -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

View File

@ -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

View File

@ -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"]

View File

@ -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.",

View File

@ -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,