mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-11 07:55:34 +03:00
allow the app to define custom capabilities
This commit is contained in:
parent
708cb9fa28
commit
b82899b96b
@ -21,6 +21,7 @@ use serde::Deserialize;
|
||||
use tauri_utils::{
|
||||
config::Config,
|
||||
namespace::{MemberResolution, NamespaceLockFile},
|
||||
plugin::Capability,
|
||||
resources::{external_binaries, resource_relpath, ResourcePaths},
|
||||
};
|
||||
|
||||
@ -233,6 +234,7 @@ impl WindowsAttributes {
|
||||
pub struct Attributes {
|
||||
#[allow(dead_code)]
|
||||
windows_attributes: WindowsAttributes,
|
||||
capabilities: Vec<Capability>,
|
||||
}
|
||||
|
||||
impl Attributes {
|
||||
@ -247,6 +249,19 @@ impl Attributes {
|
||||
self.windows_attributes = windows_attributes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Appends a capability JSON. See [`Capability`].
|
||||
#[must_use]
|
||||
pub fn capability(mut self, capability: impl AsRef<str>) -> Self {
|
||||
let capability: Capability =
|
||||
serde_json::from_str(capability.as_ref()).expect("failed to deserialize capability");
|
||||
assert!(
|
||||
!capability.id.is_empty(),
|
||||
"capability must have an identifier"
|
||||
);
|
||||
self.capabilities.push(capability);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Run all build time helpers for your Tauri Application.
|
||||
@ -479,7 +494,20 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let manifests = plugin::manifests();
|
||||
let mut manifests = plugin::manifests();
|
||||
|
||||
const APP_MANIFEST_KEY: &str = "__app__";
|
||||
|
||||
manifests.insert(
|
||||
APP_MANIFEST_KEY.into(),
|
||||
tauri_utils::plugin::Manifest {
|
||||
plugin: "".into(),
|
||||
default_capability: None,
|
||||
capabilities: attributes.capabilities,
|
||||
features: Vec::new(),
|
||||
scope_type: Vec::new(),
|
||||
},
|
||||
);
|
||||
let mut resolution = HashMap::<String, MemberResolution>::new();
|
||||
|
||||
for namespace in &config.namespaces {
|
||||
@ -496,13 +524,17 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
|
||||
let (plugin, capability) = manifests.find_capability(capability).unwrap_or_else(|| {
|
||||
panic!("could not find capability specification matching id {capability}")
|
||||
});
|
||||
member_resolution.commands.extend(
|
||||
capability
|
||||
.features
|
||||
.into_iter()
|
||||
.map(|f| format!("plugin:{plugin}|{f}"))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
if plugin == APP_MANIFEST_KEY {
|
||||
member_resolution.commands.extend(capability.features);
|
||||
} else {
|
||||
member_resolution.commands.extend(
|
||||
capability
|
||||
.features
|
||||
.into_iter()
|
||||
.map(|f| format!("plugin:{plugin}|{f}"))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ fn runtime_authority_codegen(root: &TokenStream, lockfile: NamespaceLockFile) ->
|
||||
let commands = &r.commands;
|
||||
let resolution = quote!(#root::runtime_authority::MemberResolution {
|
||||
member: #member.into(),
|
||||
commands: vec![#(#commands)*.into()]
|
||||
commands: vec![#(#commands.into(),)*]
|
||||
});
|
||||
quote!(authority.add_member(#resolution);)
|
||||
});
|
||||
|
@ -6,7 +6,10 @@
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
const DEFAULT_CAPABILITY_ID: &str = "default";
|
||||
|
||||
@ -34,6 +37,12 @@ pub struct Capability {
|
||||
/// The identifier of the capability. Must be unique.
|
||||
#[serde(default)]
|
||||
pub id: String,
|
||||
/// The component this capability refers to.
|
||||
///
|
||||
/// Currently the possible values are plugin names.
|
||||
///
|
||||
/// When no value is set, it referes to the application itself.
|
||||
pub component: Option<String>,
|
||||
/// Describes the capability in a human readable format.
|
||||
pub description: String,
|
||||
/// List of features enabled by this capability.
|
||||
@ -48,6 +57,7 @@ pub struct Capability {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Manifest {
|
||||
/// Plugin name.
|
||||
#[serde(skip_serializing_if = "String::is_empty", default)]
|
||||
pub plugin: String,
|
||||
/// Default capability.
|
||||
pub default_capability: Option<Capability>,
|
||||
@ -77,7 +87,7 @@ impl Manifest {
|
||||
.expect("failed to deserialize default capability");
|
||||
assert!(
|
||||
capability.id.is_empty(),
|
||||
"default capability cannot have an specific identifier"
|
||||
"default capability cannot have an identifier"
|
||||
);
|
||||
capability.id = DEFAULT_CAPABILITY_ID.into();
|
||||
self.default_capability.replace(capability);
|
||||
@ -90,7 +100,7 @@ impl Manifest {
|
||||
serde_json::from_str(capability.as_ref()).expect("failed to deserialize default capability");
|
||||
assert!(
|
||||
!capability.id.is_empty(),
|
||||
"capability must have an specific identifier"
|
||||
"capability must have an identifier"
|
||||
);
|
||||
self.capabilities.push(capability);
|
||||
self
|
||||
@ -121,6 +131,20 @@ impl Manifest {
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct ManifestMap(HashMap<String, Manifest>);
|
||||
|
||||
impl Deref for ManifestMap {
|
||||
type Target = HashMap<String, Manifest>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ManifestMap {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HashMap<String, Manifest>> for ManifestMap {
|
||||
fn from(value: HashMap<String, Manifest>) -> Self {
|
||||
Self(value)
|
||||
|
678
examples/api/src-tauri/Cargo.lock
generated
678
examples/api/src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@ tauri-plugin-cli = { git = "https://github.com/tauri-apps/plugins-workspace", br
|
||||
[patch.crates-io]
|
||||
tauri = { path = "../../../core/tauri" }
|
||||
tauri-build = { path = "../../../core/tauri-build" }
|
||||
tao = { path = "../../../../tao" }
|
||||
|
||||
[patch.'https://github.com/tauri-apps/tauri']
|
||||
tauri = { path = "../../../core/tauri" }
|
||||
|
@ -3,7 +3,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
fn main() {
|
||||
tauri_build::build();
|
||||
tauri_build::try_build(
|
||||
tauri_build::Attributes::new().capability(include_str!("./capabilities/allow-commands.json")),
|
||||
)
|
||||
.expect("failed to run tauri-build");
|
||||
|
||||
let mut codegen = tauri_build::CodegenContext::new();
|
||||
if !cfg!(feature = "custom-protocol") {
|
||||
|
8
examples/api/src-tauri/capabilities/allow-commands.json
Normal file
8
examples/api/src-tauri/capabilities/allow-commands.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"id": "allow-all-api-commands",
|
||||
"description": "Allows all application defined commands",
|
||||
"features": [
|
||||
"log_operation",
|
||||
"perform_request"
|
||||
]
|
||||
}
|
@ -111,6 +111,6 @@
|
||||
"id": "main",
|
||||
"description": "Main window namespace",
|
||||
"members": ["main"],
|
||||
"capabilities": ["allow-ping"]
|
||||
"capabilities": ["allow-all-api-commands", "allow-ping"]
|
||||
}]
|
||||
}
|
||||
|
@ -8,15 +8,37 @@
|
||||
"main"
|
||||
],
|
||||
"capabilities": [
|
||||
"allow-all-api-commands",
|
||||
"allow-ping"
|
||||
]
|
||||
}
|
||||
],
|
||||
"plugins": {
|
||||
"__app__": {
|
||||
"default_capability": null,
|
||||
"capabilities": [
|
||||
{
|
||||
"id": "allow-all-api-commands",
|
||||
"component": null,
|
||||
"description": "Allows all application defined commands",
|
||||
"features": [
|
||||
"log_operation",
|
||||
"perform_request"
|
||||
],
|
||||
"scope": {
|
||||
"allowed": [],
|
||||
"blocked": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"features": [],
|
||||
"scope_type": []
|
||||
},
|
||||
"sample": {
|
||||
"plugin": "sample",
|
||||
"default_capability": {
|
||||
"id": "default",
|
||||
"component": null,
|
||||
"description": "Default empty capability set",
|
||||
"features": [],
|
||||
"scope": {
|
||||
@ -27,6 +49,7 @@
|
||||
"capabilities": [
|
||||
{
|
||||
"id": "allow-ping",
|
||||
"component": null,
|
||||
"description": "Allows the ping command",
|
||||
"features": [
|
||||
"ping"
|
||||
@ -49,6 +72,8 @@
|
||||
{
|
||||
"member": "main",
|
||||
"commands": [
|
||||
"log_operation",
|
||||
"perform_request",
|
||||
"plugin:sample|ping"
|
||||
]
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user