mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-11-24 12:14:05 +03:00
refactor(core): allow referencing capabilities on the Tauri config file (#8797)
* refactor(core): capabilities must be referenced on the Tauri config file * add all capabilities by default * refactor(cli): reference all capabilities by default
This commit is contained in:
parent
0cb0a15ce2
commit
83a68deb56
7
.changes/capabilities-tauri-conf.md
Normal file
7
.changes/capabilities-tauri-conf.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri-build": patch:breaking
|
||||
"tauri-utils": patch:enhance
|
||||
"tauri-codegen": patch:enhance
|
||||
---
|
||||
|
||||
Added a new configuration option `tauri.conf.json > app > security > capabilities` to reference existing capabilities and inline new ones. If it is empty, all capabilities are still included preserving the current behavior.
|
6
.changes/update-app-template-capabilities-conf.md
Normal file
6
.changes/update-app-template-capabilities-conf.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
"tauri-cli": patch:enhance
|
||||
---
|
||||
|
||||
Update app template following capabilities configuration change.
|
@ -567,6 +567,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
|
||||
out_dir.join(PLUGIN_MANIFESTS_FILE_NAME),
|
||||
serde_json::to_string(&plugin_manifests)?,
|
||||
)?;
|
||||
|
||||
let capabilities = if let Some(pattern) = attributes.capabilities_path_pattern {
|
||||
parse_capabilities(pattern)?
|
||||
} else {
|
||||
|
@ -15,7 +15,7 @@ use tauri_utils::acl::capability::Capability;
|
||||
use tauri_utils::acl::plugin::Manifest;
|
||||
use tauri_utils::acl::resolved::Resolved;
|
||||
use tauri_utils::assets::AssetKey;
|
||||
use tauri_utils::config::{Config, FrontendDist, PatternKind};
|
||||
use tauri_utils::config::{CapabilityEntry, Config, FrontendDist, PatternKind};
|
||||
use tauri_utils::html::{
|
||||
inject_nonce_token, parse as parse_html, serialize_node as serialize_html_node,
|
||||
};
|
||||
@ -381,7 +381,8 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
};
|
||||
|
||||
let capabilities_file_path = out_dir.join(CAPABILITIES_FILE_NAME);
|
||||
let capabilities: BTreeMap<String, Capability> = if capabilities_file_path.exists() {
|
||||
let mut capabilities_from_files: BTreeMap<String, Capability> = if capabilities_file_path.exists()
|
||||
{
|
||||
let capabilities_file =
|
||||
std::fs::read_to_string(capabilities_file_path).expect("failed to read capabilities");
|
||||
serde_json::from_str(&capabilities_file).expect("failed to parse capabilities")
|
||||
@ -389,6 +390,26 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let capabilities = if config.app.security.capabilities.is_empty() {
|
||||
capabilities_from_files
|
||||
} else {
|
||||
let mut capabilities = BTreeMap::new();
|
||||
for capability_entry in &config.app.security.capabilities {
|
||||
match capability_entry {
|
||||
CapabilityEntry::Inlined(capability) => {
|
||||
capabilities.insert(capability.identifier.clone(), capability.clone());
|
||||
}
|
||||
CapabilityEntry::Reference(id) => {
|
||||
let capability = capabilities_from_files
|
||||
.remove(id)
|
||||
.unwrap_or_else(|| panic!("capability with identifier {id} not found"));
|
||||
capabilities.insert(id.clone(), capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
capabilities
|
||||
};
|
||||
|
||||
let resolved_acl = Resolved::resolve(acl, capabilities, target).expect("failed to resolve ACL");
|
||||
|
||||
Ok(quote!({
|
||||
|
@ -40,6 +40,7 @@
|
||||
"enable": false,
|
||||
"scope": []
|
||||
},
|
||||
"capabilities": [],
|
||||
"dangerousDisableAssetCspModification": false,
|
||||
"freezePrototype": false,
|
||||
"pattern": {
|
||||
@ -158,6 +159,7 @@
|
||||
"enable": false,
|
||||
"scope": []
|
||||
},
|
||||
"capabilities": [],
|
||||
"dangerousDisableAssetCspModification": false,
|
||||
"freezePrototype": false,
|
||||
"pattern": {
|
||||
@ -878,6 +880,14 @@
|
||||
"$ref": "#/definitions/PatternKind"
|
||||
}
|
||||
]
|
||||
},
|
||||
"capabilities": {
|
||||
"description": "List of capabilities that are enabled on the application.\n\nIf the list is empty, all capabilities are included.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CapabilityEntry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -1040,6 +1050,264 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CapabilityEntry": {
|
||||
"description": "A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "An inlined capability.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Capability"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Reference to a capability identifier.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Capability": {
|
||||
"description": "a grouping and boundary mechanism developers can use to separate windows or plugins functionality from each other at runtime.\n\nIf a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create trust groups and reduce impact of vulnerabilities in certain plugins or windows. Windows can be added to a capability by exact name or glob patterns like *, admin-* or main-window.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier",
|
||||
"permissions",
|
||||
"windows"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the capability.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the capability.",
|
||||
"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": [
|
||||
{
|
||||
"$ref": "#/definitions/CapabilityContext"
|
||||
}
|
||||
]
|
||||
},
|
||||
"windows": {
|
||||
"description": "List of windows that uses this capability. Can be a glob pattern.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"description": "List of permissions attached to this capability. Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionEntry"
|
||||
}
|
||||
},
|
||||
"platforms": {
|
||||
"description": "Target platforms this capability applies. By default all platforms applies.",
|
||||
"default": [
|
||||
"linux",
|
||||
"macOS",
|
||||
"windows",
|
||||
"android",
|
||||
"iOS"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Target"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"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": [
|
||||
"domains"
|
||||
],
|
||||
"properties": {
|
||||
"domains": {
|
||||
"description": "Remote domains this capability refers to. Can use glob patterns.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"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.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Reference a permission or permission set by identifier.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Reference a permission or permission set by identifier and extends its scope.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the permission or permission set.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
},
|
||||
"allow": {
|
||||
"description": "Data that defines what is allowed by the scope.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"description": "Data that defines what is denied by the scope.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Identifier": {
|
||||
"type": "string"
|
||||
},
|
||||
"Value": {
|
||||
"description": "All supported ACL values.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Represents a null JSON value.",
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`bool`].",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "Represents a valid ACL [`Number`].",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Number"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`String`].",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Represents a list of other [`Value`]s.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Represents a map of [`String`] keys to [`Value`]s.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Number": {
|
||||
"description": "A valid ACL number.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Represents an [`i64`].",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`f64`].",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Target": {
|
||||
"description": "Platform target.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "MacOS.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"macOS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Windows.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Linux.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Android.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "iOS.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"iOS"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"TrayIconConfig": {
|
||||
"description": "Configuration for application tray icon.\n\nSee more: <https://tauri.app/v1/api/config#trayiconconfig>",
|
||||
"type": "object",
|
||||
|
@ -11,7 +11,7 @@ use super::Scopes;
|
||||
|
||||
/// 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.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
pub enum PermissionEntry {
|
||||
@ -46,7 +46,7 @@ impl PermissionEntry {
|
||||
///
|
||||
/// This can be done to create trust groups and reduce impact of vulnerabilities in certain plugins or windows.
|
||||
/// Windows can be added to a capability by exact name or glob patterns like *, admin-* or main-window.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
pub struct Capability {
|
||||
/// Identifier of the capability.
|
||||
@ -100,3 +100,70 @@ pub enum CapabilityContext {
|
||||
domains: Vec<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(feature = "build")]
|
||||
mod build {
|
||||
use std::convert::identity;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
|
||||
use super::*;
|
||||
use crate::{literal_struct, tokens::*};
|
||||
|
||||
impl ToTokens for CapabilityContext {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::utils::acl::capability::CapabilityContext };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::Remote { domains } => {
|
||||
let domains = vec_lit(domains, str_lit);
|
||||
quote! { #prefix::Remote { domains: #domains } }
|
||||
}
|
||||
Self::Local => {
|
||||
quote! { #prefix::Local }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for PermissionEntry {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::utils::acl::capability::PermissionEntry };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::PermissionRef(id) => {
|
||||
quote! { #prefix::PermissionRef(#id) }
|
||||
}
|
||||
Self::ExtendedPermission { identifier, scope } => {
|
||||
quote! { #prefix::ExtendedPermission {
|
||||
identifier: #identifier,
|
||||
scope: #scope
|
||||
} }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Capability {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let identifier = str_lit(&self.identifier);
|
||||
let description = str_lit(&self.description);
|
||||
let context = &self.context;
|
||||
let windows = vec_lit(&self.windows, str_lit);
|
||||
let permissions = vec_lit(&self.permissions, identity);
|
||||
let platforms = vec_lit(&self.platforms, identity);
|
||||
|
||||
literal_struct!(
|
||||
tokens,
|
||||
::tauri::utils::acl::capability::Capability,
|
||||
identifier,
|
||||
description,
|
||||
context,
|
||||
windows,
|
||||
permissions,
|
||||
platforms
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,28 @@ const MAX_LEN_BASE: usize = 64;
|
||||
const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE;
|
||||
|
||||
/// Plugin identifier.
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Identifier {
|
||||
inner: String,
|
||||
separator: Option<NonZeroU8>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "schema")]
|
||||
impl schemars::JsonSchema for Identifier {
|
||||
fn schema_name() -> String {
|
||||
"Identifier".to_string()
|
||||
}
|
||||
|
||||
fn schema_id() -> std::borrow::Cow<'static, str> {
|
||||
// Include the module, in case a type with the same name is in another module/crate
|
||||
std::borrow::Cow::Borrowed(concat!(module_path!(), "::Identifier"))
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
String::json_schema(gen)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Identifier {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &str {
|
||||
@ -262,3 +277,19 @@ mod tests {
|
||||
assert_eq!(ident("base").unwrap().get_prefix(), None);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "build")]
|
||||
mod build {
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl ToTokens for Identifier {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let s = self.get();
|
||||
tokens
|
||||
.append_all(quote! { ::tauri::utils::acl::Identifier::try_from(#s.to_string()).unwrap() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ pub struct Commands {
|
||||
/// It can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.
|
||||
///
|
||||
/// The scope is passed to the command and handled/enforced by the command itself.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
pub struct Scopes {
|
||||
/// Data that defines what is allowed by the scope.
|
||||
|
@ -11,7 +11,7 @@ use std::fmt::Debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A valid ACL number.
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialOrd, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Copy, Clone, PartialOrd)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[serde(untagged)]
|
||||
pub enum Number {
|
||||
@ -37,7 +37,7 @@ impl From<f64> for Number {
|
||||
}
|
||||
|
||||
/// All supported ACL values.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialOrd, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, PartialOrd)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[serde(untagged)]
|
||||
pub enum Value {
|
||||
|
@ -34,7 +34,7 @@ use std::{
|
||||
/// Items to help with parsing content into a [`Config`].
|
||||
pub mod parse;
|
||||
|
||||
use crate::{TitleBarStyle, WindowEffect, WindowEffectState};
|
||||
use crate::{acl::capability::Capability, TitleBarStyle, WindowEffect, WindowEffectState};
|
||||
|
||||
pub use self::parse::parse;
|
||||
|
||||
@ -1519,7 +1519,7 @@ pub struct AssetProtocolConfig {
|
||||
///
|
||||
/// See more: <https://tauri.app/v1/api/config#securityconfig>
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct SecurityConfig {
|
||||
@ -1558,6 +1558,22 @@ pub struct SecurityConfig {
|
||||
/// The pattern to use.
|
||||
#[serde(default)]
|
||||
pub pattern: PatternKind,
|
||||
/// List of capabilities that are enabled on the application.
|
||||
///
|
||||
/// If the list is empty, all capabilities are included.
|
||||
#[serde(default)]
|
||||
pub capabilities: Vec<CapabilityEntry>,
|
||||
}
|
||||
|
||||
/// A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
pub enum CapabilityEntry {
|
||||
/// An inlined capability.
|
||||
Inlined(Capability),
|
||||
/// Reference to a capability identifier.
|
||||
Reference(String),
|
||||
}
|
||||
|
||||
/// The application pattern.
|
||||
@ -2450,6 +2466,22 @@ mod build {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for CapabilityEntry {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::utils::config::CapabilityEntry };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::Inlined(capability) => {
|
||||
quote! { #prefix::Inlined(#capability) }
|
||||
}
|
||||
Self::Reference(id) => {
|
||||
let id = str_lit(id);
|
||||
quote! { #prefix::Reference(#id) }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for SecurityConfig {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let csp = opt_lit(self.csp.as_ref());
|
||||
@ -2458,6 +2490,7 @@ mod build {
|
||||
let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification;
|
||||
let asset_protocol = &self.asset_protocol;
|
||||
let pattern = &self.pattern;
|
||||
let capabilities = vec_lit(&self.capabilities, identity);
|
||||
|
||||
literal_struct!(
|
||||
tokens,
|
||||
@ -2467,7 +2500,8 @@ mod build {
|
||||
freeze_prototype,
|
||||
dangerous_disable_asset_csp_modification,
|
||||
asset_protocol,
|
||||
pattern
|
||||
pattern,
|
||||
capabilities
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2606,6 +2640,7 @@ mod test {
|
||||
dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
|
||||
asset_protocol: AssetProtocolConfig::default(),
|
||||
pattern: Default::default(),
|
||||
capabilities: Vec::new(),
|
||||
},
|
||||
tray_icon: None,
|
||||
macos_private_api: false,
|
||||
|
@ -284,3 +284,25 @@ pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> crate::Result<Path
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(feature = "build")]
|
||||
mod build {
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl ToTokens for Target {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::utils::platform::Target };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::MacOS => quote! { #prefix::MacOS },
|
||||
Self::Linux => quote! { #prefix::Linux },
|
||||
Self::Windows => quote! { #prefix::Windows },
|
||||
Self::Android => quote! { #prefix::Android },
|
||||
Self::Ios => quote! { #prefix::Ios },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,10 @@
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "run-app",
|
||||
"description": "permissions to run the app",
|
||||
"windows": ["main", "main-*"],
|
||||
"windows": [
|
||||
"main",
|
||||
"main-*"
|
||||
],
|
||||
"permissions": [
|
||||
"app-menu:default",
|
||||
"sample:allow-ping-scoped",
|
||||
@ -86,4 +89,4 @@
|
||||
"tray:allow-set-icon-as-template",
|
||||
"tray:allow-set-show-menu-on-left-click"
|
||||
]
|
||||
}
|
||||
}
|
@ -40,6 +40,7 @@
|
||||
"enable": false,
|
||||
"scope": []
|
||||
},
|
||||
"capabilities": [],
|
||||
"dangerousDisableAssetCspModification": false,
|
||||
"freezePrototype": false,
|
||||
"pattern": {
|
||||
@ -158,6 +159,7 @@
|
||||
"enable": false,
|
||||
"scope": []
|
||||
},
|
||||
"capabilities": [],
|
||||
"dangerousDisableAssetCspModification": false,
|
||||
"freezePrototype": false,
|
||||
"pattern": {
|
||||
@ -878,6 +880,14 @@
|
||||
"$ref": "#/definitions/PatternKind"
|
||||
}
|
||||
]
|
||||
},
|
||||
"capabilities": {
|
||||
"description": "List of capabilities that are enabled on the application.\n\nIf the list is empty, all capabilities are included.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CapabilityEntry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -1040,6 +1050,264 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CapabilityEntry": {
|
||||
"description": "A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "An inlined capability.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Capability"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Reference to a capability identifier.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Capability": {
|
||||
"description": "a grouping and boundary mechanism developers can use to separate windows or plugins functionality from each other at runtime.\n\nIf a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create trust groups and reduce impact of vulnerabilities in certain plugins or windows. Windows can be added to a capability by exact name or glob patterns like *, admin-* or main-window.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier",
|
||||
"permissions",
|
||||
"windows"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the capability.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the capability.",
|
||||
"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": [
|
||||
{
|
||||
"$ref": "#/definitions/CapabilityContext"
|
||||
}
|
||||
]
|
||||
},
|
||||
"windows": {
|
||||
"description": "List of windows that uses this capability. Can be a glob pattern.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"description": "List of permissions attached to this capability. Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionEntry"
|
||||
}
|
||||
},
|
||||
"platforms": {
|
||||
"description": "Target platforms this capability applies. By default all platforms applies.",
|
||||
"default": [
|
||||
"linux",
|
||||
"macOS",
|
||||
"windows",
|
||||
"android",
|
||||
"iOS"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Target"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"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": [
|
||||
"domains"
|
||||
],
|
||||
"properties": {
|
||||
"domains": {
|
||||
"description": "Remote domains this capability refers to. Can use glob patterns.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"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.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Reference a permission or permission set by identifier.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Reference a permission or permission set by identifier and extends its scope.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the permission or permission set.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
},
|
||||
"allow": {
|
||||
"description": "Data that defines what is allowed by the scope.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"description": "Data that defines what is denied by the scope.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Identifier": {
|
||||
"type": "string"
|
||||
},
|
||||
"Value": {
|
||||
"description": "All supported ACL values.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Represents a null JSON value.",
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`bool`].",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "Represents a valid ACL [`Number`].",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Number"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`String`].",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Represents a list of other [`Value`]s.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Represents a map of [`String`] keys to [`Value`]s.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Number": {
|
||||
"description": "A valid ACL number.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Represents an [`i64`].",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`f64`].",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Target": {
|
||||
"description": "Platform target.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "MacOS.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"macOS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Windows.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Linux.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Android.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "iOS.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"iOS"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"TrayIconConfig": {
|
||||
"description": "Configuration for application tray icon.\n\nSee more: <https://tauri.app/v1/api/config#trayiconconfig>",
|
||||
"type": "object",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default-plugins",
|
||||
"identifier": "default",
|
||||
"description": "enables the default permissions",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
|
Loading…
Reference in New Issue
Block a user